什么是Docker Swarm
Docker Engine中嵌入的群集管理和编排功能是使用swarmkit构建的。Swarmkit是一个独立的项目,实现了Docker的编排层,并直接在Docker内部使用。
一个swarm包含多个运行在swarm模式下的Docker主机,作为管理器(管理成员和委派)和工作节点(运行swarm服务)。一个给定的Docker主机可以是管理器、工作节点,或者同时扮演两个角色。当创建一个服务时,定义它的最佳状态(副本数、可用的网络和存储资源、服务对外部世界暴露的端口等)。Docker会维护该期望状态。例如,如果一个工作节点变得不可用,Docker会在其他节点上安排该节点的任务。任务是运行中的容器,是swarm服务的一部分,由swarm管理器管理,而不是独立容器。
swarm服务相对于独立容器的一个关键优势是,您可以修改服务的配置,包括它连接的网络和卷,而无需手动重启服务。Docker会更新配置,停止具有过时配置的服务任务,并创建与期望配置相匹配的新任务。
当Docker在swarm模式下运行时,您仍然可以在参与swarm的任何Docker主机上运行独立容器和swarm服务。独立容器和swarm服务之间的一个关键区别是,只有swarm管理器才能管理swarm,而独立容器可以在任何守护进程上启动。Docker守护程序可以作为管理器、工作节点或两者参与swarm。
与使用Docker Compose定义和运行容器类似,您可以定义和运行Swarm服务堆栈。
Swarm关键概念
Nodes
一个node是参与swarm的Docker Engine的一个实例,可以在一个物理机或者云服务器上运行一个或者多个node
- Manager Nodes:接受定义的service并且将tasks分发给其他Work Node。Manager Nodes还负责容器编排和集群管理,用Raft自动选主保证一致性
- Worker Nodes:接受和执行tasks,Manager Nodes也可以用作Wroker
Services and Tasks
Services是一组tasks的定义,可以指定运行哪个image以及在其上运行哪些指令
task是swarm编排和调度的最小单元,一个task只会在一个node上完成它的生命周期,不会被重新调度(和K8s类似)
Load Balancing
Swarm会给每一个你想暴露给外部的服务指定一个PublishedPort,外部组件,可以通过PublishPor访问任意节点,无论这个节点目前是否正在运行task,swarm中的所有节点会将请求路由给一个正在运行task的实例
Swarm在内部有一个DNS组件,来实现内部的负载均衡
部署Swarm
在Manager Node上创建swarm集群:
docker swarm init [--advertise-addr 192.168.0.17]
上述命令的输出可以用作Worker Node加入Swarm
docker swarm join --token SWMTKN-1-09el8cnzig7p4i0p06ug5jj1tc09c3h3sh9ycc5be6xhybo1c4-1nlxvfyg4gylq005mp2kjc5ud 192.168.0.17:2377
如果上述命令输出丢失了,可以运行docker swarm join-token worker
重新获取
查看swarm当前状态
docker info | grep swarm
在Manager Node上部署一个服务
docker service create \
--replicas 3 \
--name redis \
--update-delay 10s \
redis:3.0.6
查看服务详情:
docker service ps redis
docker service inspect redis --pretty
Scale the service
docker service scale redis=5
Rolling Update Service
docker service update --image redis:3.0.7 redis
暴露一个端口给外部
创建服务的时候使用--publish
来指定一个暴露给外部的端口,target
来指定容器内的端口,如果留空published
,那么swarm会指定一个随机的端口
docker service create \
--name my-web \
--publish published=8080,target=80 \
--replicas 2 \
nginx
如果不使用路由网格而使用外部负载均衡器,请将--endpoint-mode设置为dnsrr,而不是默认值vip。在这种情况下,没有单个虚拟IP。相反,Docker为服务设置DNS条目,使得对服务名称的DNS查询返回IP地址列表,客户端直接连接其中之一。您需要提供IP地址和端口列表给您的负载均衡器。请参见“配置服务发现”。
可以按照如下配置HAProxy 作为外部的负载均衡器
vim /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