容器服务Docker&Kubernetes + 关注
手机版

DockerCon 2016 深度解读:在阿里云上体验Docker 1.12内置的编排能力

  1. 云栖社区>
  2. 容器服务Docker&Kubernetes>
  3. 博客>
  4. 正文

DockerCon 2016 深度解读:在阿里云上体验Docker 1.12内置的编排能力

易立 2016-06-24 18:24:12 浏览7244 评论1

摘要: Docker公司在DockerCon 2016上宣布Docker将提供内置的编排(Orchestration)能力,从而能使得Docker Engine原生支持集群管理和服务生命周期管理。这个宣布对每个Docker开发者和厂商都有重要影响,也会左右现有Docker编排市场格局。

screenshot

昨天才从DockerCon大会归来,阿里云容器服务团队将为大家奉献一系列深入学习的文章来帮助大家了解Docker 1.12的最新动态。

在DockerCon第一天的Keynote里面,Docker CTO Solomon Hykes宣布Docker将提供内置的编排(Orchestration)能力,从而能使得Docker Engine原生支持集群管理和服务生命周期管理。Solomon把这称为自Docker发布以来最大的一次改变。这个宣布对每个Docker开发者和厂商都有重要影响,也会左右现有Docker编排市场格局。

Docker Swarm模式简介

在Docker 1.12中,其Docker内置编排包含以下功能

  • 提供了Swarm模式

    • 将一组Docker Engine构成一个集群统一管理、调度

      • 集群环境内置Raft一致性协议,避免单点故障问题,也无需额外的类似于 Etcd/Consul/Zookeeper 的外部发现服务
      • 自动选举出leader进行集群管理
  • 节点身份加密 (Cryptographic node identity)

    • Docker节点加入集群时自动完成相应的安全配置
    • 节点之间点对点通信通过TLS证书认证,同时支持TLS证书定时刷新
  • 提供Service概念支持

    • 提供服务状态的持续逼近
    • 支持服务的不中断更新(rolling update)和其他发布策略
    • 自定义服务的健康检查规则
    • 当节点失效时,服务自动重新调度
  • 内置路由机制(Routing Mesh)

    • 通过 IPVS 实现内核空间的4层路由,实现可靠的负载均衡。
    • 可以从任意节点访问集群中服务暴露出的服务端口。


Docker Swarm模式架构如下:

14667562526936

集群中的节点可以包括worker和manager两类不同的角色,它们之间可以通过promote和demote操作互相切换。在manager节点上可以进行集群的管理操作,其状态通过一个内部的Raft一致性协议实现进行同步和持久化。manager节点中会选举出一个leader来进行调度和编排。

Swarm模式支持新的Service/Task来进行容器的调度和执行。一个服务(service)描述了任务(task)如何在集群worker节点上的调度执行。Swarm支持自我复制服务(replicated service 指定副本数目)或全局服务(global service 在每个worker上执行)。一个任务(task)是原子化执行和调度单元,对应着Docker容器和其运行配置。manager节点负责根据service描述调度task到特定worker节点执行。同时manager会根据任务当前状态,自动逼近服务指定目标状态,实现最终一致性。

阿里云上创建Docker Swarm模式集群

为了在第一时间尝鲜体验一下Docker内置的编排能力,我们先在阿里云上操练起来。

Docker Machine是一个可以帮助开发者在自己本地电脑或云服务中创建Docker运行环境的的应用工具。使用它的阿里云ECS Driver,可以大大简化在阿里云环境下Docker运行环境的部署。

Docker Machine和阿里云ECS Driver的安装步骤如下, https://help.aliyun.com/document_detail/26088.html

下面,我们来创建一个包含3个ECS节点的Docker集群,首先配置一些共用的环境变量

export DEBUG=true 
export ECS_ACCESS_KEY_ID=<您的Access Key ID>
export ECS_ACCESS_KEY_SECRET=<您的Access Key Secret>
export ECS_REGION=cn-beijing
export ECS_ZONE=cn-beijing-b
export ECS_SSH_PASSWORD=<ECS实例SSH密码>
export MACHINE_DOCKER_INSTALL_URL=http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/intranet
export ENGINE_REGISTRY_MIRROR=https://6udu7vtl.mirror.aliyuncs.com

