启动一个容器如果把端口暴露出来映射到物理机上,则直接端口通信即可,如果有多个容器共同构成一个整体对外提供服务,如典型的LNMP架构,一般只需要暴露一个80端口,此时容器之间通信可以使用docker-compose编排
docker-compose是一个二进制工具,安装docker的时候默认不带,需要额外下载;docker-compose只能实现单机容器之间通过名称+内部端口通信(这个端口无需暴露在物理机上),如果是跨机器容器之间通信docker-compose则不行;docker-compose可以通过一份YAML文件,管理一组容器
docker-swarm可以实现跨机器容器之间的通信,安装docker默认自带,无需额外安装,相比K8S功能要少得多,当然也简单的多
使用docker-compose编排docker容器,几乎没有引入任何docker知识的新概念,docker-compose工具基本上就是拿来启动、重启一组docker容器用,其它的容器调试管理,或者单个容器的重启,完全基于已有的docker知识操作即可,比如我们用docker-compose启动5个容器,然后我们再手动docker rm -fv xxx
,关掉一个容器,此时docker-compose不会有任何感知,一切按照正常docker容器的逻辑走,docker-compose不额外启动进程,更不监听端口
使用docker-swarm则不一样了,首先swarm引入了一个服务的概念,也就是我们docker service ls
看到的东西,服务背后才是容器,swarm的服务可以docker service create xxx
来创建,新版本的swarm也支持直接利用docker-compose的YAML文件来启动服务(比较复杂,对YAML文件有特定的要求)
swarm之所以能实现不同机器上的容器,直接通过服务名来通信,是因为swarm集群直接实现了overlay平面网络,我们不管overlay平面网络细节是什么,看到的效果就是每台机器上都要启动额外的swarm进程,进程之间是通过一个特定的端口通信默认是4789,K8S的flannel实现overlay平面网络的原理也类似
swarm集群里的服务,其启动和停止都要使用swarm专门的管理命令,原始的docker命令则不适用,如果某个容器被我们手动docker rm -fv xxx
删掉,swarm服务会根据自定义的规则将其重新拉起来
swarm 对比 K8S (个人使用体会)
综上,选型swarm作为集群容器编排工具,最好在规模不大,服务较固定,经过良好测试的情况下使用
之前博客园cnblogs,就使用swarm编排容器,看他们写的文章,后面swarm一些诡异问题把他们折腾的够呛,现在已换成K8S
准备3台机器
192.168.31.100
192.168.31.101
192.168.31.102
用到的端口
3台机器都安装上docker
cd /etc/yum.repos.d/
wget http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce-18.09.9 docker-ce-cli-18.09.9 containerd.io -y
systemctl start docker
mv /etc/yum.repos.d/docker-ce.repo /etc/yum.repos.d/docker-ce.repo.off
创建集群
[root@192-168-31-100 ~]# docker swarm init --advertise-addr 192.168.31.100
Swarm initialized: current node (m04s2jamtjt4r1i34ws8ogtbz) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-08u11b1u6oyigexvmv10yr8rvl161upyqbx2lo90lr0oaehjfn-82y978ljp0jx70zauaj8t3n9z 192.168.31.100:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
执行上面这条命令,输出的信息非常重要,若是生产环境搭建swarm集群,建议复制保存下来,执行完毕上面的命令,表示本机初始化为docker swarm的manager节点,swarm有manager、worker2种节点,我们这里搭建3台manager节点
我们看下本机新监听的端口
[root@192-168-31-100 ~]# netstat -lntup | grep docker
tcp6 0 0 :::2377 :::* LISTEN 1503/dockerd
tcp6 0 0 :::7946 :::* LISTEN 1503/dockerd
udp6 0 0 :::7946 :::* 1503/dockerd
下面的命令可以分别打印,新机器加入swarm集群作为manager还是worker的信息
docker swarm join-token manager #输出加入manager节点的信息
docker swarm join-token worker #输出加入worker节点的信息
docker swarm join-token --help
如下输出,拿到命令到另外2台机器执行
[root@192-168-31-100 ~]# docker swarm join-token manager
To add a manager to this swarm, run the following command:
docker swarm join --token SWMTKN-1-08u11b1u6oyigexvmv10yr8rvl161upyqbx2lo90lr0oaehjfn-e8syzjnp83ypsfwofqc41kgu5 192.168.31.100:2377
[root@192-168-31-101 ~]# docker swarm join --token SWMTKN-1-08u11b1u6oyigexvmv10yr8rvl161upyqbx2lo90lr0oaehjfn-e8syzjnp83ypsfwofqc41kgu5 192.168.31
.100:2377
This node joined a swarm as a manager.
[root@192-168-31-102 ~]# docker swarm join --token SWMTKN-1-08u11b1u6oyigexvmv10yr8rvl161upyqbx2lo90lr0oaehjfn-e8syzjnp83ypsfwofqc41kgu5
192.168.31.100:2377
This node joined a swarm as a manager.
检查
docker node ls
docker info
下面的命令3台机器都可以执行
# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
m04s2jamtjt4r1i34ws8ogtbz * 192-168-31-100 Ready Active Leader 18.09.9
oesjwho6g9ref3h2s1fsy0d60 192-168-31-101 Ready Active Reachable 18.09.9
nmvhzpwo4f54rzdya1qrgnnas 192-168-31-102 Ready Active Reachable 18.09.9
# docker info
...
Swarm: active
NodeID: m04s2jamtjt4r1i34ws8ogtbz
Is Manager: true
ClusterID: 05pvx9f8etqa69tshhlr4gcfi
Managers: 3
Nodes: 3
Default Address Pool: 10.0.0.0/8
...
Manager Addresses:
192.168.31.100:2377
192.168.31.101:2377
192.168.31.102:2377
...
可以看到本机器是否处在swarm模式下,以及本机的角色manager or worker
docker service create --replicas 1 --name helloworld alpine ping docker.com
docker service ls
只有manager节点才可以创建服务
[root@192-168-31-100 ~]# docker service create --replicas 1 --name helloworld alpine ping docker.com
nuuzvjdtplecysrv2qe4zwlqn
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
[root@192-168-31-100 ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
nuuzvjdtplec helloworld replicated 1/1 alpine:latest
[root@192-168-31-100 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
337b10f0c3f0 alpine:latest "ping docker.com" 27 seconds ago Up 25 seconds helloworld.1.skmotjl8mrh2qh
3sg6y8r4qy4
只启动一个容器副本,这个容器会根据内部算法调度到一台机器上运行,如果我们去手动用docker命令把这个容器删掉,等待一会swarm会自动将其拉起,以保证副本数量始终是1
docker service create xxx
场景服务,后面可能不好维护,可以把相关命令写到脚本里常用的swarm管理命令,基本上通过 --help 都能看到
docker node --help
docker service --help
docker service create --help
docker swarm --help
查看某个服务的详细信息
docker service inspect --pretty ${service_name}
查看某个服务跑在哪个节点上
docker service ps ${service_name}
删除某个服务
docker service rm ${service_name}
更新某个服务,让其恢复之前定义的状态(相当于重启)
docker service update ${service_name}
查看某个节点上跑了哪些服务(node名称可以是多个,空格分割)
docker node ps [NODE...] | grep ${service_name}
滚动更新某个服务
场景举例:刚开始使用 docker service create xxx 启动3个nginx副本,分布到3台机器,前端做负载均衡,后面量大,准备扩容成5个,swarm可以实现先停止1个容器,然后启动这个容器,确保其running之后,继续下个容器,与K8S滚动更新逻辑类似,更多细节参考官方文档
场景:如果我们有10个swarm节点,它们都在正常工作状态,那么新创建的服务,对应的容器每台机器上都有可能分配,而现在我们已经知道某个节点可能有问题(比如磁盘坏掉)需要让其平滑下线(从swarm集群中移除)
关键命令一览
docker node update --availability drain ${NODE_NAME}
docker node update --availability active ${NODE_NAME}
docker node demote ${NODE_NAME}
docker node promote ${NODE_NAME}
docker node rm ${NODE_NAME}
docker swarm leave -f
操作演示细节
[root@192-168-31-100 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
m04s2jamtjt4r1i34ws8ogtbz * 192-168-31-100 Ready Active Leader 18.09.9
oesjwho6g9ref3h2s1fsy0d60 192-168-31-101 Ready Active Reachable 18.09.9
nmvhzpwo4f54rzdya1qrgnnas 192-168-31-102 Ready Active Reachable 18.09.9
可以看到上面3台机器都是manager节点,都处在Active正常状态,下面我们驱逐 192-168-31-100
[root@192-168-31-100 ~]# docker node update --availability drain 192-168-31-100
192-168-31-100
[root@192-168-31-100 ~]# docker node ls | grep "192-168-31-100"
m04s2jamtjt4r1i34ws8ogtbz * 192-168-31-100 Ready Drain Leader 18.09.9
可以看到 192-168-31-100 已经变成 Drain 状态了,其上的容器会被逐步删除,调度到其它机器上,不能有绑死机器的容器,否则会调度失败,这种操作只适合被swarm管理的机器,类似docker run xxx直接启动的容器不受影响,不建议在swarm集群上手动通过docker run xxx 额外启动容器
标记成Drain,状态之后,可以再用docker ps xxx或者登录到相关机器上docker ps -a,查看是否所有容器都已被妥善驱逐
确认没有其上没有服务,并且在其它机器上已经重建该服务之后,可以 docker node rm ${NODE_NAME} ,把这个节点从swarm集群删除,待调整好之后再重新加入,不删除在那块放在问题也不大,不会有新容器调度上去,当那台机器修复好后可以用 docker node update --availability active ${NODE_NAME} ,重新加入集群
下线快速步骤参考
docker node update --availability drain ${NODE_NAME}
docker node demote ${NODE_NAME}
docker swarm leave -f #登录到需要下线的机器执行
docker node rm ${NODE_NAME}
cat /etc/haproxy/haproxy.cfg
global
log /dev/log local0
log /dev/log local1 notice
...snip...
# Configure HAProxy to listen on port 80
frontend http_front
bind *:80
stats uri /haproxy?stats
default_backend http_back
# Configure HAProxy to route requests to swarm nodes on port 8080
backend http_back
balance roundrobin
server node1 192.168.99.100:8080 check
server node2 192.168.99.101:8080 check
server node3 192.168.99.102:8080 check
结合haproxy的配置文件和上图分析:
https://docs.docker.com/engine/swarm/
https://docs.docker.com/engine/swarm/swarm-tutorial/deploy-service/
https://docs.docker.com/engine/swarm/swarm-tutorial/drain-node/
https://docs.docker.com/engine/swarm/ingress/
https://docs.docker.com/engine/swarm/how-swarm-mode-works/nodes/
csdn https://blog.csdn.net/xys2015/article/details/109537977