Swarm Mode服务管理

环境准备

[root@swarm-manager ~]# cat > ./sources.list <<END
> deb http://mirrors.aliyun.com/debian stretch main contrib non-free
> deb http://mirrors.aliyun.com/debian stretch-proposed-updates main contrib non-free
> deb http://mirrors.aliyun.com/debian stretch-updates main contrib non-free
> deb http://mirrors.aliyun.com/debian-security/ stretch/updates main non-free contrib
> END
[root@swarm-manager ~]# cat Dockerfile
FROM nginx:latest
ADD sources.list /etc/apt/sources.list
RUN apt-get update && apt-get install -y dnsutils iproute2 net-tools curl && apt-get clean
ADD index.html /usr/share/nginx/html/index.html

[root@swarm-manager ~]# echo "nginx:v1" > index.html
[root@swarm-manager ~]# docker build -t registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1 .
[root@swarm-manager ~]# echo "nginx:v2" > index.html
[root@swarm-manager ~]# docker build -t registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v2 .

[root@swarm-manager ~]# docker push registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1
[root@swarm-manager ~]# docker push registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v2

create

[root@swarm-manager ~]# docker service create --name nginx registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1
[root@swarm-manager ~]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                                               PORTS
63c04khgjl03        nginx               replicated          1/1                 registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1
[root@swarm-manager ~]# docker service ps nginx
ID                  NAME                IMAGE                                               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
zo87xl8e3in9        nginx.1             registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   swarm-node1         Running             Running 4 minutes ago

update

[root@swarm-manager ~]# docker service update --network-add my-network --publish-add 80:80 nginx
[root@swarm-manager ~]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                                               PORTS
63c04khgjl03        nginx               replicated          1/1                 registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   *:80->80/tcp
[root@swarm-manager ~]# docker service ps nginx
ID                  NAME                IMAGE                                               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
lppql3gw8phx        nginx.1             registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   swarm-node1         Running             Running 3 minutes ago
zo87xl8e3in9         _ nginx.1         registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   swarm-node1         Shutdown            Shutdown 3 minutes ago

Scale

[root@swarm-manager ~]# docker service scale nginx=2
[root@swarm-manager ~]# docker service ps nginx
ID                  NAME                IMAGE                                               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
lppql3gw8phx        nginx.1             registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   swarm-node1         Running             Running 4 minutes ago
zo87xl8e3in9         _ nginx.1         registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   swarm-node1         Shutdown            Shutdown 4 minutes ago
qqptr8htux76        nginx.2             registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   swarm-node2         Running             Running 2 minutes ago

update & rollback

查看当前版本

[root@swarm-manager ~]# curl 127.0.0.1
nginx:v1

进行rolling update

[root@swarm-manager ~]# docker service update --image registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v2 nginx
[root@swarm-manager ~]# docker service ps nginx
ID                  NAME                IMAGE                                               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
iwpnzn3ss6uo        nginx.1             registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v2   swarm-node1         Running             Running 4 minutes ago
lppql3gw8phx         _ nginx.1         registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   swarm-node1         Shutdown            Shutdown 4 minutes ago
zo87xl8e3in9         _ nginx.1         registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   swarm-node1         Shutdown            Shutdown 5 minutes ago
1c47y3e14dc0        nginx.2             registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v2   swarm-node2         Running             Running 3 minutes ago
qqptr8htux76         _ nginx.2         registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   swarm-node2         Shutdown            Shutdown 3 minutes ago
[root@swarm-manager ~]# curl 127.0.0.1
nginx:v2

进行rollback

[root@swarm-manager ~]# docker service update --rollback  nginx
nginx
[root@swarm-manager ~]# docker service ps nginx
ID                  NAME                IMAGE                                               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
xign4i5kxc0m        nginx.1             registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   swarm-node1         Running             Running 3 minutes ago
iwpnzn3ss6uo         _ nginx.1         registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v2   swarm-node1         Shutdown            Shutdown 3 minutes ago
lppql3gw8phx         _ nginx.1         registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   swarm-node1         Shutdown            Shutdown 5 minutes ago
zo87xl8e3in9         _ nginx.1         registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   swarm-node1         Shutdown            Shutdown 6 minutes ago
em9hv301ga5f        nginx.2             registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   swarm-node2         Running             Running 3 minutes ago
1c47y3e14dc0         _ nginx.2         registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v2   swarm-node2         Shutdown            Shutdown 3 minutes ago
qqptr8htux76         _ nginx.2         registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   swarm-node2         Shutdown            Shutdown 4 minutes ago
[root@swarm-manager ~]# curl 127.0.0.1
nginx:v1

healthcheck

增加健康检查

[root@swarm-manager ~]# docker service update --health-cmd "curl -f http://localhost/ || exit 1"  nginx
[root@swarm-node1 ~]# docker ps
CONTAINER ID        IMAGE                                               COMMAND                  CREATED             STATUS                             PORTS               NAMES
f7e1935f1c22        registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   "nginx -g 'daemon ..."   17 seconds ago      Up 12 seconds (health: starting)   80/tcp              nginx.1.9dz6g3bizl4kwh8lctr552c6a
[root@swarm-node1 ~]# docker ps
CONTAINER ID        IMAGE                                               COMMAND                  CREATED             STATUS                    PORTS               NAMES
f7e1935f1c22        registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   "nginx -g 'daemon ..."   44 seconds ago      Up 38 seconds (healthy)   80/tcp              nginx.1.9dz6g3bizl4kwh8lctr552c6a

故障测试

可见当健康状态异常时,将会停止并移除掉异常的容器并重新启动一个新的容器。

[root@swarm-node1 ~]# docker exec -it f7e1935f1c22 rm -f /usr/share/nginx/html/index.html
[root@swarm-node1 ~]# date
Wed Aug 16 16:48:41 CST 2017
[root@swarm-node1 ~]# docker events --since "2017-08-16T16:48:35"
2017-08-16T16:48:40.063995281+08:00 container exec_create: rm -f /usr/share/nginx/html/index.html f7e1935f1c2263112fe86a6e74c0d23a2ff369ffd54eab2781f2645a7dc7810a (com.docker.swarm.node.id=y83k6khc3vxmch1qd3j8kl4ak, com.docker.swarm.service.id=63c04khgjl033syhc5ef0e9g9, com.docker.swarm.service.name=nginx, com.docker.swarm.task=, com.docker.swarm.task.id=lkb6ags10aprqvzii5aht3pjf, com.docker.swarm.task.name=nginx.1.lkb6ags10aprqvzii5aht3pjf, image=registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1@sha256:b223de06038b1187d1d1b955df759839712a10cde33d7f2784ef3f9f5573ad71, name=nginx.1.lkb6ags10aprqvzii5aht3pjf)
...
2017-08-16T16:49:57.889494869+08:00 container health_status: unhealthy f7e1935f1c2263112fe86a6e74c0d23a2ff369ffd54eab2781f2645a7dc7810a (com.docker.swarm.node.id=y83k6khc3vxmch1qd3j8kl4ak, com.docker.swarm.service.id=63c04khgjl033syhc5ef0e9g9, com.docker.swarm.service.name=nginx, com.docker.swarm.task=, com.docker.swarm.task.id=lkb6ags10aprqvzii5aht3pjf, com.docker.swarm.task.name=nginx.1.lkb6ags10aprqvzii5aht3pjf, image=registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1@sha256:b223de06038b1187d1d1b955df759839712a10cde33d7f2784ef3f9f5573ad71, name=nginx.1.lkb6ags10aprqvzii5aht3pjf)
2017-08-16T16:49:59.891503804+08:00 container kill f7e1935f1c2263112fe86a6e74c0d23a2ff369ffd54eab2781f2645a7dc7810a (com.docker.swarm.node.id=y83k6khc3vxmch1qd3j8kl4ak, com.docker.swarm.service.id=63c04khgjl033syhc5ef0e9g9, com.docker.swarm.service.name=nginx, com.docker.swarm.task=, com.docker.swarm.task.id=lkb6ags10aprqvzii5aht3pjf, com.docker.swarm.task.name=nginx.1.lkb6ags10aprqvzii5aht3pjf, image=registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1@sha256:b223de06038b1187d1d1b955df759839712a10cde33d7f2784ef3f9f5573ad71, name=nginx.1.lkb6ags10aprqvzii5aht3pjf, signal=15)
2017-08-16T16:49:59.964124883+08:00 container die f7e1935f1c2263112fe86a6e74c0d23a2ff369ffd54eab2781f2645a7dc7810a (com.docker.swarm.node.id=y83k6khc3vxmch1qd3j8kl4ak, com.docker.swarm.service.id=63c04khgjl033syhc5ef0e9g9, com.docker.swarm.service.name=nginx, com.docker.swarm.task=, com.docker.swarm.task.id=lkb6ags10aprqvzii5aht3pjf, com.docker.swarm.task.name=nginx.1.lkb6ags10aprqvzii5aht3pjf, exitCode=0, image=registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1@sha256:b223de06038b1187d1d1b955df759839712a10cde33d7f2784ef3f9f5573ad71, name=nginx.1.lkb6ags10aprqvzii5aht3pjf)
2017-08-16T16:50:00.289350308+08:00 network disconnect i6xug49nwdsxauqqpli3apvym (container=f7e1935f1c2263112fe86a6e74c0d23a2ff369ffd54eab2781f2645a7dc7810a, name=ingress, type=overlay)
2017-08-16T16:50:00.289489879+08:00 network disconnect vxe1cwk14avlfp2xjgymhkhdl (container=f7e1935f1c2263112fe86a6e74c0d23a2ff369ffd54eab2781f2645a7dc7810a, name=my-network, type=overlay)
2017-08-16T16:50:00.345105732+08:00 container stop f7e1935f1c2263112fe86a6e74c0d23a2ff369ffd54eab2781f2645a7dc7810a (com.docker.swarm.node.id=y83k6khc3vxmch1qd3j8kl4ak, com.docker.swarm.service.id=63c04khgjl033syhc5ef0e9g9, com.docker.swarm.service.name=nginx, com.docker.swarm.task=, com.docker.swarm.task.id=lkb6ags10aprqvzii5aht3pjf, com.docker.swarm.task.name=nginx.1.lkb6ags10aprqvzii5aht3pjf, image=registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1@sha256:b223de06038b1187d1d1b955df759839712a10cde33d7f2784ef3f9f5573ad71, name=nginx.1.lkb6ags10aprqvzii5aht3pjf)
2017-08-16T16:50:00.922761678+08:00 container create 2132a1bd9287bc377f0800d9a06e6876aaddb9a71b0afd567c3838fbb6aa3934 (com.docker.swarm.node.id=y83k6khc3vxmch1qd3j8kl4ak, com.docker.swarm.service.id=63c04khgjl033syhc5ef0e9g9, com.docker.swarm.service.name=nginx, com.docker.swarm.task=, com.docker.swarm.task.id=y00kqcu26sq75js3fvpqx4kt5, com.docker.swarm.task.name=nginx.1.y00kqcu26sq75js3fvpqx4kt5, image=registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1@sha256:b223de06038b1187d1d1b955df759839712a10cde33d7f2784ef3f9f5573ad71, name=nginx.1.y00kqcu26sq75js3fvpqx4kt5)
2017-08-16T16:50:03.006063329+08:00 network destroy vxe1cwk14avlfp2xjgymhkhdl (name=my-network, type=overlay)
2017-08-16T16:50:03.376037876+08:00 container destroy 965a0ce53c2c0f2d5a740cb87c39ea51d164f1a6cf5bea0cf0679883dd99cb5c (com.docker.swarm.node.id=y83k6khc3vxmch1qd3j8kl4ak, com.docker.swarm.service.id=63c04khgjl033syhc5ef0e9g9, com.docker.swarm.service.name=nginx, com.docker.swarm.task=, com.docker.swarm.task.id=xign4i5kxc0mfp1pji7zzkoo1, com.docker.swarm.task.name=nginx.1.xign4i5kxc0mfp1pji7zzkoo1, image=registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1@sha256:b223de06038b1187d1d1b955df759839712a10cde33d7f2784ef3f9f5573ad71, name=nginx.1.xign4i5kxc0mfp1pji7zzkoo1)
2017-08-16T16:50:05.720425867+08:00 network connect i6xug49nwdsxauqqpli3apvym (container=2132a1bd9287bc377f0800d9a06e6876aaddb9a71b0afd567c3838fbb6aa3934, name=ingress, type=overlay)
2017-08-16T16:50:05.808884815+08:00 network disconnect i6xug49nwdsxauqqpli3apvym (container=2132a1bd9287bc377f0800d9a06e6876aaddb9a71b0afd567c3838fbb6aa3934, name=ingress, type=overlay)
2017-08-16T16:50:05.919636688+08:00 network create vxe1cwk14avlfp2xjgymhkhdl (name=my-network, type=overlay)
2017-08-16T16:50:06.102359133+08:00 network connect i6xug49nwdsxauqqpli3apvym (container=2132a1bd9287bc377f0800d9a06e6876aaddb9a71b0afd567c3838fbb6aa3934, name=ingress, type=overlay)
2017-08-16T16:50:06.453151382+08:00 network connect vxe1cwk14avlfp2xjgymhkhdl (container=2132a1bd9287bc377f0800d9a06e6876aaddb9a71b0afd567c3838fbb6aa3934, name=my-network, type=overlay)
2017-08-16T16:50:07.062684099+08:00 container start 2132a1bd9287bc377f0800d9a06e6876aaddb9a71b0afd567c3838fbb6aa3934 (com.docker.swarm.node.id=y83k6khc3vxmch1qd3j8kl4ak, com.docker.swarm.service.id=63c04khgjl033syhc5ef0e9g9, com.docker.swarm.service.name=nginx, com.docker.swarm.task=, com.docker.swarm.task.id=y00kqcu26sq75js3fvpqx4kt5, com.docker.swarm.task.name=nginx.1.y00kqcu26sq75js3fvpqx4kt5, image=registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1@sha256:b223de06038b1187d1d1b955df759839712a10cde33d7f2784ef3f9f5573ad71, name=nginx.1.y00kqcu26sq75js3fvpqx4kt5)
2017-08-16T16:51:07.221879814+08:00 container exec_create: /bin/sh -c curl -f http://localhost/ || exit 1 2132a1bd9287bc377f0800d9a06e6876aaddb9a71b0afd567c3838fbb6aa3934 (com.docker.swarm.node.id=y83k6khc3vxmch1qd3j8kl4ak, com.docker.swarm.service.id=63c04khgjl033syhc5ef0e9g9, com.docker.swarm.service.name=nginx, com.docker.swarm.task=, com.docker.swarm.task.id=y00kqcu26sq75js3fvpqx4kt5, com.docker.swarm.task.name=nginx.1.y00kqcu26sq75js3fvpqx4kt5, image=registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1@sha256:b223de06038b1187d1d1b955df759839712a10cde33d7f2784ef3f9f5573ad71, name=nginx.1.y00kqcu26sq75js3fvpqx4kt5)
[root@swarm-node1 ~]# docker ps
CONTAINER ID        IMAGE                                               COMMAND                  CREATED             STATUS                    PORTS               NAMES
2132a1bd9287        registry.cn-hangzhou.aliyuncs.com/vnimos/nginx:v1   "nginx -g 'daemon ..."   31 minutes ago      Up 30 minutes (healthy)   80/tcp              nginx.1.y00kqcu26sq75js3fvpqx4kt5
constraint & placement

