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: #yum装httpd
- 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
Ansible的python实现
#!/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-playbook的python实现方式
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大大简化了操作的繁杂程度,缩短了批量管理时写代码的时间,只需要修改固定的那几个地方,就可以完成了。
有些时候不需要重复的造轮子,但我们需要花更多的时间在研究自动化管理技术上,真正实现高效,可靠管理。