Docker Swarm Mode

6 年前 · 来自专栏 专业踩坑小分队

目录


1. Docker Swarm Mode简介

Docker从v1.12.0后开始集成swarm mode(swarmkit),关于swarm的所有操作可以直接使用docker swarm 命令来完成。Docker Swarm是docker原生的用于管理docker集群的工具,内置kv存储功能,不再需要外置的etcd,目前的功能主要有:

a. Docker节点集群的管理,包括集群的创建,master,worker节点的加入删除。

b. 服务的管理,包括service的创建删除,update,scale等。

c. 跨主机的网络管理(overlay)

d. 服务发现(内建DNS服务,服务可以通过dns发现)

e. 服务负载均衡LB(端口暴露routing meshing, VIP, DNS-round-robin)

Docker Swarm Mode和Swarm是有区别的,虽然都是集群管理服务编排工具。

1.1 Swarm mode基本概念

1.1.1 Swarm

Swarm就是一个运行docker engine的节点(node)的集合。这个节点集合可以用来发布和编排服务。而加入到这个swarm中的node就是运行在swarm mode。

Node可以主动初始化一个swarm cluster或者加入一个已存在的swarm cluster,这样此node就成为一个swarm mode的node。

Swarm mode节点分为manager node和worker node。类似mesos,k8s中的master节点和slave节点。


docker swarm init --advertise-addr x.x.x.x
docker swarm join-token manager

检查一个节点是否处于swarm mode:


docker info    //check swarm

1.1.2 Node

Manager节点用于cluster的管理,swarm命令基本只能在manager节点执行。一个cluster可以有多个manager节点,但只有一个节点可以成为leader manager node,leader选主通过raft协议实现,参数可配置。

Worker节点是任务执行节点,manager将service下发至worker节点执行。如下图:MANAGER STATUS为空的是worker节点,Reachable的是非leader manager node。Manager节点默认也作为worker节点。

1.1.3 Services和tasks

Task是swarm中的最小原子调度单位,目前来说就是一个单一的容器(后期可能会支持pod模式,那就是一个pod了估计)。

Services是指一组task的集合,service定义了这些task的属性。目前,services有两种模式:

a. replicated services 按照一定规则在各个worker node上运行指定个数的tasks,和k8s的replicate概念,marathon中的instance一样。

b. global services 每个woker node上运行一个此task。和marathon中的unique constraints一样(k8s是什么?)。

命令示例:


docker service create --replicas 3 --name nginx nginx //创建服务
docker service ls           //查看服务
docker service ps nginx //查看task
docker service inspect nginx       //查看服务/task详细信息

1.1.4 Load balancing

a. Ingress load balancing:

Docker Swarm Mode 使用 Ingress load balancing 来将内部服务暴露出来到非容器网络中,比如宿主机网络,甚至是 DC 外部或公网中。 Ingress load balancing 是通过 NAT 将内部服务映射到宿主机的某一端口(这个特点和 docker 原生 bridge 网络的 NAT ,或者 k8s externalIP->NodePort 类似),可以手动指定未使用端口( -p <PUBLISHED-PORT>:<TARGET-PORT> 或者 --publish <PUBLISHED-PORT>:<TARGET-PORT> );或者不指定,由 docker swarm 30000-32767中指定一个端口。

Ingress load balancing 会在每个容器中添加一块网口,用于连接到 ingress network 中( swarm 默认创建的 overlay network 10.255.0.0/16 ),并使用 VIP IPVS 技术)分发 ingress traffic 到每个容器实例中。具体技术参看下面的网络部分。

每个节点暴露出来的端口服务也可以统一接入到外部的LB上提供服务,比如Haproxy。

b. Internal load balancing:

Swarm mode有个内置的DNS模块,可以给每个service分配一个DNS条目,每个DNS条目对应着service的多个task实例。同一容器网络中可以通过该DNS条目来统一访问对应的service,从而达到负载均衡的效果。

1.1.5 Swarm mode跨主机使用

Swarm mode 节点防火墙 默认 需要开启的端口:

l 7946(TCP/UDP),节点用于发现容器网络,类似etcd作用

l 4789(UDP),用于overlay容器网络(vxlan的UDP默认通信端口)

l 2377(TCP),用于集群管理通信

l 50(IP/ESP),如果overlay network需要加密的话,需要开启此端口。Swarm mode使用IPSEC的ESP协议加密。

