Python_Ansible-playbooks编程

Ansbile基础
Ansible概述
Ansible简介
安装ansible
配置运行环境
Ansible应用
使用playbook
Yaml简介
Yaml语法
配置VIM
使用模块
创建playbook
执行playbook

Ansbile基础

Ansible概述

Ansible简介

• Ansible是一个配置管理和配置工具,类似于Chef,Puppet或Salt
• 这是一款很简单也很容易入门的部署工具,它使用 SSH 连接到服务器并运行配置好的任务 
• 服务器上不用安装任何多余的软件,只需要开启ssh, 所有工作都交给client端的ansible负责

准备环境

启动三台虚拟机:

localhost 192.168.138.129/24
web1 192.168.138.130/24
web2 192.168.138.131/24
web3 192.168.138.132/24
[root@localhost ~]# vim /etc/hosts
192.168.138.130  web1
192.168.138.131  web2
192.168.138.132  web3
192.168.138.129  localhos
[root@localhost ~]# for i in web1 web2 web3 
> do
> rsync -av /etc/hosts ${i}:/etc/
> ssh ${i} reboot
> done
[root@localhost ~]# cd /root/.ssh/
[root@localhost .ssh]# ssh-keygen -b 1024 -t rsa -f id_rsa -P ""

收集主机密钥:

[root@localhost ~]# ssh-keyscan web1 web2 web3 >> ~/.ssh/known_hosts

安装ansible

• 在线安装 
[root@localhost ~]#	pip3 install -i  https://pypi.douban.com/simple/ ansible
[root@localhost ~]# yum -y install ansible
• 使用本地安装包 
	– 参见《大型技术架构》课程ansible安装

配置运行环境

• 创建ansible工作目录 
[root@localhost ~]#	mkdir /root/ansible
• 创建配置文件 
[root@localhost ~]#	cd /root/ansible
[root@bogon ansible]# vim ansible.cfg
[defaults]
inventory =	hosts
remote_user = root

配置运行环境(续1)

• 声明被管理主机 
[root@localhost ansible]# vim hosts	
[web]
web1

[webservers]
web2
web3

配置运行环境(续2)

[root@localhost ansible]# ansible all -m ping -k
SSH password: 
web1 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
web3 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
web2 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

Ansible应用

使用playbook

• Playbooks是Ansible的配置、部署、编排语言。 
• 它们可以被描述为一个需要希望远程主机执行命令的方案,或者一组程序运行的命令集合 
• Playbook由一到多个Play组成 
• 每个play可以指定哪些主机执行哪些任务 
• 执行任务一般通过调用模块来实现

Yaml简介

• Playbooks的格式是YAML
• 语法做到最小化,意在避免 playbooks 成为一种编程语言或是脚本 
• 使用 YAML 是因为它像 XML 或 JSON 是一种利于人们读写的数据格式

Yaml语法

• 每一个 YAML 文件都是从一个列表开始 
• 列表中的每一项都是一个键值对, 通常它们被称为一个 "哈希""字典"
• 所有的 YAML 文件开始行都应该是 ---。这是 YAML 格式的一部分,表明一个文件的开始 
• 列表中的所有成员都开始于相同的缩进级别,并且使用一个 "- " 作为开头(一个横杠和一个空格) 
• 一个字典是由一个简单的 键: 值 的形式组成(冒号后面必须是一个空格) 

配置VIM

• Yaml的缩进不能使用tab键 
• 建议缩进为两个空格 
• 为了实现yml文件按tab键缩进两个空格,可以按以下方式 对vim进行定制
[root@localhost myansi]# cat ~/.vimrc
autocmd FileType yaml setlocal sw=2	ts=2 et	ai

使用模块

• Ansible的模块实际上就是一个个的python程序文件 
• Ansible执行任务就是通过调用这些模块来完成的 
• 查看模块列表
[root@localhost myansi]# ansible-doc -l
• 查看模块帮助
[root@localhost myansi]# ansible-doc yum

创建playbook,实现免密登陆

