Docker(十)Docker Swarm

版权声明:转载请注明出处! https://blog.csdn.net/wfs1994/article/details/85013058

环境说明:
使用docker-machine的实验环境,创建swarm集群

IP Hostname Node
192.168.20.201 host1 worker
192.168.20.202 host2 worker
192.168.20.203 master manager
[root@master ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
tnrfe0xadx6ry9dp1genwnkyr     host1               Ready               Active                                  18.09.0
jpx8fdobbc8pr4kd7bpieogug     host2               Ready               Active                                  18.09.0
l3uepmyv6bhafawmljop5ek9c *   master              Ready               Active              Leader              18.09.0

在swarm集群里通过service部署wordpress

所有操作都在管理节点192.168.20.203上进行

1.创建一个overlay的network:

# docker network create -d overlay demo
1iuc6sxtqxdm74jktgq91ybop

# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
bb036d9a6179        bridge              bridge              local
1iuc6sxtqxdm        demo                overlay             swarm
dea77c20e6d4        docker_gwbridge     bridge              local
2de632b4004c        host                host                local
ty3kfj24k0go        ingress             overlay             swarm
a56a6ac11428        none                null                local

2.运行service:

# mysql
# docker service create --name mysql --env MYSQL_ROOT_PASSWORD=root --env MYSQL_DATABASE=wordpress --network demo --mount type=volume,source=mysql-data,destination=/var/lib/mysql mysql:5.7

# wordpress
# docker service create --name wordpress -p 80:80 --env WORDPRESS_DB_PASSWORD=root --env WORDPRESS_DB_HOST=mysql --network demo wordpress

--mount type=volume,source=mysql-data,destination=/var/lib/mysql等价于在docker run时指定-v mysql-data:/var/lib/mysql

3.查看service:

# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
4mgu43o5z5wa        mysql               replicated          1/1                 mysql:5.7           
pdt70uonc44p        wordpress           replicated          1/1                 wordpress:latest    *:80->80/tcp

# docker service ps wordpress
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE             ERROR                              PORTS
5z32wlxzqafc        wordpress.1         wordpress:latest    host1               Running             Running 3 minutes ago  

登录到host1上查看

# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
c95b340e8659        wordpress:latest    "docker-entrypoint.s…"   4 minutes ago       Up 4 minutes        80/tcp              wordpress.1.5z32wlxzqafcp16xve8lkivap

到此,我们的wordpress就部署好了,可以发现访问集群中任何一个节点的80端口都能够访问wordpress,这其实是swarm的 routing mesh的作用
`

集群服务间通信之Routing Mesh

Routing Mesh的两种体现:

  • Internal:Container和Container之间访问通过overlay网络(通过VIP)
  • Ingress:如果服务有绑定接口,则此服务可以通过任意swarm节点的相应接口访问

容器间互访

微服务架构的应用由若干 service 组成。比如有运行 httpd 的 web 前端,有提供缓存的 memcached,有存放数据的 mysql,每一层都是 swarm 的一个 service,每个 service 运行了若干容器。在这样的架构中,service 之间是必然要通信的。

服务发现:
一种实现方法是将所有 service 都 publish 出去,然后通过 routing mesh 访问。但明显的缺点是把 memcached 和 mysql 也暴露到外网,增加了安全隐患。
如果不 publish,那么 swarm 就要提供一种机制,能够:

  1. 让 service 通过简单的方法访问到其他 service。
  2. 当 service 副本的 IP 发生变化时,不会影响访问该 service 的其他 service。
  3. 当 service 的副本数发生变化时,不会影响访问该 service 的其他 service。

这其实就是服务发现service discovery)。Docker Swarm 原生就提供了这项功能,通过服务发现,service 的使用者不需要知道 service 运行在哪里,IP 是多少,有多少个副本,就能与 service 通信。

创建 overlay 网络:
要使用服务发现,需要相互通信的 service 必须属于同一个 overlay 网络,所以我们先得创建一个新的 overlay 网络。

# docker network create -d overlay demo

部署 service 到 overlay:
部署一个 web 服务,并将其挂载到新创建的 overlay 网络。

# docker service create --name web --replicas=3 --network demo nginx

部署一个 test 服务用于测试,挂载到同一个 overlay 网络。

# docker service create --name test --network demo busybox:1.28.3 sleep 100000000

sleep 100000000 的作用是保持 busybox 容器处于运行的状态

验证:

# docker service ps test
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
nrjyalzghbtl        test.1              busybox:1.28.3      host2               Running             Running 28 seconds ago                        				

登录到test所在节点

[root@host2 ~]# docker exec test.1.nrjyalzghbtlhxez9rx6jb068 ping -c 3 web
PING web (10.0.0.2): 56 data bytes
64 bytes from 10.0.0.2: seq=0 ttl=64 time=0.194 ms
64 bytes from 10.0.0.2: seq=1 ttl=64 time=0.128 ms
64 bytes from 10.0.0.2: seq=2 ttl=64 time=0.119 ms

可以看到web的IP是10.0.0.2
然后可以执行nslookup命令查看每个副本的 IP

[root@host2 ~]# docker exec test.1.nrjyalzghbtlhxez9rx6jb068 nslookup tasks.web
Server:    127.0.0.11
Address 1: 127.0.0.11

Name:      tasks.web
Address 1: 10.0.0.5 web.3.a0ne2us0dg78xuswgd1av75yx.demo
Address 2: 10.0.0.4 web.2.9df3f8fejnj9xcpejgnk6htvm.demo
Address 3: 10.0.0.3 web.1.5dmbr5f35dc4n8o9fb5m3cd68.demo

注意:新版busybox镜像执行nslookup会报错

可以看到10.0.0.3、10.0.0.4、10.0.0.5 才是各个副本自己的 IP。10.0.0.2 是 web service 的 VIP(Virtual IP),swarm 会将对 VIP 的访问负载均衡到每一个副本。不过对于服务的使用者(这里是test.1),根本不需要知道 web副本的 IP,也不需要知道 web 的 VIP,只需直接用 service 的名字 web 就能访问服务。

外部访问容器

在这里插入图片描述

Docker Stack部署wordpress

在 Swarm 集群中也可以使用 compose 文件(docker-compose.yml) 来配置、启动多个服务。
在swarm下使用docker-compose文件部署需要使用 docker stack命令。

# docker stack --help
Usage:  docker stack [OPTIONS] COMMAND
Manage Docker stacks
Options:
	  --orchestrator string   Orchestrator to use (swarm|kubernetes|all)
Commands:
  deploy      Deploy a new stack or update an existing stack
  ls          List stacks
  ps          List the tasks in the stack
  rm          Remove one or more stacks
  services    List the services in the stack
Run 'docker stack COMMAND --help' for more information on a command.

对之前创建wordpress的yml文件做如下修改:

version: '3'
services:
  web:
    image: wordpress
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_PASSWORD: root
    networks:
      - my-network
    depends_on:
      - mysql
    deploy:		
      mode: replicated		#初始化3个副本
      replicas: 3
      restart_policy:			#设置重启策略
        condition: on-failure
        delay: 5s
        max_attempts: 3
      update_config:		#设置更新策略
        parallelism: 1
        delay: 10s

  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: wordpress
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - my-network
    deploy:		#设置mysql只能部署到manager节点,且只能运行一个副本
      mode: global
      placement:
        constraints:
          - node.role == manager

volumes:
  mysql-data:

networks:
  my-network:
    driver: overlay	#使用overlay网络

depoly参数用法:https://docs.docker.com/compose/compose-file/#deploy

使用 compose 文件创建service:

# docker stack deploy wordpress --compose-file=docker-compose.yml 
Creating network wordpress_my-network
Creating service wordpress_web
Creating service wordpress_mysql 

# docker stack ls
NAME                SERVICES            ORCHESTRATOR
wordpress           2                   Swarm	

# docker stack ps wordpress
ID                  NAME                                        IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
teexafxvv2cf        wordpress_mysql.l3uepmyv6bhafawmljop5ek9c   mysql:5.7           master              Running             Running 29 seconds ago                       
mzop59r1uyd3        wordpress_web.1                             wordpress:latest    host2               Running             Running 29 seconds ago                       
o0cttjj5tnv6        wordpress_web.2                             wordpress:latest    master              Running             Running 30 seconds ago                       
yjf0po2jglw2        wordpress_web.3                             wordpress:latest    host1               Running             Running 29 seconds ago                       


# docker stack services wordpress
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
rhgsre2kmc31        wordpress_web       replicated          3/3                 wordpress:latest    *:8080->80/tcp
zpejq396z4k7        wordpress_mysql     global              1/1                 mysql:5.7   

Docker Secret管理和使用

Docker 提供了 secrets 管理功能,用户可以在 Swarm 集群中安全地管理密码、密钥证书等敏感数据,并允许在多个 Docker 容器实例之间共享访问指定的敏感数据。

Secret management:

  • 存在swarm manager节点Raft database里
  • Secret可以assign给一个service,这个service就能看到这个Secret
  • 在container内部Secret看起来像文件,但是实际是在内存中

可以用 docker secret 命令来管理敏感信息

创建Secret有两种方式:

# docker secret create --help
Usage:  docker secret create [OPTIONS] SECRET [file|-]
Create a secret from a file or STDIN as content
Options:
  -d, --driver string            Secret driver
  -l, --label list               Secret labels
	  --template-driver string   Template driver

第一种:通过文件创建:
# cat password 
adminadmin
# docker secret create my-pw password 
xpspv8d47tbtk9zp95f1i9j15
# docker secret ls
ID                          NAME                DRIVER              CREATED              UPDATED
xpspv8d47tbtk9zp95f1i9j15   my-pw                                   About a minute ago   About a minute ago

第二种:从标准输入创建
# echo "adminadmin" | docker secret create my-pw2 - 
eoodcgcq94jvrhzuu35kgwks3
# docker secret ls
ID                          NAME                DRIVER              CREATED             UPDATED
xpspv8d47tbtk9zp95f1i9j15   my-pw                                   2 minutes ago       2 minutes ago
eoodcgcq94jvrhzuu35kgwks3   my-pw2                                  5 seconds ago       5 seconds ago	

在service中使用secret:

# docker service create --name db --secret my-pw -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/my-pw mysql:5.7

登录到db所在节点,进入容器查看:
# docker exec -it  2dbd3d8259a9 sh
# cat /run/secrets/my-pw
adminadmin
# 
# mysql -uroot -padminadmin
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.24 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 	
# docker service create --name db --secret source=my-pw,target=mysql_root_password -e MYSQL_ROOT_PASSWORD_FILE="/run/secrets/mysql_root_password" mysql:5.7

--secret source=my-pw,target=mysql_root_password 的作用就是指定使用 secret my-pw,然后把器解密后的内容保存到容器 /run/secrets/mysql_root_password 文件中,文件名称 mysql_root_passwordtarget 指定。

相比于在环境变量中直接指定密码,使用secret可以将密码和容器解耦和,secret可以由管理员创建,而运行容器的用户只需使用 secret 而不需要知道 secret 的内容。

案例:创建一个 MySQL service,将密码保存到 secret 中。我们还会创建一个 WordPress service,它将使用 secret 连接 MySQL。

使用 secret 避免在 image 中存放敏感信息,或者在命令行中直接传递敏感数据

$ docker service create \
     --name mysql \
     --replicas 1 \
     --network mysql_private \
     --mount type=volume,source=mydata,destination=/var/lib/mysql \
     --secret source=mysql_root_password,target=mysql_root_password \
     --secret source=mysql_password,target=mysql_password \
     -e MYSQL_ROOT_PASSWORD_FILE="/run/secrets/mysql_root_password" \
     -e MYSQL_PASSWORD_FILE="/run/secrets/mysql_password" \
     -e MYSQL_USER="wordpress" \
     -e MYSQL_DATABASE="wordpress" \
     mysql:latest
	 
$ docker service create \
     --name wordpress \
     --replicas 1 \
     --network mysql_private \
     --publish target=30000,port=80 \
     --mount type=volume,source=wpdata,destination=/var/www/html \
     --secret source=mysql_password,target=wp_db_password,mode=0400 \
     -e WORDPRESS_DB_USER="wordpress" \
     -e WORDPRESS_DB_PASSWORD_FILE="/run/secrets/wp_db_password" \
     -e WORDPRESS_DB_HOST="mysql:3306" \
     -e WORDPRESS_DB_NAME="wordpress" \
     wordpress:latest

Secret在stack中的使用

version: '3'
services:
  web:
    image: wordpress
    ports:
      - 8080:80
    secrets:
      - my-pw
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_PASSWORD_FILE: /run/secrets/my-pw
    networks:
      - my-network
    depends_on:
      - mysql
    deploy:
      mode: replicated
      replicas: 3
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
      update_config:
        parallelism: 1
        delay: 10s

  mysql:
    image: mysql:5.7
    secrets:
      - my-pw
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/my-pw
      MYSQL_DATABASE: wordpress
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - my-network
    deploy:
      mode: global
      placement:
        constraints:
          - node.role == manager

volumes:
  mysql-data:

networks:
  my-network:
    driver: overlay
	
#secrets:	#如果secret没有事先创建可以在yml中指定(不建议)
#  my-pw:
#    file: ./password

Visualizer

Visualizer是一个图形化显示docker swarm集群中各个节点状态以及运行了什么容器和负载情况的监控工具

注意:docker.sock这个文件必须要挂载到容器里面去,不然读取不到集群的状态

启动:

# docker run -d --name visualizer -p 80:8080 -v /var/run/docker.sock:/var/run/docker.sock dockersamples/visualizer

或者通过配置文件创建:

# cat visualizer.yml 
version: '3'

services:
  visualizer:
    image: dockersamples/visualizer:stable
    ports:
      - 80:8080
    stop_grace_period: 1m30s
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints:
          - node.role == manager

# docker stack deploy visualizer --compose-file=visualizer.yml	

可以横向扩展web services,查看效果:

# docker service scale wordpress_web=4

# docker service ps wordpress_web 
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE                ERROR               PORTS
srtm9te7yqbj        wordpress_web.1     wordpress:latest    host1               Running             Running 6 minutes ago                            
151hhhiqtcqg        wordpress_web.2     wordpress:latest    host2               Running             Running 6 minutes ago                            
nt28i3esyij4        wordpress_web.3     wordpress:latest    master              Running             Running 6 minutes ago                            
itz5hexoop8w        wordpress_web.4     wordpress:latest    host1               Running             Running about a minute ago 

在这里插入图片描述

service滚动更新

滚动更新降低了应用更新的风险,如果某个副本更新失败,整个更新将暂停,其他副本则可以继续提供服务。同时,在更新的过程中,总是有副本在运行的,因此也保证了业务的连续性。

示例:部署两副本的服务,镜像使用 httpd:2.2.31,然后将其更新到 httpd:2.2.32。

# docker service create --name myweb --replicas=2 httpd:2.2.31

# docker service ps myweb
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE             ERROR               PORTS
lq7g3n0keb7z        myweb.1             httpd:2.2.31        host2               Running             Running 2 minutes ago                            
7gtztdiy5hs4        myweb.2             httpd:2.2.31        host1               Running             Running about a minute ago  

将 service 更新到 httpd:2.2.32:

# docker service update --image httpd:2.2.32 myweb
--image 指定新的镜像。

# docker service ps myweb
ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE                ERROR               PORTS
e4s92g98ssn9        myweb.1             httpd:2.2.32        host2               Running             Running about a minute ago                       
lq7g3n0keb7z         \_ myweb.1         httpd:2.2.31        host2               Shutdown            Shutdown 4 minutes ago                           
fazxhm2t1s4z        myweb.2             httpd:2.2.32        master              Running             Running 4 minutes ago                            
7gtztdiy5hs4         \_ myweb.2         httpd:2.2.31        host1               Shutdown            Shutdown 6 minutes ago 	

注意:在更新的过程中,用户可能访问到新的内容也可能访问到旧的内容

Swarm 将按照如下步骤执行滚动更新:

  1. 停止第一个副本。
  2. 调度任务,选择 worker node。
  3. 在 worker 上用新的镜像启动副本。
  4. 如果副本(容器)运行成功,继续更新下一个副本;如果失败,暂停整个更新过程。

默认配置下,Swarm 一次只更新一个副本,并且两个副本之间没有等待时间。我们可以通过 --update-parallelism 设置并行更新的副本数目,通过 --update-delay 指定滚动更新的间隔时间。

# docker service update --replicas 6 --update-parallelism 2 --update-delay 1m30s myweb
service 增加到六个副本,每次更新两个副本,间隔时间一分半钟。

Swarm 还有个方便的功能是回滚,如果更新后效果不理想,可以通过 --rollback 快速恢复到更新之前的状态。

注意,--rollback 只能回滚到上一次执行 docker service update 之前的状态,并不能无限制地回滚。

其他更新可以查看帮助:

# docker service update --help

如端口更新:

docker service update --publish-rm 8080:80 --publish-add 80:80 web 

猜你喜欢

转载自blog.csdn.net/wfs1994/article/details/85013058