对于 devops 来说,容器技术绝对是我们笑傲江湖的法宝。本文通过一个小 demo 来介绍如何使用容器技术来改进我们的 devops 工作流。
devops 的日常工作中难免会有一些繁琐的重复性劳动。比如管理 Azure 上的各种资源,我们会使用 Azure CLI 工具。同时我们也会使用 Ansible 完成一些自动化的任务。当我们同时使用二者的时候就会碰到一些尴尬的事情:Azure CLI 依赖的 python 版本为 3.x,而 Ansible 的主流版本还在依赖 python 2.x。如果我们要同时使用二者,就需要在环境中搞一些飞机。如果团队中的每个成员都需要使用这样的工具,那么每个人的环境中都需要这些飞机!下面是一些比较类似的问题:
- 一些工作流在陌生的环境中不能正确的工作
- 在工作流中加入新的工具时,整个团队都需要获取并安装这些新的工具
- 运行 devops 工作流不能对当前的环境产生影响(应该允许在 build 环境中运行 devops 工作流)
- 工作流的变化不会对运行环境产生任何的影响
实现这些需求的最好方式就是容器技术!通过容器把我们的 devops 工作流和运行环境隔离开就可以了。文本的 demo 会演示一个非常简单的使用 Azure CLI 的工作流,我们的目标是为整个团队打造一个满足以上需求的工具集(容器镜像)。其大体步骤如下:
- 创建构造容器镜像的 Dockerfile 文件
- 在本地构建容器镜像并进行测试
- 对容器镜像不断的升级完善
- 把容器镜像分享给整个团队
构建容器镜像
让我们使用 Dockerfile 来创建自己的容器镜像。先创建目录 cazurecli,并在目录下创建 Dockerfile 文件:
$ mkdir cazurecli $ cd cazurecli $ touch Dockerfile
编辑 Dockerfile 文件的内容如下:
FROM microsoft/azure-cli:latest CMD bash
其中的 FROM 指令用来指定 base 镜像,这里我们直接使用了微软提供的 azrue-cli 镜像,只是把容器启动时执行的命令通过 CMD 指令设置为 bash。
然后执行下面的命令构建容器:
$ docker build -t azcli .
上图的输出显示容器镜像构建成功,我们可以通过 azcli:latest 来引用新构建的容器镜像。那就让我们启动容器并执行 azure cli 命令:
$ docker run --rm -it azcli:latest
进入容器中的命令行后,尝试通过 az account list 查看 azure 账号信息:
bash-4.3# az account list
红框中的信息是提示我们先通过 az login 命令登录才能查看账号信息:
bash-4.3# az login
然后按照提示信息打开浏览器,输入验证码进行登录。在浏览器中登录完成后命令行上的登录过程也随之完成,然后重新执行 az account list 命令:
这样就可以输出你的账号信息了。
解决 Azure CLI 的登录问题
如果你实验了 az login 命令,就会发现登录的过程还是挺繁琐的,如果每次启动容器都需要执行登录操作你会怎么想呢?肯定是弱爆了!
好在我们可以通过 bind mount 的方式把 azure 的登录信息保存在 host 的文件中。以后启动容器时挂载这些登录信息就可以了。下面是具体的步骤。
先在用户的家目录中创建 .azure 目录:
$ mkdir ${HOME}/.zaure
然后启动一个容器并以 bind 的模式挂载 .azure 目录:
$ docker run --rm -it --mount type=bind,source=${HOME}/.azure,target=/root/.azure azcli
在容器中进行一次登录操作:
# az login
登录完成后,登录的信息被保存到了 /root/.azure 目录中:
退出当前的容器,执行下面的命令创建一个新的容器:
$ docker run --rm -it --mount type=bind,source=${HOME}/.azure,target=/root/.azure azcli
然后再执行一次 az account list 命令试试,这次就不需要登录了!
注意:即便这样也不是一劳永逸的,默认的登录信息过期时间为两周,到时候你需要再次进行登录。
添加自定义的工作流
对于一名 devops 工程师来说,我们在 azure 上的操作多是一些枯燥的重复动作。
比如:
- Start/Stop/Deallocate/Restart 数量众多的虚机
- 检查大量的虚机状态
- 拿到 IP 地址后查出对应的主机名称等等
其实我们可以把这样的功能进行封装,从而简化具体的操作。下面我们举个简单的例子,就是把查询 ResourceGroup 和虚机的操作封装成 bash 中的函数。先在 cazurecli 目录下创建 scripts 目录:
$ mkdir scripts
然后在 scripts 目录下创建 search.sh 文件:
$ touch scripts/search.sh
编辑 search.sh 文件的内容如下:
#!/bin/bash # search for Resource Group by name function search-group () { query=$1 az group list --query "[?name | contains(@,'$query')].{ResourceGroup:name}" -o table } # search for VM by name function search-vms () { query=$1 az vm list --query "[?name | contains(@,'$query')].{ResourceGroup:resourceGroup,Name:name}" -o table }
在这段脚本中我们定义了两个函数,分别是通过名称来查询 ResourceGroup 和虚机(要了解相关的查询语法,请参考 az 命令)。
下面我们把 search.sh 脚本集成到容器的镜像中,并把脚本中的函数导入到 bash,编辑 Dockerfile 如下:
FROM microsoft/azure-cli:latest COPY scripts/ scripts/ RUN echo -e " ; for f in /scripts/*; do chmod a+x ${f}; source ${f}; done;" >> ~/.bashrc CMD bash
用新的 Dockerfile 重新构建容器镜像:
$ docker build -t azcli .
创建容器并尝试使用 search-group 和 search-vms 函数:
$ docker run --rm -it --mount type=bind,source=${HOME}/.azure,target=/root/.azure azcli bash-4.3# search-group learnrg bash-4.3# search-vms testdesktop
这样用起来是不是简便很多了!如果我们把常用的操作都写成脚本封装起来,是不是就能够打造一系列的自动化工作流了!
把镜像放在 docker hub 上进行共享
demo 虽小,但我们还是要完成一个完整的用例的最后一步,就是在整个团队中分享上面创建的容器化工作流。具体的做法大概有两种:
- 通过 dockerhub 等第三方平台分享容器镜像
- 在公司内搭建内部使用的镜像管理平台
两种方式都很方便,喜欢第二种方式的朋友可以参考笔者的博文《局域网内部署 Docker Registry》。这里只简单的介绍一下 dockerhub 的用法。首先你需要去 dockerhub 的官网注册一个账号,注册后创建一个 repository,比如笔者的用户名为 ljfpower,新创建的 repository 名称为 azcli。然后需要在本地通过 docker login 命令进行登录。登录后为本地的容器镜像创建一个 tag,比如:
$ docker tag azcli ljfpower/azcli
最后一步便是把这个 tag 标识的容器镜像推送到 dockerhub 上去:
$ docker push ljfpower/azcli:latest
推送完成后你会在 dockerhub 上看到你的镜像:
简单起见笔者使用的是公有镜像,也就是任何人都可以下载使用该镜像。所以你只需要一条 pull 命令就可以享受别人分享的工作流了:
$ docker pull ljfpower/azcli
总结
我们打造了一个工具包,并把它容器化了。因此任何的团队成员都可以通过容器在自己的环境中无差别的运行这些工作流。
这就是生产力呀!因为没人会再抱怨:"这个工具配置起来好恶心","为什么在我的机器上运行不了 xxx" ...
同时,如果需要,你可以在任何环境中运行这些工作流,比如构建产品的服务器上,因为运行这些工作流并不需要安装额外的工具(python、azure cli 等)。
本文的名字起的很大而 demo 很小,权当抛砖引玉了!