一、背景与环境
在一个四节点规模的docker swarm集群上,使用Portainer的Agent模式进行集群管理。
- docker被收购后,官方已经放弃docker swarm。。。但这里因为是小规模集群,使用K8S得不偿失,而K3S/MicroK8S等轻量级工具出现时间不长,尚无成熟落地案例。因此这里依然使用docker swarm作为docker集群管理工具。
- Portainer是一个docker集群管理UI工具,有CE版和商业版。其中CE版本已经足够使用,这里使用的是CE版。
4个节点的操作系统均为CentOS7,CentOS7使用的防火墙是firewalld,如果是生产环境不能关闭防火墙,则应该规划好各个节点哪些服务和端口允许访问。例如,每个节点都执行以下配置(默认使用public区域):
# 查看允许访问的服务与端口
firewall-cmd --zone=public --list-services
firewall-cmd --zone=public --list-ports
# 允许http与https访问
firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --permanent --zone=public --add-service=https
firewall-cmd --reload
firewall-cmd --zone=public --list-services
# 允许访问的端口
firewall-cmd --zone=public --add-port=2375/tcp --permanent
firewall-cmd --zone=public --add-port=2376/tcp --permanent
firewall-cmd --zone=public --add-port=2377/tcp --permanent
firewall-cmd --zone=public --add-port=4789/udp --permanent
firewall-cmd --zone=public --add-port=7946/tcp --permanent
firewall-cmd --zone=public --add-port=7946/udp --permanent
firewall-cmd --zone=public --add-port=9001/tcp --permanent
firewall-cmd --reload
firewall-cmd --zone=public --list-ports
http/https用于一些web服务的访问,2375/tcp,2376/tcp,2377/tcp,4789/udp,7946/tcp,7946/udp 这些都是docker swarm所需的端口/协议,9001/tcp 是Portainer需要的端口/协议。
二、安装Portainer
本文并不详细讲述如何搭建docker swarm集群,只是在后续章节介绍一下部分注意事项。
在已经搭建好docker swarm集群之后(例如这里在四个节点上搭建了docker swarm集群,两个manager节点,两个worker节点),执行以下操作。
2.1 安装Portainer:
选择一个manager节点,例如manager01,安装portainer:
docker network create \
--driver overlay \
--attachable \
--subnet 10.12.0.0/24 \
portainer_agent_network
docker run -d -p 9000:9000 --name portainer \
--network portainer_agent_network \
--restart always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /docker/data/portainer:/data portainer/portainer
- 为何要先创建一个overlay网络?是为了保持后续创建的全局服务
portainer_agent
与Portainer容器位于一个网络内,便于相互通信。- 为何要手动创建网络?为了手动指定网段,防止自动创建时与实际网段冲突。
添加防火墙规则,允许访问9000端口
firewall-cmd --zone=public --add-port=9000/tcp --permanent
firewall-cmd --reload
firewall-cmd --zone=public --query-port=9000/tcp
因为Portainer只在一个manager节点上运行,因此只需要在该节点添加该防火墙配置即可。
另外,Portainer没有必要高可用,它只是集群运维管理使用,且数据已经挂到宿主机的/docker/data/portainer
目录,且指定了重启策略。
从客户端浏览器访问:
http://<manager01的Host或IP>:9000/
首次访问时创建管理员用户,然后停在这里,等待接下来的portainer_agent服务启动后再继续操作。
2.2 使用Agent模式管理DockerSwarm集群
在swarm集群上创建portainer_agent服务:
docker service create \
--name portainer_agent \
--network portainer_agent_network \
--mode global \
--constraint 'node.platform.os == linux' \
--mount type=bind,src=//var/run/docker.sock,dst=/var/run/docker.sock \
--mount type=bind,src=//var/lib/docker/volumes,dst=/var/lib/docker/volumes \
portainer/agent
mode指定为global
,即,在swarm集群的所有active节点上尝试启动对应的docker容器;constraint约束条件指定为node.platform.os == linux
,即,只在linux节点上启动。
通过manager节点上执行docker service ls
,以及各个节点上执行docker ps
查看服务及容器启动成功后,登入Portainer管理UI,添加Agent
作为Swarm集群的统一EndPoint:
Name根据需要命名,Agent URL填写tasks.portainer_agent:9001
即可。该值由之前创建的服务portainer_agent
决定。9001
是portainer_agent的默认访问端口。
2.3 其他安装Portainer与Agent的方法
我们也可以采用其他方式安装Portainer与Agent。
将portainer作为service启动
创建portainer_agent服务的方式不变,但可以将portainer作为service启动,如下所示:
docker service create \
--name portainer \
--network portainer_agent_network \
--publish 9000:9000 \
--replicas=1 \
--constraint 'node.hostname == manager01.xxx.com' \
portainer/portainer -H "tcp://tasks.portainer_agent:9001" --tlsskipverify
docker-compose统一编排
我们还可以将Portainer与Agent服务放在一个docker-compose编排文件中定义,然后使用docker compose或docker stack启动。
在任意目录编写编排文件,如portainer-agent-stack.yml
,内容如下:
version: '3.2'
services:
agent:
image: portainer/agent
environment:
AGENT_CLUSTER_ADDR: tasks.portainer_agent
# CAP_HOST_MANAGEMENT: 1
# AGENT_SECRET: secrettokenforportainerinxxxcom
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /var/lib/docker/volumes:/var/lib/docker/volumes
# - /:/host
# ports:
# - target: 9001
# published: 9001
# protocol: tcp
# mode: host
networks:
- agent_net
deploy:
mode: global
placement:
constraints: [node.platform.os == linux]
portainer:
image: portainer/portainer
command: -H tcp://tasks.portainer_agent:9001 --tlsskipverify
# environment:
# AGENT_SECRET: secrettokenforportainerinxxxcom
ports:
- "9000:9000"
# - "8000:8000"
volumes:
- /docker/data/portainer:/data
networks:
- agent_net
deploy:
mode: replicated
replicas: 1
placement:
constraints: [node.hostname == manager01.xxx.com]
networks:
agent_net:
driver: overlay
attachable: true
然后用docker compose或docker stack启动,例如用docker stack启动:
docker stack deploy --compose-file=portainer-agent-stack.yml portainer
三、docker swarm集群搭建
关于如何搭建docker swarm集群,这里不做详细介绍,只提几个注意点。
- 根据需要规划节点角色,比如这里4个节点,配置相同,规划了两个manager和两个worker;
- 各节点docker安装完成后,建议修改一下仓库镜像,默认网段,以及允许通过
2375
端口访问docker API。 - 在初始化swarm之前,建议手动在各个节点创建虚拟网络
docker_gwbridge
,并指定一个不与实际网段冲突的网段:
docker network create --subnet 10.11.0.0/24 \
--opt com.docker.network.bridge.name=docker_gwbridge \
--opt com.docker.network.bridge.enable_icc=false \
--opt com.docker.network.bridge.enable_ip_masquerade=true \
docker_gwbridge
可以使用route
命令查看本地路由表,确认实际网段有哪些。
- 初始化swarm以及其他节点加入swarm集群时,务必指定各自的
--advertise-addr
与--listen-addr
参数,避免以后发生负载均衡失效的问题。 - 防火墙不能关闭的场景,注意要执行本文开头与中间所述的防火墙设置,然后要重启docker服务
systemctl daemon-reload
systemctl restart docker
- 发现异常现象时,注意查看docker daemon日志。可以通过
service docker status -l
查看,或cat /var/log/messages | grep dockerd
查看。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。