注:

然后我们可以通过如下命令在阿里云上创建3个ECS节点,并安装最新的测试版Docker Engine

docker-machine create -d aliyunecs node1
docker-machine create -d aliyunecs node2
docker-machine create -d aliyunecs node3

我们可以通过如下命令执行如下命令显示node1节点内网地址,并利用docker swarm命令创建集群和注册manager节点

docker-machine ssh node1 ip addr show eth0
docker-machine ssh node1 docker swarm init --advertise-addr <NODE1_IP>

屏幕输出如下

Swarm initialized: current node (xxxxxxx) is now a manager.

To add a worker to this swarm, run the following command:
    docker swarm join \
    --token SWMTKN-1-1xxxxxxx-xxxxxxx \
    10.xx.xx.xx:2377

To add a manager to this swarm, run the following command:
    docker swarm join \
    --token SWMTKN-1-1xxxxxxx-xxxxxxx \
    10.xx.xx.xx:2377

之后,我们把node-2和node-3作为worker加入Docker Swarm集群,执行docker-machine ssh 之后拷贝上文返回的第一个命令来添加一个worker节点

docker-machine ssh node-2 docker swarm join --token <WORKER_TOKEN> <NODE1_IP>:2377
docker-machine ssh node-3 docker swarm join --token <WORKER_TOKEN> <NODE1_IP>:2377

这样整个Docker集群就已经创建成功了,是不是非常简单 :-)

下面我们将体验Docker的Swarm模式,如需进一步了解请参考Docker Swarm模式官方文档

管理集群节点

我们利用 docker-machine ssh node1命令登入node1节点,并用下面的命令查看集群节点

root@node1:~# docker node ls
ID                           NAME   MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
3bj13a80xdltndle20c6rzc55 *  node1  Accepted    Ready   Active        Leader
b5x26rpfbqhg18nn11arkxzdz    node3  Accepted    Ready   Active        
cqgyh1yv0rn6llckzi1hv84fa    node2  Accepted    Ready   Active        

部署管理

下面我们部署一个nginx服务到集群上

root@node1:~# docker service create -p 80 --name nginx nginx:1.11
9wxstra98838kc0hbeeq0hliz

然后我们检查nginx服务状态和它包含的tasks信息

root@node1:~# docker service ls
ID            NAME   REPLICAS  IMAGE       COMMAND
9wxstra98838  nginx  1/1       nginx:1.11  
root@node1:~# docker service ps nginx
ID                         NAME     SERVICE  IMAGE       LAST STATE         DESIRED STATE  NODE
86lnce96t55dempycyp4si0gm  nginx.1  nginx    nginx:1.11  Running 7 minutes  Running        node1

我们可以伸缩nginx服务到三个任务

root@node1:~# docker service scale nginx=3
nginx scaled to 3

更新服务

下面我们部署一个redis服务到Swarm集群,采用redis:3.0.6镜像,其初始包含3个任务。我们还定义了服务的更新策略:每次更新1个Redis容器,更新延迟10s

root@node1:~# docker service create --replicas 3 --name redis --update-delay 10s --update-parallelism 1 redis:3.0.6
5dz319epmfflcmfoftn4w1uga

查看Service列表,并检查redis服务细节

root@node1:~# docker service inspect redis --pretty
ID:        5dz319epmfflcmfoftn4w1uga
Name:        redis
Mode:        Replicated
 Replicas:    3
Placement:
 Strategy:    Spread
UpdateConfig:
 Parallelism:    1
 Delay:        10s
ContainerSpec:
 Image:        redis:3.0.6
Resources:
Reservations:
Limits:

下面,我们可以更新redis服务的Docker镜像到redis:3.0.7。Swarm manager将依照之前的更新策略来更新服务:

root@node1:~# docker service update --image redis:3.0.7 redis
redis

再次检查redis服务细节,和相应的task信息

root@node1:~# docker service inspect --pretty redis
ID:        5dz319epmfflcmfoftn4w1uga
Name:        redis
Mode:        Replicated
 Replicas:    3
