注意!因為 open source 的工具改版的速度非常快速,而本文提到的 ansible-container 更是一個非常新的專案,恐怕不用幾天的時間,本文就會變成過期文章,因此閱讀之前建議先確認一下 ansible-container 目前的最新狀態,避免因為本文而讓你產生誤解。
(謎之音:所以你寫了一篇超短命的文章。)
本文確實已經過期,超短命的! ansible-container 已經更新好幾回合了,現在按官方文件操作就可以正常試用了喔!
(再次更新,ansible-container 已經 DEPRECATED 了,原本使用它來 build container 的人,請改用 ansible-bender;如果是使用它來 deploy container 至 K8s,則請改用 Ansible Operators。)
Ansible 官方這次更新的 2.1.0.0 版本,其中一個特點就是與 Container 有更好的互動,像官方部落格就特別寫了一篇文《SIX WAYS ANSIBLE MAKES DOCKER-COMPOSE BETTER》來介紹一部分重點。
不僅如此,Ansible 官方其實從五月就悶不吭聲的在 Github 上新建了一個新的工具 ansible-container,目標讓 Ansible 在操控與管理 Container 上能更靈活。
以下就依據目前官方 GitHub 上已釋出的資訊,搶先試用一下 ansible-container
。但文章很長,因為記錄了幾個雷,如果你只想要爽爽順順的試用,那可以跳到最後一個段落,我有將最後除雷完後的環境,做一個簡單的記錄。
如果你很有耐心一起除雷,那就繼續往下看吧!
安裝
ansible-container
必須要手動安裝,所以第一步當然是將官方 repo 先 clone 一份回來。
接著是安裝 docker-compose
,因為根據官方文件 ansible-container
需要依賴 docker-compose library,因此使用它的前提就是你也必須安裝好 docker-compose
。
(但其實不止如此,repo 中還有一個 requirements.txt
請務必閱讀,並將其中所列的 python lib 全都預備齊全為佳,不然可能會踩到雷。)
再來就進到 repo 中透過 python
安裝。
python setup.py install
執行上面的指令後,資料夾內會多出了 ansible_container.egg-info
、build
兩個資料夾。並且 command-line 中就多了 ansible-container
的指令可以使用。如下圖可先透過 --help
指令,查看目前 ansible-container
提供了哪些 subcommand 可以使用。
試用與除雷
接著我打算直接用官方 repo 中提供的測試範例來試玩一番。
首先進入路徑 test/ansible
中,會發現內含三個檔案 container.yml
、requirements.txt
、sample.yml
。
container.yml
= 是用來定義你的 orchestrate containers,在一個 yml 中定義出我需要的 orchestration 是由哪些 container 組成,但其實它就是docker-cmopose.yml
啦。requirements.txt
= 說明所需的 Python library docker-py 的版本,非必備檔案。sample.yml
= 就是ansible playbook
,想要對 container 執行的 tasks 就寫在這裡。
我才準備要爽爽試玩,但在第一個指令 ansible-container build
馬上就遇到錯誤。
No module named docker.engine
在官方 repo 上已經有人反應此 issue,因此只要按著這個 commit 的內容修改 setup.py
,在 packages 那一段補上 'container.docker'
,並再次 python setup.py install
重新安裝 ansible-container
即可解決。
再次執行 ansible-container build
,感覺怪怪的,因為畫面上沒有任何進度顯示,只有一句 Starting Docker build of Ansible Container image…
心理覺得不安,於是再開一個 Terminal,用 docker ps
查看,發現程式確實有在運作, ansible-container
正在 build 一個名為 ansible-container-builder
的 Docker image。
接著就遇到第二個錯誤了,docker client 與 docker server 的版本不合。這問題我當初在架設 GitLab 時也有遇過,當時是設定 GitLab 使用 Docker 來進行 CI 的 build,因此 GitLab 也需要操控 Docker server,但因為 NAS 上的 Docker server 版本太舊,而安裝 GitLab 的環境上的 Docker client 版本較新,兩者無法匹配而導致錯誤發生。
所以此項錯誤要修正很簡單,就是讓 docker client 與 docker server 的版本能匹配即可,因為我是 Server 版本比較舊,於是就按照 Docker 官方步驟 upgrade 測試環境中的 docker server 版本。
第三次執行 ansible-container build
,這一次就有進度顯示,看起來 ansible-container
已開始幫我下載 container.yml
中記載所需的 Docker image 了。
可惜很不幸的,迎接第三次的 ERROR。
在處理第三個錯誤時,因為一心只想要快速解決,很快地瞄到在官方 repo 的 issue 中有人提到這與沒有設定 DOCKER_CERT_PATH
有關,因此沒多想的認為這問題應該是與 Docker daemon 的安全性有關。該不會 Docker daemon 一定要開啟 --tlsverify
的模式吧?這下累人了,因為這設定起來挺麻煩的,因為要與 openssl 打架,設定 server.pem 這些有的沒的東西。
(但其實對方根本不是這個意思啊,我的眼睛怎麼了!)
因此就更想要偷懶了,也許隨便設定一個 DOCKER_CERT_PATH
就能避開這個 ERROR,但很可惜如果設定了錯誤的 DOCKER_CERT_PATH
,只會得到下圖的提示,它還是會叫你好好的把 Docker 官方文件看完並照做一遍。
但其實根本不需如此大費周章,此項 ERROR 可以很簡單的排除,一樣只要修改 repo 中的檔案,並再次重新安裝 ansible-container
即可。
這次要改的檔案是放在 container/templates
之下的 build-docker-compose.j2.yml
、build-docker-compose-v1.j2.yml
、listhosts-docker-compose.j2.yml
及 listhosts-docker-compose-v1.j2.yml
。
請將上述 yml 檔內 volumes
: 區塊內的 - $DOCKER_CERT_PATH:/docker-certs/
刪除或註解。修改完記得要重新安裝 ansible-container
,附帶一提重新安裝前,最好將 ansible_container.egg-info
、build
兩個資料夾刪除,確保重新安裝時它們也有確實的被重新建立。
# - $DOCKER_CERT_PATH:/docker-certs/
如此一來當 ansible-container
在運行時,取用到上述的 template
時,就不會因為 DOCKER_CERT_PATH
沒有設定而導致 Docker 在掛載 volumes 時出現路徑不正確而噴 ERROR。
辛苦過後,讓我嘗試第四次的 ansible-container build
,但結果依舊噴錯。
踩雷到現在覺得這樣不可行,決定重新來過,回歸一個最乾淨與單純環境再來實驗。於是我又重新用 vagrant
建立一個乾淨的 VM,並且將上面所有的雷都預先修正完畢。
但令人沮喪的是,即便如此結果還是有錯,當 ansible-container
建立並運行 ansible-container-builder
之後,它應該要透過 ansible-container-builder
來連上 container.yml
中所設定 host1、host2 這兩個 container,並執行 sample.yml
中的 tasks 才對。然而畫面上卻會噴錯表示 “Cannot connect to the Docker daemon.”。
踩雷到現在不知道各位的耐心還夠嗎?接下來大概還有三個錯誤,但為了不再占用更多的篇幅,我就僅用簡單描述了。
- 為了解決 “Cannot connect to the Docker daemon.”,索性直接修改
build-docker-compose.j2.yml
,讓ansible-container-builder
運行時會將/run/docker.sock
掛載進 container 之中。 - 另外還碰到噴錯誤表示 “error while loading shared libraries: libapparmor.so.1: cannot open shared object file: No such file or directory”。一樣修改
build-docker-compose.j2.yml
,讓ansible-container-builder
運行時會將這些缺少的 .so 全部都掛載進 container 之中。 - 再來
ansible-container
可以順利運行 tasks 了,但官方 repo 中的範例test
、test-v1
,在container.yml
所指定用來建立 host1、host2 的 Docker image 都是ubuntu:trusty
。如果你有用過這個 Image 你就會知道它裡面是沒有 python 的!所以又噴錯啦!因為你要ansible
如何在沒有 python 的環境上幫你運行 tasks?最後只好自己另外 build 一個包含了 python 的ubuntu:trusty
,並修改container.yml
讓它改用我指定的 Image。
除雷結果
經過了上述的踩雷之旅,我終於能爽爽的試用 ansible-container
了,如果你也想要爽爽的試用,以下是我終於成功的環境記錄,你可以參考照做,應該就能爽爽試用。
利用
vagrant
建立一台乾淨的 VM。我選用的 vagrant box 是
bento/ubuntu-14.04
。VM 建立之後記得
apt-get update; apt-get -y upgrade
更新一下,並安裝 wget、vim、git 等必備軟體。安裝 Docker。
安裝 pip、Ansible。
安裝
requirements.txt
中列出的所有 python lib,包含 docker-compose。設定
nameserver 8.8.8.8
,避免有時會遇到無法連上 docker hub 下載 Docker image 的問題。git clone
官方 repo。修改
setup.py
,在 packages 那一段補上'container.docker'
。修改
container/templates
之下的build-docker-compose.j2.yml
、build-docker-compose-v1.j2.yml
、listhosts-docker-compose.j2.yml
及listhosts-docker-compose-v1.j2.yml
。將
- $DOCKER_CERT_PATH:/docker-certs/
與- {{ which_docker }}:/usr/bin/docker
改為註解。# - $DOCKER_CERT_PATH:/docker-certs/ # - {{ which_docker }}:/usr/bin/docker
續上同樣修改這四個檔案,在
volumes:
區段中補上- /usr/bin/docker:/usr/bin/docker - /run/docker.sock:/var/run/docker.sock - /usr/lib/x86_64-linux-gnu/libapparmor.so.1.1.0:/lib/x86_64-linux-gnu/libapparmor.so.1 - /lib/x86_64-linux-gnu/libsystemd-journal.so.0.10.2:/lib/x86_64-linux-gnu/libsystemd-journal.so.0 - /lib/x86_64-linux-gnu/libcgmanager.so.0.0.0:/lib/x86_64-linux-gnu/libcgmanager.so.0 - /lib/x86_64-linux-gnu/libnih.so.1.0.0:/lib/x86_64-linux-gnu/libnih.so.1 - /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0:/lib/x86_64-linux-gnu/libnih-dbus.so.1 - /lib/x86_64-linux-gnu/libdbus-1.so.3.7.6:/lib/x86_64-linux-gnu/libdbus-1.so.3 - /lib/x86_64-linux-gnu/libgcrypt.so.11.8.2:/lib/x86_64-linux-gnu/libgcrypt.so.11
執行
python setup.py install
進入資料夾 test 或 test-v1 中,再執行
ansible-container build
即可!順利 build 完成後,你就可以執行
ansible-container run
,就就如同docker-compose up
一樣,ansible-contianer
就會幫你把 container 都運行起來。
好啦,其實我有把上述步驟改寫一個簡單的 Vagrantfile + shell script,幫大家省一點時間。 (謎之音:怎麼不寫成 ansible playbook?答:為了搶快嘛,你沒看到這個 script 寫得多土法煉鋼~)
再補充一個 issue,如果你要執行的 tasks 需要較長的執行時間,那有可能會遇到 timeout 的問題,這部分尚沒看到有進一步的回應,所以如果要用自己的 playbook 來測試 ansible-container,最好挑簡單一點的,不然就找網路速度較佳的環境測試,因為我自己測試時也遇過在 apt-get install 的 task 中發生 timeout。
小結
經過了踩雷之旅,並稍微查看過程式碼之後,可以理解到 ansible-container
的運作方式大致如下:
- 它等於是在
docker-compose
外再包一層 command 來幫助你操控docker-compose
- 它會先 build 出
ansible-container-builder
這個 image,接著將它運行為 container,再透過它來幫你 build 及執行 playbook 來完成其他 container 的配置管理。
因此 ansible-container
它提供了一個新的可能性,它讓你原本已經學會的 docker-compose 及 ansible playbook 的能力可以結合在一起使用。個人覺得這一步走的不錯,似乎也不得不走,因為 Container 的勢力如此茁壯,配置管理工具們勢必都會需要往它靠攏,避免客群流失。其中一種應對方式就是讓原本已習慣使用自家工具的使用者,可以繼續用與原本相同或類似的操作方式即能進入 Container 的世界。
ansible-container
目前真的還是搶先試用的狀態,如果你真的想用它,最好再等等,等到它更穩定一點比較好。
本次的搶先血淚史就分享到此,謝謝大家的收看。