lable

[root@swarm-manager ~]# docker node update --label-add project=nginx swarm-node2
[root@swarm-manager ~]# docker node update --label-add "datacenter=xiamen" swarm-node1
[root@swarm-manager ~]# docker node update --label-add "datacenter=fuzhou" swarm-node2
[root@swarm-manager ~]# docker node inspect -f {{.Spec.Labels}} swarm-node1
map[datacenter:xiamen]
[root@swarm-manager ~]# docker node inspect -f {{.Spec.Labels}} swarm-node2
map[datacenter:fuzhou project:nginx]

constraint

[root@swarm-manager ~]# docker service create --replicas=4 --constraint 'node.hostname == swarm-node1' --name nginx-c1 nginx
[root@swarm-manager ~]# docker service create --replicas=4 --constraint 'node.labels.project == nginx' --name nginx-c2 nginx
[root@swarm-manager ~]# docker service ps nginx-c1
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
sqcyg8wm8gdt        nginx-c1.1          nginx:latest        swarm-node1         Running             Running 5 minutes ago
ttst5umkpt6g        nginx-c1.2          nginx:latest        swarm-node1         Running             Running 5 minutes ago
lpiz1vsaj6p3        nginx-c1.3          nginx:latest        swarm-node1         Running             Running 5 minutes ago
ykvrdyty4qie        nginx-c1.4          nginx:latest        swarm-node1         Running             Running 5 minutes ago
[root@swarm-manager ~]# docker service ps nginx-c2
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
x322u16dfnyt        nginx-c2.1          nginx:latest        swarm-node2         Running             Running 5 minutes ago
zjp93whpf4ah        nginx-c2.2          nginx:latest        swarm-node2         Running             Running 5 minutes ago
ff3usxkpo5ae        nginx-c2.3          nginx:latest        swarm-node2         Running             Running 5 minutes ago
p3g0haaqg6yu        nginx-c2.4          nginx:latest        swarm-node2         Running             Running 5 minutes ago

placement

[root@swarm-manager ~]# docker service create --replicas=6 --placement-pref 'spread=node.labels.datacenter' --name nginx-c3 nginx
[root@swarm-manager ~]# docker service ps nginx-c3
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
p3y7774kpu0w        nginx-c3.1          nginx:latest        swarm-node2         Running             Running 3 minutes ago
081l22wh87ok        nginx-c3.2          nginx:latest        swarm-node1         Running             Running 3 minutes ago
lj1t30mok3te        nginx-c3.3          nginx:latest        swarm-node1         Running             Running 3 minutes ago
fhb90j6brwuv        nginx-c3.4          nginx:latest        swarm-node2         Running             Running 3 minutes ago
ein699law198        nginx-c3.5          nginx:latest        swarm-node2         Running             Running 3 minutes ago
vo91976o481m        nginx-c3.6          nginx:latest        swarm-node1         Running             Running 3 minutes ago

deploy

Docker1.13推出了一个新版本的Docker Compose(V3)。该版本的主要特征是,允许Swarm Mode使用Docker Compose文件定义直接部署服务。

定义compose-file

[root@swarm-manager ~]# cat docker-compose.yml 
version: '3'
services:
  mysql:
    image: mysql
    environment:
      - MYSQL_ROOT_PASSWORD=password
  wordpress:
    image: wordpress
    ports:
      - 80:80
    links:
      - mysql:mysql
    environment:
      - WORDPRESS_DB_PASSWORD=password

在Swarm Mode下,需要使用docker stack deploy命令进行部署,如果直接使用docker-compose up则将会出现如下警告:

[root@swarm-manager ~]# docker-compose up
WARNING: The Docker Engine you're using is running in swarm mode.

Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.

To deploy your application across the swarm, use `docker stack deploy`.

通过compose-file部署多个Service

[root@swarm-manager ~]# docker stack deploy --compose-file=docker-compose.yml demo
Creating network demo_my-network
Creating service demo_mysql
Creating service demo_wordpress
[root@swarm-manager ~]# docker stack ps demo
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
5n5x8z9oso6d        demo_wordpress.1    wordpress:latest    swarm-node2         Running             Running 3 minutes ago
66wmzw3u50i0        demo_mysql.1        mysql:latest        swarm-node1         Running             Running 4 minutes ago
[root@swarm-manager ~]# docker stack services demo
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
k791axfnh6le        demo_wordpress      replicated          1/1                 wordpress:latest    *:80->80/tcp
wp0rz1kls1m1        demo_mysql          replicated          1/1                 mysql:latest

Docker Swarm 下搭建 MongoDB 分片+副本+选举集群

一、环境准备

三台服务器,建立 Docker Swarm 集群,一个 Manager,两个 Worker。

  • docker 版本:17-09
  • mongo 版本:3.6

二、MongoDB 集群架构设计

未分类

高清图地址: https://www.processon.com/view/link/5a3c7386e4b0bf89b8530376

三、搭建集群

1、【Manager】创建集群网络

docker network create -d overlay --attachable mongo

–attachable 允许其他容器加入此网络

2、创建 9 个 Data 服务,3 个 Config 服务,1 个 Global 模式的 Mongos 服务

2.1、【所有机器】创建相关文件夹

mkdir /root/mongo/config /root/mongo/shard1 /root/mongo/shard2 /root/mongo/shard3

2.2、【Manager】创建 stack.yml