调整vim的配置,使它能够适应yaml的语法

[root@localhost ansible]# vim ~/.vimrc 
set ai
set ts=4
set et
set encoding=utf8
autocmd FileType yaml setlocal sw=2 ts=2 et ai
[root@room8pc16 ~]# ansible-doc authorized_key
[root@localhost myansi]# vim install_web.yml
---
- name: 服务器
  hosts: all
  tasks:
    - name: 免密登陆
      authorized_key:
        user: root
        state: present
        key: "{{ lookup('file', '/root/.ssh/id_rsa.pub') }}"

执行playbook

• 检查语法 
[root@localhost ansible]# ansible-playbook --syntax-check auth.yml
• 执行
[root@localhost ansible]# ansible-playbook auth.yml -k

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vTyQlAx5-1584802721423)(C:\Users\Administrator\Desktop\Ansible\图片\ansible.png)]

通过playbook配置yum

---
- name: 服务器
  hosts: all
  tasks:
    - name: cp repo
      copy:
        src: files/server.repo
        dest: /etc/yum.repos.d/server.repo

playbook:在dbservers上配置mariadb,在webservers上配置apache

# 检查web服务器是否安装了mariadb-server
[root@localhost ansible]# ansible all -m yum -a "list=mariadb-server"
[root@localhost ansible]# vim lamp.yml
---
- name: dui web
  hosts: web
  tasks:
    - name: install mariadb
      yum:
        name: mariadb-server
        state: present
    - name: start mariadb
      service:
        name: mariadb
        state: started
        enabled: yes

- name: configure webservers
  hosts: webservers
  tasks:
    - name: install apache
      yum:
        name: [httpd, php, php-mysql]
        state: latest
    - name: start httpd
      service:
        name: httpd
        state: started
        enabled: yes
[root@localhost ansible]# ansible-playbook --syntax-check lamp.yml
[root@localhost ansible]# ansible-playbook lamp.yml

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gVg7JA4j-1584802721425)(C:\Users\Administrator\Desktop\Ansible\图片\ansible1.png)]

Ansible编程
Ansible编程基础
命名元组
Ansible常用属性
ad-hoc模式
使用TaskQueueManager
导入模块
设置参数
执行ad-hoc命令
调用playbook
Playbook编程概述
相关模块
创建元组
创建其他相关参数
执行playbook

Ansible编程

Ansible编程基础

命名元组

Ansible官方手册 — > Ansible Documentation — > 搜索python api。把python api example中的代码复制粘贴到adhoc.py

[root@localhost ansible]# python3 adhoc.py

命名元组:为元组的下标起名,仍然具有元组的属性

• 命名元组与普通元组一样,有相同的表现特征,其添加的功能就是可以根据名称引用元组中的项 
• collections 模块提供了namedtuple()函数,用于创建自定义的元组数据类型
>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y', 'z'])
>>> p1 = Point(10, 20, 25)
>>> len(p1)
3
>>> p1[0]
10
>>> p1[1:]
(20, 25)
>>> p1.x
10
>>> p1.y
20
>>> p1.z
25

Ansible常用属性

from ansible.parsing.dataloader import DataLoader
		– 用来加载解析yaml文件或JSON内容,并且支持vault的解密 
• from ansible.vars.manager import VariableManager
		– 管理变量的类,包括主机,组,扩展等变量 
• from ansible.inventory.manager import InventoryManager
		– 用于创建主机清单,主机清单的源采用配置文件或是逗号分开主机名字符串

ad-hoc模式

使用TaskQueueManager

• 创建TaskQueueManager实例,用于管理子进程、通过主机列表和任务建立对象 
• TaskQueueManager需要主机清单参数、主机变量参数、连接选项等

导入模块

• 不管是执行ad-hoc还是playbook都需要以下模块
#!/usr/bin/env python

import shutil
from collections import namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars.manager import VariableManager
from ansible.inventory.manager import InventoryManager
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
import ansible.constants as C

设置参数

