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。