一、docker swarm介绍
集群使用容器面临的问题主要为:
如何管理多个node上的多个容器?
如何方便低横向扩展容器?
如果容器down了,如何自动恢复?
如何去更新容器而不影响业务?
如何监控追踪容器?
如何调度容器的创建?
如何保护隐私数据?
docker swarm,是Docker官方提供的一款集群管理工具,其主要作用是把若干台 Docker 主机抽象为一个整体,并且通过一个入口统一管理这些 Docker 主机上的各种 Docker 资源。
swarm集群初始化
不包含在任何 Swarm 中的 Docker 节点,称为运行于单引擎(Single-Engine)模式。一旦被加入 Swarm 集群,则切换为 Swarm 模式。
docker swarm集群安装方法:
1)vagrant+virtualbox:使用vagrantfile定义虚拟机,需要10min+时间部署;
2)docker machine+virtualbox:分钟级部署;
3)play with docker http://labs.play-with-docker.com/:秒级部署swarm集群,最多保存4h;
二、docker swarm入门手册
###本次采用VMware虚拟机直接创建swarm集群; ###在manager1节点执行; docker swarm init --advertise-addr 192.168.66.10:2377 --listen-addr 192.168.66.10:2377 #初始化一个新的 Swarm,并将自身设置为第一个管理节点。同时也会使该节点开启 Swarm 模式。--advertise-addr 指定其他节点用来连接到当前管理节点的 IP 和端口。这一属性是可选的,当节点上有多个 IP 时,可以用于指定使用哪个IP。此外,还可以用于指定一个节点上没有的 IP,比如一个负载均衡的 IP。--listen-addr 指定用于承载 Swarm 流量的 IP 和端口。其设置通常与 --advertise-addr 相匹配,但是当节点上有多个 IP 的时候,可用于指定具体某个 IP。并且,如果 --advertise-addr 设置了一个远程 IP 地址(如负载均衡的IP地址),该属性也是需要设置的。建议执行命令时总是使用这两个属性来指定具体 IP 和端口。Swarm 模式下的操作默认运行于 2337 端口。虽然它是可配置的,但 2377/tcp 是用于客户端与 Swarm 进行安全(HTTPS)通信的约定俗成的端口配置。 docker node ls #查看docker节点; docker swarm join-token manager #添加manager节点进swarm集群; docker swarm join-token worker #查看“添加worker节点进swarm集群”的命令; ###在manager2节点执行; docker swarm join --token SWMTKN-1-0d0h5xmlok2iowbnc1h8e9fa0geccu48wxhmr0dfnu2flvqi07-9lefauyigjuw2gt8n3g4hycrv 192.168.66.10:2377 ###在worker1节点执行; docker swarm join --token SWMTKN-1-0d0h5xmlok2iowbnc1h8e9fa0geccu48wxhmr0dfnu2flvqi07-1h61zl9f6bpb93d9iz2bsrhxj 192.168.66.10:2377 docker node ls #查看docker节点;
###service创建及扩容 docker service ls #查看service明细; docker service create --name swarm_test1 busybox sh -c "while true;do sleep 3600;done" #swarm集群不再通过docker run启动服务; docker service inspect swarm_test1 #查看service详细信息; docker service scale swarm_test1=4 #设置service副本为4; docker service ps swarm_test1 #查看service副本调度信息; docker rm -f 8b56e958b7a2 && docker service ps swarm_test1 && docker ps #删除一个容器后,查看swarm会自动创建一个容器副本; docker service rm swarm_test1 #删除service;
案例2:DNS服务发现
docker pull jwilder/whoami docker network create -d overlay demo docker service create --name whoami -p 1000:8000 --network swarm_test1 -d jwilder/whoami #swarm必须使用overlay网络才可创建服务; docker service ps whoami #确认client调度至object1节点; docker service create --name client --network swarm_test1 -d busybox sh -c "while true;do sleep 3600;done" docker service ps client #确认client调度至controller节点; docker exec -it client.1.ovjcidh62dvxbupp236c97jyn nslookup whoami #查看service name绑定的VIP; docker exec -it client.1.ovjcidh62dvxbupp236c97jyn ping whoami -c 3 #在controller节点执行ping,解析IP为10.0.1.5,该IP为VIP; docker exec -it whoami.1.hayk0otka6t2r55nsrzgs9933 ip a #在object1节点执行,查询容器IP为10.0.1.6; docker service scale whoami=3 #设置service副本为3;
docker exec -it 493244154edf nslookup tasks.whoami #解析service name调度到各容器的具体IP;
docker routing mesh:一种docker网络技术,用于支撑docker集群间容器服务的通信。有2中体现形式:
internal routing mesh---不通node的容器通过overlay网络访问其他node服务的VIP,然后通过负载均衡将访问落到某个node中的容器;
ingress routing mesh---如果服务绑定接口,则此服务可以通过任意swarm节点的相应接口访问。
ingress network包传输过程:
1)外部访问swarm集群的负载均衡;
2)swarm集群服务的端口被暴露到各个swarm节点;
3)集群内部通过IPVS进行负载均衡调度访问任务;
如下图所示,client容器访问whoami容器流程---client发送请求包,swarm集群的DNS服务解析被访问容器的域名VIP,然后有iptables+LVS|IPVS转发包到目的node的容器。
curl 127.0.0.1:1000 #在所有swarm节点(manager|worker节点)都可访问服务暴露的端口;
iptables -nvL -t nat #查看swarm集群节点iptables转发nat规则:任何访问swarm集群几点1000端口的数据都会转发至172.21.0.2:1000,这就造成“swarm集群服务的端口被暴露到各个swarm节点;”现象。
iptables -nvL -t nat #查看swarm集群节点iptables转发nat规则:任何访问swarm集群几点1000端口的数据都会转发至172.21.0.2:1000,这就造成“swarm集群服务的 端口被暴露到各个swarm节点;”现象。 ip a #宿主机查看IP,确认172.21.0.2所在网络与docker_gwbridge网卡的网络一致; brctl show #列出宿主机所有网桥; docker network inspect docker_gwbridge #查看网络详细信息,其中ingress-sbox容器的IP为:172.21.0.2; ls /var/run/docker/netns #查看容器运行期间的network namespace,找到ingress_sbox的网络名称空间; nsenter --net=/var/run/docker/netns/ingress_sbox #进入ingress_sbox的网络名称空间; ip a && exit #查看名称空间中的IP;
yum -y install ipvsadm #安装ipvsadm; nsenter --net=/var/run/docker/netns/ingress_sbox ipvsadm -l #查看负载均衡调度规则:里面为调度节点的容器IP;表示访问swarm节点的8000端口时,iptables会转发包至ingress_sbox,然后通过ipvs转发包至具体的某个容器。
三、docker swarm故障排查
问题1:swarm节点无法假如集群?
[root@k8s-master02 ~]# docker swarm join --token SWMTKN-1-28u942qj5l0h67v0gofn410g0zcuelk5d23epd66h12min98dm-1aku87enhdh278w27u9kj40sx 192.168.66.10:2377
Error response from daemon: This node is already part of a swarm. Use "docker swarm leave" to leave this swarm and join another one.
[root@k8s-master02 ~]# docker swarm leave
Error response from daemon: You are attempting to leave the swarm on a node that is participating as a manager. Removing this node leaves 1 managers out of 3. Without a Raft quorum your swarm will be inaccessible. The only way to restore a swarm that has lost consensus is to reinitialize it with `--force-new-cluster`. Use `--force` to suppress this message.
原因分析:未删除节点出某个swarm集群;
解决方法:强制删除节点出swarm集群,并重新假如新群;
[root@k8s-master02 ~]# docker swarm leave -f
Node left the swarm.
[root@k8s-master02 ~]# docker swarm join --token SWMTKN-1-28u942qj5l0h67v0gofn410g0zcuelk5d23epd66h12min98dm-1aku87enhdh278w27u9kj40sx 192.168.66.10:2377
This node joined a swarm as a manager.
问题2:服务创建失败,提示没有网络?
[root@controller ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
6d9335948452 bin_my-bridge bridge local
e80f0665add1 bridge bridge local
ada3e422721a compose-flask-redis_default bridge local
4e532531e901 compose-lb-scale_default bridge local
3ce035d8549b demo bridge local
4c5814b179e2 docker_gwbridge bridge local
c04897e2966d host host local
6p96ig0ldtld ingress overlay swarm
746689e8990f none null local
qy2uef7soa7w swarm_test1 overlay swarm
[root@controller ~]# docker service create --name whoami -p 1000:8000 --network demo -d jwilder/whoami
Error: No such network: demo
原因分析:swarm集群使用的overlay网络不存在;
解决方法:使用overlay网络创建service;
[root@controller ~]# docker service create --name whoami -p 1000:8000 --network swarm_test1 -d jwilder/whoami
l18jnwic9d01g87u9ksrn51fk
问题3:节点加入swarm集群失败?
[root@manager02 ~]# docker swarm join --token SWMTKN-1-4wgfok640zgto34q23ed44983nri58vbi9viv7d8oass6vn30v-8vx1em106t7bt59hohd1h3lya 192.168.66.10:2377
Error response from daemon: rpc error: code = Unavailable desc = all SubConns are in TransientFailure, latest connection error: connection error: desc = "transport: Error while dialing dial tcp 192.168.66.10:2377: connect: no route to host"
原因分析:节点防火墙等未关闭。
解决方法:关闭防火墙等。
systemctl disable --now firewalld && systemctl status firewalld
setenforce 0 && getenforce;sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
问题4:所有节点时间已同步,但节点加入swarm集群失败?
[root@worker01 ~]# docker swarm join --token SWMTKN-1-4wgfok640zgto34q23ed44983nri58vbi9viv7d8oass6vn30v-20mvqgqw2q1xqroby35i8649j 192.168.66.10:2377
Error response from daemon: error while validating Root CA Certificate: x509: certificate has expired or is not yet valid
原因分析:初始化第一个swarm manager节点时会生成带有时间的CA证书;而后期同步时间了并不会修改CA证书中的时间。
解决方法:重新初始化swarm manager节点,然后再将其他节点加入集群。