Docker之路-通过swarm管理配置及服务升级回滚
管理密钥
在动态的、大规模的分布式集群上,管理和分发 密码
、证书
等敏感信息是极其重要的工作。传统的密钥分发方式(如密钥放入镜像中,设置环境变量,volume 动态挂载等)都存在着潜在的巨大的安全风险。
Docker 目前已经提供了 secrets
管理功能,用户可以在 Swarm 集群中安全地管理密码、密钥证书等敏感数据,并允许在多个 Docker 容器实例之间共享访问指定的敏感数据。
我们可以用 docker secret
命令来管理敏感信息。接下来我们在上面章节中创建好的 Swarm 集群中介绍该命令的使用。
这里我们以在 Swarm 集群中部署 mysql
和 wordpress
服务为例。
创建密钥
我们使用 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.conf
以 tmpfs
文件系统挂载到容器的 /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
我们能看到版本变化的详细信息。