使用ansible kubectl外掛連線kubernetes pod以及實現原理
ansible kubectl connection plugin
ansible是目前業界非常火熱的自動化運維工具。ansible可以通過ssh連線到目標機器上,從而完成指定的命令或者操作。
在kubernetes叢集中,因為並不是所有的服務都是那麼容器化。有時候也會用到ansible進行一些批量運維的工作。
一種方式是可以在容器中啟動ssh,然後再去連線執行。但是並不是所有的容器都會啟動ssh。
針對於這種情況,我想到了直接用kubectl進行連線操作,因此開發了kubectl的connection外掛,並貢獻給了社群。
該功能無需容器中啟動ssh服務即可使用,已經合入ansible的主幹,自ansible 2.5版本後隨ansible釋出。
詳細操作文件可以參考https://docs.ansible.com/ansible/latest/plugins/connection/kubectl.html 。本文將對其主要功能和設計的思路原理進行一下介紹。
安裝使用
ansible 2.5後內建了該connection plugin,所以之後的版本都可以自動支援。如果是之前的版本,需要自行合併該PR。
PR參考:https://github.com/ansible/ansible/commit/ca4eb07f46e7e3112757cb1edc7bd71fdd6dacad#diff-12d9b364560fd0bec5a1cee5bd0b3c24。
該connection plugin需要使用kubectl的二進位制檔案,務必將kubectl先進行安裝 ,一般可以放置在/usr/bin下。
操作樣例
以下是一個inventory的配置。
[root@f34cee76e36a kubesql]# cat inventory [kube-test:vars] ansible_connection=kubectl ansible_kubectl_kubeconfig=/etc/kubeconfig [kube-test] hcnmore-32385abb-9f753dda-nxr8h ansible_kubectl_namespace=nevermore
對於kube-test組,ansible_connection=kubectl
用於標識使用kubectl的連線外掛。
ansible_kubectl_kubeconfig
用於標識使用的kubeconfig的位置。當然,也支援使用無認證、使用使用者名稱密碼認證等等方式進行連線。這些配置可以參考官網的說明:https://docs.ansible.com/ansible/latest/plugins/connection/kubectl.html#parameters
在inventory配置完成後,即可進行ansible的操作了。這裡我們檢視一下當前的工作目錄。
[root@f34cee76e36a kubesql]# ansible -i inventory kube-test -m shell -a "pwd" hcnmore-32385abb-9f753dda-nxr8h | CHANGED | rc=0 >> /
playbook樣例使用
該connection plugin同樣支援使用playbook對批量任務進行執行。以下是一個playbook的樣例。
- hosts: kube-test gather_facts: False tasks: - shell: pwd
我們複用了先前樣例的inventory進行執行,同時開啟-v
進行觀察。
[root@f34cee76e36a kubesql]# ansible-playbook -i inventory playbook -v Using /etc/ansible/ansible.cfg as config file PLAY [kube-test] ************************************************************************************************************************************************************************************************* TASK [shell] ***************************************************************************************************************************************************************************************************** changed: [hcnmore-32385abb-9f753dda-nxr8h] => {"changed": true, "cmd": "pwd", "delta": "0:00:00.217860", "end": "2019-03-18 20:55:39.479859", "rc": 0, "start": "2019-03-18 20:55:39.261999", "stderr": "", "stderr_lines": [], "stdout": "/", "stdout_lines": ["/"]} PLAY RECAP ******************************************************************************************************************************************************************************************************* hcnmore-32385abb-9f753dda-nxr8h : ok=1changed=1unreachable=0failed=0
可以看到在目標機器上成功進行了命令執行。
優勢與弊端
kubectl connection plugin不僅支援命令的執行,其他如cp檔案、fetch檔案等基本操作都可以執行。當然如執行shell、script指令碼、金鑰管理等複雜操作也都可以通過這個外掛進行執行。但是這些複雜操作有的需要目標機器上安裝python等環境進行支援,這個要根據不同模組的需求具體來看。
使用openshift的外掛oc的使用方式與kubectl類似,這裡不重複介紹了。
可以說這個kubectl的外掛可以解決大部分的日常運維操作,但是也有一些弊端,就是使用kubectl的二進位制進行連線。每次每個連線都需要啟動一個程序進行kubectl執行,而且連線速度不快。因此不太適合大批量的容器高頻操作。
我個人的建議是可以用這個外掛進行注入金鑰、低頻啟停服務的運維操作。大批量的操作仍然最好使用ssh進行。
實現原理
ansible connection plugin
ansible的connection plugin有很多,目前支援的有ssh、docker、kubectl等等。要實現一個ansible的連線外掛,其實主要實現的是三個介面:
- exec_command: 在目標機執行一個命令,並返回執行結果。
- put_file: 將本地的一個檔案傳送到目標機上。
- fetch_file: 將目標機的一個檔案拉回到本地。
這三個介面對應三個原生的模組,依次是raw,cp和fetch。而ansible的幾乎所有複雜功能,都是通過這三個介面來進行實現的。比如shell或者script,就是通過將指令碼或者命令形成的指令碼cp到目標機上,而後進行命令執行完成的。
kubectl exec
kubectl exec天然就是執行命令的。docker client 有cp的功能,但是kubectl並不具有(kubectl 1.5版本後也支援了cp)。這裡用了一個小的技巧,就是使用dd命令配合kubectl exec進行檔案的傳輸和拉取。
因此要求目標容器中也要有dd命令,否則該外掛也無法工作。
dd主要用於讀取、轉換和輸出資料。我們將一個src檔案拷貝到另外一個地方dest,可以使用dd if=/tmp/src of=/tmp/dest
。dd也支援從標準輸入中獲取資料或者輸出到標準輸出中。因此拷貝也就可以使用dd if=/tmp/src | dd of=/tmp/dest
的方法。
理解了這些,我們就可以使用kubectl來進行檔案的傳輸了。那麼向容器中傳輸檔案的方式就可以使用dd if=/tmp/src | kubectl exec -i podname dd of=/tmp/dest
。反過來,從容器中拉取檔案就對應可以使用kubectl exec -i podname dd of=/tmp/src | dd of=/tmp/src
。
特別注意,向容器中傳輸檔案的-i
引數是必須的。因為需要用-i引數開啟支援kubectl從標準輸入中獲取資料。
這樣就通過kubectl exec,實現了執行命令、檔案傳輸以及拉取的效果。對應在ansible的connection plugin中進行實現,即可使得kubernetes的pod容器也支援ansible的運維控制。具體實現程式碼就不再重複講述,詳細可以參考https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/connection/kubectl.py 。