Ansible管理:一般我们常常使用yml格式进行管理。但yml格式的编写较为苛刻,不好排除错误且比较费时费力

 于是思考,是否能够使用python 协助进行ansible的批量命令管理:

1.ansible搭建

在自己设定的ansible安装位置,设置myansi文件夹,收管理的集群必须与ansible管理主机免密通讯

在下面创建两个文本: ansible.cfg  hosts

Vim ansible:

[defaults]

inventory = hosts   //查看分组情况

remote_user = root //远端登录的用户


Vim hosts:    //设置管理的集群

[dbservers]

node1.XXX.cn

 

[webservers]

node2.XXX.cn

node3.XXX.cn

 

设置远程的hosts

Echo 192.168.4.1{1..3} node {1..3} >> /etc/hosts

设置免应答文件:

ssh-keyscan 192.168.4.1{1..3} node{1..3} node{1..3} node{1..3}.XXX.cn  >> ~/.ssh/known_hosts

检验是否可用ansible ping

ansible all -m ping -k



设置vim小工具,方便配置yml

Vim ~/.vimrc

set ai     #自动缩进

set ts=4  #一个tab=4空格

set et     #tab转化位空格

autocmd FileType yaml setlocal sw = 2 ts = 2 et ai #yaml ts =2 ai et


对比:

 ansible的一般yml操作

1 . 设置密钥/安装yum:

 

vim auth_key.yml

---

- name: configure authorized key

  hosts: all

  tasks:

  - name: root key

    authorized_key:

      user: root

      state: present

      key: "{{ lookup('file', '/root/.ssh/id_rsa.pub') }}"

 

  - name: copy yum file

    copy:

      src: files/dvd.repo

      dest: /etc/yum.repos.d/

 

#语法检测+执行

ansible-playbook --syntax-check auth_key.yml

ansible-playbook auth_key.yml

 

2.安装web,db应用到各个主机上

执行程序:

---

- name: configure web serivce   #创建web任务

  hosts: webservers              #任务所属组

  tasks:                           #具体的执行任务

    - name: install web app      

      yum:

        name: "{{item}}"        #设置变量for循环

        state: present

      with_items:                #yumhttpd

        - httpd

        - php

        - php-mysql

    - name: config web service   #设置开机启动

      service:

        name: httpd

        state: started

        enabled: true

 检测:

ansible-playbook --syntax-check lamp.yml

ansible-playbook lamp.yml

 



Ansiblepython实现

#!/usr/bin/env python
# coding:utf8

import shutil
from collections import namedtuple
# DataLoder用于解析yaml/json/ini
from ansible.parsing.dataloader import DataLoader
from ansible.vars.manager import VariableManager
#用于分析ansible用到的变量
from ansible.inventory.manager import InventoryManager
#主机清单,用于分析主机
from ansible.playbook.play import Play
#剧本模块
from ansible.executor.task_queue_manager import TaskQueueManager
#任务队列管理器
from ansible.plugins.callback import CallbackBase
#callback回调函数
import ansible.constants as C
#ansible简化为C常量


# since API is constructed for CLI it expects certain options to always be set, named tuple 'fakes' the args parsing options object
Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'become', 'become_method', 'become_user', 'check', 'diff'])
options = Options(
connection='smart', module_path=['/to/mymodules'], forks=10, become=None, become_method=None, become_user=None, check=False, diff=False)

#connection有三个选项local/ssh/smart(自动选择)

# initialize needed objects
loader = DataLoader() # Takes care of finding and reading yaml, json and ini files
passwords = dict(vault_pass=None)

#加密登录等,需要的时候才加