version: '3.3'
services:
  mongors1n1:
    # docker 中国的镜像加速地址
    image: registry.docker-cn.com/library/mongo
    command: mongod --shardsvr --replSet shard1 --dbpath /data/db --port 27017
    networks:
      - mongo
    volumes:
      - /etc/localtime:/etc/localtime
      - /root/mongo/shard1:/data/db
    deploy:
      restart_policy:
        condition: on-failure
      replicas: 1
      placement:
        # 指定在服务器 manager 上启动
        constraints:
          - node.hostname==manager
  mongors2n1:
    image: registry.docker-cn.com/library/mongo
    command: mongod --shardsvr --replSet shard2 --dbpath /data/db --port 27017
    networks:
      - mongo
    volumes:
      - /etc/localtime:/etc/localtime
      - /root/mongo/shard2:/data/db
    deploy:
      restart_policy:
        condition: on-failure
      replicas: 1
      placement:
        constraints:
          - node.hostname==manager
  mongors3n1:
    image: registry.docker-cn.com/library/mongo
    command: mongod --shardsvr --replSet shard3 --dbpath /data/db --port 27017
    networks:
      - mongo
    volumes:
      - /etc/localtime:/etc/localtime
      - /root/mongo/shard3:/data/db
    deploy:
      restart_policy:
        condition: on-failure
      replicas: 1
      placement:
        constraints:
          - node.hostname==manager
  mongors1n2:
    image: registry.docker-cn.com/library/mongo
    command: mongod --shardsvr --replSet shard1 --dbpath /data/db --port 27017
    networks:
      - mongo
    volumes:
      - /etc/localtime:/etc/localtime
      - /root/mongo/shard1:/data/db
    deploy:
      restart_policy:
        condition: on-failure
      replicas: 1
      placement:
        constraints:
          - node.hostname==worker1
  mongors2n2:
    image: registry.docker-cn.com/library/mongo
    command: mongod --shardsvr --replSet shard2 --dbpath /data/db --port 27017
    networks:
      - mongo
    volumes:
      - /etc/localtime:/etc/localtime
      - /root/mongo/shard2:/data/db
    deploy:
      restart_policy:
        condition: on-failure
      replicas: 1
      placement:
        constraints:
          - node.hostname==worker1
  mongors3n2:
    image: registry.docker-cn.com/library/mongo
    command: mongod --shardsvr --replSet shard3 --dbpath /data/db --port 27017
    networks:
      - mongo
    volumes:
      - /etc/localtime:/etc/localtime
      - /root/mongo/shard3:/data/db
    deploy:
      restart_policy:
        condition: on-failure
      replicas: 1
      placement:
        constraints:
          - node.hostname==worker1
  mongors1n3:
    image: registry.docker-cn.com/library/mongo
    command: mongod --shardsvr --replSet shard1 --dbpath /data/db --port 27017
    networks:
      - mongo
    volumes:
      - /etc/localtime:/etc/localtime
      - /root/mongo/shard1:/data/db
    deploy:
      restart_policy:
        condition: on-failure
      replicas: 1
      placement:
        constraints:
          - node.hostname==worker2
  mongors2n3:
    image: registry.docker-cn.com/library/mongo
    command: mongod --shardsvr --replSet shard2 --dbpath /data/db --port 27017
    networks:
      - mongo
    volumes:
      - /etc/localtime:/etc/localtime
      - /root/mongo/shard2:/data/db
    deploy:
      restart_policy:
        condition: on-failure
      replicas: 1
      placement:
        constraints:
          - node.hostname==worker2
  mongors3n3:
    image: registry.docker-cn.com/library/mongo
    command: mongod --shardsvr --replSet shard3 --dbpath /data/db --port 27017
    networks:
      - mongo
    volumes:
      - /etc/localtime:/etc/localtime
      - /root/mongo/shard3:/data/db
    deploy:
      restart_policy:
        condition: on-failure
      replicas: 1
      placement:
        constraints:
          - node.hostname==worker2
  cfg1:
    image: registry.docker-cn.com/library/mongo
    command: mongod --configsvr --replSet cfgrs --smallfiles --dbpath /data/db --port 27017
    networks:
      - mongo
    volumes:
      - /etc/localtime:/etc/localtime
      - /root/mongo/config:/data/db
    deploy:
      restart_policy:
        condition: on-failure
      replicas: 1
      placement:
        constraints:
          - node.hostname==manager
  cfg2:
    image: registry.docker-cn.com/library/mongo
    command: mongod --configsvr --replSet cfgrs --smallfiles --dbpath /data/db --port 27017
    networks:
      - mongo
    volumes:
      - /etc/localtime:/etc/localtime
      - /root/mongo/config:/data/db
    deploy:
      restart_policy:
        condition: on-failure
      replicas: 1
      placement:
        constraints:
          - node.hostname==worker1
  cfg3:
    image: registry.docker-cn.com/library/mongo
    command: mongod --configsvr --replSet cfgrs --smallfiles --dbpath /data/db --port 27017
    networks:
      - mongo
    volumes:
      - /etc/localtime:/etc/localtime
      - /root/mongo/config:/data/db
    deploy:
      restart_policy:
        condition: on-failure
      replicas: 1
      placement:
        constraints:
          - node.hostname==worker2
  mongos:
    image: registry.docker-cn.com/library/mongo
    # mongo 3.6 版默认绑定IP为 127.0.0.1,此处绑定 0.0.0.0 是允许其他容器或主机可以访问
    command: mongos --configdb cfgrs/cfg1:27017,cfg2:27017,cfg3:27017 --bind_ip 0.0.0.0 --port 27017
    networks:
      - mongo
    # 映射宿主机的 27017 端口
    ports:
      - 27017:27017
    volumes:
      - /etc/localtime:/etc/localtime
    depends_on:
      - cfg1
      - cfg2
      - cfg3
    deploy:
      restart_policy:
        condition: on-failure
      # 在集群内的每一台服务器上都启动一个容器
      mode: global
networks:
  mongo:
    external: true

2.3、启动服务,在 Manager 上执行

docker stack deploy -c stack.yml mongo

2.4、【Manager】查看服务的启动情况

docker service ls

正常情况下,会出现如下结果:

[docker@manager ~]# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                                         PORTS
z1l5zlghlfbi        mongo_cfg1          replicated          1/1                 registry.docker-cn.com/library/mongo:latest
lg9vbods29th        mongo_cfg2          replicated          1/1                 registry.docker-cn.com/library/mongo:latest
i6d6zwxsq0ss        mongo_cfg3          replicated          1/1                 registry.docker-cn.com/library/mongo:latest
o0lfdavd8kpj        mongo_mongors1n1    replicated          1/1                 registry.docker-cn.com/library/mongo:latest
n85yeyod7mlu        mongo_mongors1n2    replicated          1/1                 registry.docker-cn.com/library/mongo:latest
cwurdqng9tdk        mongo_mongors1n3    replicated          1/1                 registry.docker-cn.com/library/mongo:latest
vu6al5kys28u        mongo_mongors2n1    replicated          1/1                 registry.docker-cn.com/library/mongo:latest
xrjiep0vrf0w        mongo_mongors2n2    replicated          1/1                 registry.docker-cn.com/library/mongo:latest
qqzifwcejjyk        mongo_mongors2n3    replicated          1/1                 registry.docker-cn.com/library/mongo:latest
tddgw8hygv1b        mongo_mongors3n1    replicated          1/1                 registry.docker-cn.com/library/mongo:latest
qrb6fjty03mw        mongo_mongors3n2    replicated          1/1                 registry.docker-cn.com/library/mongo:latest
m8ikdzjssmhn        mongo_mongors3n3    replicated          1/1                 registry.docker-cn.com/library/mongo:latest
mnnlm49b7kyb        mongo_mongos        global              3/3                 registry.docker-cn.com/library/mongo:latest   *:27017->27017/tcp

3、初始化集群

3.1 【Manager】初始化 Mongo 配置集群

docker exec -it $(docker ps | grep "cfg1" | awk '{ print $1 }') bash -c "echo 'rs.initiate({_id: "cfgrs",configsvr: true, members: [{ _id : 0, host : "cfg1" },{ _id : 1, host : "cfg2" }, { _id : 2, host : "cfg3" }]})' | mongo"

3.2 【Manager】初始化三个 Mongo 数据集群

docker exec -it $(docker ps | grep "mongors1n1" | awk '{ print $1 }') bash -c "echo 'rs.initiate({_id : "shard1", members: [{ _id : 0, host : "mongors1n1" },{ _id : 1, host : "mongors1n2" },{ _id : 2, host : "mongors1n3", arbiterOnly: true }]})' | mongo"

docker exec -it $(docker ps | grep "mongors2n1" | awk '{ print $1 }') bash -c "echo 'rs.initiate({_id : "shard2", members: [{ _id : 0, host : "mongors2n1" },{ _id : 1, host : "mongors2n2" },{ _id : 2, host : "mongors2n3", arbiterOnly: true }]})' | mongo"

docker exec -it $(docker ps | grep "mongors3n1" | awk '{ print $1 }') bash -c "echo 'rs.initiate({_id : "shard3", members: [{ _id : 0, host : "mongors3n1" },{ _id : 1, host : "mongors3n2" },{ _id : 2, host : "mongors3n3", arbiterOnly: true }]})' | mongo"

3.3 【Manager】将三个数据集群当做分片加入 mongos

docker exec -it $(docker ps | grep "mongos" | awk '{ print $1 }') bash -c "echo 'sh.addShard("shard1/mongors1n1:27017,mongors1n2:27017,mongors1n3:27017")' | mongo "

docker exec -it $(docker ps | grep "mongos" | awk '{ print $1 }') bash -c "echo 'sh.addShard("shard2/mongors2n1:27017,mongors2n3:27017,mongors2n3:27017")' | mongo "

docker exec -it $(docker ps | grep "mongos" | awk '{ print $1 }') bash -c "echo 'sh.addShard("shard3/mongors3n1:27017,mongors3n2:27017,mongors3n3:27017")' | mongo "

4、连接集群

4.1 内部:在 mongo 网络下的容器,通过 mongos:27017 连接

4.2 外部:通过 IP:27017 连接,IP 可以为三台服务的中的一个的 IP

为Docker Swarm群集配置Nutanix持久存储为Docker Swarm群集配置Nutanix持久存储

本文介绍如何用Docker卷插件的方式,给Docker Swarm的群集挂载Nutanix存储。Nutanix Container Volume Plug-in 简称DVP,可以给容器提供数据持久化的功能。

本文使用ownCloud网盘应用做功能测试。测试的过程如下,安装部署Docker Datacenter,配置好群集,在UCP的界面里调用DVP插件建持久的数据卷,建立ownCloud服务,部署和测试该服务。

Nutanix DVP (Docker Volume Plug-in)安装和配置

这一部分描述DVP的安装部署过程,需要连接互联网;安装调试完毕之后,作虚拟机的镜像模板使用。这样Docker Swarm的其它节点也都不需要重复这个步骤了。

本文使用的是Docker社区文档稳定版 17.03.1-ce ;本文使用的OS是CentOS 7.3。所Docker安装的版本如下:

[root@centos7-temp]# docker version
Client:
 Version:      17.03.1-ce
 API version:  1.27
 Go version:   go1.7.5
 Git commit:   c6d412e
 Built:        Mon Mar 27 17:05:44 2017
 OS/Arch:      linux/amd64

Server:
 Version:      17.03.1-ce
 API version:  1.27 (minimum version 1.12)
 Go version:   go1.7.5
 Git commit:   c6d412e
 Built:        Mon Mar 27 17:05:44 2017
 OS/Arch:      linux/amd64
 Experimental: false

[root@centos7-temp]# rpm -qa|grep docker
docker-ce-17.03.1.ce-1.el7.centos.x86_64
docker-ce-selinux-17.03.1.ce-1.el7.centos.noarch

本文使用的Docker 安装yum源如下:

[root@centos7-temp]# cat /etc/yum.repos.d/docker-ce.repo
[docker-ce-stable]
name=Docker CE Stable - $basearch
baseurl=https://download.docker.com/linux/centos/7/$basearch/stable
enabled=1
gpgcheck=1
gpgkey=https://download.docker.com/linux/centos/gpg

[docker-ce-stable-debuginfo]
name=Docker CE Stable - Debuginfo $basearch
baseurl=https://download.docker.com/linux/centos/7/debug-$basearch/stable
enabled=0
gpgcheck=1
gpgkey=https://download.docker.com/linux/centos/gpg

[docker-ce-stable-source]
name=Docker CE Stable - Sources
baseurl=https://download.docker.com/linux/centos/7/source/stable
enabled=0
gpgcheck=1
gpgkey=https://download.docker.com/linux/centos/gpg