• 运行命令时有很多参数要指定,这些参往往很长,可以先把它们提前定义出来
Options	= namedtuple('Options',	['connection', 'module_path', 'forks',	
'become', 'become_method', 'become_user', 'check', 'diff'])
options	= Options(connection='local', module_path=[''],	forks=10,	
become=None, become_method=None, become_user=None, check=False, diff=False)
loader = DataLoader()
passwords = dict(vault_pass='secret')
inventory = InventoryManager(loader=loader,	sources='localhost,')
variable_manager = VariableManager(loader=loader,	
inventory=inventory)

设置参数( 续1 )

• 运行命令时有很多参数要指定,这些参往往很长,可以先把它们提前定义出来
play_source = dict(
    name = "Ansible Play",
    hosts =	'localhost',
    gather_facts = 'no',
    tasks =	[
    	dict(action=dict(module='shell', args='mkdir /tmp/mytestdir'), register='shell_out'),
    ]
	)
play = Play().load(play_source,	variable_manager=variable_manager, loader=loader)

执行ad-hoc命令

• 创建实例并执行命令
tqm = None
try:
    tqm = TaskQueueManager(
        inventory=inventory,
        variable_manager=variable_manager,
        loader=loader,
        options=options,
        passwords=passwords,
)
	result = tqm.run(play)	
finally:
	if	tqm is not None:
		tqm.cleanup()
shutil.rmtree(C.DEFAULT_LOCAL_TMP,	True)

调用playbook

Playbook编程概述

• Playbooks 是 Ansible的配置、部署、编排语言 
• 它们可以被描述为一个需要希望远程主机执行命令的方案或者一组IT程序运行的命令集合 
• 可以通过python编程的方式执行playbook

相关模块

• 与执行ad-hoc命令一样,playbook的执行也需要相关模块
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

创建元组

• Playbook的参数更多,元组更大
Options	= namedtuple('Options',
    [‘connection', 'remote_user',
    ‘ask_sudo_pass', 'verbosity',
    ‘ack_pass', 'module_path',
    ‘forks', 'become',
    ‘become_method', 'become_user',
    'check', 'listhosts',
    'listtasks',
    'listtags',
    'syntax',
    'sudo_user', 'sudo',
    'diff'])

创建元组( 续1 )

• Playbook的参数更多,元组更大
ops	= Options(connection='smart',
    remote_user=None, ack_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,
    listtasks=None,
    listtags=None,
    syntax=None)

创建其他相关参数

loader = DataLoader()
passwords = dict()
inventory = InventoryManager(loader=loader, sources=['hosts'])
variable_manager = VariableManager(loader=loader, inventory=inventory)

执行playbook

def playbookrun(playbook_path):
    playbook = PlaybookExecutor(playbooks=playbook_path,
            inventory=inventory,
            variable_manager=variable_manager,
            loader=loader,	options=ops, passwords=passwords)
    result = playbook.run()
    return result
if	__name__ ==	'__main__':
	playbookrun(playbook_path=['install_web.yml'])
编写ansible模块
模块基础
官方模块
模块执行流程
模块开发
模块库目录
编写模块头
创建模块入口
执行动作
返回结果
编写测试playbook
执行playbook

编写ansible模块

模块基础

官方模块

• Ansible官方已经提供了大量模块,在编写模块之前,可以查看是否已有现成模块 
• 官方已发布模块 
	– http://docs.ansible.com/ansible/modules.html
• 官方正在开发的模块 
	– https://github.com/ansible/ansible/labels/module

模块执行流程

• 将模块文件读入内存,然后添加传递给模块的参数,最后将模块中所需要的类添加到内存,由zipfile压缩后,再由base64进行编码,写入到模板文件内 
• 通过默认的连接方式(一般是ssh),ansible连接到远程主机,创建临时目录,并关闭连接 
• 打开另外一个ssh连接,将模板文件以sftp方式传送到刚刚创建的临时目录中,写完后关闭连接

模块执行流程( 续1 )

