1. Ansible优势
- Ansible是python的一套完整的自动化执行任务模块
- Ansible的play_book模式,采用yaml配置,对于自动化任务执行一目了然
- 自动化场景支持丰富(shell,定时,用户管理或者第三方模块)
2. Ansible安装
- 通过系统的方式yum, apt-get等
- 通过python方式
- Python ./setup.py install
Easy_insatll ansible
Pip install ansible
3. Ansible的配置文件
/etc/ansible/
|____ansible.cfg 执行需求的全局性、默认的配置文件。
|____hosts 默认的主机资产清单文件
可以使用export ANSIBLE_CONFIG=路径方式修改默认配置文件
Ansible.cfg
Ansible.cfg是ansible自动化任务所用的一个核心配置文件,大部分的配置文件都集中在defualts配置项目中。我的自动化实战课程讲解到ansble配置的时候,提供如下的问题,给大家作为参考阅读,defaults下的配置项,下面列出常用的配置参数:
1)inventory
该参数表示资源清单inventory文件的位置,资源清单就是一些Ansible需要连接管理的主机列表
inventory = /root/ansible/hosts
2)library
Ansible的操作动作,无论是本地或远程,都使用一小段代码来执行,这小段代码称为模块,这个library参数就是指向存放Ansible模块的目录
library = /usr/share/ansible
3)forks
设置默认情况下Ansible最多能有多少个进程同时工作,默认设置最多5个进程并行处理。具体需要设置多少个,可以根据控制主机的性能和被管理节点的数量来确定。
forks = 5
4)sudo_user
这是设置默认执行命令的用户,也可以在playbook中重新设置这个参数
sudo_user = root
//注意:新版本已经作了修改,如ansible2.4.1下已经为:
default_sudo_user = root
5)remote_port
这是指定连接被关节点的管理端口,默认是22,除非设置了特殊的SSH端口,不然这个参数一般是不需要修改的
remote_port = 22
6)host_key_checking
这是设置是否检查SSH主机的密钥。可以设置为True或False
host_key_checking = False
7)timeout
这是设置SSH连接的超时间隔,单位是秒。
timeout = 20
8)log_path
Ansible系统默认是不记录日志的,如果想把Ansible系统的输出记录到人i治稳健中,需要设置log_path来指定一个存储Ansible日志的文件
log_path = /var/log/ansible.log
另外需要注意,执行Ansible的用户需要有写入日志的权限,模块将会调用被管节点的syslog来记录,口令是不会出现的日志中的
9)private_key_file
在使用ssh公钥私钥登录系统时候,使用的密钥路径。
private_key_file=/path/to/file.pem
还有更多的配置项,大家可以参考官方文档,如下:
http://docs.ansible.com/ansible/latest/intro_configuration.html#private-key-file#private-key-file
Hosts
[group_name]
10.10.10.10:22 ansible_ssh_user=root ansible_ssh_pass=Y131231312
10.10.10.11:22 ansible_ssh_user=root ansible_ssh_pass=Hua1213
10.10.10.11:22 ansible_ssh_user=root ansible_ssh_private_key_file=/root/.ssh/id_rsa
[group_name]
test1
ansible_ssh_user=root ansible_ssh_private_key_file=idrsapath
别名 + ssh用户 + ssh密钥
4. Ad-hoc模式和playbook
区别
ad-hoc简而言之,就是临时命令,playbook是保存成一个配置文件下次还可以执行。
Ad-hoc
1. Ad-hoc使用的场景(临时性)
在多台机器上,查看某个进程是否启动。
在多台机器上,拷贝指定日志文件到本地。
2. Ad-hoc模式命令的使用
组,正则表达式匹配,全部用于匹配主机名或者主机组名> [options]
Ansible 192.168.1.* -a ‘ls /tmp’ 匹配192.168.1段
Ansible group1 -a ‘ls /tmp’ 匹配192.168.1段
Ansible test1 -a ‘ls /tmp’ 匹配192.168.1段 (别名的方式)
3. ansible命令的参数,如下:
-v, --verbose:输出更详细的执行过程信息,-vvv可得到所有执行过程信息。
-i PATH, --inventory=PATH:指定inventory信息,默认/etc/ansible/hosts。
-f NUM, --forks=NUM:并发线程数,默认5个线程。
--private-key=PRIVATE_KEY_FILE:指定密钥文件。
-m NAME, --module-name=NAME:指定执行使用的模块。
-M DIRECTORY, --module-path=DIRECTORY:指定模块存放路径,默认/usr/share/ansible,也可以通过ANSIBLE_LIBRARY设定默认路径。
-a 'ARGUMENTS', --args='ARGUMENTS':模块参数。
-k, --ask-pass SSH:认证密码。
-K, --ask-sudo-pass sudo:用户的密码(—sudo时使用)。
-o, --one-line:标准输出至一行。
-s, --sudo:相当于Linux系统下的sudo命令。
-t DIRECTORY, --tree=DIRECTORY:输出信息至DIRECTORY目录下,结果文件以远程主机名命名。
-T SECONDS, --timeout=SECONDS:指定连接远程主机的最大超时,单位是:秒。
-B NUM, --background=NUM:后台执行命令,超NUM秒后kill正在执行的任务。
-P NUM, --poll=NUM:定期返回后台任务进度。
-u USERNAME, --user=USERNAME:指定远程主机以USERNAME运行命令。
-U SUDO_USERNAME, --sudo-user=SUDO_USERNAM:E使用sudo,相当于Linux下的sudo命令。
-c CONNECTION, --connection=CONNECTION:指定连接方式,可用选项paramiko (SSH), ssh, local。Local方式常用于crontab 和 kickstarts。
-l SUBSET, --limit=SUBSET:指定运行主机。
-l ~REGEX, --limit=~REGEX:指定运行主机(正则)。
--list-hosts:列出符合条件的主机列表,不执行任何其他命令
ansible-playbook模式常用命令的使用
执行方式:
ansible-playbook playbook.yml [options]
-u REMOTE_USER, --user=REMOTE_USER # ssh 连接的用户名
-k, --ask-pass #ssh登录认证密码
-s, --sudo #sudo 到root用户,相当于Linux系统下的sudo命令
-U SUDO_USER, --sudo-user=SUDO_USER #sudo 到对应的用户
-K, --ask-sudo-pass #用户的密码(—sudo时使用)
-T TIMEOUT, --timeout=TIMEOUT # ssh 连接超时,默认 10 秒
-C, --check # 指定该参数后,执行 playbook 文件不会真正去执行,而是模拟执行一遍,然后输出本次执行会对远程主机造成的修改
-e EXTRA_VARS, --extra-vars=EXTRA_VARS # 设置额外的变量如:key=value 形式 或者 YAML or JSON,以空格分隔变量,或用多个-e
-f FORKS, --forks=FORKS # 进程并发处理,默认 5
-i INVENTORY, --inventory-file=INVENTORY # 指定 hosts 文件路径,默认 default=/etc/ansible/hosts
-l SUBSET, --limit=SUBSET # 指定一个 pattern,对- hosts:匹配到的主机再过滤一次
--list-hosts # 只打印有哪些主机会执行这个 playbook 文件,不是实际执行该 playbook
--list-tasks # 列出该 playbook 中会被执行的 task
--private-key=PRIVATE_KEY_FILE # 私钥路径
--step # 同一时间只执行一个 task,每个 task 执行前都会提示确认一遍
--syntax-check # 只检测 playbook 文件语法是否有问题,不会执行该 playbook
-t TAGS, --tags=TAGS #当 play 和 task 的 tag 为该参数指定的值时才执行,多个 tag 以逗号分隔
--skip-tags=SKIP_TAGS # 当 play 和 task 的 tag 不匹配该参数指定的值时,才执行
-v, --verbose #输出更详细的执行过程信息,-vvv可得到所有执行过程信息。
5. Python-ansible的使用
资产配置清单
from ansible.parsing.dataloader import DataLoader
from ansible.inventory.manager import InventoryManager
from ansible.vars.manager import VariableManager
# InventoryManager类
loader = DataLoader()
inventory = InventoryManager(loader=loader, sources=['hosts'])
# 获取主机组资源
print(inventory.get_groups_dict())
# 获取指定的主机对象
print(inventory.get_hosts())
print(inventory.get_host(hostname='10.10.10.10'))
# 添加主机到指定主机组
inventory.add_host(host='127.0.0.1', port=22, group='test_group1')
print(inventory.get_groups_dict())
# VariableManager类 变量管理
variable_manager = VariableManager(loader=loader, inventory=inventory)
# 查看变量方法 get_vars
variable_manager.get_vars(host=inventory.get_host(hostname='10.10.10.10'))
# 设置主机变量方法 set_host_variable
variable_manager.set_host_variable(host=inventory.get_host(hostname='10.10.10.10'),
varname='ansible_ssh_user',
value='root')
# 添加扩展变量 extra_vars
variable_manager.extra_vars={'myweb': 'imocc.com', 'myname':'ribbon'}
Ad-hoc
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.plugins.callback import CallbackBase
from ansible.parsing.dataloader import DataLoader
from ansible.inventory.manager import InventoryManager
from ansible.vars.manager import VariableManager
from collections import namedtuple
loader = DataLoader()
inventory = InventoryManager(loader=loader, sources=['hosts'])
variable_manager = VariableManager(loader=loader, inventory=inventory)
# 执行选项
Options = namedtuple('Options', ['connection', 'remote_user', 'forks', 'become',
'become_method', 'become_user', 'check', 'module_path',
'diff'])
options = Options(connection='smart', remote_user='root', forks=100, become=None,
become_method=None, become_user=None, check=False, module_path=None,
diff=None)
# Play执行对象和模块
play_source = dict(
name='Ansible PLAY ad-hoc test',
hosts='10.10.10.10',
gather_facts='no',
tasks = [
dict(action=dict(module='shell', args='touch adhoc_test.txt'))
]
)
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
# 任务队列
passwords = dict()
tqm = TaskQueueManager(
inventory=inventory,
variable_manager=variable_manager,
loader=loader,
options=options,
passwords=passwords
)
result = tqm.run(play)
Playbook
.py
# coding=utf-8
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
from ansible.plugins.callback import CallbackBase
from ansible.parsing.dataloader import DataLoader
from ansible.inventory.manager import InventoryManager
from ansible.vars.manager import VariableManager
from collections import namedtuple
from ansible.executor.playbook_executor import PlaybookExecutor
loader = DataLoader()
inventory = InventoryManager(loader=loader, sources=['hosts'])
variable_manager = VariableManager(loader=loader, inventory=inventory)
# 执行选项
Options = namedtuple('Options', ['connection', 'remote_user',
'ack_pass', 'sudo_user',
'forks', 'sudo',
'ask_sudo_pass', 'verbosity',
'module_path', 'become',
'become_method', 'become_user',
'check', 'diff', 'listhosts',
'listtasks', 'listtags', 'syntax'])
options = Options(connection='smart', remote_user='root', forks=100, ack_pass=None,
sudo_user=None, 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)
# 任务队列
passwords = dict()
playbook = PlaybookExecutor(
playbooks=['f1.yaml'],
inventory=inventory,
variable_manager=variable_manager,
loader=loader,
options=options,
passwords=passwords
)
playbook.run()
f1.yaml
---
- hosts : 10.10.10.10
remote_user : root
vars :
touch_file : imooc.file
tasks :
- name: touch file
shell: "touch /tmp/{{touch_file}}"
hosts
[test_group1]
10.10.10.11:22 ansible_ssh_user=root ansible_ssh_private_key_file=/root/.ssh/id_rsa
[test_group2]
10.10.10.10:22 ansible_ssh_user=root ansible_ssh_pass='Yanwentao123'
Callback类重写
Adhoc callback改写.py
# coding=utf-8
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.plugins.callback import CallbackBase
from ansible.parsing.dataloader import DataLoader
from ansible.inventory.manager import InventoryManager
from ansible.vars.manager import VariableManager
from collections import namedtuple
import datetime
import json
class ModelResultsCollector(CallbackBase):
def __init__(self, *args, **kwargs):
super(ModelResultsCollector, self).__init__(*args, **kwargs)
self.host_ok = {}
self.host_unreachable = {}
self.host_failed = {}
def v2_runner_on_ok(self, result, **kwargs): # 定义成功
"""Print a json representation of the result
This method could store the result in an instance attribute for retrieval later
"""
self.host_ok[result._host.get_name()] = result
host = result._host
currt_tiem = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
logs = json.dumps({currt_tiem: {host.name: result._result['msg']}}, indent=4)
# with open('/opt/aaaa.json', 'a') as f:
# f.write(logs + '\n')
self.result_log = result._result['msg']
def v2_runner_on_unreachable(self, result, **kwargs):
"""Print a json representation of the result
This method could store the result in an instance attribute for retrieval later
"""
self.host_ok[result._host.get_name()] = result
host = result._host
currt_tiem = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
self.result_log = result._result['msg']
logs = json.dumps({currt_tiem: {host.name: self.result_log}}, indent=4)
# with open('/opt/aaaa.json', 'a') as f:
# f.write(logs + '\n')
def v2_runner_on_failed(self, result, **kwargs):
"""Print a json representation of the result
This method could store the result in an instance attribute for retrieval later
"""
self.host_failed[result._host.get_name()] = result
host = result._host
currt_tiem = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
self.result_log = result._result['msg']
logs = json.dumps({currt_tiem: {host.name: self.result_log}}, indent=4)
# with open('/opt/aaaa.json', 'a') as f:
# f.write(logs + '\n')
loader = DataLoader()
inventory = InventoryManager(loader=loader, sources=['hosts'])
variable_manager = VariableManager(loader=loader, inventory=inventory)
# 执行选项
Options = namedtuple('Options', ['connection', 'remote_user',
'ack_pass', 'sudo_user',
'forks', 'sudo',
'ask_sudo_pass', 'verbosity',
'module_path', 'become',
'become_method', 'become_user',
'check', 'diff', 'listhosts',
'listtasks', 'listtages', 'systax'])
options = Options(connection='smart', remote_user='root', forks=100, ack_pass=None,
sudo_user=None, 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,
listtages=None, systax=None)
# Play执行对象和模块
play_source = dict(
name='Ansible PLAY ad-hoc test',
hosts='10.10.10.10',
gather_facts='no',
tasks = [
dict(action=dict(module='shell', args='touch adhoc_test.txt'))
]
)
play = Play().load(play_source, variable_manager=variable_manager, loader=loader)
# callback
callback = ModelResultsCollector()
# 任务队列
passwords = dict()
tqm = TaskQueueManager(
inventory=inventory,
variable_manager=variable_manager,
loader=loader,
options=options,
passwords=passwords,
stdout_callback=callback
)
result = tqm.run(play)
# 输出callback状态
print callback.host_ok.items()
result_raw = {'success':{},
'failed':{},
'unreach':{}}
for host, result in callback.host_failed.items():
result_raw['failed'][host] = result._result
for host, result in callback.host_ok.items():
result_raw['success'][host] = result._result
for host, result in callback.host_unreachable.items():
result_raw['unreach'][host] = result._result
print(result_raw)
Playbook callback改写.py
# coding=utf-8
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
import json
import datetime
from ansible.plugins.callback import CallbackBase
from ansible.parsing.dataloader import DataLoader
from ansible.inventory.manager import InventoryManager
from ansible.vars.manager import VariableManager
from collections import namedtuple
from ansible.executor.playbook_executor import PlaybookExecutor
class PlayBookResultsCollector(CallbackBase):
CALLBACK_VERSION = 2.0
def __init__(self, *args, **kwargs):
super(PlayBookResultsCollector, self).__init__(*args, **kwargs)
self.task_ok = {}
self.task_skipped = {}
self.task_failed = {}
self.task_status = {}
self.task_unreachable = {}
def v2_runner_on_ok(self, result, **kwargs): # 定义成功
self.task_ok[result._host.get_name()] = result
def v2_runner_on_unreachable(self, result, **kwargs):
self.task_unreachable[result._host.get_name()] = result
def v2_runner_on_failed(self, result, **kwargs):
self.task_failed[result._host.get_name()] = result
def v2_runner_on_skipped(self, result):
self.task_skipped[result._host.get_name()] = result
def v2_playbook_on_stats(self, stats):
hosts = sorted(stats.processed.keys())
for h in hosts:
t = stats.summarize(h)
self.task_status[h] = {
'ok':t['ok'],
'changed': t['changed'],
'unreachable':t['unreachable'],
'skipped':t['skipped'],
'failed':t['failures']
}
loader = DataLoader()
inventory = InventoryManager(loader=loader, sources=['hosts'])
variable_manager = VariableManager(loader=loader, inventory=inventory)
#Options 执行选项
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'])
options = 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)
callback = PlayBookResultsCollector()
# 任务队列
passwords = dict()
playbook = PlaybookExecutor(
playbooks=['f1.yaml'],
inventory=inventory,
variable_manager=variable_manager,
loader=loader,
options=options,
passwords=passwords
)
playbook._tqm._stdout_callback = callback
playbook.run()
result_raw = {'ok':{},
'failed':{},
'unreach':{},
'status':{},
'skipped':{}}
for host, result in callback.task_ok.items():
result_raw['ok'][host] = result._result
print(result_raw)
Django_Ansible