[docker-ce-edge]
name=Docker CE Edge - $basearch
baseurl=https://download.docker.com/linux/centos/7/$basearch/edge
enabled=0
gpgcheck=1
gpgkey=https://download.docker.com/linux/centos/gpg

[docker-ce-edge-debuginfo]
name=Docker CE Edge - Debuginfo $basearch
baseurl=https://download.docker.com/linux/centos/7/debug-$basearch/edge
enabled=0
gpgcheck=1
gpgkey=https://download.docker.com/linux/centos/gpg

[docker-ce-edge-source]
name=Docker CE Edge - Sources
baseurl=https://download.docker.com/linux/centos/7/source/edge
enabled=0
gpgcheck=1
gpgkey=https://download.docker.com/linux/centos/gpg

[docker-ce-test]
name=Docker CE Test - $basearch
baseurl=https://download.docker.com/linux/centos/7/$basearch/test
enabled=0
gpgcheck=1
gpgkey=https://download.docker.com/linux/centos/gpg

[docker-ce-test-debuginfo]
name=Docker CE Test - Debuginfo $basearch
baseurl=https://download.docker.com/linux/centos/7/debug-$basearch/test
enabled=0
gpgcheck=1
gpgkey=https://download.docker.com/linux/centos/gpg

[docker-ce-test-source]
name=Docker CE Test - Sources
baseurl=https://download.docker.com/linux/centos/7/source/test
enabled=0
gpgcheck=1
gpgkey=https://download.docker.com/linux/centos/gpg

本机所使用的所有安装源如下:

[root@centos7-temp]# yum repolist
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * epel: mirrors.aliyun.com
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
repo id                                   repo name                                                         status
base/7/x86_64                             CentOS-7 - Base - mirrors.aliyun.com                               9,363
docker-ce-stable/x86_64                   Docker CE Stable - x86_64                                              4
epel/x86_64                               Extra Packages for Enterprise Linux 7 - x86_64                    11,808
extras/7/x86_64                           CentOS-7 - Extras - mirrors.aliyun.com                               381
updates/7/x86_64                          CentOS-7 - Updates - mirrors.aliyun.com                            1,859
repolist: 23,415

安装docker引擎,并启动服务,并校验服务状态。安装过程参考如下:

[root@centos7-temp]# yum install -y docker-ce
[root@centos7-temp]# systemctl enable docker
[root@centos7-temp]# systemctl start docker
[root@centos7-temp]# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2017-06-20 20:30:49 CST; 19min ago
     Docs: https://docs.docker.com
 Main PID: 875 (dockerd)
   CGroup: /system.slice/docker.service
           ├─ 875 /usr/bin/dockerd
           ├─ 942 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-in...
           ├─2008 docker-containerd-shim 0ca2346b6126de702fb4dda5f807c0a69a402eb643f15c142730277d0eb7bbcb /var/...
           └─0ca2346b6126de702fb4dda5f807c0a69a402eb643f15c142730277d0eb7bbcb
             └─2038 /usr/bin/python /code/main.py --prism-ip 10.68.69.22 --dataservices-ip 10.68.69.23 --prism-...

到目前为止,Docker安装配置完成。

下面开始安装DVP,安装和配置过程参考页面。

https://store.docker.com/plugins/nutanix-dvp-docker-volume-plug-in

下面是给操作系统安装iscsi initiator服务的参考步骤:

