對於 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 很小,權當拋磚引玉了!
