ansible是目前業界很是火熱的自動化運維工具。ansible能夠經過ssh鏈接到目標機器上,從而完成指定的命令或者操做。
在kubernetes集羣中,由於並非全部的服務都是那麼容器化。有時候也會用到ansible進行一些批量運維的工做。
一種方式是能夠在容器中啓動ssh,而後再去鏈接執行。可是並非全部的容器都會啓動ssh。html
針對於這種狀況,我想到了直接用kubectl進行鏈接操做,所以開發了kubectl的connection插件,並貢獻給了社區。
該功能無需容器中啓動ssh服務便可使用,已經合入ansible的主幹,自ansible 2.5版本後隨ansible發佈。
詳細操做文檔能夠參考https://docs.ansible.com/ansible/latest/plugins/connection/kubectl.html。本文將對其主要功能和設計的思路原理進行一下介紹。python
ansible 2.5後內置了該connection plugin,因此以後的版本均可以自動支持。若是是以前的版本,須要自行合併該PR。git
PR參考:https://github.com/ansible/ansible/commit/ca4eb07f46e7e3112757cb1edc7bd71fdd6dacad#diff-12d9b364560fd0bec5a1cee5bd0b3c24。github
該connection plugin須要使用kubectl的二進制文件,務必將kubectl先進行安裝,通常能夠放置在/usr/bin下。sql
如下是一個inventory的配置。docker
[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的鏈接插件。shell
ansible_kubectl_kubeconfig
用於標識使用的kubeconfig的位置。固然,也支持使用無認證、使用用戶名密碼認證等等方式進行鏈接。這些配置能夠參考官網的說明: https://docs.ansible.com/ansible/latest/plugins/connection/kubectl.html#parameters運維
在inventory配置完成後,便可進行ansible的操做了。這裏咱們查看一下當前的工做目錄。ssh
[root@f34cee76e36a kubesql]# ansible -i inventory kube-test -m shell -a "pwd" hcnmore-32385abb-9f753dda-nxr8h | CHANGED | rc=0 >> /
該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=1 changed=1 unreachable=0 failed=0
能夠看到在目標機器上成功進行了命令執行。
kubectl connection plugin不只支持命令的執行,其餘如cp文件、fetch文件等基本操做均可以執行。固然如執行shell、script腳本、密鑰管理等複雜操做也均可以經過這個插件進行執行。可是這些複雜操做有的須要目標機器上安裝python等環境進行支持,這個要根據不一樣模塊的需求具體來看。
使用openshift的插件oc的使用方式與kubectl相似,這裏不重複介紹了。
能夠說這個kubectl的插件能夠解決大部分的平常運維操做,可是也有一些弊端,就是使用kubectl的二進制進行鏈接。每次每一個鏈接都須要啓動一個進程進行kubectl執行,並且鏈接速度不快。所以不太適合大批量的容器高頻操做。
我我的的建議是能夠用這個插件進行注入密鑰、低頻啓停服務的運維操做。大批量的操做仍然最好使用ssh進行。
ansible的connection plugin有不少,目前支持的有ssh、docker、kubectl等等。要實現一個ansible的鏈接插件,其實主要實現的是三個接口:
這三個接口對應三個原生的模塊,依次是raw,cp和fetch。而ansible的幾乎全部複雜功能,都是經過這三個接口來進行實現的。好比shell或者script,就是經過將腳本或者命令造成的腳本cp到目標機上,然後進行命令執行完成的。
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。