ansible-container 搶先用之踩雷之旅

注意!因為 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-infobuild 兩個資料夾。並且 command-line 中就多了 ansible-container 的指令可以使用。如下圖可先透過 --help 指令,查看目前 ansible-container 提供了哪些 subcommand 可以使用。

試用與除雷

接著我打算直接用官方 repo 中提供的測試範例來試玩一番。

首先進入路徑 test/ansible 中,會發現內含三個檔案 container.ymlrequirements.txtsample.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.ymlbuild-docker-compose-v1.j2.ymllisthosts-docker-compose.j2.ymllisthosts-docker-compose-v1.j2.yml

請將上述 yml 檔內 volumes: 區塊內的 - $DOCKER_CERT_PATH:/docker-certs/ 刪除或註解。修改完記得要重新安裝 ansible-container,附帶一提重新安裝前,最好將 ansible_container.egg-infobuild 兩個資料夾刪除,確保重新安裝時它們也有確實的被重新建立。

# - $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 中的範例 testtest-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.ymlbuild-docker-compose-v1.j2.ymllisthosts-docker-compose.j2.ymllisthosts-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 目前真的還是搶先試用的狀態,如果你真的想用它,最好再等等,等到它更穩定一點比較好。

本次的搶先血淚史就分享到此,謝謝大家的收看。

轉貼本文時禁止修改,禁止商業使用,並且必須註明來自「艦長,你有事嗎?」原創作者 Cheng Wei Chen,及附上原文連結。

工商服務

更多文章