• 打开一个ssh连接将任务对象赋予可执行权限,执行 成功后关闭连接 
• 最后,ansible将再打开一个新连接来执行模块,并删除临时目录及其所有内容 
• 模块的结果是从标准输出stdout中获取json格式的字符串。ansible将解析和处理此字符串

模块开发

模块库目录

• 可以使用 ANSIBLE_LIBRARY环境变量来指定模块的存放位置 
• 也可以在playbook当前目录下创建library目录
[root@localhost myansi]# mkdir library/

编写模块头

• 在文件头部加入下列语句,表示该模块使用python运行 
#!/usr/bin/env python
• 导入所需要的模块,如shutil模块
import shutil
from ansible.module_utils.basic import AnsibleModule

创建模块入口

• 使用AnsibleModule类中的argument_spec来接受参数
def main():
    module = AnsibleModule(
        argument_spec =	dict(
        source=dict(required=True, type='str'),
        dest=dict(required=True, type='str')
    )
)

执行动作

• 使用shutil.copy拷贝文件
hutil.copy(module.params['source'],	module.params['dest'])

返回结果

• 拷贝完成后,返回json数据 
module.exit_json(changed=True)
• 编写主程序代码
if __name__	== '__main__':
	main()

编写测试playbook

• 编写playbook,测试编写的模块 
[root@localhost myansi]# vim mytest.yml
---
- name:	test remote_copy module
	hosts: myself
    
	tasks:
- name:	remote_copy file
    remote_copy:
    source:	/etc/hosts
    dest: /tmp/zj.txt

执行playbook

• 执行playbook
[root@localhost myansi]# ansible-playbook mytest.yml
PLAY [test remote_copy module]	
*************************************************
TASK [Gathering	Facts]	
*********************************************************
ok:	[localhost] 
TASK [remote_copy file]	
********************************************************
changed: [localhost] PLAY RECAP	
********************************************************
localhost :	ok=2 changed=1 unreachable=0 failed=0	

ansible模块开发

# 建立自定义模块目录
[root@localhost ~]# mkdir jsck
[root@localhost ~]# cd jsck/
[root@localhost jsck]# pwd
/root/jsck
[root@localhost jsck]# export ANSIBLE_LIBRARY=/root/jsck
# 编写模块,用于在远程主机上将一个文件拷贝到目标位置
[root@localhost jsck]# vim py_copy.py
import shutil
from ansible.module_utils.basic import AnsibleModule

def main():
    module = AnsibleModule(
        argument_spec=dict(
            yuan=dict(required=True, type='str'),
            mubiao=dict(required=True, type='str')
        )
    )
    shutil.copy(module.params['yuan'], module.params['mubiao'])
    module.exit_json(changed=True)

if __name__ == '__main__':
    main()
    
[root@localhost jsck]# ansible all -m py_copy -a "yuan=/etc/hosts mubiao=/tmp/tt.txt"

ansible-cmdb模块

用于将ansible收集下来的主机信息转换成html页面

官网ansible-cmdb

[root@localhost ~]# pip3 install -i  https://pypi.douban.com/simple/ ansible-cmdb
[root@localhost ~]# find / -name ansible-cmdb
/usr/local/python3/bin/ansible-cmdb
[root@localhost ~]# vim /usr/local/python3/bin/ansible-cmdb
PY_BIN=$(which python3)		# 第8行改为python3,默认是python2

# 通过setup模块收集远程主机信息并保存到/tmp/out/目录
[root@localhost ansible]# ansible all -m setup --tree /tmp/out/
[root@localhost ansible]# ll /tmp/out/
总用量 48
-rw-r--r--. 1 root root 15885 321 22:47 web1
-rw-r--r--. 1 root root 15886 321 22:47 web2
-rw-r--r--. 1 root root 15886 321 22:47 web3
# 利用ansible-cmdb分析/tmp/out/下的文件,生成html
[root@localhost ansible]# /usr/local/python3/bin/ansible-cmdb /tmp/out/ > /tmp/hosts.html

在这里插入图片描述

发布了96 篇原创文章 · 获赞 100 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43395428/article/details/105019618