Swarm
docker swarm 是 docker内置的容器编排工具。
从docker1.12开始swarm内置于docker engine.
swarm mode具有内置kv存储,服务发现,负载均衡,路由网格,动态伸缩,滚动更新,安全传输等功能。
swarm: 老版本的swarm, 需要kv store, 可以作为独立的container运行, 已废弃, 已经被docker swarm mode 代替.
https://github.com/docker/swarm
swarmkit:
https://github.com/docker/swarmkit
swarm命令
创建集群
docker swarm init
--advertise-addr <ip> 多网卡情况下指定manager的ip
docker swarm join --token <token> <host:port>
# 查看token
docker swarm join-token manager 获取添加manager命令
docker swarm join-token worker 获取添加worker命令
docker swarm join-token -q worker
docker swarm leave -f/--force
docker swarm update
管理节点
docker node ls
docker node ls --format "{{.Hostname}}"
docker node rm
docker node inspect
# 查看node上运行的tasks/container
docker node ps -f/--filter NODE
# 添加label, node.labels.role=api
docker node update --label-add role=api node1
# 删除label
docker node update --label-rm role node1
# 活跃节点
docker node update --availability active node1
# 指定该节点满载,不再分派任务,关闭已有任务并重新分派.
docker node update --availability drain node1
# 已有任务继续运行,不分配新任务.
docker node update --availability pause node1
# 查看所有node和label
docker node ls -q | xargs docker node inspect -f '{{ .ID }} [{{ .Description.Hostname }}]: {{ .Spec.Labels }}'
service
# 相当于docker-compose.yml里面的service.
docker service ls # 列出所有service
docker service rm SERVICE
docker service inspect SERVICE
# 查看service的log
docker service logs -f SERVICE
# 查看service的状态,在哪些node上运行,运行状态等
docker service ps SERVICE
docker service update
docker service update --image <url:tag> # 根据镜像更新服务
docker service scale
docker service rollback
docker service create
--constraint node.id/node.hostname/node.role/node.labels/engine.labels
--env/-e
--label
--limit-cpu
--limit-memory
--replicas
--restart-condition
--user/--group
--mode global/replicated
--endpoint-mode vip/dnsrr
stack
# stack = n*service
# service = n*task(container)
docker stack ls # 列出所有stack
# 查看stack的service
docker stack services <stack>
# 查看stack的task/container
docker stack ps <stack>
docker stack rm STACK
# 根据docker-compose.yml部署应用
docker stack deploy -c/--compose-file <docker-compose.yml> STACK
docker stack deploy --bundle-file <DAB> STACK
# 默认所有node从docker hub pull, 如果是私有镜像,需要加参数
# 需要在manager上docker login private-registry
docker stack deploy --with-registry-auth -c test.yml test
docker stack deploy --resolve-image (always|changed|never) ...
docker stack deploy --orchestrator (swarm|kubernetes|all) ...
swarm compose
其它字段参考Compose, 这里只分析deploy下的字段.
通过compose文件部署服务.
deploy:
endpoint_mode:
// 给service打标签(不作用于container)
labels:
com.examples.key: value
// 默认mode=replicated, replicas=1.
mode: replicated
max_replicas_per_node:
replicas: 1
// 部署到匹配的全部node.
mode: global
# global和replicated都可以用placement.
placement:
preferences: // 只支持spreed.
- spreed: node.labels.datacenter
constraints:
# 多个约束是and关系
- node.id==...
- node.hostname==...
- node.role==...
- node.role==manager/worker
- node.platform.os!=windows
- node.platform.arch==x86
- engine.labels.<key>==<value>
# 用户自定义标签
- node.labels.<key>==<value>
resources:
limits:
cpus: '0.5'
memory: 1G
reservations:
cpus: '0.25'
memory: 20M
restart_policy:
condition: any(default)/on-failure/none
delay: 0(default)/5s
max_attempts: never give up(default)/3
window: decide immediately(default)/10s
update_config/rollback_config:
parallelism: 0 (default 0 means all)
delay: 10s (容器升级间隔时间)
failure_action: pause(default)/continue/rollback
monitor: 0s (更新完成后确认成功的时间)
max_failure_ratio: 更新期间允许的失败率
order: stop-first(default)/start-first
// 默认endpoint_mode=vip, 支持route mesh, 自动负载均衡和服务发现.
deploy:
endpoint_mode: vip
ports:
- target: 80
published: 8080
// 默认mode=ingress, 也可以改为host.
mode: ingress
protocol: tcp/udp
- 8080:80/tcp
// dnsrr 模式
deploy:
endpoint_mode: dnsrr
update_config:
// 如果expose端口,不能start-first, 否则报错no suitable node (host-mode port already in use on 1 node
order: stop-first
// 设置iptables规则,外部访问8080通过prerouting做dnat指定目的ip,通过forward转发给container的80.
// iptables->nat->prerouting:
// DNAT tcp -- !docker_gwbridge * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.18.0.16:80
// iptables->filter->forward:
// ACCEPT tcp -- enp5s0 * 0.0.0.0/0 0.0.0.0/0 multiport dports 80
ports:
- target: 80
published: 8080
// dnsrr只能用port->mode=host.
mode: host
protocol: tcp/udp
swarm network
global模式container:
eth0: overlay(user define overlay)
eth1: ingress(swarm define ingress)
eth2: docker_gwbridge(swarm define bridge)
replicate模式container:
eth0: overlay(user define overlay)
eth1: docker_gwbridge(swarm define bridge)
overlay: 通过4789/udp跨主机访问其他container, host不能访问overlay的ip,只有container之间通过container-servicename或者container-overlay的ip相互访问.
overlay 问题: 通过overlay连接,默认15分钟timeout, 所以数据库建议用dnsrr模式; 如果用vip模式,需要修改内核网络参数:
$ sudo sysctl -w net.ipv4.tcp_keepalive_time=600 net.ipv4.tcp_keepalive_intvl=60 net.ipv4.tcp_keepalive_probes=3
vip模式就是访问的虚拟ip,replicated的service如果有多个container,通过servicename访问的就是同一个vip,通过vip解析到背后container的真实overlay-ip(自动负载均衡).
dnsrr模式就是直接解析container的overlay-ip来访问,如果是replicated的service有多个container,每次访问的就是从dns列表中根据负载均衡算法拿到其中一个overlay-ip.
ingress network: 是一个特殊的 overlay 网络,用于服务节点间的负载均衡。当任何 Swarm 节点在发布的端口上接收到请求时,它将该请求交给一个名为 IPVS 的模块。IPVS 跟踪参与该服务的所有IP地址,选择其中的一个,并通过 ingress 网络将请求路由到它。
docker_gwbridge: host和container之间通过ip访问, container能访问host的物理网卡的ip和docker_gwbridge的ip, host也能访问container的docker_gwbridge的ip, 但是container之间不能访问bridge的ip.
修改默认的docker_gwbridge:
// 对于已存在的,要先删除
$ service docker stop
$ sudo ip link set docker_gwbridge down
$ sudo ip link del dev docker_gwbridge
// 创建swarm之前创建好网络
$ docker network create --subnet "172.18.0.0/16" --ip-range “172.18.1.0/16” \
--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
// 创建swarm
$ docker swarm init
endpoint_mode:
- vip: 通过vip这个虚拟ip对外访问,提供负载均衡,不暴露具体的container的ip.
- dnssr: DNS round-robin, 为每个服务设置dns,连接到其中一个具体的contaier的ip.
swarm scheduler
filter过滤器可以实现特定的容器运行在特定的node上, swarm支持3种策略和6个过滤器.
swarm strategy:
- spread: 默认策略,配置相同的情况下选择容器数量最少的node
- binpack: 尽可能将容器放到一台node上运行。
- random: 直接随机分配
swarm node filters:
- constraint
- health
- containerslots
swarm container-configuration filters:
- affinity
- dependency
- port