2. Docker Swarm Mode基本操作

2.1 示例环境及组件

本文所有步骤均在UCLOUD的云主机Uhost上操作。

2.2 Docker安装及配置(centos 7- Docke version: 1.12.5)

添加docker yum源文件: /etc/yum.repos.d/docker-main.repo


[docker-main-repo]
name=Docker main Repository
baseurl=Index of /repo/main/centos/7/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg

安装docker 1.12.5


yum install -y docker-engine-1.12.5-1.el7.centos.x86_64
docker –v

将--live-restore设置成false

Start docker service:


service docker start

2.3 集群创建/退出

2.3.1 创建集群

a. 在一个manager节点上初始化swarm。


docker swarm init --advertise-addr 10.10.245.53

注:

初始化的时候会打印出worker的join-token,其他worker要加入swarm集群的话需要执行:


docker swarm join --token [woker-join-token] 10.10.245.53:2377

也可以通过命令docker swarm join-token worker来获取worker的join-token。

如果是其他的manager要加入swarm集群,需要先获取manager的join-token,通过manager节点执行以下命令获取:


//get manager join-token
docker swarm join-token manager
//manager join
docker swarm join --token [manager-join-token] 10.10.245.53:2377

b. 添加manager node

先获取manager join-token


docker swarm join-token manager

将节点10.10.218.59加入swarm中:


docker swarm join \
    --token
SWMTKN-1-0qlpkzimxxt2htogs64mz991x4xe8q37mkn3t130b2175jxu0a-6yjcu2mrjjvqc9gt9y7guiryw \
    10.10.245.53:2377

c. 添加woker node

使用swarm init时给出的worker join-token:


docker swarm join \
    --token
SWMTKN-1-0qlpkzimxxt2htogs64mz991x4xe8q37mkn3t130b2175jxu0a-9e3umt71jpw78czdh67p5wcfy \
    10.10.245.53:2377

d. 查看集群节点

可以通过命令docker node ls 查看整个swarm集群的节点信息。

可以看到整个集群已经创建成功,有2个manager,3个worker节点。

2.3.2 worker节点退出

如果节点仅仅是worker node:

执行下面命令退出swarm cluster。


docker swarm leave

也可以在manager节点将worker node删除。


docker node rm [OPTIONS] NODE [NODE...]

2.3.3 manager节点退出

如果节点是manager节点:

Manager节点退出需要先demote,再做删除节点操作。


docker node demote NODE [NODE...]
docker node rm [OPTIONS] NODE [NODE...]

2.4 服务创建/扩缩实例/滚动升级/删除

2.4.1 Create Service

使用docker service create来创建service,具体参数参看docker service create -h。

下面例子中创建了一个名称为nginx的服务,3个实例,镜像为nginx,默认bridge网络。


docker service create xxx
//查看所有service
docker service ls
//查看具体service
docker service ps xxx

2.4.2 Scale service

可以使用docker service scale来对service的实例进行扩缩。


docker service scale SERVICE=REPLICAS [SERVICE=REPLICAS...]

2.4.3 Update service

可以使用docker service update来对service进行更新。


docker service update [OPTIONS] SERVICE

2.4.4 Delete service

使用docker service rm来删除service


docker service rm [OPTIONS] SERVICE [SERVICE...]

2.5 Ingress LB使服务被外部访问

Swarm mode使用--publish <PUBLISHED-PORT>:<TARGET-PORT>来将容器服务暴露至外部网络,从而被外部访问。


docker service create --name=nginx-mesh
--publish 8080:80 --replicas 3 nginx:dnstools

从宿主机网络访问服务:

通过uhost的EIP访问服务(修改防火墙规则,开启8080端口权限):

2.6 Internal LB(DNS轮询)

Swarm mode会有一个内置DNS组件,用于在同一个overlay的network中为service提供域名服务。当创建service的时候使用--endpoint-mode dnsrr时,swarm会将该service的DNS对应到所有的容器实例,从而实现LB。

默认nginx镜像中没有nslookup命令,需要手动安装。我将安装完curl和nslookup的nginx镜像重新制成新的镜像nginx:dnstools.

2.6.1 nginx:dnstools镜像制作

Dockerfile:


FROM nginx
MAINTAINER xxx
RUN apt-get update && 
apt-get install -y dnsutils && apt-get install -y curl
&& apt-get clean

