9/24/2015

Ansible結合Docker的使用方式

前言

為什麼不直接用Docker就好?
以現況來說,如果服務暫時無法移植到container執行, 要在私有雲上跑, 仍然需使用Ansible或是Chef或是Puppet這一類的工具。

目標

讓習慣Ansible的開發人員用原有的腳本在筆電上重複進行部署測試。
單純利用Docker的好處節省在開發機上安裝一堆VM (節省安裝OS的時間&空間)。
學習少量的Docker指令。

觀念

Ansible是從common role負責安裝所有的機器, 再由其他role安裝與設定其他各式Server。
Ansible需要為各種role撰寫playbook。
Docker的觀念是通過建立自己的base image 例如from Cent OS 7, 設置防火牆 VPN 與時區校正之後, commit, tag, 再從base image上安裝軟體變成各式Server。
用docker-compose以及links可以直接組裝許多Official images, 基本上只需要設計服務所需要的Application layer的images。
Docker需要為各種image撰寫Dockerfile。

安裝Docker

請按照官方步驟在Mac安裝完Docker環境之後在spotlight可以找到docker QuickStart Terminal 
你會得到一隻鯨魚以及一個IP, 那個就是虛擬機的IP, 請抄起來。

假設我們需要1台空白機讓Ansible管理, 執行:
bash-3.2$ docker run -d shooding/docker-ubuntu-openssh
bash-3.2$ docker ps
你會看到1台機器(container)正在執行。

這裏我解釋一下參數
-d = daemon背景模式執行
shooding/docker-ubuntu-openssh 是我放在docker hub上面的image名稱
如果有興趣可以看一下Dockerfile的寫法, 這裏使用的是Ubuntu 14.04 LTS版本。

安裝Ansible
$ brew install ansible

設定Inventory

Inventory就是要被Ansible管理的機器群。
剛剛已經用docker開好1台機器(container), 一般會分成staging和production來區分環境。
現在是在筆電上進行測試, 使用staging
把container的資訊加入到~/staging

$ vim ~/staging

請把IP換成你剛剛抄起來的IP。請把account換成你的User名稱。
[app_servers] 
app-1 ansible_ssh_host=192.168.99.100 ansible_ssh_port=2222

[app_servers:vars]

ansible_connection=ssh
ansible_ssh_user=root

將Ansible的Inventory路徑設定到環境變數當作預設值
$ vim ~/.profile
$ export ANSIBLE_HOSTS=/Users/shooding/staging
$ source ~/.profile

測試一下對於1台機器的連接狀況
$ ansible all -m ping 
你會得到...

用過Ansible就知道它是透過SSH連到被控制的主機(node)

因此我們需要將docker的SSH port forward出來, 並且將公鑰複製進去被控制的機器。
如果你還不會產生SSH 公鑰/私鑰, 請先完成產生SSH金鑰 的步驟。
或是直接執行:
$ ssh-keygen
會產生~/.ssh/id_rsa和~/.ssh/id_rsa.pub

那麼...

剛剛忘記把docker的port forward出來, 再進行一次吧
先停止所有的機器
bash-3.2$ docker stop $(docker ps -q)
bash-3.2$ docker run -d -p "2222:22" shooding/docker-ubuntu-openssh

參數說明 -p port forward 將SSH port 22 對應到外埠2222
也就是在ansible裡面設定的ansible_ssh_port = 2222

接著將公鑰複製進去被控制的機器
bash-3.2$ docker cp ~/.ssh/id_rsa.pub 660246bd6146:/root/.ssh/authorized_keys
660246bd6146 (這裏請換成你的 container id )

使用Ansible測試連接是否成功?
$ ansible all -m ping
參數說明: 使用ping module測試所有機器
XXXX | success >> {
    "changed": false,
    "ping": "pong"
}


成功了, 在這之後就可以照原來Ansible的使用方法囉!

附錄小幫手
如果你需要所有機器的private IP, 有時候建置互相連接的cluster會用到
bash-3.2$ docker inspect $(docker ps -q) | grep '"IPAddress"'

TODO
其實我很想要省掉docker cp的操作, 而直接將id_rsa.pub透過 docker -v 參數分享空間到
container裡面。例如開機器的時候改成:
docker run -d -p "2222:22" -v ~/.ssh/id_rsa.pub:/root/.ssh/authorized_keys shooding/docker-ubuntu-openssh

但是很可惜這樣做會造成SSH無法登入, 大神請在回應中點評一下。