ansible-playbook
9.1 插件
9.1.1 插件介绍
ansible插件是增强ansible的核心功能的代码片段,ansible使用插件架构来实现丰富,灵活和可扩展的功能集。
Ansible提供了许多方便的插件,您可以轻松编写自己的插件。
下边简单介绍Ansible包含的各种插件(插件具体用法请参考官方文档或者ansible-doc):
- action插件
Action插件与模块一起执行PlayBook任务所需的操作。它们通常在后台自动执行,在模块执行之前进行必要的工作。“normal” action插件用于尚未拥有action插件的模块。
您可以启用一个自定义操作插件,方法是将其放置到与role中的play相邻的action_plugins目录中,当使用关联模块时,Action插件默认执行,不需要采取任何行动 - cache插件
缓存插件实现的后端缓存机制,可以使ansible存储获得的facts和inventory元数据,不必再从源头检索这些数据,而降低性能。
默认的缓存插件是memory plugin,它只缓存ansible目前执行的数据,其他持久存储的插件也可以缓存数据 - callback插件
回调插件可以在响应事件时向Ansible添加新行为。
默认情况下,回调插件控制运行命令行程序时看到的大部分输出,但也可用于添加其他输出,与其他工具集成并将事件整理到存储后端。 - inventory插件
清单插件允许用户指向数据源,以便通过-i /path/to/file和/ 或-i 'host1,host2 命令行参数或其他配置来源编译Ansible用于定位任务的主机清单。 - lookup插件
查找插件允许Ansible从外部来源访问数据。这可以包括:联系外部数据存储和服务,读取文件系统。
查找插件返回的数据可以使用Ansible中的标准模板系统提供,通常用于从这些系统中加载包含信息的变量或模板。
lookups是Jinja2模板语言的Ansible特定扩展。 - shell插件
shell插件可以确保Ansible运行的基本命令格式正确,可与目标机器一起使用,并允许用户配置某些与Ansible执行任务相关的行为 - strategy插件
策略插件通过处理play和hosts调度来控制play执行的流程。 - vars插件
vars插件将额外的变量注入到Ansible中运行,这些运行不是来自库存源,剧本或命令行。
Playbook使用vars插件构建像’host_vars’和’group_vars’的工作目录。
Vars插件在Ansible 2.0中部分实现,并被重写为从Ansible 2.4开始全面实施。Ansible附带的host_group_vars插件可以从主机变量和组变量中读取变量。 - filters
Ansible中的过滤器来自Jinja2,用于转换模板表达式中的数据。
Jinja2附带很多过滤器。请参阅官方Jinja2模板文档中的内置过滤器。
考虑到模板产生在Ansible控制器上,而不是在任务的目标主机上,所以过滤器也在控制器上执行,因为它们处理本地数据。
除了jinja2,Ansible附带自己的产品,并允许用户添加他们自己的自定义过滤器。 - tests
Jinja中的tests是评估模板表达式,并返回True或False的一种方式,Jinja附带许多这些。在官方Jinja模板文档中查看内置测试。
tests和filters之间的主要区别在于Jinja tests用于比较,而filters用于数据处理,并且在jinja中有不同的应用程序,如map()和select()来选择列表中的项目。像所有模板一样,tests总是在Ansible控制器上执行,而不是在任务的目标上执行,因为他们测试本地数据。
除了jinjia2 tests,Ansible提供更多功能,用户可以自己轻松创建。
9.1.2 修改默认的回调插件
同时只能有一个回调插件作为主要的管理者,用于输出到屏幕。
如果想替换,应该在这个插件中修改CALLBACK_TYPE = stdout
,之后再ansible.cfg中配置stdout插件。
修改默认配置文件:
# vi /etc/ansible/ansible.cfg
stdout_callback = json # 以JSON的格式输出结果
或使用自定义的回调:
stdout_callback = mycallback
默认情况下着仅对playbook生效,如果想让ad-hoc方式生效应该在ansible.cfg文件中做如下设置:
- ad-hoc方式,以json格式输出为例:
[root@dbc-server-554 ansible]# cat /etc/ansible/ansible.cfg |grep bin_ansi
#bin_ansible_callbacks = False
bin_ansible_callbacks = True
[root@dbc-server-554 ansible]# ansible all -i hosts -m shell -a "date +'%F %T'"
{
"custom_stats": {},
"global_custom_stats": {},
"plays": [
{
"play": {
"duration": {
"end": "2023-01-06T08:44:49.875862Z",
"start": "2023-01-06T08:44:49.441463Z"
},
"id": "382c4a62-66df-a33f-bd69-000000000007",
"name": "Ansible Ad-Hoc"
},
...
- playbook方式:
[root@dbc-server-554 ansible]# cat remotedate.yml
---
- name: remote server date
hosts: all
gather_facts: no
tasks:
- name: test
shell: date +"%F %T"
[root@dbc-server-554 ansible]# ansible-playbook remotedate.yml
{
...
"tasks": [
{
"hosts": {
"192.168.71.183": {
...
"cmd": "date +\"%F %T\"",
...
"stdout": "2023-01-06 11:54:32",
...
}
}
}
9.1.3 启用其他内置的回调插件
大部分情况下,无论是内置的回调插件还是自定义的回调插件,都需要在ansible.cfg中添加到白名单中,从而才能启用。
callback_whitelist=timer,mail,profile_roles,custom_callback
参数:
timer 这个回调插件可以计算整个playbook的运行时间
mail这个回调插件可以实现发送邮件的功能
profile_roles这个插件是在执行中提添加用时时间
custom_callback 是自定义的插件,稍后会讲
注释掉前面ansible.cfg所改动的json
#stdout_callback = json
正常情况未启动其他内置的回调插件
[root@dbc-server-554 ansible]# cat sleep.yml
---
- hosts: all
gather_facts: no
tasks:
- name: sleep
command: sleep 2
[root@dbc-server-554 ansible]# ansible-playbook sleep.yml
PLAY [all] *********************************************************************
TASK [sleep] *******************************************************************
changed: [192.168.71.183]
PLAY RECAP *********************************************************************
192.168.71.183 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
启用timer
[root@dbc-server-554 ansible]# cat /etc/ansible/ansible.cfg|grep callback_wh
callback_whitelist = timer, mail
[root@dbc-server-554 ansible]# ansible-playbook sleep.yml
PLAY [all] *********************************************************************
TASK [sleep] *******************************************************************
changed: [192.168.71.183]
PLAY RECAP *********************************************************************
192.168.71.183 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Playbook run took 0 days, 0 hours, 0 minutes, 2 seconds
9.1.4 获取帮助
ansible-doc -t callback -l
可以插看当前可用的回调插件列表(callback_whitelist有才可以看得到)
ansible-doc -t callback <callback plugins name>
可查看具体回调插件的帮助文档
[root@dbc-server-554 ansible]# ansible-doc -t callback timer
> TIMER (/usr/lib/python2.7/site-packages/ansible/plugins/callback/timer.py)
This callback just adds total play duration to the play stats.
* This module is maintained by The Ansible Community
REQUIREMENTS: whitelist in configuration
CALLBACK_TYPE: aggregate
METADATA:
status:
- preview
supported_by: community
9.1.5 回调插件的类型
回调插件类型在回调插件类中定义:
class CallbackModule(CallbackBase):
CALLBACK_TYPE = 'notification'
类型:
stdout 标准输出类型,用在回调的主管理器
aggregate聚合类型,把此类型插件处理的结果和stdout类型插件合并一起输出到标准输出。比如:timer,profile_tasks等。
notification通知类型,不参与标准输出,也不影响标准输出插件的正常输出,只是会把执行playbook的返回值写的指定的媒介中。
notification通知类型比如:log_plays,mail。假如自定义把执行playbook的结果输出到数据库中就可以使用此类型。
ansible-doc -t callback mail
查看所有默认的查看类型
[root@dbc-server-554 ansible]# grep 'CALLBACK_TYPE =.*' /usr/lib/python2.7/site-packages/ansible/plugins/callback/*.py | cut -d: -f 2 | sort -u
CALLBACK_TYPE = 'aggregate'
CALLBACK_TYPE = 'notification'
CALLBACK_TYPE = 'stdout'
9.1.6 把返回结果输出到日志中
内置的回调插件log_plays会将playbook的返回信息输出到var/log/ansible/hosts目录中。
可以在ansible.cfg中配置指定的目录,使用log_folder
比如,把日志存到/tmp/ansible/hosts/目录下在ansible.cfg 文件的最后添加如下配置
# ansible-doc -t callback log_plays
- log_folder
The folder where log files will be created.
[Default: /var/log/ansible/hosts]
set_via:
env:
- name: ANSIBLE_LOG_FOLDER
ini:
- key: log_folder
section: callback_log_plays
# vi /etc/ansible/ansible.cfg
bin_ansible_callbacks = True
[callback_log_plays]
log_folder=/tmp/ansible/hosts/
进行配置到白名单中
# vi /etc/ansible/ansible.cfg
callback_whitelist = log_plays
运行
[root@dbc-server-554 ansible]# ansible-playbook remotedate.yml
PLAY [remote server date] ******************************************************
TASK [test] ********************************************************************
changed: [192.168.71.183]
PLAY RECAP *********************************************************************
192.168.71.183 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@dbc-server-554 ansible]# ls /tmp/ansible/hosts/192.168.71.183
/tmp/ansible/hosts/192.168.71.183
[root@dbc-server-554 ansible]# cat /tmp/ansible/hosts/192.168.71.183
Jan 06 2023 17:31:05 - OK - {"module_args": {"creates": null, "executable": null, "_uses_shell": true, "strip_empty_ends": true, "_raw_params": "date +\"%F %T\"", "removes": null, "argv": null, "warn": true, "chdir": null, "stdin_add_newline": true, "stdin": null}} => {"stderr_lines": [], "changed": true, "end": "2023-01-06 12:30:52.284394", "_ansible_no_log": false, "stdout": "2023-01-06 12:30:52", "cmd": "date +\"%F %T\"", "start": "2023-01-06 12:30:52.279880", "delta": "0:00:00.004514", "stderr": "", "rc": 0, "stdout_lines": ["2023-01-06 12:30:52"], "ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}}
9.2 开发自定义插件
9.2.1 log_plays插件源码分析
获取源码
[root@dbc-server-554 ansible]# ansible-doc -t callback log_plays
> LOG_PLAYS (/usr/lib/python2.7/site-packages/ansible/plugins/callback/log_pl
This callback writes playbook output to a file per host in the
`/var/log/ansible/hosts` directory
...
[root@dbc-server-554 ~]# cat /usr/lib/python2.7/site-packages/ansible/plugins/callback /log_plays.py
# (C) 2012, Michael DeHaan, <michael.dehaan@gmail.com>
# (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3. 0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
callback: log_plays
type: notification
short_description: write playbook output to log file
version_added: historical
description:
- This callback writes playbook output to a file per host in the `/var/log/ansib le/hosts` directory
requirements:
- Whitelist in configuration
- A writeable /var/log/ansible/hosts directory by the user executing Ansible on t he controller
options:
log_folder:
version_added: '2.9'
default: /var/log/ansible/hosts
description: The folder where log files will be created.
env:
- name: ANSIBLE_LOG_FOLDER
ini:
- section: callback_log_plays
key: log_folder
'''
import os
import time
import json
from ansible.utils.path import makedirs_safe
from ansible.module_utils._text import to_bytes
from ansible.module_utils.common._collections_compat import MutableMapping
from ansible.parsing.ajson import AnsibleJSONEncoder
from ansible.plugins.callback import CallbackBase
# NOTE: in Ansible 1.2 or later general logging is available without
# this plugin, just set ANSIBLE_LOG_PATH as an environment variable
# or log_path in the DEFAULTS section of your ansible configuration
# file. This callback is an example of per hosts logging for those
# that want it.
class CallbackModule(CallbackBase):
"""
logs playbook results, per host, in /var/log/ansible/hosts
"""
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'notification'
CALLBACK_NAME = 'log_plays'
CALLBACK_NEEDS_WHITELIST = True
TIME_FORMAT = "%b %d %Y %H:%M:%S"
MSG_FORMAT = "%(now)s - %(category)s - %(data)s\n\n"
def __init__(self):
super(CallbackModule, self).__init__()
def set_options(self, task_keys=None, var_options=None, direct=None): # 重写
super(CallbackModule, self).set_options(task_keys=task_keys, var_options=var_o ptions, direct=direct)
self.log_folder = self.get_option("log_folder")
if not os.path.exists(self.log_folder):
makedirs_safe(self.log_folder)
def log(self, host, category, data): #日志
if isinstance(data, MutableMapping):
if '_ansible_verbose_override' in data:
# avoid logging extraneous data
data = 'omitted'
else:
data = data.copy()
invocation = data.pop('invocation', None)
data = json.dumps(data, cls=AnsibleJSONEncoder)
if invocation is not None:
data = json.dumps(invocation) + " => %s " % data
path = os.path.join(self.log_folder, host)
now = time.strftime(self.TIME_FORMAT, time.localtime())
msg = to_bytes(self.MSG_FORMAT % dict(now=now, category=category, data=data))
with open(path, "ab") as fd:
fd.write(msg)
def runner_on_failed(self, host, res, ignore_errors=False):
self.log(host, 'FAILED', res)
def runner_on_ok(self, host, res):
self.log(host, 'OK', res)
def runner_on_skipped(self, host, item=None):
self.log(host, 'SKIPPED', '...')
def runner_on_unreachable(self, host, res):
self.log(host, 'UNREACHABLE', res)
def runner_on_async_failed(self, host, res, jid):
self.log(host, 'ASYNC_FAILED', res)
def playbook_on_import_for_host(self, host, imported_file):
self.log(host, 'IMPORTED', imported_file)
def playbook_on_not_import_for_host(self, host, missing_file):
self.log(host, 'NOTIMPORTED', missing_file)
9.2.2 开发插件规则
- 用Python编写
- 引发错误,就是遇到问题后,主动抛出异常
- 返回以unicode编码的字符串,主要是兼容Jinja2
- 符合Ansible的配置和文档标准,就是可以通过ansible.cfg 进行配置
使用兼容的Python版本编写
由于开发出来的插件将在控制器上执行,因此您必须使用兼容版本的Python(Python 2(2.7版)或Python3(3.5版及更高版本)的)进行编写。
9.2.3 抛出异常错误信息
应该通过引发AnsibleError()或类似的类并返回描述错误的消息来返回插件执行过程中遇到的错误。
将其他异常包装到错误消息中时,应始终使用Ansible的函数to_native来确保跨Python版本的字符串兼容性:
from ansible.module_utils._text import to_native
from ansible.errors import AnsibleError
try:
cause_an_exception()
except Exception as e:
raise AnsibleError(' Something happened, this was original exception:%s'% to_native(e))
9.2.4 妥当处理字符串
您必须将插件返回的所有字符串转换为Python的unicode类型。转换为unicode可确保这些字符串可以通过Jinja2运行。
转换字符串:
from ansible.module_utils._text import to_text
result_string=to_text(result_string)
9.2.5 插件配置和文档标准
Ansible的在线帮助文档(ansible-doc)是根据每个模块的源代码中的DOCUMENTATION模块块生成的。该DOCUMENTATION块必须是有效的YAML。
需要为您的插件定义可配置选项,在python文件的部分DOCUMENTATION中对其进行描述。自Ansible2.4版以来,回调和连接插件已经开始以这种方式声明配置要求了。现在大多数插件类型都执行相同的操作。这种方法可确保插件选项的文档始终是正确的和最新的。
DOCUMENTATION块中的所有字段均为小写。除非另有说明,否则所有字段都是必填字段:
DOCUMENTATION = '''
callback: log_plays
type: notification
short_description: write playbook output to log file
version_added: historical
description:
- 此插件的详细描述信息。
- 使用多条目,不要使用一个较长的语句。
- 不应该提及模块名称。
requirements:
- 必须要求清单
- 包括最低版本的限制
options:
log_folder:
version_added: '2.9' 此插件添加到 Ansible 时候的当时 Ansible 的版本。
default: 选项的默认值,如果 required 是 False, 则 default 可以设置
description: 此选项的作用的详细说明。应该用完整的句子写成。
env:
- name: 环境变量的名字
ini:
- section: 在 asible.cfg 中的配置块名称 [xx]
key: log_folder在对应配置块下面的变量名称 [xx]下对应的变量名
required: True/False 必需时为 True,如果不设置,就认为
不是必须的。
type: int/str/list 不是必须设置
'''
要访问插件中的配置设置,请使用self.get_option(“log_folder”)
如果需要显式个配置选项设置值,请使用self.set_options()
9.3 开发回调插件mysql_plays
将PlayBook的结果写在mysql里
回调插件会在响应事件时,向Ansible添加新行为。
要创建回调插件,请使用(CallbacksBase)类作为父类创建一个新类:
from ansible.plugins.callback import CallbackBase
class CallbackModule(CallbackBase):
pass
在 CallbackModule 覆盖 CallbackBase 中的特定方法。
对于打算与Ansible 2.0及更高版本一起使用的插件,您应该仅覆盖以v2开头的方法。
对于可以重写哪些方法呢,可以参阅 lib/ansible/plugins/callback
目录下的 init.py 文件的内容。
我们下面就参考 log_plays 插件编写一个可以将 playbook 的执行结果写如到 MySQL 中的插件。
9.3.1 准备数据库
[root@dbc-server-554 ~]# yum install mysql
[root@dbc-server-554 ~]# yum install mariadb-server
[root@dbc-server-554 ~]# pip install pymysql==0.7.11
[root@dbc-server-554 ansible]# cat /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
...
[root@server ~]# mysqladmin -u root password '123'
[root@server ~]# mysql -u root -p
Enter password:
首先要设计一个库和表用于存储结果
mysql> create database if not exists ansible default charset utf8mb4 collate utf8mb4_general_ci;
Query OK, 1 row affected (0.00 sec)
mysql> grant all on ansible.* to root@'%' identified by '123';
Query OK, 0 rows affected, 1 warning (0.00 sec)
9.3.2 准备表
mysql5.7以上版本
mysql> use ansible;
mysql> create table playsresult(
id int auto_increment primary key,
user varchar(16) not null,
host varchar(32) not null,
category varchar(11) not null,
result text,
create_time datetime NOT NULL Default CURRENT_TIMESTAMP;
);
mysql> MariaDB [ansible]> show columns from playsresult;
+-------------+-------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user | varchar(16) | NO | | NULL | |
| host | varchar(32) | NO | | NULL | |
| category | varchar(11) | NO | | NULL | |
| result | text | YES | | NULL | |
| create_time | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------------+-------------+------+-----+-------------------+----------------+
6 rows in set (0.00 sec)
mysql5.7以下版本
create table playsresult(
id int auto_increment primary key,
user varchar(16) not null,
host varchar(32) not null,
category varchar(11) not null,
result text,
create_time datetime(0) comment 'create time');
Alter table playsresult modify create_time timestamp Default CURRENT_TIMESTAMP NOT NULL;
9.3.3 编写插件
在log_plays基础上进行修改
#vi /root/.ansible/plugins/callback/mysql_plays.py
# 开发文档
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
callback: mysql_plays
type: notification
short_description: 将 playbook 的执行结果输出到 MySQL 中。
version_added: historical
description:
- 这个回调插件将会把输出存入 MySQL 服务器中。
requirements:
- 需要配置到 ansible.cfg 中 Whitelist
- 可以被访问的 MySQL 服务器实例
- Python 版本对应的 pymysql 或者 mysqlclient 模块
- 创表语句(注意:这里的表名需要根据选项中 mysql_table 的值一致)
create table playsresult(
id int auto_increment primary key,
user varchar(16) not null,
host varchar(32) not null,
category varchar(11) not null,
result text,
create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
);
options:
mysql_host:
version_added: '2.9'
default: locallhost
description: MySQL 服务器 IP或者主机名.
env: # 环境变量大写
- name: ANSIBLE_MYSQL_HOST
ini:
- section: callback_mysql_plays
key: mysql_host
mysql_port:
version_added: '2.9'
default: 3306
description: MySQL 服务器监听端口.
env:
- name: ANSIBLE_MYSQL_PORT
ini:
- section: callback_mysql_plays
key: mysql_port
type: int
mysql_user:
version_added: '2.9'
default: root
description: MySQL 服务器登录用户.
env:
- name: ANSIBLE_MYSQL_USER
ini:
- section: callback_mysql_plays
key: mysql_user
mysql_password:
version_added: '2.9'
default: '123'
description: MySQL 服务器登录用户.
env:
- name: ANSIBLE_MYSQL_PASSWORD
ini:
- section: callback_mysql_plays
key: mysql_password
mysql_db:
version_added: '2.9'
default: ansible
description: 存放数据的库名称.
env:
- name: ANSIBLE_MYSQL_DB
ini:
- section: callback_mysql_plays
key: db
mysql_table:
version_added: '2.9'
default: playsresult
description: 存放数据的表名称.
env:
- name: ANSIBLE_MYSQL_TABLE
ini:
- section: callback_mysql_plays
key: mysql_table
'''
9.3.4 保存插件到有效的目录下
[root@dbc-server-554 ansible]# cat /usr/lib/python2.7/site-packages/ansible/plugins/callback/mysql_plays.py
9.3.5 开启使用插件
添加到白名单
[root@dbc-server-554 ansible]# cat /etc/ansible/ansible.cfg |grep callback_whitelist
#callback_whitelist = timer, mail
callback_whitelist = log_plays,mysql_plays,timer
默认此插件仅对 playbook 生效,假如希望在 ad-hoc (快捷命令)中生效,继续打开如下配置,并职位 True
bin_ansible_callbacks = True
9.3.6 关于此插件的使用先决条件等信息
#查看有没有mysql插件
[root@dbc-server-554 ansible]# ansible-doc -t callback -l | grep mysql
mysql_plays 将 playbook 的执行结果输出到 MySQL 中。
#查看有无错误
[root@dbc-server-554 ~]# ansible-doc -t callback mysql_plays
> MYSQL_PLAYS (/usr/lib/python2.7/site-packages/ansible/plugins/callback/mysql_plays.py)
这个回调插件将会把输出存入 MySQL 服务器中。
* This module is maintained by The Ansible Community
OPTIONS (= is mandatory):
- mysql_db
存放数据的库名称.
[Default: ansible]
set_via:
env:
- name: ANSIBLE_MYSQL_DB
ini:
- key: db
section: callback_mysql_plays
version_added: 2.9
- mysql_host
MySQL 服务器 IP或者主机名.
[Default: locallhost]
set_via:
env:
- name: ANSIBLE_MYSQL_HOST
ini:
- key: mysql_host
section: callback_mysql_plays
version_added: 2.9
- mysql_password
MySQL 服务器登录用户.
[Default: 123]
set_via:
env:
- name: ANSIBLE_MYSQL_PASSWORD
ini:
- key: mysql_password
section: callback_mysql_plays
version_added: 2.9
- mysql_port
MySQL 服务器监听端口.
[Default: 3306]
set_via:
env:
- name: ANSIBLE_MYSQL_PORT
ini:
- key: mysql_port
section: callback_mysql_plays
type: int
version_added: 2.9
- mysql_table
存放数据的表名称.
[Default: playsresult]
set_via:
env:
- name: ANSIBLE_MYSQL_TABLE
ini:
- key: mysql_table
section: callback_mysql_plays
version_added: 2.9
- mysql_user
MySQL 服务器登录用户.
[Default: root]
set_via:
env:
- name: ANSIBLE_MYSQL_USER
ini:
- key: mysql_user
section: callback_mysql_plays
version_added: 2.9
REQUIREMENTS: 需要配置到 ansible.cfg 中 Whitelist, 可以被访问的 MySQL 服务器实例, Python 版本对应的 pymysql
或者 mysqlclient 模块, 创表语句(注意:这里的表名需要根据选项中 mysql_table 的值一致) create
table playsresult( id int auto_increment primary key, user
varchar(16) not null, host varchar(32) not null, category
varchar(11) not null, result text, create_time datetime NOT NULL
DEFAULT CURRENT_TIMESTAMP );
METADATA:
status:
- preview
supported_by: community
TYPE: notification
(END)
9.3.7 配置插件使用的选项
关于限制条件
此插件已经有默认值,如果想修改需在 ansible.cfg 文件的最后添加如下配置
[callback_mysql_plays]
mysql_host = MySQL IP
mysql_port = MySQL 监听端口
mysql_user = MySQL 用户
mysql_password = MySQL 密码
mysql_db = MySQL 库名
mysql_table = MySQL 表名
[root@dbc-server-554 ~]# cat /etc/ansible/ansible.cfg
...
[callback_mysql_plays]
mysql_host = localhost
mysql_port = 3306
mysql_user = root
mysql_password = 123
mysql_db = ansible
mysql_talbe = playresult
9.3.7 执行 playbook
[root@dbc-server-554 ansible]# cat remotedate.yml
---
- name: remote server date
hosts: all
gather_facts: no
tasks:
- name: test
shell: date +"%F %T"
[root@dbc-server-554 ansible]# ansible-playbook -i hosts remotedate.yml
9.3.8 在mysql中验证
MariaDB [(none)]> use ansible;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [ansible]> select * from playsresult\G;
*************************** 1. row ***************************
id: 1
user: root
host: 192.168.71.183
category: OK
result: {"module_args": {"creates": null, "executable": null, "_uses_shell": true, "strip_empty_ends": true, "_raw_params": "date +\"%F %T\"", "removes": null, "argv": null, "warn": true, "chdir": null, "stdin_add_newline": true, "stdin": null}} => {"stderr_lines": [], "changed": true, "end": "2023-01-09 11:47:18.051449", "_ansible_no_log": false, "stdout": "2023-01-09 11:47:18", "cmd": "date +\"%F %T\"", "start": "2023-01-09 11:47:18.047806", "delta": "0:00:00.003643", "stderr": "", "rc": 0, "stdout_lines": ["2023-01-09 11:47:18"], "ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}}
create_time: 2023-01-09 16:47:39
1 row in set (0.00 sec)
ERROR: No query specified
9.4 结语
ansible中最难的就是自己编写回调插件(或其他插件)部分,主要是涉及python脚本编写和其他软件一些使用规范,笔者也是边用边学。
对于批量处理服务器,ansible非常好用,但是ansible的模块太多,对于大部分做到了解即可,对于常用的应该掌握。对于常用软件安装配置应该做好笔记。
在测试环境中,多做研发性测试,对于生产环境,一定要验证通过,并尽可能考虑多种因素后再实施。