Docker之路-通过swarm管理配置及服务升级回滚

管理密钥


在动态的、大规模的分布式集群上,管理和分发 密码证书 等敏感信息是极其重要的工作。传统的密钥分发方式(如密钥放入镜像中,设置环境变量,volume 动态挂载等)都存在着潜在的巨大的安全风险。

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

我们可以用 docker secret 命令来管理敏感信息。接下来我们在上面章节中创建好的 Swarm 集群中介绍该命令的使用。

这里我们以在 Swarm 集群中部署 mysqlwordpress 服务为例。

创建密钥

我们使用 docker secret create 命令以管道符的形式创建 secret

[root@node1 /opt/mycontainer/wordpress]# openssl rand -base64 20 | docker secret create mysql_password -
q59vqmmatae02sve9p5jrnjvr
[root@node1 /opt/mycontainer/wordpress]# openssl rand -base64 20 | docker secret create mysql_root_password -
jmei7gfyzhndxd3byeexfi2m8

查看密钥

使用 docker secret ls 命令来查看 secret

[root@node1 /opt/mycontainer/wordpress]# docker secret ls
ID                          NAME                  DRIVER              CREATED             UPDATED
q59vqmmatae02sve9p5jrnjvr   mysql_password                            16 seconds ago      16 seconds ago
jmei7gfyzhndxd3byeexfi2m8   mysql_root_password                       7 seconds ago       7 seconds ago

如何使用密钥

我们在启动服务时指定密钥位置,secret 默认通过 tmpfs 文件系统挂载到容器的 /run/secrets 目录中。

为这次的服务创建属于自己的网络接口(overlay类型):

[root@node1 /opt/mycontainer/wordpress]# docker network create -d overlay mqsql_worldpress
sp7k7aiuhk7glj87cj7xujfov

创建mysql服务:

[root@node1 /opt/mycontainer/wordpress]# docker service create 
     --name mysql 
     --replicas 1 
     --network mysql_worldpress 
     --mount type=volume,source=mydata,target=/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
wxqgnjh5ykmlh7xnc5xmgrcq4
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged

创建worldpress服务:

# 这里请耐性等待一会儿,稍微有点儿慢...
[root@node1 /opt/mycontainer/wordpress]# docker service create 
		--name wordpress 
		--replicas 1 
		--network mysql_worldpress 
		--publish 80 
		--mount type=volume,source=wpdata,target=/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
cf7a60orb2a51r18qa1gto3om
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged

服务验证

现在浏览器访问 IP:8081,即可开始 WordPress 的安装与使用。

通过以上方法,我们没有像以前通过设置环境变量来设置 MySQL 密码, 而是采用 docker secret 来设置密码,防范了密码泄露的风险。

[root@node1 /opt/mycontainer/wordpress]# docker service ls

ID            NAME   MODE        REPLICAS  IMAGE
wxqgnjh5ykml  mysql      replicated  1/1       mysql:latest
cf7a60orb2a5  wordpress  replicated  1/1       wordpress:latest

管理配置信息


在动态的、大规模的分布式集群上,管理和分发配置文件也是很重要的工作。

传统的配置文件分发方式(如配置文件放入镜像中,设置环境变量,volume 动态挂载等)都降低了镜像的通用性。

在 Docker 17.06 以上版本中,Docker 新增了 docker config 子命令来管理集群中的配置信息,以后你无需将配置文件放入镜像或挂载到容器中就可实现对服务的配置。

注意:config 仅能在 Swarm 集群中使用。

下面以官方的例子为例来来进行展示:

创建配置文件

首先我们先创建一个redis的配置文件:

~]# cat redis.conf
port 6380

然后我们根据该文件内容来创建docker 管理的配置文件

[root@node1 /opt/mycontainer/redis]# docker config create redis.conf redis.conf
ho5m631aiz4hw3tmj2hoz6mnq
[root@node1 /opt/mycontainer/redis]# docker config ls
ID                          NAME                CREATED             UPDATED
ho5m631aiz4hw3tmj2hoz6mnq   redis.conf          6 seconds ago       6 seconds ago

创建redis服务

[root@node1 /opt/mycontainer/redis]# $ docker service create 
     --name redis 
     # --config source=redis.conf,target=/etc/redis.conf 
     --config redis.conf 
     -p 6379:6380 
     redis:latest 
     redis-server /redis.conf

如果你没有在 target 中显式的指定路径时,默认的 redis.conftmpfs 文件系统挂载到容器的 /config.conf