yum install -y iscsi-initiator-utils 
systemd-tmpfiles --create
systemctl start iscsid
systemctl enable iscsid
systemctl status iscsid
● iscsid.service - Open-iSCSI
   Loaded: loaded (/usr/lib/systemd/system/iscsid.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2017-06-20 20:30:46 CST; 24min ago
     Docs: man:iscsid(8)
           man:iscsiadm(8)
 Main PID: 888 (iscsid)
   CGroup: /system.slice/iscsid.service
           ├─882 /usr/sbin/iscsid
           └─888 /usr/sbin/iscsid

Jun 20 20:30:46 centos7-temp.zenlab.local systemd[1]: Starting Open-iSCSI...
Jun 20 20:30:46 centos7-temp.zenlab.local iscsid[878]: iSCSI logger with pid=882 started!
Jun 20 20:30:46 centos7-temp.zenlab.local systemd[1]: Failed to read PID from file /var/run/iscsid.pid: Inva...ent
Jun 20 20:30:46 centos7-temp.zenlab.local systemd[1]: Started Open-iSCSI.
Jun 20 20:30:47 centos7-temp.zenlab.local iscsid[882]: iSCSI daemon with pid=888 started!
Hint: Some lines were ellipsized, use -l to show in full.

解释一下DVP的工作原理是,它是让Docker主机通过iSCSI协议连接Nutanix的存储服务。DVP插件的配置里包含了连接存储服务和存储容器(这个容器是Nutanix的存储术语,非Docker说的容器)的相关信息。这样Docker主机上用该卷插件建立的数据卷都会指向Nutanix后台的存储容器中;数据通过iSCSI协议连接Nutanix存储服务的时候,就可以利用到Nutanix群集提供的负载均衡能力;当数据块写入Nutanix存储池的过程中和之后,就可以利用到到Nutanix存储容器所具备的其它重要特性:数据块2~3副本的高可靠性、冷热数据分成、压缩、去重、纠删码等;而且存储空间对于容器或者Docker Swarm里的服务都是透明和无限容量的。

现在做一些安装DVP的准备工作,询问Nutanix系统管理员下面信息:

  • 获得Prism 的IP
  • 获得Nutanix群集数据服务的IP,这个IP是群集上的虚拟服务IP
  • 获得群集的用户名和密码
  • 新建一个测试存储容器,获得容器名

参考下面的DVP安装命令:

docker plugin install ntnx/nutanix_volume_plugin PRISM_IP="10.68.69.22" DATASERVICES_IP="10.68.69.23" PRISM_PASSWORD="nutanix/4u" PRISM_USERNAME="admin" DEFAULT_CONTAINER="ddc-sc1" --alias nutanix

以上的命令执行结果如下:

[root@centos7-temp]# docker plugin install ntnx/nutanix_volume_plugin PRISM_IP="10.68.69.22" DATASERVICES_IP="10.68.69.23" PRISM_PASSWORD="nutanix/4u" PRISM_USERNAME="admin" DEFAULT_CONTAINER="ddc-sc1" --alias nutanix
Plugin "ntnx/nutanix_volume_plugin" is requesting the following privileges:
 - network: [host]
 - mount: [/dev]
 - mount: [/lib/modules]
 - mount: [/etc/iscsi]
 - mount: [/var/lock/iscsi]
 - mount: [/proc]
 - allow-all-devices: [true]
 - capabilities: [CAP_SYS_ADMIN CAP_SYS_PTRACE CAP_IPC_LOCK CAP_IPC_OWNER CAP_NET_ADMIN CAP_MKNOD CAP_SYS_MODULE]
Do you grant the above permissions? [y/N] y (输入y,按回车)
latest: Pulling from ntnx/nutanix_volume_plugin
be892c8cb64d: Download complete
Digest: sha256:5a3730ffae077eb6ddc0c125620283d56852528b686cbe42f2f58696eab82c0d
Status: Downloaded newer image for ntnx/nutanix_volume_plugin:latest
Installed plugin ntnx/nutanix_volume_plugin

确认VDP安装结果,这个插件应该是最新版、启动的状态,如下:

[root@centos7-temp]# docker plugin ls
ID                  NAME                DESCRIPTION                        ENABLED
f0e38fbc11b3        nutanix:latest      Nutanix volume plugin for docker   true

执行下面的测试,确认DVP工作正常。

[root@centos7-temp]# docker volume create testvol -d nutanix:latest
testvol
[root@centos7-temp]# docker volume ls
DRIVER              VOLUME NAME
nutanix:latest      testvol
[root@centos7-temp]#

回到Nutanix的Prisum界面(主要的群集管理图形化界面)中查看Storage –> table –> Volume Group,应该能看到这个命令所创建的名为testvol的数据卷。如下图所示:

未分类

在命令行删除这个测试的卷。

[root@centos7-temp]# docker volume rm testvol
testvol
[root@centos7-temp]# docker volume ls
DRIVER              VOLUME NAME
[root@centos7-temp]#

在回到Prisum界面中查看刚才看到的那个卷应该就消失了。到此为止所有节点的DVP部署配置工作就完毕了,并且确认docker服务和DVP功能都很正常。用 sys-unconfig 命令关机,把这个虚拟机在Prisum里面做一个快照备用,也可以在Nutanix的acli命令行里面把它做成一个基础镜像。

我们已经理解和熟悉了DVP的基本操作,配置和部署,下面开始安装Docker Datacenter;Docker Datacenter的架构图如下所示:

未分类

本文安装的架构是:

  • 一个 UCP manager 节点
  • 一个 DTR 节点
  • 两个 worker node 节点

在Nutanix的Prisum中用刚才制作的那个快照或者镜像模板,克隆/新建4个虚拟机。虚拟机的参考配置如下:

  • 2 vCPU
  • 4GB RAM
  • 50GB Disk

安装UCP(Docker Universal Control Plane)节点

在Nutanix的Prisum中从刚才新建的四个虚拟机中选择一个,Power on开机;ssh登录到操作系统内之后,设定主机名和IP地址。

安装配置参考文档:https://docs.docker.com/datacenter/ucp/2.1/guides/admin/install/install-offline/#download-the-offline-package

注意事项,提前下载好安装包,这个tar包里面包含了UCP需要的所有镜像,可以一次性导入到UCP的节点上。

wget https://packages.docker.com/caas/ucp_images_2.1.4.tar.gz -O docker-datacenter.tar.gz

docker load < docker-datacenter.tar.gz

载入完毕后,可以看到如下镜像。

[root@ucp-master ~]# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
docker/ucp-metrics      2.1.4               e3e24ef156bd        3 weeks ago         92.2 MB
docker/ucp-swarm        2.1.4               d8b51d6801e5        3 weeks ago         21 MB
docker/ucp-hrm          2.1.4               38a19323327d        3 weeks ago         14.8 MB
docker/ucp-etcd         2.1.4               9aa382502e19        3 weeks ago         38.5 MB
docker/ucp-controller   2.1.4               5a852aa3039e        3 weeks ago         28 MB
docker/ucp-dsinfo       2.1.4               66ee9368796a        3 weeks ago         159 MB
docker/ucp              2.1.4               7a28dbfc44e4        3 weeks ago         19.1 MB
docker/ucp              latest              7a28dbfc44e4        3 weeks ago         19.1 MB
docker/ucp-cfssl        2.1.4               acdc1f147711        3 weeks ago         15.1 MB
docker/ucp-compose      2.1.4               25775e989077        3 weeks ago         32.9 MB
docker/ucp-auth-store   2.1.4               f27ad13dee6c        3 weeks ago         58.7 MB
docker/ucp-agent        2.1.4               d716a096c331        3 weeks ago         22.5 MB
docker/ucp-auth         2.1.4               1f4739cd3c08        3 weeks ago         25.1 MB
[root@ucp-master ~]#

安装UCP的命令参考如下:

docker run --rm -it --name ucp 
  -v /var/run/docker.sock:/var/run/docker.sock 
  docker/ucp:2.1.4 install 
  --host-address 10.68.69.12 
  --interactive

以上命令中10.68.69.12是UCP主机的ip地址,建议UCP使用固定IP。以上命令完毕后用浏览器访问这个IP。

参考以下文档,完成UCP的安装步骤,其中需要到Docker网站获得30天的试用版许可证文件。

https://docs.docker.com/datacenter/ucp/2.1/guides/admin/install/

能够正常登陆访问UCP之后,在首页下方点击 【Add Node】按钮,获得加其它节点到群集里的命令,参考命令如下:

docker swarm join 
  --token SWMTKN-1-1310ah7gzj9e7bk6a5yobo2qyiwf93ybrd29flkved1zqydd6i-7pir0884sag5pjofwzjq5o1um 
  10.68.69.12:2377

把以上命令记录在写字板中备用。

加3个节点到群集里

把剩下的三个虚拟机开机,进入操作系统后设定主机名和IP。其中的一个安装DTR(Docker镜像仓库)的节点建议使用固定IP。

在每个操作系统里面用docker命令确认DVP是否正常。

  • docker plugin ls
  • docker volume ls
  • systemctl status iscsid

下面就可以把上一步所记录命令在命令行里面执行以下,完毕之后回到UCP的界面中查看是否它们已经添加成功。如下图所示:

未分类

安装DTR-Docker镜像仓库

在UCP首页的下方,找到并点击 【Install DTR】的按钮,取得安装命令(记得从清单中选择固定IP地址的DTR主机);在登录DTR主机的控制台里面输入这个命令,命令如下:

docker run -it --rm 
  docker/dtr:2.2.5 install 
  --ucp-node 10.68.69.12 
  --ucp-insecure-tls

DTR节点没有离线安装的整合包,它需要联网下载很多相关镜像,如果网络速度不是很快的话,下载和安装的过程需要至少半个小时,过程中还需要输入UCP的管理员,用户名和密码。

参考文档如: https://docs.docker.com/datacenter/dtr/2.2/guides/admin/install/#step-3-install-dtr

DTR正常工作了以后,登录建立一个名为owncloud的镜像库,点击【New Rrepository】输入owncloud。 在一个节点上下载owncloud镜像,添加新的tag,上传到这个镜像到镜像库里备用。参考命令如下:

docker login dtr.zenlab.local
docker pull owncloud
docker tag owncloud:latest dtr.zenlab.local/admin/owncloud:latest
docker push dtr.zenlab.local/admin/owncloud:latest
Screen Shot 2017-06-20 at 10.10.13 P

未分类

注意:如果你的环境中没有DNS,就把dtr.zenlab.local换成DTR的IP地址。

以上这个步骤主要是方便以后,反复使用和测试这个镜像的可能性,如果所有的节点都有高速的互联网链接,可以忽略以上步骤。

Docker Swarm群集中使用DVP

这里使用UCP的图形化界面,在一个所有节点都配置和部署了VDP的群集上,给群集挂载外部Nutanix的数据卷。

登录UCP主页,点击Resource,点击Volumes,点击 【Create Volume】,输入相关参数,如下图所示。图中的sizeMb=500000这个参数是制定VolumeGroup的大小,不设定这个参数的话,默认是10GB。

未分类

在到Nutanix的Prism里面查看这个Volume Group是否存在。应该如下图所示:

未分类

部署OwnCloud网盘服务

登录UCP主页,点击 Service , 点击 【Create a Service】按钮;开始建立这个服务。输入服务名,镜像名;点击 【Next】按钮。

未分类

点击 【Next】按钮。进入 Resource页面,这里需要配置端口和数据卷。

未分类

未分类

最后点击【Deploy Now】按钮。 部署完毕之后,显示这个服务的状态为正常。

未分类

未分类

点击这个服务,到这个页面的最下方,找到右下角的发布端口的链接,点击后,就可以看到ownCloud的初始化配置页面了。

未分类

输入管理员的用户名和密码,进入之后,上传一些图片,测试一下功能是否正常。

未分类

尝试一些Docker Datacenter的高级功能,如服务的高可用性;同时Nutanix的DVP在底层保障了数据的持久性和完全性。测试步骤如下:

  • 找到运行owncloud的容器,删除这个容器
  • 在服务页面查看owncloud服务的状态变化
  • 等ownCloud的状态恢复正常之后
  • 再次登录ownCloud页面
  • 查看和确认刚才上传的文件是否还在

总结

Nutanix是一种融合和了计算、存储和虚拟化(内置KVM)的超融合平台。Nutanix DVP (Docker Volume Plug-in)可以让平台里的容器用上持久化存储服务。DVP不仅可以给单独虚拟机里的容器提供持久卷服务,还能给类似于Docker Swarm的其它容器编排平台提供持久化数据服务功能。我后续的文章还会分享路测试Kubernetes等其它平台。

管理swarm(20) – 管理和维护swarm

当你运行Docker Engines swarm,管理节点是管理swarm和存储swarm状态的关键组件。为了正确地部署和维护swarm,理解管理节点一些关键的功能很重要。

swarm的管理节点

swarm管理节点使用Raft一致性算法来管理swarm的状态。你只需要理解Raft的一些常见概念以便来更好的管理swarm。
对管理节点的数量没有限制。关于要实现多少个管理器节点的决定是性能和容错之间的折衷。增加更多管理节点到swarm使得swarm有更好的容灾能力。不过额外的管理节点会降低写入性能,因为更多的节点必须确认更新swarm状态的提议。意味着产生更多的流量,花更多的时间。
Raft要求大多数管理者(也称为法定人数)同意对swarm的建议更新。 法定人数的管理人员还必须同意节点添加和删除。 成员资格操作受到与状态复制相同的约束。

使用一个advertise静态IP地址

当启动一个swarm时,你必须指定–advertise-addr一个IP地址来通告swarm中的其它管理节点。因为管理节点是一个相对稳定的组件,你应该使用一个固定的IP地址来避免机器重启时IP变更其它管理节点无法连接。
如果整个swarm重启,随便每个管理节点都获取到一个新的IP地址,那么任何的节点都没有办法连接到一个已存在的管理节点。worker节点就可以使用动态IP地址。

添加管理节点来容错

你应该维护奇数个swarm管理节点以支持管理节点故障而不影响swarm运行。奇数的管理节点数量确保了在网络故障分裂为两部分时,有很大可能管理节点的数量仍然为法定数量(即数量超过一半)来选举出新的leader节点。如果遇到网络分裂超过三部分,那就不能保证有法定数量的管理节点了。
例如,在一个有5个管理节点的swarm中,如果你失去了3个节点,余下的2个节点没有超过一半,达不到法定数量,无法选举出新的leader节点。因此在你恢复不可用的管理节点或使用灾难恢复命令恢复swarm前,你不能添加或删除节点。
虽然可以将一个swarm缩放为单个管理器节点,但不可能降级最后一个管理器节点。这可以确保你能访问swarm,并且swarm仍然能处理请求。缩放为单个管理节点是一个不安全的操作且不建议。如果你最后一个节点在降级操作期间突然变得不可用,在你重启节点或使用–force-new-cluster重启前,swarm将变得不可用。

分布管理节点到多个区域

除了维护奇数个管理节点,在部署管理节点时注意数据中心拓扑。为了实现最佳容错性,将管理节点分布在至少3个可用性区域中,以支持整个机房或常见维护情况的故障。如果任意一个区域发生故障,swarm管理节点的数量仍然会超过一半来选举出leader节点。
下面的图表说明在三个可用区域中部署管理节点的数量。
虚拟化技术

运行仅负责管理的节点

默认下管理节点也作为worker节点。意味着调度器可以分配任务给管理节点。对于小的和非关键的swarm,只要你使用cpu和内存的资源约束来调度服务,则向管理节点分配任务的风险相对较低。
然而因为管理节点使用Raft一致性算法以一致的方式复制数据,它们对资源匮乏较敏感。你应该设置管理节点不接受任务以避免影响swarm心跳或leader选举。
为了避免影响管理节点的相关管理操作,你可以设置管理节点为drain状态不再继续作为worker节点。

  1. docker node update –availability drain <NODE>

当你drain一个节点,调度器会重新分配这个节点上运行的任务到其它可用节点。也会阻止调度器分配新的任务到这个节点。

备份swarm状态

Docker管理节点存储swarm状态和日志在以下目录:

  1. /var/lib/docker/swarm/raft

经常的备份raft数据目录以便你能灾难恢复swarm。

监控swarm状态

你可以通过/nodes HTTP endpoint以JSON格式查询docker nodes API来监视管理节点的运行状况。
也可以在命令行执行docker node inspect 来查询节点。
例如,查询管理节点的reachability:

  1. docker node inspect manager1 –format "{{ .ManagerStatus.Reachability }}"
  2. reachable

查询worker节点的接受任务的状态:

  1. docker node inspect manager1 –format "{{ .Status.State }}"
  2. ready

从这些命令的输出来看,我们可以知道manager1作为管理节点时状态为reachable,作为worker节点时为ready。
unreachable状态意味着从其它管理节点无法访问这个管理节点。这种情况你需要马上恢复这个不可用的管理节点:

  • 重启docker进程来看管理节点是否会恢复为reachable
  • 重启机器
  • 如果以上都没有用,你应该添加一个管理节点或升级一个worker节点为管理节点。你也需要使用docker node demote 和docker node rm 来清除失效的管理节点。
  • 或者你可以在管理节点上执行docker node ls来查看所有节点的运行情况:

    1. docker node ls
    2. ID                           HOSTNAME  MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS
    3. 1mhtdwhvsgr3c26xxbnzdc3yp    node05    Accepted    Ready   Active
    4. 516pacagkqp2xc3fk9t1dhjor    node02    Accepted    Ready   Active        Reachable
    5. 9ifojw8of78kkusuc4a6c23fx *  node01    Accepted    Ready   Active        Leader
    6. ax11wdpwrrb6db3mfjydscgk7    node04    Accepted    Ready   Active
    7. bb1nrq2cswhtbg4mrsqnlx1ck    node03    Accepted    Ready   Active        Reachable
    8. di9wxgz8dtuh9d2hn089ecqkf    node06    Accepted    Ready   Active

    强制删除一个节点

    在大多数情况下在你要使用docker node rm命令来删除一个节点时应该先关闭这个节点。如果某个节点变得不可达,无响应或受损,你可以通过传递–force标志强制删除该节点,而不关闭它。例如如果node9受损:

    1. $ docker node rm node9
    2.  
    3. Error response from daemon: rpc error: code = 9 desc = node node9 is not down and can’t be removed
    4.  
    5. $ docker node rm –force node9
    6.  
    7. Node node9 removed from swarm

    在你强制删除一个管理节点之前,你必须先降级它为worker节点。如果你降级或删除一个管理节点,必须始终确保管理节点数量为奇数。

    灾难恢复

    Swarm对故障适应能力强,并且可以从任何数量的临时节点故障(机器重新启动或与崩溃时重新启动)恢复。
    在N个管理节点的swarm中,为了使swarm处理请求并保持可用,必须有大于管理节点总数的50%(或(N / 2)+1)的管理节点的法定数量。 这意味着swarm可以容忍多达(N-1)/ 2个永久故障,超过这些永久故障,无法处理涉及swarm管理的请求。 这些类型的故障包括数据损坏或硬件故障。
    即使你遵循此处的指南,也可能会丢失一个仲裁节点。 如果无法通过常规方法(如重新启动故障节点)恢复仲裁,则可以通过在管理节点上运行docker swarm init –force-new-cluster来恢复该swarm。

    1. # From the node to recover
    2. docker swarm init –force-new-cluster –advertise-addr node01:2377

    –force-new-cluster参数设置为单管理节点的swarm。 它丢弃失去法定数量的管理节点之前存在的成员信息,但它保留Swarm所需的数据,例如服务,任务和worker节点的列表。

    强制重新平衡swarm

    一般情况下,你不需要强制平衡swarm的任务。当你添加一个新节点到swarm或者节点不可用一段时间后重新连接,swarm不会自动重新将运行在其它节点的任务分配到这个空闲节点。swarm是这样设计的。如果为了平衡,swarm周期性的迁移任务到不同的节点,使用这些任务的用户会被中断。如果启动一个新任务或者一个运行的节点变为不可用,它们的任务会分配到不太繁忙的节点。目标是保证对用户影响最小来达到重新平衡。
    如果你不在意中断运行的服务来强制平衡swarm任务,你可以临时的增大服务的规模。
    使用docker service inspect –pretty 来查看服务的规模。使用docker service scale时,调度器会把任务优先分配到最低任务数的节点。 你的swarm中可能有多个负载不足的节点。 你可能需要多次增大服务的规模,以实现所有节点上所需的平衡。
    如果平衡满足你的要求,你可以恢复服务到原来的规模数。可以使用docker service ps命令来评估跨节点的服务的当前平衡。

    管理swarm(19) – 将服务附加到覆盖网络

    Docker Engine的swarm模式原生支持覆盖网络(overlay networks),所以你可以启用容器到容器的网络。swarm模式的覆盖网络包括以下功能:

  • 你可以附加多个服务到同一个网络
  • 默认情况下,service discovery为每个swarm服务分配一个虚拟IP地址(vip)和DNS名称,使得在同一个网络中容器之间可以使用服务名称为互相连接。
  • 你可以配置使用DNS轮循而不使用VIP
  • 为了可以使用swarm的覆盖网络,在启用swarm模式之间你需要在swarm节点之间开放以下端口:

  • TCP/UDP端口7946 – 用于容器网络发现
  • UDP端口4789 – 用于容器覆盖网络
  • 在swarm中创建一个覆盖网络

    当你运行Docker Engine的swarm模式时,你可以在管理节点执行docker network create命令来创建一个覆盖网络。例如,创建一个名为my-network的网络:

    1. $ docker network create
    2.   –driver overlay
    3.   –subnet 10.0.9.0/24
    4.   –opt encrypted
    5.   my-network
    6.  
    7. 273d53261bcdfda5f198587974dae3827e947ccd7e74a41bf1f482ad17fa0d33

    默认情况下swarm中的节点通信是加密的。在不同节点的容器之间,可选的–opt encrypted参数能在它们的vxlan流量启用附加的加密层。
    –subnet参数指定覆盖网络的子网。当你不指定一个子网时,swarm管理器自动选择一个子网并分配给网络。在一些旧的内核,包括kernel 3.10,自动分配的地址可能会与其它子网重叠。这样的重叠可能引起连接问题。
    执行docker network ls来查看网络:

    1. $ docker network ls
    2.  
    3. NETWORK ID          NAME        DRIVER   SCOPE
    4. f9145f09b38b        bridge      bridge   local
    5. ..snip..
    6. 273d53261bcd        my-network  overlay  swarm

    swarm scope表示部署到swarm的服务可以使用这个网络。当你创建一个服务并附加到一个网络后,swarm仅仅扩展该网络到服务运行的节点上。在一个没有运行有附加到网络的服务worker节点上,network ls命令不会显示有任何网络。

    附加服务到覆盖网络

    要附加一个服务到一个覆盖网络,在创建服务的时候传递–network参数。例如创建一个nginx服务并附加到一个名为my-network的网络:

    1. $ docker service create
    2.   –replicas 3
    3.   –name my-web
    4.   –network my-network
    5.   nginx

    注意:在附加服务到网络前,必须先创建这个网络。

    在同一个覆盖网络的容器之间能互相连接。在管理节点执行docker service ps 来查看哪些节点运行着这个服务:

    1. $ docker service ps my-web
    2.  
    3. ID                         NAME      IMAGE  NODE   DESIRED STATE  CURRENT STATE               ERROR
    4. 63s86gf6a0ms34mvboniev7bs  my-web.1  nginx  node1  Running        Running 58 seconds ago
    5. 6b3q2qbjveo4zauc6xig7au10  my-web.2  nginx  node2  Running        Running 58 seconds ago
    6. 66u2hcrz0miqpc8h0y0f3v7aw  my-web.3  nginx  node3  Running        Running about a minute ago

    pic1
    你可以在运行着附加有网络的服务的节点上查看这个网络的详情:

    1. $ docker network inspect <NETWORK>

    这个网络信息包括了该节点上附加到该网络的容器的列表。例如:

    1. $ docker network inspect my-network
    2. [
    3.     {
    4.         "Name": "my-network",
    5.         "Id": "273d53261bcdfda5f198587974dae3827e947ccd7e74a41bf1f482ad17fa0d33",
    6.         "Scope": "swarm",
    7.         "Driver": "overlay",
    8.         "EnableIPv6": false,
    9.         "IPAM": {
    10.             "Driver": "default",
    11.             "Options": null,
    12.             "Config": [
    13.                 {
    14.                     "Subnet": "10.0.9.0/24",
    15.                     "Gateway": "10.0.9.1"
    16.                 }
    17.             ]
    18.         },
    19.         "Internal": false,
    20.         "Containers": {
    21.             "404d1dec939a021678132a35259c3604b9657649437e59060621a17edae7a819": {
    22.                 "Name": "my-web.1.63s86gf6a0ms34mvboniev7bs",
    23.                 "EndpointID": "3c9588d04db9bc2bf8749cb079689a3072c44c68e544944cbea8e4bc20eb7de7",
    24.                 "MacAddress": "02:42:0a:00:09:03",
    25.                 "IPv4Address": "10.0.9.3/24",
    26.                 "IPv6Address": ""
    27.             }
    28.         },
    29.         "Options": {
    30.             "com.docker.network.driver.overlay.vxlanid_list": "257"
    31.         },
    32.         "Labels": {}
    33.     }
    34. ]

    在上面的示例中,my-web服务的容器my-web.1.63s86gf6a0ms34mvboniev7bs附加到该节点的my-network网络。

    使用swarm模式的service discovery

    默认情况下,当你创建一个服务并附加到一个网络时,swarm就给服务分配一个VIP。VIP根据服务名称映射到DNS别名。在该网络的容器之间通过gossip来共享DNS映射信息,所以在该网络的容器能通过服务名称来访问彼此。
    你不需要公开特定于服务的端口,以使服务可用于同一覆盖网络上的其他服务。 swarm的内部负载均衡会自动将请求分发到服务VIP。
    你可以使用如下命令来查看服务的VIP:

    1. $ docker service inspect
    2.   –format='{{json .Endpoint.VirtualIPs}}’
    3.   my-web
    4.  
    5. [{"NetworkID":"7m2rjx0a97n88wzr4nu8772r3" "Addr":"10.0.0.2/24"}]

    下面的示例展示如何添加一个busybox服务到与nginx服务相同的网络,以及busybox服务使用DNS名称my-web访问nginx服务:
    1.在管理节点,部署busybox服务到与my-web同一个网络:

    1. $ docker service create
    2.   –name my-busybox
    3.   –network my-network
    4.   busybox
    5.   sleep 3000

    2.查看哪个节点运行着my-busybox服务:

    1. $ docker service ps my-busybox
    2.  
    3. ID                         NAME          IMAGE    NODE   DESIRED STATE  CURRENT STATE          ERROR
    4. 1dok2cmx2mln5hbqve8ilnair  my-busybox.1  busybox  node1  Running        Running 5 seconds ago

    3.登录上一步查询到的node1节点,在busybox容器中打开一个可交互的shell:

    1. $ docker exec -it my-busybox.1.1dok2cmx2mln5hbqve8ilnair /bin/sh

    你可以将容器名称推断为 + 。 或者,你可以在运行任务的节点上运行docker ps。
    4.在busybox容器内部,查询my-web服务的VIP:

    1. $ nslookup my-web
    2.  
    3. Server:    127.0.0.11
    4. Address 1: 127.0.0.11
    5.  
    6. Name:      my-web
    7. Address 1: 10.0.9.2 ip-10-0-9-2.us-west-2.compute.internal

    5.在busybox容器内部,查询的DNS记录来找出my-web服务的所有容器IP地址:

    1. $ nslookup tasks.my-web
    2.  
    3. Server:    127.0.0.11
    4. Address 1: 127.0.0.11
    5.  
    6. Name:      tasks.my-web
    7. Address 1: 10.0.9.4 my-web.2.6b3q2qbjveo4zauc6xig7au10.my-network
    8. Address 2: 10.0.9.3 my-web.1.63s86gf6a0ms34mvboniev7bs.my-network
    9. Address 3: 10.0.9.5 my-web.3.66u2hcrz0miqpc8h0y0f3v7aw.my-network

    6.在busybox容器内,执行wget来访问my-web服务的nginx web server:

    1. $ wget -O- my-web
    2.  
    3. Connecting to my-web (10.0.9.2:80)
    4. <!DOCTYPE html>
    5. <html>
    6. <head>
    7. <title>Welcome to nginx!</title>
    8. …snip…

    通过访问服务的VIP,swarm负载均衡自动将HTTP请求路由可用的容器中。 它使用轮循的方式来平均地分发请求。

    使用DNS轮循请求

    你可以配置服务直接使用DNS轮循而不用VIP,在创建服务的时候设置–endpoint-mode dnsrr。在你要使用你自己的负载均衡器时可能会用此方法。
    下面的示例展示一个服务使用dnsrr endpoint模式:

    1. $ docker service create
    2.   –replicas 3
    3.   –name my-dnsrr-service
    4.   –network my-network
    5.   –endpoint-mode dnsrr
    6.   nginx

    当你查询服务名称的DNS记录时,DNS服务会返回所有该服务容器的IP地址:

    1. $ nslookup my-dnsrr-service
    2. Server:    127.0.0.11
    3. Address 1: 127.0.0.11
    4.  
    5. Name:      my-dnsrr
    6. Address 1: 10.0.9.8 my-dnsrr-service.1.bd3a67p61by5dfdkyk7kog7pr.my-network
    7. Address 2: 10.0.9.10 my-dnsrr-service.3.0sb1jxr99bywbvzac8xyw73b1.my-network
    8. Address 3: 10.0.9.9 my-dnsrr-service.2.am6fx47p3bropyy2dy4f8hofb.my-network

    管理swarm(18) – 部署服务

    创建服务

    简单地在swarm中创建一个服务,你仅需要提供一个镜像名称:

    1. $ docker service create <IMAGE>

    这时协调器开始调度任务给一个可用节点。任务基于你给的镜像来运行一个容器。例如,你可以执行如下命令来创建一个nginx web服务器的实例服务:

    1. $ docker service create –name my_web nginx
    2.  
    3. anixjtol6wdfn6yylbkrbj2nx

    在这个示例中–name参数命名服务为my_web。
    在管理节点上执行docker service ls来列出服务:

    1. $ docker service ls
    2.  
    3. ID            NAME    REPLICAS  IMAGE  COMMAND
    4. anixjtol6wdf  my_web  1/1       nginx

    要让web服务器在swarm外部可用,你需要发布一个swarm监听web请求的端口。
    你可以在指定镜像后添加一个命令来运行在容器内部:

    1. $ docker service create <IMAGE> <COMMAND>

    例如启动一个alpine镜像来执行ping docker.com:

    1. $ docker service create –name helloworld alpine ping docker.com
    2.  
    3. 9uk4639qpg7npwf3fn2aasksr

    配置运行环境

    你可以使用如下选项来配置容器的运行环境:

  • 使用–env参数配置环境变量
  • 使用–workdir参数配置容器工作目录
  • 使用–user参数配置程序运行使用的用户或ID
  • 例如:

    1. $ docker service create –name helloworld
    2.   –env MYVAR=myvalue
    3.   –workdir /tmp
    4.   –user my_user
    5.   alpine ping docker.com
    6.  
    7. 9uk4639qpg7npwf3fn2aasksr

    控制服务规模和布局

    swarm模式有两种类型的服务,副本(replicated)和全局(global)。对于副本服务,你可以指定任务副本的数量。对于全局服务,调度器将在每个可用节点都执行一个相同的任务。
    你可以使用–mode参数来设置服务类型。如果不指定,默认服务类型为副本。对于副本服务,你可以使用–replicas参数为设置副本数量。例如,启动一个副本数为3的nginx服务:

    1. $ docker service create –name my_web –replicas 3 nginx

    要启动一个全局服务,在创建服务执行docker service create时传递–mode global参数。当任何时候一个新的节点可用,调度器会调度全局服务的任务到该新节点。例如在每个节点上执行alpine服务:

    1. $ docker service create –name myservice –mode global alpine top

    控制服务规模和布局

    swarm模式中有两种可以访问服务的方法:

  • 使用ingress网络来发布端口到swarm外部
  • 在swarm的覆盖网络内部连接服务和任务
  • 发布端口到swarm外部网络

    你可以使用–publish:参数来发布服务端口到swarm外部网络。发布服务端口时,无论该节点上是否有任务运行,swarm都会使服务在每个节点的目标端口上可访问。
    例如,假设你想部署一个3个副本的nginx服务到一个10个节点的swarm:

    1. docker service create –name my_web –replicas 3 –publish 8080:80 nginx

    调度器会把nginx任务分配到三个可用节点。不过swarm会设置10个节点都监听8080端口,访问此端口时会把请求转发到nginx容器的80端口。你可以使用curl在任意的节点上测试服务:

    1. $ curl localhost:8080
    2.  
    3. <!DOCTYPE html>
    4. <html>
    5. <head>
    6. <title>Welcome to nginx!</title>
    7. <style>
    8.     body {
    9.         width: 35em;
    10.         margin: 0 auto;
    11.         font-family: Tahoma, Verdana, Arial, sans-serif;
    12.     }
    13. </style>
    14. </head>
    15. <body>
    16. <h1>Welcome to nginx!</h1>
    17. <p>If you see this page, the nginx web server is successfully installed and
    18. working. Further configuration is required.</p>
    19.  
    20. <p>For online documentation and support please refer to
    21. <a href="http://nginx.org/">nginx.org</a>.<br/>
    22. Commercial support is available at
    23. <a href="http://nginx.com/">nginx.com</a>.</p>
    24.  
    25. <p><em>Thank you for using nginx.</em></p>
    26. </body>
    27. </html>

    添加一个覆盖网络

    使用覆盖网络可以在swarm内连接一个或多个服务。
    首先在管理节点执行docker network create来创建一个覆盖网络:

    1. $ docker network create –driver overlay my-network
    2.  
    3. etjpu59cykrptrgw0z0hk5snf

    当你在swarm模式创建一个覆盖网络后,所有的管理节点都可以访问这个网络。
    可以在创建服务时传递–network参数过去指定服务加入的覆盖网络:

    1. $ docker service create
    2.   –replicas 3
    3.   –network my-network
    4.   –name my-web
    5.   nginx
    6.  
    7. 716thylsndqma81j6kkkb5aus

    配置更新策略

    你可以在创建服务或更新服务时指定swarm应用服务更新的策略。
    –update-delay标志配置更新到服务任务或任务集之间的时间延迟。 你可以将时间T描述为秒数Ts,分钟Tm或小时Th的组合。 所以10m30s表示10分30秒的延迟。
    默认情况下,调度器一次更新1个任务。 你可以传递–update-parallelism标志来配置调度器同时更新的最大服务任务数。
    当对单个任务的更新返回RUNNING状态时,调度器通过继续执行另一个任务,直到所有任务都更新为止,继续更新。 如果在更新期间的任何时间任务返回FAILED,则调度器暂停更新。 你可以使用–update-failure-action标志控制docker服务创建或docker服务更新的行为。
    在下面的示例服务中,调度器一次最多应用更新2个副本。 当更新的任务返回RUNNING或FAILED时,调度程序在停止下一个要更新的任务之前等待10秒钟:

    1. $ docker service create
    2.   –replicas 10
    3.   –name my_web
    4.   –update-delay 10s
    5.   –update-parallelism 2
    6.   –update-failure-action continue
    7.   alpine
    8.  
    9. 0u6a4s31ybk7yw2wyvtikmu50

    配置挂载

    你可以创建两种类型的swarm服务挂载,volume挂载或bind挂载。在创建服务时传递–mount参数指定挂载类型。默认挂载类型是volume。

  • Volumes存储在容器任务被删除时仍然会保留。
    挂载volumes首先方法是利用已存在的volumes:

    1. $ docker service create
    2.   –mount src=<VOLUME-NAME>,dst=<CONTAINER-PATH>
    3.   –name myservice
    4.   <IMAGE>

    下面的方法是在部署服务时创建一个volume:

    1. $ docker service create
    2.   –mount type=volume,src=<VOLUME-NAME>,dst=<CONTAINER-PATH>,volume-driver=<DRIVER>,volume-opt=<KEY0>=<VALUE0>,volume-opt=<KEY1>=<VALUE1>
    3.   –name myservice
    4.   <IMAGE>
  • Bind挂载是把容器中的目录挂载到运行容器所在的主机上的目录。在swarm初始化任务容器时,主机文件系统路径必须存在。
    下面的示例显示bind挂载的语法:

    1. # Mount a read-write bind
    2. $ docker service create
    3.   –mount type=bind,src=<HOST-PATH>,dst=<CONTAINER-PATH>
    4.   –name myservice
    5.   <IMAGE>
    6.  
    7. # Mount a read-only bind
    8. $ docker service create
    9.   –mount type=bind,src=<HOST-PATH>,dst=<CONTAINER-PATH>,readonly
    10.   –name myservice
    11.   <IMAGE>
  • 管理swarm(17) – 管理节点

    在swarm的生命周期中,你可能需要查看或更新节点,如:

  • 列出swarm中的节点
  • 查看单个节点详信息
  • 更新节点
  • 脱离swarm
  • 列出节点

    在管理节点在执行docker node ls来列出swarm中的节点:

    1. $ docker node ls
    2.  
    3. ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
    4. 46aqrk4e473hjbt745z53cr3t    node-5    Ready   Active        Reachable
    5. 61pi3d91s0w3b90ijw3deeb2q    node-4    Ready   Active        Reachable
    6. a5b2m3oghd48m8eu391pefq5u    node-3    Ready   Active
    7. e7p8btxeu3ioshyuj6lxiv6g0    node-2    Ready   Active
    8. ehkv3bcimagdese79dn78otj5 *  node-1    Ready   Active        Leader

    AVAILABILITY显示出调度器是否能分配任务给这个节点:

  • Active意味着调度器可以分配任务给节点
  • Pause意味着调度器不能分配任务给节点,不过已存在的任务仍然继续运行
  • Drain意味着调度器不能分配任务给节点。调度器关闭已存在的任务并调度它们到其它可用节点
  • MANAGER STATUS列显示节点是否参与到Raft一致性:

  • 没有值表示worker节点不参与到swarm管理
  • Leader表示该节点是主要管理节点,负责全部的swarm管理工作和编排决策。
  • Reachable表示该节点是一个管理节点并参与到Raft一致性。如果leader节点变为不可用,该节点有资格被选为新的leader。
  • Unavailable表示该节点是一个管理节点,不过目前不能与其它管理节点通信。如果一个管理节点变为不可用,你应该加入一个新的管理节点或者提升一个worker节点为管理节点。
  • 查看单个节点详细信息

    你可以在管理节点上执行docker node inspect 来查看单个节点的详细信息。默认输出来json格式,你可以传递–pretty参数来输出较易读的格式,如:

    1. docker node inspect self –pretty
    2.  
    3. ID:                     ehkv3bcimagdese79dn78otj5
    4. Hostname:               node-1
    5. Joined at:              2016-06-16 22:52:44.9910662 +0000 utc
    6. Status:
    7.  State:                 Ready
    8.  Availability:          Active
    9. Manager Status:
    10.  Address:               172.17.0.2:2377
    11.  Raft Status:           Reachable
    12.  Leader:                Yes
    13. Platform:
    14.  Operating System:      linux
    15.  Architecture:          x86_64
    16. Resources:
    17.  CPUs:                  2
    18.  Memory:                1.954 GiB
    19. Plugins:
    20.   Network:              overlay, host, bridge, overlay, null
    21.   Volume:               local
    22. Engine Version:         1.12.0-dev

    更新节点

    更新节点状态

    更新节点的状态可以:

  • drain一个管理节点,可以使该节点只完成swarm管理任务,而不接收来自调度器的任务并停止已存在的任务
  • drain一个节点,你可以下线该节点来进行维护工作
  • pause一个节点,使它不再接收新任务
  • restore一个不可用或暂停的节点为可用状态
  • 例如,设置一个管理节点为Drain:

    1. $ docker node update –availability drain node-1
    2.  
    3. node-1

    添加或删除标签元数据

    节点标签提供了一种灵活的节点组织方法。 你还可以在服务约束中使用节点标签。 在创建服务时应用约束,以限制调度器为服务分配任务的节点。
    在管理节点上运行docker node update –label-add以将标签元数据添加到节点。 –label-add标志支持或 = 对。
    每添加一个节点标签需要传递一次label-add参数:

    1. $ docker node update –label-add foo –label-add bar=baz node-1
    2.  
    3. node-1

    升级或降级节点

    你可以升级一个worker节点为管理节点。这个在管理节点变为不可用或者你想下线管理节点来维护会比较有帮助。当然,你也可以降级一个管理节点为worker节点。
    不管你降级和升级节点是出于什么原因,你应该始终确保swarm中管理节点数量为奇数。
    在管理节点执行docker node promote来升级一组worker节点:

    1. $ docker node promote node-3 node-2
    2.  
    3. Node node-3 promoted to a manager in the swarm.
    4. Node node-2 promoted to a manager in the swarm.

    在管理节点执行docker node demote来降级一组节点:

    1. $ docker node demote node-3 node-2
    2.  
    3. Manager node-3 demoted in the swarm.
    4. Manager node-2 demoted in the swarm.

    docker node promote和docker node demote分别是docker node update –role manager和docker node update –role worker命令等效。

    脱离节点

    要从swarm删除一个节点,首先要执行docker swarm leave命令。
    例如从swarm脱离一个worker节点:

    1. $ docker swarm leave
    2.  
    3. Node left the swarm.

    当一个节点脱离swarm时,Docker Engine不再以swarm模式运行。orchestrator不再调度任务给该节点。
    当节点脱离swarm之后,你可以在管理节点执行docker node rm命令来从节点列表中删除该节点。
    例如:

    1. docker node rm node-2
    2.  
    3. node-2

    管理swarm(16) – 将节点加入到swarm

    当你首次创建一个swarm时,你就放置了一个Docker Engine到swarm中。为了充分利用swarm模式的优势,你可以添加节点到swarm:

  • 添加worker节点来增加集群容量。当你部署一个服务到swarm,Engine调度任务到可用的节点中(不管是worker节点或者是manager节点)。当你添加一个worker节点到swarm中,你增加了swarm的规模来处理更多的任务而不会影响到管理器raft的一致性
  • 多个manager节点可以增强集群容错能力。manager节点执行swarm的编排和集群管理功能。在manager节点中,单个leader节点执行编排任务。当leader节点出现故障,余下的manager节点选出一个新的leader节点并恢复编排和维护swarm状态。默认情下,manager节点也执行任务。
  • 在添加节点到swarm之前你必须安装Docker Engine 1.12或之后的版本。

    添加worker节点

    要获取添加worker到swarm的命令,在manager节点上执行:

    1. $ docker swarm join-token worker
    2.  
    3. To add a worker to this swarm, run the following command:
    4.  
    5.     docker swarm join
    6.     –token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c
    7.     192.168.99.100:2377

    在要添加到swarm的worker节点上执行如下命令来加入到swarm:

    1. $ docker swarm join
    2.   –token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c
    3.   192.168.99.100:2377
    4.  
    5. This node joined a swarm as a worker.

    docker swarm join做了如下工作:

  • 切换当前节点的Docker Engine为swarm模式
  • 从manager节点请求一个TLS证书
  • 以机器主机名命名节点
  • 基于swarm token和manager节点监听的地址来添加当前节点到swarm
  • 设置当前节点为Active状态,意味着它可以接收从调度器分配的任务
  • 将ingress覆盖网络扩展到当前节点
  • 添加manager节点

    当你执行docker swarm join并传递manager token,跟worker节点一样Docker Engine切换到swarm模式。新添加的manager节点也参与到raft一致性当中。新的节点应该是可访问的,但之前的leader节点仍然不变。
    Docker推荐3个或5个manager节点的集群来实现高可用。因为swarm模式的manager节点使用Raft共享数据,必须是奇数的manager节点数。只要超过一半的manager节点可用,swarm就可以继续工作。
    要获取添加manager到swarm的加入命令,执行:

    1. $ docker swarm join-token manager
    2.  
    3. To add a manager to this swarm, run the following command:
    4.  
    5.     docker swarm join
    6.     –token SWMTKN-1-61ztec5kyafptydic6jfc1i33t37flcl4nuipzcusor96k7kby-5vy9t8u35tuqm7vh67lrz9xp6
    7.     192.168.99.100:2377

    在要添加到swarm的manager节点上执行:

    1. $ docker swarm join
    2.   –token SWMTKN-1-61ztec5kyafptydic6jfc1i33t37flcl4nuipzcusor96k7kby-5vy9t8u35tuqm7vh67lrz9xp6
    3.   192.168.99.100:2377
    4.  
    5. This node joined a swarm as a manager.

    管理swarm(15) – 以swarm模式运行Docker Engine

    当你首次安装并开始使用Docker Engine,默认情况下swarm模式是关闭的。当你激活swarm模式,你开始可以使用docker service命令来管理服务。
    有两种方法来激活swarm模式:

  • 创建一个新的swarm,本文将介绍
  • 加入一个已存在的swarm
  • 当你在你本地机器运行docker engine的swarm模式,你可以基于你之前创建的镜像或其它可用镜像来创建和测试服务。在生产环境中,swarm模式提供了集群管理的容错功能来保持你服务一直可用。
    本文假设你已经在你机器安装了Docker Engine 1.12或更高版本。

    创建一个swarm

    当你运行创建swarm的命令,Docker Engine就开始以swarm模式运行了。
    执行docker swarm init命令在当前节点创建一个单节点的swarm。Docker Engine设置swarm的步骤为:

  • 切换当前节点进入swarm模式
  • 创建一个名为default的swarm
  • 将当前节点指定为该swarm的leader管理器节点。
  • 以机器主机名命名节点
  • 配置管理节点监听端口2377
  • 设置当前节点为Active状态,意味着当前节点可以接收来自调度器的任务
  • 创建一个内部的分布式数据存储来维护swarm的一致状态
  • 默认下为swarm生成一个自签名根CA证书
  • 默认下生成一个token用来worker和manager节点加入swarm
  • 创建一个名为ingress的覆盖网络用来发布服务端口,以连接swarm外部网络
  • docker swarm init命令的输出提供了worker节点加入swarm的命令:

    1. $ docker swarm init
    2. Swarm initialized: current node (dxn1zf6l61qsb1josjja83ngz) is now a manager.
    3.  
    4. To add a worker to this swarm, run the following command:
    5.  
    6.     docker swarm join
    7.     –token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c
    8.     192.168.99.100:2377
    9.  
    10. To add a manager to this swarm, run ‘docker swarm join-token manager’ and follow the instructions.

    配置advertise地址

    管理节点使用一个advertise地址来允许swarm中的其它节点进入Swarmkit API和覆盖网络。其它节点必须能够通过advertise地址连接管理节点。
    如果你没有指定一个advertise地址,Docker会检查系统是否只有一个IP地址,如果是,Docker就使用这个IP地址监听2377端口。如果系统有多个IP地址,你就必须指定一个正确的–advertise-addr来启用内部管理间通信和覆盖网络。

    1. $ docker swarm init –advertise-addr <MANAGER-IP>

    注意有时候其它节点连接管理节点的地址不绑定在管理节点本身系统上,即使用ifconfig看不到能用于连接管理节点的地址时,也需要手动指定正确的advertise地址。例如在云服务器中有多个不同的区域,主机有用于内部通过的内部地址和用于外部通过的外部地址。在这种情况下,需要指定其它节点能连接管理节点的地址。

    查看join命令或更新swarm join token

    节点需要一个秘密token来加入swarm。worker节点用来加入swarm的token与manager节点的token不一样。节点只在加入swarm的时候使用token。当在一个节点加入swarm后更新token不会影响节点的swarm成员资格。更改token只是为了确保其它新的节点不能使用旧的token来尝试加入swarm。
    要获取用于worker节点加入swarm的token,执行:

    1. $ docker swarm join-token worker
    2.  
    3. To add a worker to this swarm, run the following command:
    4.  
    5.     docker swarm join
    6.     –token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c
    7.     192.168.99.100:2377
    8.  
    9. This node joined a swarm as a worker.

    要获取用于manager节点加入swarm的token,执行:

    1. $ docker swarm join-token manager
    2.  
    3. To add a worker to this swarm, run the following command:
    4.  
    5.     docker swarm join
    6.     –token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c
    7.     192.168.99.100:2377

    传递–quiet参数只打印token:

    1. $ docker swarm join-token –quiet worker
    2.  
    3. SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c

    我们建议在以下情况来更新token:

  • 如果token不小心进入到了版本管理系统,群组聊天或打印到了日志文件中
  • 如果你怀疑节点已被入侵
  • 如果你想确保没有新的节点可以加入swarm
  • 除此之外,我们建议你定时的更新token。建议至少6个月更新一个token。
    运行swarm join-token –rotate以使旧token无效并生成新token。 指定更新的是worker节点token还是manager节点:

    1. $docker swarm join-token  –rotate worker
    2.  
    3. To add a worker to this swarm, run the following command:
    4.  
    5.     docker swarm join
    6.     –token SWMTKN-1-2kscvs0zuymrsc9t0ocyy1rdns9dhaodvpl639j2bqx55uptag-ebmn5u927reawo27s3azntd44
    7.     172.17.0.2:2377

    管理swarm(14) – 服务介绍

    要在Docker Engine swarm模式中部署一个应用程序镜像,你需要创建一个服务。通常时候,一个服务对于一些规模比较大的应用程序的一个微服务镜像。例如服务比较包含一个HTTP服务器,一个数据库或者你想运行在分布式环境的可执行程序。
    当你创建一个服务,你可以指定使用哪个容器镜像和在容器中运行的命令。你也可以定义服务的选项,包括:

  • 可在swarm外部访问服务的端口
  • 在swarm中服务之间可以互相通信的覆盖网络
  • CPU和内存限制和预留
  • 滚动更新策略
  • 运行在swarm的镜像副本的数量
  • 服务,任务和容器

    当你部署服务到swarm,swarm管理器接收你对服务期望状态的定义。然后它为你服务在swarm中的节点调度一个或多个副本任务。这些任务在swarm的节点上彼此独立地运行。
    例如假设你想负载均衡三个HTTP服务器实例。下面的图表展示了三个HTTP服务器副本。三个HTTP实例中的每一个是swarm中的一个任务。
    虚拟化技术
    一个容器是孤立的进程。在swarm模式模型中,每个任务调用一个容器。任务包含着容器。一旦容器运行正常,调度器就会把相此容器相关联的任务识别为在线状态。否则容器停止或有异常,则任务显示为终止。

    任务和调度

    任务是swarm内调度的原子单位。当你通过创建或更新服务声明一个期望状态的服务,调度器通过调度任务来实现期望的状态。例如,你指定一个服务始终保持运行三个HTTP实例。调度器就创建三个任务。每个任务运行一个容器。容器是任务的实例化。如果一个HTTP容器之后出现故障停止,此任务被标志为失败,调度器就会创建一个新的任务来生成一个新容器。
    任务是一个单向机制。它单向地执行一系统状态,assigned, prepared, running等。如果一个任务失败了,调度器就会删除这个任务和它的容器,然后创建一个新的任务来替换它。
    下面的图表显示swarm模式是如何接收服务创建请求和调度任务到worker节点的。
    虚拟化技术

    副本和全局服务

    有两种类型的服务部署,副本和全局。
    对于副本服务,你可以指定运行相同任务的数量。例如,你决定部署三个HTTP实例的副本,每个提供相同的内容。
    一个全局服务是在每个节点上运行一个相同的任务。不需要预先指定任务的数量。每次你增加一个节点到swarm中,协调器就会创建一个任务,然后调度器把任务分配给新节点。比如你希望在每个节点上运行监控代理,病毒扫描器等。
    下面的图表显示以黄色标注的三个副本的服务和灰色标注的一个全局服务。
    虚拟化技术