使用Dockerfile创建镜像:


docker build –t nginx:dnstools .

2.6.2 创建overlay network


docker network create --subnet=192.168.10.0/24 -d overlay my-net

2.6.3 使用dnsrr创建service


docker service create --endpoint-mode dnsrr --replicas 3 --name
nginx-dnsrr --network my-net nginx:dnstools

2.6.4 Check service

可以在同一个网络中创建其他的容器或service来通过域名“nginx-dnsrr”访问刚才创建的nginx-dnsrr服务;也可以直接使用nginx-dnsrr中的任一容器来访问nginx-dnsrr。从nslookup的结果可知,nginx-dnsrr域名对应后端的三个容器IP。


docker exec -it nginx-dnsrr.1.2fnr14ahknrdygbxz3nascfb8 nslookup
nginx-dnsrr
docker exec -it nginx-dnsrr.1.2fnr14ahknrdygbxz3nascfb8 curl
nginx-dnsrr

3. Docker Swarm Mode Network

Swarm mode创建service默认使用bridge模式,此时,跨主机的容器间无法通信。要使跨主机容器间通信,需要将service接入overlay network(ingress或自定义),或者是使用第三方的网络插件。

Swarm mode cluster默认会创建多个容器网络:

l bridge:默认的容器网络,将容器接入默认的docker0网桥,与之前版本一致。

l docker_gwbridge:local的bridge网络,用于连通单主机上的容器,使用overlay网络的时候会默认分配一个此网络的网卡给容器,使容器可以用NAT的方式和外部网络通信。

l ingress: swarm集群可见的overlay网络,当设置端口映射(-p)时,swarm会为每个service的容器分配一块网卡,连接到ingress网络(10.255.0.0/16)。

3.1 Bridge Network

a. 创建默认网络的service


docker service create --name=nginx --replicas=3 nginx:dnstools

b. 查看容器网卡信息

容器接入到docker0网桥,分配的是172.17.0.0/16网段IP。

此时,可以通过flannel来连通跨宿主机的容器网络通信。

c. 查看宿主机网桥信息

3.2 Ingress network

只有使能了端口映射(published port)的service才会将容器加入ingress network,ingress network本身是一个基于vxlan的overlay network。默认网段为10.255.0.0/16.


docker network inspect ingress

3.2.1 bridge network设置published port

a. Service设置published-port


docker service create --name=nginx-mesh --publish 8080:80 --replicas
3 nginx:dnstools

b. 查看容器网卡信息


docker exec -it nginx-mesh.2.d5wi6ds494rdl4pe1mt8dajx8 ip addr

可以看到容器有两个网卡(除lo),一个接入docker_gwbridge网络,另一个接入ingress网络。不同节点间的容器在ingress网段互通。

3.2.2 Overlay network设置published port

a. Service设置published port


docker service create --name=nginx-overlay --replicas=3
--network=my-net -p 8100:80 nginx:dnstools

b. 查看容器网卡信息


docker exec -it nginx-overlay.2.dljwj0snimwznrafav7zf5mc8 ip addr

可以看到又多了一块my-net overlay网络的网卡。

3.2.3 Dnsrr的Overlay network设置published port

设置了dnsrr的network不能再设置published port,也就是不能加入ingress network。

3.3 自定义overlay网络

Swarm中的Overlay网络有两种endpoint mode:

l DNS-RR:DNS轮询,此模式下的service有统一的域名解析到不同的task容器IP,达到LB。


docker service inspect nginx-dnsrr

l VIP:virtual IP,本质是用到了linux内核中的LVS技术(IPVS),对外有统一的service域名(解析到VIP),和唯一的VIP。VIP会相应负载均衡至每个task实例。


docker service inspect nginx-overlay

3.3.1 VIP


docker exec -it nginx-overlay.2.dljwj0snimwznrafav7zf5mc8 nslookup
nginx-overlay
docker exec -it nginx-overlay.2.dljwj0snimwznrafav7zf5mc8 nslookup
tasks.nginx-overlay

3.3.2 DNSRR


docker exec -it nginx-overlay.2.dljwj0snimwznrafav7zf5mc8 nslookup
nginx-dnsrr
docker exec -it nginx-overlay.2.dljwj0snimwznrafav7zf5mc8 nslookup