基于 Docker Swarm 的容器编排实战
1. Docker Swarm 基础概念
Docker Swarm 是 Docker 原生的容器编排工具,它使得在多个 Docker 主机上部署和管理容器变得更加容易。它将一组 Docker 主机变成一个单一的虚拟主机,在这个虚拟主机上,用户可以像在单个主机上一样管理容器。
1.1 节点类型
- Manager 节点:负责管理集群的状态和任务调度。Manager 节点存储集群的状态信息,包括服务定义、节点列表以及任务的分配情况等。在生产环境中,通常会运行多个 Manager 节点以实现高可用性,它们之间通过 Raft 一致性算法来同步状态。
- Worker 节点:负责运行实际的容器任务。Worker 节点从 Manager 节点接收任务分配,并在本地的 Docker 引擎上启动和管理容器。Worker 节点不参与集群管理决策,只专注于执行任务。
1.2 服务与任务
- 服务(Service):是 Swarm 中部署和管理容器的基本单位。一个服务定义了运行容器的镜像、启动命令、资源限制等参数,并且可以指定运行的副本数量。例如,可以定义一个使用 Nginx 镜像的服务,并指定运行 3 个副本,Swarm 会确保在集群的节点上始终运行这 3 个 Nginx 容器。
- 任务(Task):是服务的一个实例。当创建一个服务时,Swarm 会根据服务的定义创建相应数量的任务,并将这些任务分配到合适的节点上运行。每个任务都有自己的生命周期,包括创建、调度、运行、停止和删除等阶段。
2. 搭建 Docker Swarm 集群
在开始搭建 Docker Swarm 集群之前,确保已经在每台主机上安装了 Docker 引擎。以下步骤以三台主机为例进行说明,主机 IP 分别为 192.168.1.100
、192.168.1.101
和 192.168.1.102
。
2.1 初始化 Manager 节点
在其中一台主机(例如 192.168.1.100
)上执行以下命令初始化 Docker Swarm 集群:
docker swarm init --advertise-addr 192.168.1.100
执行上述命令后,会得到类似以下的输出:
Swarm initialized: current node (92x5f464z2279327127341) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-556233959703943349-479487563797461434 192.168.1.100:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
这个输出包含了两个重要信息:
- Worker 节点加入命令:其他主机作为 Worker 节点加入集群时需要执行的命令。
- Manager 节点加入命令:如果需要添加更多的 Manager 节点,可以通过
docker swarm join-token manager
命令获取加入命令。
2.2 添加 Worker 节点
在另外两台主机(192.168.1.101
和 192.168.1.102
)上执行上述获取到的 Worker 节点加入命令,例如:
docker swarm join \
--token SWMTKN-1-556233959703943349-479487563797461434 192.168.1.100:2377
执行成功后,在 Manager 节点上执行 docker node ls
命令,可以看到集群中的节点列表:
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
92x5f464z2279327127341 * manager1 Ready Active Leader 19.03.12
089c6a9e7d7f20776367387295 worker1 Ready Active 19.03.12
12c4f7e3c8a209876367387295 worker2 Ready Active 19.03.12
其中,带有 *
标记的是当前执行命令的节点,MANAGER STATUS
为 Leader
的是集群的主 Manager 节点。
2.3 添加更多 Manager 节点
如果需要添加更多的 Manager 节点以实现高可用性,可以在 Manager 节点上执行以下命令获取 Manager 节点加入令牌:
docker swarm join-token manager
输出结果类似以下内容:
To add a manager to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-556233959703943349-479487563797461434 192.168.1.100:2377
在需要加入的主机上执行上述命令,即可将其添加为 Manager 节点。
3. 服务部署与管理
3.1 创建简单服务
以部署一个 Nginx 服务为例,在 Manager 节点上执行以下命令:
docker service create --name my-nginx --replicas 3 nginx
上述命令中:
--name my-nginx
:指定服务的名称为my-nginx
。--replicas 3
:指定运行 3 个副本。nginx
:指定使用的 Docker 镜像为官方 Nginx 镜像。
执行命令后,可以通过以下命令查看服务的状态:
docker service ls
输出类似以下内容:
ID NAME MODE REPLICAS IMAGE PORTS
f9f7f6e227932712734 my-nginx replicated 3/3 nginx:latest
其中,REPLICAS
列显示了当前运行的副本数量和期望的副本数量,这里 3/3
表示 3 个副本都已成功运行。
3.2 扩展与收缩服务
如果需要增加或减少服务的副本数量,可以使用 docker service scale
命令。例如,将 my-nginx
服务的副本数量增加到 5:
docker service scale my-nginx=5
执行命令后,再次查看服务状态:
docker service ls
输出:
ID NAME MODE REPLICAS IMAGE PORTS
f9f7f6e227932712734 my-nginx replicated 5/5 nginx:latest
可以看到副本数量已更新为 5。
如果要收缩服务,例如将副本数量减少到 2:
docker service scale my-nginx=2
3.3 更新服务
假设需要更新 my-nginx
服务使用的镜像版本,可以使用 docker service update
命令。首先,拉取最新的 Nginx 镜像:
docker pull nginx:latest
然后更新服务:
docker service update --image nginx:latest my-nginx
在更新过程中,Swarm 会采用滚动更新的方式,即逐步停止旧版本的容器并启动新版本的容器,以确保服务的可用性。可以通过 docker service ps my-nginx
命令查看更新过程中任务的状态。
3.4 服务网络
Docker Swarm 提供了多种网络模式,包括 overlay 网络和 bridge 网络。overlay 网络适用于跨节点的容器通信,而 bridge 网络主要用于同一节点内的容器通信。
创建 overlay 网络:
docker network create --driver overlay my-overlay
创建服务时,可以指定使用该网络:
docker service create --name my-nginx --replicas 3 --network my-overlay nginx
这样,在 my-overlay
网络中的容器可以通过服务名称进行通信,例如,在另一个容器中可以通过 my-nginx
这个名称访问 Nginx 服务,而无需关心具体的 IP 地址。
4. 服务发现与负载均衡
4.1 服务发现
在 Docker Swarm 中,服务发现是自动实现的。当一个服务创建后,集群中的其他容器可以通过服务名称来访问该服务,而无需知道具体的 IP 地址。例如,在一个 Python 应用容器中,可以通过以下代码访问 my-nginx
服务:
import requests
response = requests.get('http://my-nginx')
print(response.text)
Docker Swarm 会自动将 my-nginx
解析为实际运行 Nginx 服务的容器的 IP 地址。
4.2 负载均衡
Swarm 内置了负载均衡功能,对于暴露端口的服务,Swarm 会自动在所有运行该服务的副本之间进行负载均衡。例如,在创建 Nginx 服务时,可以将 Nginx 的 80 端口映射到主机的 8080 端口:
docker service create --name my-nginx --replicas 3 -p 8080:80 nginx
此时,外部请求发送到任意一个节点的 8080 端口,Swarm 会将请求负载均衡到运行 my-nginx
服务的各个副本上。
Swarm 使用的负载均衡算法是基于轮询(Round - Robin)的,它会依次将请求分配到各个可用的副本上,以实现负载的平均分配。
5. 持久化存储
在容器化应用中,数据的持久化是非常重要的。Docker Swarm 支持多种持久化存储方式,包括本地卷和分布式存储。
5.1 本地卷
创建一个使用本地卷的服务示例,以 MySQL 数据库为例:
docker service create --name my-mysql \
--mount type=volume,source=my-mysql-data,destination=/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=rootpassword \
-e MYSQL_DATABASE=mydb \
-e MYSQL_USER=myuser \
-e MYSQL_PASSWORD=mypassword \
mysql:5.7
上述命令中,--mount type=volume,source=my-mysql-data,destination=/var/lib/mysql
表示创建一个名为 my-mysql-data
的本地卷,并将其挂载到容器内的 /var/lib/mysql
目录,用于存储 MySQL 的数据文件。
5.2 分布式存储
对于跨节点的数据持久化需求,可以使用分布式存储解决方案,如 GlusterFS 或 Ceph。以 GlusterFS 为例,首先需要在各个节点上安装 GlusterFS 客户端,然后创建 GlusterFS 卷:
gluster volume create myglustervol replica 3 transport tcp 192.168.1.100:/var/gluster/data 192.168.1.101:/var/gluster/data 192.168.1.102:/var/gluster/data
gluster volume start myglustervol
接下来,在 Docker Swarm 中创建服务时,可以使用 GlusterFS 卷:
docker service create --name my-mysql \
--mount type=volume,source=myglustervol,destination=/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=rootpassword \
-e MYSQL_DATABASE=mydb \
-e MYSQL_USER=myuser \
-e MYSQL_PASSWORD=mypassword \
mysql:5.7
这样,MySQL 容器的数据会存储在 GlusterFS 卷上,实现了跨节点的数据持久化和高可用性。
6. 滚动更新与回滚策略
6.1 滚动更新策略
在更新服务时,可以指定滚动更新的策略,以控制更新的速度和对服务可用性的影响。例如,在更新 my-nginx
服务时,可以指定每次只更新一个副本,并且等待 5 秒确认更新成功后再继续更新下一个副本:
docker service update \
--image nginx:latest \
--update-delay 5s \
--update-parallelism 1 \
my-nginx
--update-delay 5s
:指定每个副本更新之间的延迟时间为 5 秒。--update-parallelism 1
:指定每次只更新一个副本。
通过这种方式,可以在更新过程中密切观察每个副本的运行状态,确保更新不会对服务造成严重影响。
6.2 回滚策略
如果在更新过程中发现问题,可以随时回滚到上一个版本。执行以下命令回滚 my-nginx
服务:
docker service rollback my-nginx
回滚过程同样采用滚动的方式,逐步将容器恢复到上一个版本的状态。在回滚过程中,也可以通过 docker service ps my-nginx
命令查看任务的状态。
7. 安全与认证
7.1 节点认证
Docker Swarm 使用 TLS(Transport Layer Security)进行节点之间的通信加密和认证。在初始化 Swarm 集群时,会自动生成自签名的 TLS 证书,用于节点之间的身份验证和数据加密。
如果需要使用自定义的证书,可以在初始化 Swarm 集群时通过 --tls
相关参数指定证书文件的路径。例如:
docker swarm init \
--advertise-addr 192.168.1.100 \
--tls \
--tlscacert /path/to/ca.crt \
--tlscert /path/to/server.crt \
--tlskey /path/to/server.key
这样,在节点加入集群时,会使用指定的证书进行认证。
7.2 服务认证
对于服务之间的通信安全,可以使用服务网格(如 Istio)来实现更细粒度的认证和授权。Istio 可以在容器之间建立安全的通信通道,并提供基于策略的访问控制。
以 Istio 为例,首先需要在 Swarm 集群上安装 Istio,然后将服务部署到 Istio 服务网格中。例如,对于 my-nginx
服务,可以通过 Istio 的配置文件启用认证和授权:
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system
spec:
mtls:
mode: STRICT
上述配置表示在 Istio 服务网格中启用严格的 mTLS(Mutual Transport Layer Security)认证,确保服务之间的通信是安全加密的。
8. 监控与日志管理
8.1 监控
可以使用 Prometheus 和 Grafana 对 Docker Swarm 集群进行监控。首先,需要部署 Prometheus 来收集集群的指标数据,例如节点资源使用情况、容器运行状态等。可以通过 Docker 镜像部署 Prometheus:
docker service create --name prometheus \
--mount type=bind,source=/path/to/prometheus.yml,destination=/etc/prometheus/prometheus.yml \
prom/prometheus
在 prometheus.yml
配置文件中,需要配置对 Swarm 集群的监控目标:
scrape_configs:
- job_name:'swarm'
static_configs:
- targets: ['192.168.1.100:9323', '192.168.1.101:9323', '192.168.1.102:9323']
这里的 9323
端口是 Docker Swarm 暴露的监控端口。
然后,部署 Grafana 用于可视化监控数据:
docker service create --name grafana \
--mount type=bind,source=/path/to/grafana.ini,destination=/etc/grafana/grafana.ini \
--mount type=bind,source=/path/to/provisioning,destination=/etc/grafana/provisioning \
--publish 3000:3000 \
grafana/grafana
通过 Grafana 可以创建各种仪表盘,展示集群的性能指标、服务运行状态等信息。
8.2 日志管理
Docker Swarm 支持多种日志驱动,如 json - file
、syslog
、fluentd
等。以 fluentd
为例,首先需要部署 fluentd
服务:
docker service create --name fluentd \
--mount type=bind,source=/path/to/fluentd.conf,destination=/fluentd/etc/fluentd.conf \
fluent/fluentd
在 fluentd.conf
配置文件中,配置接收 Docker 容器日志的源和日志存储的目标,例如:
<source>
@type forward
port 24224
bind 0.0.0.0
</source>
<match **>
@type file
path /var/log/docker/%{tag}.log
</match>
然后,在创建服务时指定使用 fluentd
日志驱动:
docker service create --name my-nginx \
--log-driver fluentd \
--log-opt fluentd-address=192.168.1.100:24224 \
nginx
这样,my-nginx
服务的日志会发送到 fluentd
服务,由 fluentd
进行存储和管理。
通过上述对 Docker Swarm 的详细介绍和实战操作,可以看到 Docker Swarm 在容器编排方面提供了强大而灵活的功能,能够满足不同规模和复杂度的后端开发需求。无论是简单的应用部署,还是复杂的分布式系统构建,Docker Swarm 都能提供有效的解决方案。在实际应用中,需要根据具体的业务场景和需求,合理地配置和使用 Docker Swarm 的各项功能,以实现高效、可靠和安全的容器化应用部署与管理。