Placement:
 Strategy:    Spread
UpdateConfig:
 Parallelism:    1
 Delay:        10s
ContainerSpec:
 Image:        redis:3.0.7
Resources:
Reservations:
Limits:

root@node1:~# docker service ps redis
ID                         NAME         IMAGE        NODE   DESIRED STATE  CURRENT STATE           ERROR
agiq4u5b4ttokf95ilgd8ogpt  redis.1      redis:3.0.7  node2  Running        Running 3 minutes ago   
0zc6bsqlhw50er0agzhetyw0q   \_ redis.1  redis:3.0.6  node3  Shutdown       Shutdown 3 minutes ago  
6l5ch8hg2n6dht3oste72n2x0  redis.2      redis:3.0.7  node3  Running        Running 2 minutes ago   
dfmgh0re6ntspra4yxi5dqj3u   \_ redis.2  redis:3.0.6  node1  Shutdown       Shutdown 2 minutes ago  
515317fk5zfkth66dfop1or5f  redis.3      redis:3.0.7  node3  Running        Running 2 minutes ago   
2taa6br9kdwm5qzz34037lywm   \_ redis.3  redis:3.0.6  node1  Shutdown       Shutdown 3 minutes ago  

当redis更新时,可以看到redis:3.0.6容器会逐渐被基于redis:3.0.7镜像的容器陆续更新

集群可用性验证

我们可以利用下面命令把node2,node3也设置为集群的manager节点

root@node1:~# docker node promote node2
Node node2 promoted to a manager in the swarm.
root@node1:~# docker node ls
ID                           NAME   MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
3bj13a80xdltndle20c6rzc55 *  node1  Accepted    Ready   Active        Leader
b5x26rpfbqhg18nn11arkxzdz    node3  Accepted    Ready   Active        
cqgyh1yv0rn6llckzi1hv84fa    node2  Accepted    Ready   Active        Reachable
root@node1:~# docker node promote node3
Node node3 promoted to a manager in the swarm.
root@node1:~# docker node ls
ID                           NAME   MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
3bj13a80xdltndle20c6rzc55 *  node1  Accepted    Ready   Active        Leader
b5x26rpfbqhg18nn11arkxzdz    node3  Accepted    Ready   Active        
cqgyh1yv0rn6llckzi1hv84fa    node2  Accepted    Ready   Active        Reachable

当我们重启Docker服务来模拟Docker Engine故障时,我们可以发现leader已经被自动切换到其他节点上

root@node1:~# service docker restart
docker stop/waiting
docker start/running, process 7077
root@node1:~# docker node ls
ID                           NAME   MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
3bj13a80xdltndle20c6rzc55 *  node1  Accepted    Ready   Active        Reachable
b5x26rpfbqhg18nn11arkxzdz    node3  Accepted    Ready   Active        Leader
cqgyh1yv0rn6llckzi1hv84fa    node2  Accepted    Ready   Active        Reachable

现在我们来模拟node3下线维护过程,现在node3上运行的节点有如下任务

root@node1:~# docker node tasks node3
ID                         NAME     SERVICE  IMAGE        LAST STATE         DESIRED STATE  NODE
88mklyn50dun7telyn97m5grm  redis.2  redis    redis:3.0.7  Running 5 minutes  Running        node3
6l612n075rr95ditjdl6x2pe7  redis.3  redis    redis:3.0.7  Running 6 minutes  Running        node3
emxsw4qosd6qkahpyrq8hpx3n  nginx.3  nginx    nginx:1.11   Running 9 minutes  Running        node3

我们将node3设置为排水模式,让其下线并将其上运行中容器自动迁移到其他活跃节点

root@node1:~# docker node update --availability drain node3
node3

我们可以看到所有的容器已经迁移到node1和node2上,