以前我们通过监听主机目录来配置 Redis,就需要在集群的每个节点放置该文件,如果采用 docker config 来管理服务的配置信息,我们只需在集群中的管理节点创建 config,当部署服务时,集群会自动的将配置文件分发到运行服务的各个节点中,大大降低了配置信息的管理和分发难度。

[root@node1 /opt/mycontainer/redis]# redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> set docker "k8s"
OK
127.0.0.1:6379> get docker
"k8s"

滚动升级


我们通过swarm创建的服务,那么该怎么升级?

错误做法❌:先停止原来的服务,再使用新镜像部署一个服务,就完成服务的 “升级” 。

我们先构建一个低版本的nginx服务:

[root@node1 /opt/mycontainer/redis]# docker service create --name nginx --replicas 3 -p 80:80 nginx:1.13.7-alpine
pofnib1a1c5ybefck3sbuxxnw
overall progress: 3 out of 3 tasks
1/3: running   [==================================================>]
2/3: running   [==================================================>]
3/3: running   [==================================================>]
verify: Service converged

我们尝试升级:

[root@node1 /opt/mycontainer/redis]# docker service update nginx --image nginx:1.13.12-alpine
nginx
overall progress: 3 out of 3 tasks
1/3: running   [==================================================>]
2/3: running   [==================================================>]
3/3: running   [==================================================>]
verify: Service converged

[root@node1 /opt/mycontainer/redis]# docker service ps nginx
ID                  NAME                IMAGE                  NODE                    DESIRED STATE       CURRENT STATE                 ERROR               PORTS
ujh469k4ta37        nginx.1             nginx:1.13.12-alpine   node2   Running         Running 2 minutes ago
3iodal770wzd         \_ nginx.1         nginx:1.13.7-alpine    node2   Shutdown        Shutdown 2 minutes ago
2dzwc981805l        nginx.2             nginx:1.13.12-alpine   node1   Running         Running 48 seconds ago
cyc3sudi4w8f         \_ nginx.2         nginx:1.13.7-alpine    node1   Shutdown        Shutdown about a minute ago
4dzp1irwv0dh        nginx.3             nginx:1.13.12-alpine   node2   Running         Running about a minute ago
t3l9vn1uspsg         \_ nginx.3         nginx:1.13.7-alpine    node2   Shutdown        Shutdown about a minute ago

通过--image 选项更新了服务的镜像。通过docker service ps nginx可以看到版本更新成功了。

回滚


现在假设我们发现 nginx 服务的镜像升级到 nginx:1.13.12-alpine 出现了一些问题,我们可以使用命令一键回退。

[root@node1 /opt/mycontainer/redis]# docker service rollback nginx
nginx
rollback: manually requested rollback
overall progress: rolling back update: 3 out of 3 tasks
1/3: running   [>                                                  ]
2/3: running   [>                                                  ]
3/3: running   [>                                                  ]
verify: Service converged

[root@node1 /opt/mycontainer/redis]# docker service ps nginx
ID                  NAME                IMAGE                  NODE                    DESIRED STATE       CURRENT STATE             ERROR               PORTS
zjm1b7je4530        nginx.1             nginx:1.13.7-alpine    node2   Running         Running 50 seconds ago
ujh469k4ta37         \_ nginx.1         nginx:1.13.12-alpine   node2   Shutdown        Shutdown 50 seconds ago
3iodal770wzd         \_ nginx.1         nginx:1.13.7-alpine    node2   Shutdown        Shutdown 4 minutes ago
1fqs48zdo3b7        nginx.2             nginx:1.13.7-alpine    node1   Running         Running 18 seconds ago
2dzwc981805l         \_ nginx.2         nginx:1.13.12-alpine   node1   Shutdown        Shutdown 19 seconds ago
cyc3sudi4w8f         \_ nginx.2         nginx:1.13.7-alpine    node1   Shutdown        Shutdown 3 minutes ago
o20xcgwmyjis        nginx.3             nginx:1.13.7-alpine    node2   Running         Running 46 seconds ago
4dzp1irwv0dh         \_ nginx.3         nginx:1.13.12-alpine   node2   Shutdown        Shutdown 46 seconds ago
t3l9vn1uspsg         \_ nginx.3         nginx:1.13.7-alpine    node2   Shutdown        Shutdown 3 minutes ago

通过docker service ps 我们能看到版本变化的详细信息。

原文地址:https://www.cnblogs.com/vinsent/p/docker.html