#声明ansible管理的主机有哪些,也可以使用主机清单文件,将主机放入列表中
inventory = InventoryManager(loader=loader, sources='/root/PycharmProjects/day016/myansi/hosts'#改到host文件的路径

#各台主机上的参数
variable_manager = VariableManager(loader=loader, inventory=inventory)

#执行命令的时候的名字,这里相当于ansible中的yml

play_source =  dict(
       
name = "Ansible Play",  #play的名字
        hosts = 'webserver',    #在那些主机上执行命令
        gather_facts = 'no',    #不会搜集主机信息
        tasks = [               #执行任务
            dict(action=dict(module='yum', args='name=httpd state=absent'), register='shell_out'),
           
# dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}')))
        
]
    )

# Create play object, playbook objects use .load instead of init or new methods,
# this will also automatically create the task objects from the info provided in play_source
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)

# 任务管理器 使用异常诊断
tqm = None
try
:
    tqm = TaskQueueManager(
             
inventory=inventory,
             
variable_manager=variable_manager,
             
loader=loader,
             
options=options,
             
passwords=None#不加密码写none
         
)
    result = tqm.run(play)
# most interesting data for a play is actually sent to the callback's methods
finally:
   
# we always need to cleanup child procs and the structres we use to communicate with them
   
if tqm is not None:
        tqm.cleanup() 
#清理操作

   
# Remove ansible tmpdir
   
shutil.rmtree(C.DEFAULT_LOCAL_TMP, True)


 

Ansible-playbookpython实现方式

 from collections import  namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars.manager import VariableManager
from ansible.inventory.manager import InventoryManager
from ansible.executor.playbook_executor import PlaybookExecutor



Options = namedtuple(
   
'Options',
    [
       
'connection',
       
'remote_user',
        
'ask_sudo_pass',
       
'verbosity',
       
'ask_pass',
       
'module_path',
       
'forks',
       
'become',
       
'become_method',
       
'become_user',
       
'check',
       
'listhosts',
       
'listtasks',
       
'listtags',
        
'syntax',
       
'sudo_user',
       
'sudo',
       
'diff'
   
]
)

ops = Options(
   
connection='smart',
   
remote_user=None,
   
ask_pass=None,
   
sudo_user=None,
   
forks=5,
   
sudo=None,
   
ask_sudo_pass=False,
   
verbosity=5,
   
module_path=None,
   
become=None,
   
become_method=None,
   
become_user=None,
   
check=False,
   
diff=False,
   
listhosts=None,
   
listtags=None,
   
listtasks=None,
   
syntax=None
)
loader = DataLoader()
passwords =
dict()
inventory = InventoryManager(
   
loader=loader,
   
sources=['myansi/hosts']
)
variable_manager = VariableManager(
   
loader=loader,
   
inventory=inventory
)


def run_pb(pb_path):
    playbook = PlaybookExecutor(
       
playbooks=pb_path,
       
inventory=inventory,
       
variable_manager=variable_manager,
       
loader=loader,
       
options=ops,
       
passwords=passwords
    )
    result = playbook.run()
   
return result

if __name__ == '__main__':
    run_pb(
pb_path=['myansi/lamp.yml'])


自制ansible.copy模块:

#自制一个ansible.copy一样的模块


#!/usr/bin/env python
 
import shutil
from ansible.module_utils.basic import AnsibleModule
#导入自定义的ansible制作模块
 
def main():
    mokuai = AnsibleModule( #编译模块
        argument_spec=dict(
            yuan=dict(required=True, type='str'),
            mudi=dict(required=True, type='str')
        )
)
#将上面定义的内容用shutil从源地址拷贝到目标地址
    shutil.copy(mokuai.params['yuan'], mokuai.params['mudi'])
    mokuai.exit_json(change=True)
#输出为json格式的
 
if __name__ == '__main__':
main()

验证:ansible dbservers -m rcopy -a "yuan=/etc/hosts mudi=/opt"


后记:参考网址

https://docs.ansible.com/ansible/latest/index.html   --查找ansible API ,上面的内容绝大部分都是从这些地方去改模板,一点点调试

使用python写的脚本运行ansible大大简化了操作的繁杂程度,缩短了批量管理时写代码的时间,只需要修改固定的那几个地方,就可以完成了。

有些时候不需要重复的造轮子,但我们需要花更多的时间在研究自动化管理技术上,真正实现高效,可靠管理。