root@node1:~# docker node tasks node1
ID                         NAME     SERVICE  IMAGE        LAST STATE         DESIRED STATE  NODE
1pm1dyxuwrh57kysyh7j5s48w  redis.1  redis    redis:3.0.7  Running 5 minutes  Running        node1
7gstf6nn9ydwm8knbjwb7c0ag  nginx.2  nginx    nginx:1.11   Running 5 minutes  Running        node1
46l5e1zmdpbwn2ptcfqtrdpue  redis.3  redis    redis:3.0.7  Running 9 seconds  Running        node1
root@node1:~# docker node tasks node2
ID                         NAME     SERVICE  IMAGE        LAST STATE          DESIRED STATE  NODE
5tn4bgod6a76k4bjl886vprrb  nginx.1  nginx    nginx:1.11   Running 11 minutes  Running        node2
3lj30togrr1j19rya5wc9bxi7  redis.2  redis    redis:3.0.7  Running 12 seconds  Running        node2
1hnvm1kuji5auegexd2u7lm4x  nginx.3  nginx    nginx:1.11   Running 12 seconds  Running        node2
root@node1:~# docker node tasks node3
ID  NAME  SERVICE  IMAGE  LAST STATE  DESIRED STATE  NODE

我们可以把node3再修改成为活跃(active)状态,之后系统可以在node3上创建或重新调度容器。

root@node1:~# docker node update --availability active node3
node3

下面我们将测试当一个节点失效时集群的行为。

利用docker-machine我们可以对指定节点强制关机,打开另外一个终端窗口执行下面命令杀死node2节点

docker-machine kill node2

稍等一会儿,我们检查docker的节点和上面的任务状态

root@node1:~# docker node ls
ID                           NAME   MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
3bj13a80xdltndle20c6rzc55 *  node1  Accepted    Ready   Active        Reachable
b5x26rpfbqhg18nn11arkxzdz    node3  Accepted    Ready   Active        Leader
cqgyh1yv0rn6llckzi1hv84fa    node2  Accepted    Down    Active        Reachable
root@node1:~# docker node tasks node1
ID                         NAME     SERVICE  IMAGE        LAST STATE          DESIRED STATE  NODE
1pm1dyxuwrh57kysyh7j5s48w  redis.1  redis    redis:3.0.7  Running 12 minutes  Running        node1
7gstf6nn9ydwm8knbjwb7c0ag  nginx.2  nginx    nginx:1.11   Running 12 minutes  Running        node1
46l5e1zmdpbwn2ptcfqtrdpue  redis.3  redis    redis:3.0.7  Running 7 minutes   Running        node1
root@node1:~# docker node tasks node3
ID                         NAME     SERVICE  IMAGE        LAST STATE         DESIRED STATE  NODE
cb99d1ga8dsv2prwvsc3np1fq  nginx.1  nginx    nginx:1.11   Running 2 minutes  Running        node3
3r9hniyuq54j12mwtytm9x88k  redis.2  redis    redis:3.0.7  Running 2 minutes  Running        node3
9p9jik29urimlruo7alabfcmp  nginx.3  nginx    nginx:1.11   Running 2 minutes  Running        node3

我们可以发现这时候,node2节点是"Down"状态,并且所有容器已经被自动迁移到node1和node3之上。

总结

我们利用Docker Machine的ECS driver,可以方便地在阿里云上创建Docker环境。学习并体验了Docker在编排方面的最新特性:节点管理、服务管理和高可用性等。

客观地讲,Docker的Swarm模式确实极大简化了容器编排技术的部署和使用,这体现了Docker公司所强调的“democratize orchestration”的愿景,把容器编排变成为大众化的技术。但是这也会在某种程度上抑制技术的多样性,其他的编排技术的市场空间会受到很大影响。另外作为Docker内置编排方案的第一个版本,其还有很多不足和和可能变化的地方。在DockerCon上我们也和Docker的工程师探讨了是否能够提供扩展机制来定制不同的路由和发布策略等问题。我们期待Docker的进一步发展,同时也希望Docker社区能够更加多元化和健康发展。

阿里云容器服务完全兼容Docker原生的编排技术,目前支持Docker 1.11正式版本。它现在的容器化服务生命周期管理的方式和新的Swarm模式很接近。当Docker 1.12稳定版发布之后,我们会很快推出对新Swarm模式的支持。

想了解更多容器服务内容,请访问 https://www.aliyun.com/product/containerservice

【云栖快讯】一站式开发者服务,海量学习资源免费学  详情请点击

网友评论