侧边栏壁纸
博主头像
小续的成长时光 博主等级

行动起来,活在当下

  • 累计撰写 21 篇文章
  • 累计创建 14 个标签
  • 累计收到 3 条评论

目 录CONTENT

文章目录

Ansible自动化 1、入门

小续
2024-06-17 / 0 评论 / 0 点赞 / 47 阅读 / 0 字 / 正在检测是否收录...

一、Ansible 概述

Ansible 是一个简单的自动化引擎,可以完成配置管理、应用部署、服务编排等需求。Ansible 是一款使用 Python 语言开发实现的开源软件,依赖 Jinja2、paramiko 和 PyYAML。

1、Ansible 的优点

① 安装部署简单:Ansible 只需在主控端部署环境,被控端无须做任何操作。

② 基于 SSH 进行配置管理,充分利用现成的机制。

③ 不需要守护进程。

④ 日志集中存储:所有操作日志都存储在 Ansible 发起服务器。

⑤ 简单易用:运行一个部署命令就可以完成应用的部署。此外,Ansible 使用 YAML 语法管理配置,YAML 本身是一种可读性非常强的标记语言。

⑥ 功能强大:通过模块来实现各种功能。

⑦ 设计优秀,便于分享:使用 role 组织 Playbook 并提供了分享 role 的平台(galaxy.ansible.com)。

⑧ 对云计算和大数据平台都有很好的支持。

2、Ansible 的安装

pip install ansible
​
# 安装完成后,控制端服务器会增加以下可执行程序:
ansible
ansible-doc
ansible-playbook
ansible-vault
ansible-console
ansible-galaxy
ansible-pull

3、Ansible 的运行环境

3.1、编辑配置文件

配置文件优先级:

  • 环境变量

  • 当前目录下的 .ansible.cfg 文件

  • 当前目录下的 ansible.cfg 文件

  • /etc/ansible/ansible.cfg

# 在 Ansible 中,有多种方式使用 ansible.cfg 文件。查找顺序如下:
	ANSIBLE_CONFIG 环境变量指定的配置文件
	当前目录下的 ansible.cfg 文件
	当前用户家目录下的 .ansible.cfg 文件
	Ansible 默认的 /etc/ansible/ansible.cfg 文件
	
# ansible.cfg 中常用的配置项:
## 默认配置
inventory:				指定 Inventory 文件的路径
remote_user:			ssh 连接时使用的用户名
remote_port:			ssh 连接时使用的端口号
private_key_file:		ssh 连接时使用的私钥文件
roles_path:				查找 role 的路径,可以指定多个查找路径,路径之间用冒号分隔
log_path:				Ansible 的日志文件路径
host_key_checking:		类似于 ssh 命令中的 StrictHostKeyChecking,当该选项设置为 False 时,不检查远程服务器是否存在于 know_hosts 文件中
forks:					并行进程的数量
gathering:				控制收集 Facts 变量的策略

## ssh 连接配置
ssh_args:				控制 ssh 连接
pipelining:				多个 task 共享 ssh 连接
control_path:			保存 ControlPath socket 的路径

## 权限提升配置
become:					是否进行权限提升
become_method:			权限提升的方式,默认为 sudo
become_user:			提升为哪个用户的权限,默认为 root
become_ask_pass:		默认为 False,表示权限提升时不需要密码

3.1.1、示例文件

[defaults]
inventory = ~/.ansible/hosts
remote_tmp = ~/.ansible/tmp
local_tmp = ~/.ansible/tmp
poll_interval = 15
module_name = command
nocolor = false
host_key_checking = false

[paramiko_connection]
timeout = 10

[privilege_escalation]
become_allow_same_user = true
become_method = sudo
become_ask_pass = False

3.1.2、解释

[defaults]
inventory = ~/.ansible/hosts				#指定主机清单配置文件inventory
remote_tmp = ~/.ansible/tmp					#指定远程主机的执行路径的临时目录,用于存放远程主机的模块文件
local_tmp = ~/.ansible/tmp					#ansible管理节点的临时目录
poll_interval = 15							#轮询时间
module_name = command						#定义ansible默认执行模块
nocolor = false								#是否带颜色输出,true为不带颜色,默认为false

ask_pass = false							#是否需要输入登录密码
private_key_file = /path/to/file.pem		#指定ssh私钥文件
host_key_checking = false					#定义是否需要检查主机的首次连接的指纹验证
remote_user = root							#指定远程登录用户
forks = 5									#用于设置ansible的最大fork数。

[paramiko_connection]
remote_port = 22							#远程ssh端口
timeout = 10								#设置超时时间

[privilege_escalation]
become_allow_same_user = true
become_method = sudo
become_user = root
become_ask_pass = False

3.2、编辑hosts文件

使用 Ansible 操作远程服务器时,首先需要确定的是操作哪些服务器,然后再确定执行哪些操作。Ansible 会默认读取 /etc/ansible/hosts 文件中配置的远程服务器列表。例如:

cat /etc/ansible/hosts
[test1]
10.10.1.1
10.10.1.2

[test2]
10.10.1.3

# Ansible 默认使用当前用户和默认的 22 端口号与远程服务器建立 SSH 连接,如果需要其他用户或端口号,可以自行配置:

cat /etc/ansible/hosts
[test1]
10.10.1.1 ansible_user=abc ansible_port=1234
10.10.1.2 ansible_user=abc ansible_port=1234

[test2]
10.10.1.3 ansible_user=abc ansible_port=1234


# Ansible 默认使用 /etc/ansible/ansible.cfg 文件,可以在这个配置文件中设定一些默认值:

cat /etc/ansible/ansible.cfg
[defaults]
remote_port = 1234
remote_user = abc

二、Ansible 的 ad-hoc 模式

# 格式:
ansible {服务器组名} -m {模块名} -a "参数"

# 例子:
ansible test -m ping
ansible test -m command -a "hostname"
ansible test -m copy -a "src=/tmp/data.txt dest=/tmp/data.txt"

-become 参数的作用等同于 sudo

# 其他参数:
		-k,--ask-pass 登录密码,提示输入SSH密码而不是假设基于密钥的验证
		--ask-su-pass su切换密码
		-K,--ask-sudo-pass 提示密码使用sudo,sudo表示提权操作
		--ask-vault-pass 假设我们设定了加密的密码,则用该选项进行访问
		-B SECONDS #后台运行超时时间
		-C #模拟运行环境并进行预运行,可以进行查错测试
		-c CONNECTION #连接类型使用
		-f FORKS #并行任务数,默认为5
		--list-hosts #查看有哪些主机组
		-o #压缩输出,尝试将所有结果在一行输出,一般针对收集工具使用
		-S #用 su 命令
		-s #用 sudo 命令
		-R SU_USER #指定 su 的用户,默认为 root 用户
		-U SUDO_USER #指定 sudo 到哪个用户,默认为 root 用户
		-T TIMEOUT #指定 ssh 默认超时时间,默认为10s,也可在配置文件中修改
		-u REMOTE_USER #远程用户,默认为 root 用户
		-v #查看详细信息,同时支持-vvv,-vvvv可查看更详细信息

三、Ansible 的 Inventory 管理

1、文件位置

# Inventory 指的是可管理的服务器的集合。

# 在 Ansible 中,有三种指定 hosts 文件的方式:
① 默认读取 /etc/ansible/hosts 文件
② 通过命令行参数的 -i 指定 hosts 文件
③ 通过 ansible.cfg 文件中的 inventory 选项指定。

# 这里的 --list-hosts 的功能是列出匹配的服务器列表。
ansible test -i hosts --list-hosts
	
# 也可以在 ansible.cfg 中指定:
cat /etc/ansible/ansible.cfg
[defaults]
remote_port = 1234
remote_user = abc
inventory = /home/abc/hosts

2、灵活定义和匹配 hosts 文件内容

# 可以将服务器分组:
test.example.com

[webservers]
foo.example.com
bar.example.com

[dbservers]
one.example.com
two.example.com

# 分组后,可以使用组的名称匹配改组下的所有服务器:
root@xkj-Thinkbook16:~# ansible webservers --list-hosts
  hosts (2):
    foo.example.com
    bar.example.com

# all 或 * 代表所有服务器:
root@xkj-Thinkbook16:~# ansible '*' --list-hosts
root@xkj-Thinkbook16:~# ansible all --list-hosts
  hosts (5):
    test.example.com
    foo.example.com
    bar.example.com
    one.example.com
    two.example.com

# 也可以定义一个包含服务器组名称的组,其中的“:children”用来声明这是一个特殊的组:
[common:children]
webservers
dbservers

# 定义格式也可以更简单:
[webservers]
web[1:3].example.com

[dbservers]
db[a:b].example.com

root@xkj-Thinkbook16:~# ansible all --list-hosts
  hosts (5):
    web1.example.com
    web2.example.com
    web3.example.com
    dba.example.com
    dbb.example.com

# 服务器匹配规则:

规则

含义

192.168.0.1 或 web.example.com

匹配目标 IP 地址或服务器名,如果有多个 IP 或服务器,使用“:”分隔。

webservers

匹配目标组为 webservers,多个组使用“:”分隔。

all 或 '*'

匹配所有服务器

webservers:!dbservers

匹配在 webservers 中,不在 dbservers 中的服务器

webservers:&dbservers

匹配同时在 webservers 和 dbservers 中的服务器

*.example.com 或 192.168.*

使用通配符进行匹配

webservers[0],webservers[1:],webservers[-1]

使用索引或切片操作的方式匹配组中的服务器

~ (web db).*.example.com

以 ~ 开头的匹配表示使用正则表达式匹配

3、Inventory 行为参数

行为参数指的是在指定服务器地址时,可以同时指定的一些参数,这些参数可以通过 ansible.cfg 更改默认值:

名称

默认值

描述

ansible_host

主机的名称

ssh 目的主机名或 IP

ansible_user

当前用户

ssh 连接的主机名

ansible_port

22

ssh 连接的端口号

ansible_ssh_private_key_file

none

ssh 连接使用的私钥

ansible_connection

smart

Ansible使用的连接模式,取值为 smart、ssh 或 paramiko

ansible_become

none

类似于 linux 下的 sudo

ansible_become_user

none

切换到哪个用户执行命令

ansible_shell_type

sh

执行命令所用的 shell

ansible_python_interpreter

/usr/bin/python

使用的 python 的解释器

ansible*interpreter

none

指定任意语言的解释器

4、定义普通变量

# 在 hosts 文件中也可以定义普通变量。例如:
[test]
10.10.1.1 mysql_port=3306
10.10.1.2 mysql_port=3307

# 可以查看这个普通变量的值:
ansible all -a 'echo {{mysql_port}}'
10.10.1.1 | SUCCESS | rc=0 >>
3306

10.10.1.2 | SUCCESS | rc=0 >>
3307

# 如果一个组里边同一个变量的取值相同,也可以定义组变量:
[test]
10.10.1.1
10.10.1.2

[test:vars]
mysql_port=3306

# Ansible 提供了更好的方法来管理服务器与群组的变量,即为每个服务器和群组创建独立的变量文件。
	将组的变量存放在一个名为 group_vars 目录下,目录下的文件名与组的名称相同,文件的扩展名可以是 .yml 或 .yaml,也可以没有扩展名。
	服务器的变量存放在一个名为 host_vars 的目录下,该目录下的文件名为服务器的名称。

# Ansible 将依次在 playbook 所在的目录、hosts 文件所在的目录和 /etc/ansible 目录寻找 group_vars 目录和 host_vars 目录。这里假设位于 /etc/ansible 目录下:

$ cd /etc/ansible
$ tree
.
|---- ansible.cfg
└---- group_vars
|     └---- test.yaml
|---- hosts
└---- host_vars
      └---- 127.0.0.1.yaml

$ cat group_vars/test.yaml
mysql_port: 3306

四、Ansible 模块

1、介绍

# Ansible 对远程服务器的操作实际上是通过模块完成的,其工作原理如下:
1)将模块拷贝到远程服务器
2)执行模块定义的操作,完成对服务器的修改
3)在远程服务器中删除模块

# Ansible 中的模块是幂等的,多次执行的操作,只有第一次生效。
ansible-doc -l          # 查看模块列表
ansible-doc {模块名}     # 获取模块的帮助信息
ansible-doc -l {模块名}  # 获取模块的帮助信息

2、常用模块

2.1、ping 模块

# ping 模块用来测试现有的 ssh 参数是否能够顺利连通远程服务器。
ansible test -m ping

2.2、远程命令模块

# command 是默认模块,可以不指定模块名称直接运行 linux 命令。command 模块的重要选项有:
    chdir:在执行指令之前,先切换到指定的目录
    executable:切换 shell 来执行命令
    command 模块在执行 linux 命令时不能使用管道。
​
# 示例
ansible test -a 'hostname'
ansible test -m command -a 'hostname'
​
# 如果执行的命令需要使用管道,可以使用 raw 模块,
    raw 模块相当于使用 ssh 直接执行 linux 命令,不会进入到 Ansible 的模块子系统中。
    也可以使用 shell 模块,shell 模块还可以执行远程服务器上的 shell 脚本文件,脚本文件需要使用绝对路径。
​
ansible test -m raw -a 'cat /etc/passwd | wc -l'
ansible test -m shell -a 'cat /etc/passwd | wc -l'
ansible test -m shell -a '/home/abc/test.sh'
​
# script 模块可以在远程服务器上执行主控节点中的脚本文件。
ansible test -m script -a 'test.sh'

2.3、file 模块

file 模块主要用于对远程服务器上的文件(包括链接和目录)进行操作,包括修改文件的权限、修改文件的所有者、创建文件、删除文件等。
​
# 重要选项有:
path:       指定文件/目录的路径
recurse:    递归设置文件属性,只对目录有效
group:      定义文件/目录的组
mode:       定义文件/目录的权限
owner:      定义文件/目录的所有者
src:        被链接的源文件路径,只应用于 state 为 link 的情况
dest:       被链接到的路径,只应用于 state 为 link 的情况
force:      
在两种情况下会强制创建软链接,一种是源文件不存在但之后会建立的情况;另一种是目标软链接已存在,需要先取消之前的软链接,然后创建新的软链接,默认取值为 no
​
state:      有多种取值。
directory    如果目录不存在,创建目录
file         即使文件不存在也不会被创建,存在则返回文件的信息
link         创建软链接
hard         创建硬链接
touch        如果文件不存在,创建一个新的文件,如果文件或目录已存在,更新其最后访问时间和修改时间
absent       删除目录、文件或链接
​
# 创建一个目录
ansible test -m file -a 'path=/tmp/aaa state=directory mode=0755'
​
# 修改文件的权限
ansible test -m file -a 'path=/tmp/aaa state=touch mode="u=rw,g=r,o=r"'
​
# 创建软链接
ansible test -m file -a 'src=/tmp/aaa dest=/tmp/bbb owner=abc group=abc state=link'
​
# 修改文件的所有者
ansible test -m file -a 'path=/tmp/aaa owner=root group=root mode=0644' -become
​

2.4、copy 模块

# 将主控节点的文件或目录拷贝到远程服务器上,同时也可以设置文件在远程服务器的权限和所有者。
src:
要复制到远程服务器的文件地址,可以是绝对路径或相对路径,如果路径是目录,将递归复制。如果路径以 “/” 结尾,只复制目录里的内容,否则复制包含目录在内的整个内容。
​
dest:
文件复制的目的地,必须是绝对路径,如果源文件是一个目录,dest 指向也必须是一个目录。
​
force:
默认值为 yes,表示目标服务器包含该文件,但内容不同时会强制覆盖。如果该选项设置为 no,则只有当目标服务器的目标位置不存在于该文件时,才会进行复制。
​
backup:
默认值为 no,如果配置为 yes,在覆盖之前将原文件进行备份。
​
directory_mode:
递归设定目录权限,默认为系统默认权限。
​
remote_src: 
默认为false,设置src是否在远程主机上,
​
所有 file 模块的选项都可以在这里使用
​
# 拷贝文件到远程服务器
ansible test -m copy -a "src=test.sh dest=/tmp/test.sh"
​
# 拷贝文件到远程服务器,如果文件已经存在,备份该文件
ansible test -m copy -a "src=test.sh dest=/tmp/test.sh backup=yes force=yes"
​
# 拷贝文件到远程服务器,并且修改文件的所有者和权限
ansible test -m copy -a "src=test.sh dest=/tmp/test.sh owner=root group=root mode=644 force=yes" -become

2.5、user 和 group 模块

# user 模块请求的是 useradd、userdel、usermod 三个指令,group 模块请求的是 groupadd、groupdel、groupmod 三个指令。
name:               需要操作的用户名(或组名)
comment:            用户的详细描述
createhome:         创建用户时,是否创建家目录,默认为 yes
home:               指定用户的家目录,需要与 createhome 选项配合使用
groups:             指定用户的属组
uid:                设置用户的 uid
gid:                设置组的 gid
password:           设置用户的密码
update_password      假如设置的密码不同于原密码,会更新密码
state:              是创建用户(组)还是删除用户(组),取值包括 present 和 absent
expires:            用户的过期时间
shell                指定用户的 shell 环境
generate_ssh_key     设置为yes将会为用户生成密钥,这不会覆盖原来的密钥
ssh_key_type         指定用户的密钥类型,默认rsa,具体类型取决于被管理节点
remove               当与 state=absent 一起使用时,删除一个用户及关联的目录,比如家目录, 邮箱目录,yes|no
​
# 创建一个用户
ansible test -m user -a 'name=abc comment="test" uid=1234 group=root' -become
​
# 删除一个用户
ansible test -m user -a 'name=abc state=absent' -become
​
# 创建一个用户,并产生一对秘钥
ansible test -m user -a 'name=abc comment="test" generate_ssh_key=yes ssh_key_bits=2048' -become
​
# 创建组
ansible test -m group -a "name=ansible state=present gid=1234" -become
​
# 删除组
ansible test -m group -a "name=ansible state=absent" -become

2.6、apt 模块

# 在 Debian/Ubuntu 系统中安装、删除软件
name:           软件包的名称
state:          软件包的状态,可以取值为 latest、absent、present、build-dep,默认为 present
autoremove:     默认值为 no,如果值为 yes,移除不需要的软件包
force:          强制安装或删除软件包
update_cache:   相当于 apt-get update
deb:            deb文件的路径
​
# 安装软件包
ansible test -m apt -a "name=git state=present" -become
​
# 卸载软件包
ansible test -m apt -a "name=git state=absent" -become
​
# 更新源
ansible test -m apt -a "update_cache=yes" -become

2.7、yum 模块

# 在 Redhat 或 centOS 系统中安装、删除软件
name:               软件包名
state:              软件包的状态,可以取值为 present、installed、latest、absent 和 removed
disable_gpg_check:  禁用 rpm 包的公钥 gpg 验证
enable_repo:        指定安装软件包时临时启用的yum源
disable_repo:       指定安装软件包时临时禁用的yum源
​
# 安装软件包
ansible test -m yum -a "name=git state=present" -become
​
# 卸载软件包
ansible test -m yum -a "name=git state=absent" -become

2.8、get_url 模块

# 从互联网下载数据到本地,可以控制下载后的数据所有者、权限以及检查下载数据的 checksum 等
url:        文件的下载地址
dest:       文件保存的绝对路径
mode:       文件的权限
checksum:   文件的校验码
headers:    传递给下载服务器的 HTTP Headers
backup:     如果本地已经存在同名文件,则备份文件
timeout:    下载的超时时间
所有 file 模块的选项都可以在这里使用

2.9、unarchive 模块

# 用于解压文件,将控制节点的压缩包拷贝到远程服务器
remote_src:yes 
表示解压的文件存在远程服务器中,no 表示解压的文件存在控制节点所在的服务器中,默认值为 no,表示解压之前先把文件拷贝到远程主机中。
​
src:        制定压缩文件的路径,所在服务器取决于 remote_src 的取值。
dest:       远程服务器上的绝对路径,表示压缩文件解压的路径。
list_files: 默认 no。取 yes 时,在解压的之后的返回值中列出压缩包里的文件。
exclude:    解压文件时排除的文件或目录
keep_newer: 默认 False。如果为 True,当目标地址中存在同名的文件且文件比压缩包中的文件更新时,不进行覆盖。
owner:      解压后的所有者
group:      解压后的所属的组
mode:       解压后的权限
​
# 解压本地文件
ansible test -m unarchive -a "src=data.tar.gz dest=/tmp/data list_files=yes"
​
# 解压远程的文件
ansible test -m unarchive -a "src=/tmp/data.tar.bz2 dest=/tmp remote_src=yes"

2.10、git 模块

# 在远程服务器执行 git 相关的操作
repo:       远程 git 库的地址,可以是一个 git 协议、ssh 协议或 http 协议 的 git 库地址
dest:       git 库 clone 到本地服务器后保存的绝对路径
version:    git 库的版本,可以取 HEAD、分支的名称、tag 的名称,也可以是一个 commit 的 hash 值
force:      默认 no。如果 yes,如果本地 git 库有修改,会抛弃本地的修改
accept_hostkey:
如果 git 库的服务器不在 know_hosts 中,则添加到 know_hosts 中,key_file 指定克隆远程 git 库地址时使用的私钥
        
# 示例
ansible test -m git -a "repo=https://github.com/kennethreitz/requests.git dest=/tmp/requests version=HEAD"

2.11、stat 模块

# 用于获取远程服务器上的文件信息,可以获取 atime、ctime、mtime、checksum、size、uid、gid 等信息
ansible test -m stat -a "path=/etc/passwd"

2.12、cron 模块

# 管理计划任务
		backup:默认 no,表示修改之前先备份
		state:present 或 absent,表示创建还是删除该计划任务
		name:计划任务的描述
		job:添加或删除任务,取决于 state 的取值
		user:指定 crontab 所属用户
		cron_file:如果指定该选项,用该文件替换远程服务器上的 cron.d 目录下的用户任务计划
		month weekday day minute hour:指定 crontab 的时间参数
		
# 示例
ansible test -m cron -a 'backup=yes name="test cron" minute=*/2 hour=* job="ls /tmp > /dev/null"'

2.13、service 模块

# 相当于 service 命令,用来启动、停止、重启服务
		name:服务的名称
		state:可以取值为 started、stopped、restarted 和 reloaded。started 和 stopped 是幂等的。如果服务已经启动了,执行 started 不会执行任何操作。
		sleep:重启的过程中,先停止服务然后 sleep 几秒再启动
		pattern:定义一个模式,Ansible 首先通过 status 命令查看服务的状态,判断服务是否在运行。如果通过 status 查看服务状态时没有响应,Ansible 会尝试匹配 ps 命令的输出,当匹配到相应的模式时,认为服务已经启动,否则认为没有启动。
		enabled:设置服务是否开机启动

# 停止 Apache
ansible test -m service -a "name=apache2 state=stopped"

# 重启 Apache
ansible test -m service -a "name=apache2 state=restarted"

2.14、systemd 模块

# 相当于 systemctl 命令,用来启动、停止、重启服务
		name:服务名称
		pattern:定义一个模式,Ansible 首先通过 status 命令查看服务的状态,判断服务是否在运行。如果通过 status 查看服务状态时没有响应,Ansible 会尝试匹配 ps 命令的输出,当匹配到相应的模式时,认为服务已经启动,否则认为没有启动。
		sleep:重启的过程中,先停止服务然后 sleep 几秒再启动
		state:可取值为 started、stopped、restarted、reloaded
		enabled:设置服务是否开机启动
		daemon_reload:重新载入 systemd

2.15、sysctl 模块

# 用于控制内核参数
		name:需要设置的参数
		value:需要设置的值
		sysctl_file:sysctl.conf 文件的绝对路径,默认路径是 /etc/sysctl.conf
		reload:默认yes,表示设置完成后是否需要执行 sysctl -p

# 设置 overcommit_memory 参数的值为 1
ansible test -m sysctl -a "name=vm.overcommit_memory value=1" -become

2.16、mount 模块

# 在远程服务器上挂载磁盘,如果挂载点指定的路径不存在,将创建该路径
		name:挂载点的路径
		state:可取值为 present、absent、mounted、unmounted,其中,mounted 和 unmounted 用来处理磁盘的挂载和卸载,且正确配置 fstab 文件,present 和 absent 只会设置 fstab 文件,不会操作磁盘
		fstype:指定文件系统类型,当 state 取值为 present 或 mounted 时,此为必选项
		src:挂载的设备
		
# 示例
ansible test -m mount -a "name=/mnt/data src=/dev/vda fstype=ext4 state=mounted"

2.17、syncronize 模块

# 对 rsync 的封装
		src:需要同步的文件或目录
		dest:远程服务器保存数据的路径
		archive:默认值为 yes,相当于同时开启 recursive、links、perms、times、owner、group、-D 等选项
		compress:在同步过程中是否启用压缩
		delete:默认为 no,取值为 yes 时,表示删除 dest 中存在而 src 中不存在的文件
		
# 示例
ansible test -m syncronize -a "src=test dest=/tmp"

2.18、gather_facts

# 用于收集有关远程主机的信息,例如主机名、IP地址、操作系统、网络接口、硬件信息等。它可以帮助您获取主机的事实信息,并将这些信息存储在Ansible的变量中,以供后续任务使用。

# 默认情况下调用 ansible.builtin.setup  模块

# 命令行
ansible all -m gather_facts

# playbook
- name: Gather Facts
  hosts: all
  gather_facts: yes
  tasks:
    - name: Display Facts
      debug:
        var: ansible_facts
ansible all -m gather_facts
192.168.2.52 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "172.17.0.1",
            "192.168.2.52"
        ],
        "ansible_all_ipv6_addresses": [
            "fe80::a157:95cb:e63c:10dc"
        ],
        "ansible_apparmor": {
            "status": "disabled"
        },
        "ansible_architecture": "x86_64",
        "ansible_bios_date": "11/12/2020",
        "ansible_bios_vendor": "Phoenix Technologies LTD",
        "ansible_bios_version": "6.00",
        "ansible_board_asset_tag": "NA",
        "ansible_board_name": "440BX Desktop Reference Platform",
        "ansible_board_serial": "None",
        "ansible_board_vendor": "Intel Corporation",
        "ansible_board_version": "None",
        "ansible_chassis_asset_tag": "No Asset Tag",
        "ansible_chassis_serial": "None",
        "ansible_chassis_vendor": "No Enclosure",
        "ansible_chassis_version": "N/A",
        "ansible_cmdline": {
            "BOOT_IMAGE": "/vmlinuz-3.10.0-1160.el7.x86_64",
            "LANG": "en_US.UTF-8",
            "quiet": true,
            "rd.lvm.lv": "centos/swap",
            "rhgb": true,
            "ro": true,
            "root": "/dev/mapper/centos-root"
        },
        "ansible_date_time": {
            "date": "2023-12-29",
            "day": "29",
            "epoch": "1703818015",
            "epoch_int": "1703818015",
            "hour": "10",
            "iso8601": "2023-12-29T02:46:55Z",
            "iso8601_basic": "20231229T104655687445",
            "iso8601_basic_short": "20231229T104655",
            "iso8601_micro": "2023-12-29T02:46:55.687445Z",
            "minute": "46",
            "month": "12",
            "second": "55",
            "time": "10:46:55",
            "tz": "CST",
            "tz_dst": "CST",
            "tz_offset": "+0800",
            "weekday": "星期五",
            "weekday_number": "5",
            "weeknumber": "52",
            "year": "2023"
        },
        "ansible_default_ipv4": {
            "address": "192.168.2.52",
            "alias": "ens33",
            "broadcast": "192.168.2.255",
            "gateway": "192.168.2.1",
            "interface": "ens33",
            "macaddress": "00:0c:29:1d:c2:4f",
            "mtu": 1500,
            "netmask": "255.255.255.0",
            "network": "192.168.2.0",
            "prefix": "24",
            "type": "ether"
        },
        "ansible_default_ipv6": {},
        "ansible_device_links": {
            "ids": {
                "dm-0": [
                    "dm-name-centos-root",
                    "dm-uuid-LVM-SJen3omEsNW5XUfryBMiUG9dk1VsTwbHDg0UdvWIxxiMWICoXjkhZvYcDfYWPwBw"
                ],
                "dm-1": [
                    "dm-name-centos-swap",
                    "dm-uuid-LVM-SJen3omEsNW5XUfryBMiUG9dk1VsTwbHHv8kIG9QXQiYL8HyznjqKOGod8NGPNjJ"
                ],
                "dm-2": [
                    "dm-name-centos-home",
                    "dm-uuid-LVM-SJen3omEsNW5XUfryBMiUG9dk1VsTwbHXT7h4M80G2UxiojdOyNnW3W9QZiExlzr"
                ],
                "sda2": [
                    "lvm-pv-uuid-nmGG2H-Jie4-MLvx-EYS8-NGGJ-VDm8-303P14"
                ],
                "sr0": [
                    "ata-VMware_Virtual_IDE_CDROM_Drive_00000000000000000001"
                ]
            },
            "labels": {
                "sr0": [
                    "CentOS\\x207\\x20x86_64"
                ]
            },
            "masters": {
                "sda2": [
                    "dm-0",
                    "dm-1",
                    "dm-2"
                ]
            },
            "uuids": {
                "dm-0": [
                    "c49578c1-a5ed-4f02-b6aa-fb84c9adba87"
                ],
                "dm-1": [
                    "d5067ec0-4f37-4d25-a9ca-2241ebf26514"
                ],
                "dm-2": [
                    "47c77545-e92a-4057-b348-c43e12402268"
                ],
                "sda1": [
                    "8dffff29-d37b-4980-8be6-c531a832b9b7"
                ],
                "sr0": [
                    "2020-11-04-11-36-43-00"
                ]
            }
        },
        "ansible_devices": {
            "dm-0": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-centos-root",
                        "dm-uuid-LVM-SJen3omEsNW5XUfryBMiUG9dk1VsTwbHDg0UdvWIxxiMWICoXjkhZvYcDfYWPwBw"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "c49578c1-a5ed-4f02-b6aa-fb84c9adba87"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "104857600",
                "sectorsize": "512",
                "size": "50.00 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-1": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-centos-swap",
                        "dm-uuid-LVM-SJen3omEsNW5XUfryBMiUG9dk1VsTwbHHv8kIG9QXQiYL8HyznjqKOGod8NGPNjJ"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "d5067ec0-4f37-4d25-a9ca-2241ebf26514"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "16515072",
                "sectorsize": "512",
                "size": "7.88 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-2": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-centos-home",
                        "dm-uuid-LVM-SJen3omEsNW5XUfryBMiUG9dk1VsTwbHXT7h4M80G2UxiojdOyNnW3W9QZiExlzr"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "47c77545-e92a-4057-b348-c43e12402268"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "295944192",
                "sectorsize": "512",
                "size": "141.12 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "sda": {
                "holders": [],
                "host": "SCSI storage controller: Broadcom / LSI 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "VMware Virtual S",
                "partitions": {
                    "sda1": {
                        "holders": [],
                        "links": {
                            "ids": [],
                            "labels": [],
                            "masters": [],
                            "uuids": [
                                "8dffff29-d37b-4980-8be6-c531a832b9b7"
                            ]
                        },
                        "sectors": "2097152",
                        "sectorsize": 512,
                        "size": "1.00 GB",
                        "start": "2048",
                        "uuid": "8dffff29-d37b-4980-8be6-c531a832b9b7"
                    },
                    "sda2": {
                        "holders": [
                            "centos-root",
                            "centos-swap",
                            "centos-home"
                        ],
                        "links": {
                            "ids": [
                                "lvm-pv-uuid-nmGG2H-Jie4-MLvx-EYS8-NGGJ-VDm8-303P14"
                            ],
                            "labels": [],
                            "masters": [
                                "dm-0",
                                "dm-1",
                                "dm-2"
                            ],
                            "uuids": []
                        },
                        "sectors": "417331200",
                        "sectorsize": 512,
                        "size": "199.00 GB",
                        "start": "2099200",
                        "uuid": null
                    }
                },
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "deadline",
                "sectors": "419430400",
                "sectorsize": "512",
                "size": "200.00 GB",
                "support_discard": "0",
                "vendor": "VMware,",
                "virtual": 1
            },
            "sr0": {
                "holders": [],
                "host": "IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)",
                "links": {
                    "ids": [
                        "ata-VMware_Virtual_IDE_CDROM_Drive_00000000000000000001"
                    ],
                    "labels": [
                        "CentOS\\x207\\x20x86_64"
                    ],
                    "masters": [],
                    "uuids": [
                        "2020-11-04-11-36-43-00"
                    ]
                },
                "model": "VMware IDE CDR00",
                "partitions": {},
                "removable": "1",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "deadline",
                "sectors": "9203712",
                "sectorsize": "2048",
                "size": "4.39 GB",
                "support_discard": "0",
                "vendor": "NECVMWar",
                "virtual": 1
            }
        },
        "ansible_distribution": "CentOS",
        "ansible_distribution_file_parsed": true,
        "ansible_distribution_file_path": "/etc/redhat-release",
        "ansible_distribution_file_variety": "RedHat",
        "ansible_distribution_major_version": "7",
        "ansible_distribution_release": "Core",
        "ansible_distribution_version": "7.9",
        "ansible_dns": {
            "nameservers": [
                "223.5.5.5"
            ]
        },
        "ansible_docker0": {
            "active": false,
            "device": "docker0",
            "features": {
                "busy_poll": "off [fixed]",
                "fcoe_mtu": "off [fixed]",
                "generic_receive_offload": "on",
                "generic_segmentation_offload": "on",
                "highdma": "on",
                "hw_tc_offload": "off [fixed]",
                "l2_fwd_offload": "off [fixed]",
                "large_receive_offload": "off [fixed]",
                "loopback": "off [fixed]",
                "netns_local": "on [fixed]",
                "ntuple_filters": "off [fixed]",
                "receive_hashing": "off [fixed]",
                "rx_all": "off [fixed]",
                "rx_checksumming": "off [fixed]",
                "rx_fcs": "off [fixed]",
                "rx_gro_hw": "off [fixed]",
                "rx_udp_tunnel_port_offload": "off [fixed]",
                "rx_vlan_filter": "off [fixed]",
                "rx_vlan_offload": "off [fixed]",
                "rx_vlan_stag_filter": "off [fixed]",
                "rx_vlan_stag_hw_parse": "off [fixed]",
                "scatter_gather": "on",
                "tcp_segmentation_offload": "on",
                "tx_checksum_fcoe_crc": "off [fixed]",
                "tx_checksum_ip_generic": "on",
                "tx_checksum_ipv4": "off [fixed]",
                "tx_checksum_ipv6": "off [fixed]",
                "tx_checksum_sctp": "off [fixed]",
                "tx_checksumming": "on",
                "tx_fcoe_segmentation": "on",
                "tx_gre_csum_segmentation": "on",
                "tx_gre_segmentation": "on",
                "tx_gso_partial": "on",
                "tx_gso_robust": "on",
                "tx_ipip_segmentation": "on",
                "tx_lockless": "on [fixed]",
                "tx_nocache_copy": "off",
                "tx_scatter_gather": "on",
                "tx_scatter_gather_fraglist": "on",
                "tx_sctp_segmentation": "on",
                "tx_sit_segmentation": "on",
                "tx_tcp6_segmentation": "on",
                "tx_tcp_ecn_segmentation": "on",
                "tx_tcp_mangleid_segmentation": "on",
                "tx_tcp_segmentation": "on",
                "tx_udp_tnl_csum_segmentation": "on",
                "tx_udp_tnl_segmentation": "on",
                "tx_vlan_offload": "on",
                "tx_vlan_stag_hw_insert": "on",
                "udp_fragmentation_offload": "on",
                "vlan_challenged": "off [fixed]"
            },
            "hw_timestamp_filters": [],
            "id": "8000.02421336b3b7",
            "interfaces": [],
            "ipv4": {
                "address": "172.17.0.1",
                "broadcast": "172.17.255.255",
                "netmask": "255.255.0.0",
                "network": "172.17.0.0",
                "prefix": "16"
            },
            "macaddress": "02:42:13:36:b3:b7",
            "mtu": 1500,
            "promisc": false,
            "stp": false,
            "timestamping": [
                "rx_software",
                "software"
            ],
            "type": "bridge"
        },
        "ansible_domain": "",
        "ansible_effective_group_id": 0,
        "ansible_effective_user_id": 0,
        "ansible_ens33": {
            "active": true,
            "device": "ens33",
            "features": {
                "busy_poll": "off [fixed]",
                "fcoe_mtu": "off [fixed]",
                "generic_receive_offload": "on",
                "generic_segmentation_offload": "on",
                "highdma": "off [fixed]",
                "hw_tc_offload": "off [fixed]",
                "l2_fwd_offload": "off [fixed]",
                "large_receive_offload": "off [fixed]",
                "loopback": "off [fixed]",
                "netns_local": "off [fixed]",
                "ntuple_filters": "off [fixed]",
                "receive_hashing": "off [fixed]",
                "rx_all": "off",
                "rx_checksumming": "off",
                "rx_fcs": "off",
                "rx_gro_hw": "off [fixed]",
                "rx_udp_tunnel_port_offload": "off [fixed]",
                "rx_vlan_filter": "on [fixed]",
                "rx_vlan_offload": "on",
                "rx_vlan_stag_filter": "off [fixed]",
                "rx_vlan_stag_hw_parse": "off [fixed]",
                "scatter_gather": "on",
                "tcp_segmentation_offload": "on",
                "tx_checksum_fcoe_crc": "off [fixed]",
                "tx_checksum_ip_generic": "on",
                "tx_checksum_ipv4": "off [fixed]",
                "tx_checksum_ipv6": "off [fixed]",
                "tx_checksum_sctp": "off [fixed]",
                "tx_checksumming": "on",
                "tx_fcoe_segmentation": "off [fixed]",
                "tx_gre_csum_segmentation": "off [fixed]",
                "tx_gre_segmentation": "off [fixed]",
                "tx_gso_partial": "off [fixed]",
                "tx_gso_robust": "off [fixed]",
                "tx_ipip_segmentation": "off [fixed]",
                "tx_lockless": "off [fixed]",
                "tx_nocache_copy": "off",
                "tx_scatter_gather": "on",
                "tx_scatter_gather_fraglist": "off [fixed]",
                "tx_sctp_segmentation": "off [fixed]",
                "tx_sit_segmentation": "off [fixed]",
                "tx_tcp6_segmentation": "off [fixed]",
                "tx_tcp_ecn_segmentation": "off [fixed]",
                "tx_tcp_mangleid_segmentation": "off",
                "tx_tcp_segmentation": "on",
                "tx_udp_tnl_csum_segmentation": "off [fixed]",
                "tx_udp_tnl_segmentation": "off [fixed]",
                "tx_vlan_offload": "on [fixed]",
                "tx_vlan_stag_hw_insert": "off [fixed]",
                "udp_fragmentation_offload": "off [fixed]",
                "vlan_challenged": "off [fixed]"
            },
            "hw_timestamp_filters": [],
            "ipv4": {
                "address": "192.168.2.52",
                "broadcast": "192.168.2.255",
                "netmask": "255.255.255.0",
                "network": "192.168.2.0",
                "prefix": "24"
            },
            "ipv6": [
                {
                    "address": "fe80::a157:95cb:e63c:10dc",
                    "prefix": "64",
                    "scope": "link"
                }
            ],
            "macaddress": "00:0c:29:1d:c2:4f",
            "module": "e1000",
            "mtu": 1500,
            "pciid": "0000:02:01.0",
            "promisc": false,
            "speed": 1000,
            "timestamping": [
                "tx_software",
                "rx_software",
                "software"
            ],
            "type": "ether"
        },
        "ansible_env": {
            "HOME": "/root",
            "LANG": "zh_CN.UTF-8",
            "LESSOPEN": "||/usr/bin/lesspipe.sh %s",
            "LOGNAME": "root",
            "LS_COLORS": "rs=0:di=38;5;27:ln=38;5;51:mh=44;38;5;15:pi=40;38;5;11:so=38;5;13:do=38;5;5:bd=48;5;232;38;5;11:cd=48;5;232;38;5;3:or=48;5;232;38;5;9:mi=05;48;5;232;38;5;15:su=48;5;196;38;5;15:sg=48;5;11;38;5;16:ca=48;5;196;38;5;226:tw=48;5;10;38;5;16:ow=48;5;10;38;5;21:st=48;5;21;38;5;15:ex=38;5;34:*.tar=38;5;9:*.tgz=38;5;9:*.arc=38;5;9:*.arj=38;5;9:*.taz=38;5;9:*.lha=38;5;9:*.lz4=38;5;9:*.lzh=38;5;9:*.lzma=38;5;9:*.tlz=38;5;9:*.txz=38;5;9:*.tzo=38;5;9:*.t7z=38;5;9:*.zip=38;5;9:*.z=38;5;9:*.Z=38;5;9:*.dz=38;5;9:*.gz=38;5;9:*.lrz=38;5;9:*.lz=38;5;9:*.lzo=38;5;9:*.xz=38;5;9:*.bz2=38;5;9:*.bz=38;5;9:*.tbz=38;5;9:*.tbz2=38;5;9:*.tz=38;5;9:*.deb=38;5;9:*.rpm=38;5;9:*.jar=38;5;9:*.war=38;5;9:*.ear=38;5;9:*.sar=38;5;9:*.rar=38;5;9:*.alz=38;5;9:*.ace=38;5;9:*.zoo=38;5;9:*.cpio=38;5;9:*.7z=38;5;9:*.rz=38;5;9:*.cab=38;5;9:*.jpg=38;5;13:*.jpeg=38;5;13:*.gif=38;5;13:*.bmp=38;5;13:*.pbm=38;5;13:*.pgm=38;5;13:*.ppm=38;5;13:*.tga=38;5;13:*.xbm=38;5;13:*.xpm=38;5;13:*.tif=38;5;13:*.tiff=38;5;13:*.png=38;5;13:*.svg=38;5;13:*.svgz=38;5;13:*.mng=38;5;13:*.pcx=38;5;13:*.mov=38;5;13:*.mpg=38;5;13:*.mpeg=38;5;13:*.m2v=38;5;13:*.mkv=38;5;13:*.webm=38;5;13:*.ogm=38;5;13:*.mp4=38;5;13:*.m4v=38;5;13:*.mp4v=38;5;13:*.vob=38;5;13:*.qt=38;5;13:*.nuv=38;5;13:*.wmv=38;5;13:*.asf=38;5;13:*.rm=38;5;13:*.rmvb=38;5;13:*.flc=38;5;13:*.avi=38;5;13:*.fli=38;5;13:*.flv=38;5;13:*.gl=38;5;13:*.dl=38;5;13:*.xcf=38;5;13:*.xwd=38;5;13:*.yuv=38;5;13:*.cgm=38;5;13:*.emf=38;5;13:*.axv=38;5;13:*.anx=38;5;13:*.ogv=38;5;13:*.ogx=38;5;13:*.aac=38;5;45:*.au=38;5;45:*.flac=38;5;45:*.mid=38;5;45:*.midi=38;5;45:*.mka=38;5;45:*.mp3=38;5;45:*.mpc=38;5;45:*.ogg=38;5;45:*.ra=38;5;45:*.wav=38;5;45:*.axa=38;5;45:*.oga=38;5;45:*.spx=38;5;45:*.xspf=38;5;45:",
            "MAIL": "/var/mail/root",
            "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
            "PWD": "/root",
            "SHELL": "/bin/bash",
            "SHLVL": "2",
            "SSH_CLIENT": "192.168.2.7 38822 22",
            "SSH_CONNECTION": "192.168.2.7 38822 192.168.2.52 22",
            "SSH_TTY": "/dev/pts/0",
            "TERM": "xterm-256color",
            "USER": "root",
            "XDG_RUNTIME_DIR": "/run/user/0",
            "XDG_SESSION_ID": "19",
            "_": "/usr/bin/python"
        },
        "ansible_fibre_channel_wwn": [],
        "ansible_fips": false,
        "ansible_form_factor": "Other",
        "ansible_fqdn": "node1",
        "ansible_hostname": "node1",
        "ansible_hostnqn": "",
        "ansible_interfaces": [
            "lo",
            "docker0",
            "ens33"
        ],
        "ansible_is_chroot": false,
        "ansible_iscsi_iqn": "",
        "ansible_kernel": "3.10.0-1160.el7.x86_64",
        "ansible_kernel_version": "#1 SMP Mon Oct 19 16:18:59 UTC 2020",
        "ansible_lo": {
            "active": true,
            "device": "lo",
            "features": {
                "busy_poll": "off [fixed]",
                "fcoe_mtu": "off [fixed]",
                "generic_receive_offload": "on",
                "generic_segmentation_offload": "on",
                "highdma": "on [fixed]",
                "hw_tc_offload": "off [fixed]",
                "l2_fwd_offload": "off [fixed]",
                "large_receive_offload": "off [fixed]",
                "loopback": "on [fixed]",
                "netns_local": "on [fixed]",
                "ntuple_filters": "off [fixed]",
                "receive_hashing": "off [fixed]",
                "rx_all": "off [fixed]",
                "rx_checksumming": "on [fixed]",
                "rx_fcs": "off [fixed]",
                "rx_gro_hw": "off [fixed]",
                "rx_udp_tunnel_port_offload": "off [fixed]",
                "rx_vlan_filter": "off [fixed]",
                "rx_vlan_offload": "off [fixed]",
                "rx_vlan_stag_filter": "off [fixed]",
                "rx_vlan_stag_hw_parse": "off [fixed]",
                "scatter_gather": "on",
                "tcp_segmentation_offload": "on",
                "tx_checksum_fcoe_crc": "off [fixed]",
                "tx_checksum_ip_generic": "on [fixed]",
                "tx_checksum_ipv4": "off [fixed]",
                "tx_checksum_ipv6": "off [fixed]",
                "tx_checksum_sctp": "on [fixed]",
                "tx_checksumming": "on",
                "tx_fcoe_segmentation": "off [fixed]",
                "tx_gre_csum_segmentation": "off [fixed]",
                "tx_gre_segmentation": "off [fixed]",
                "tx_gso_partial": "off [fixed]",
                "tx_gso_robust": "off [fixed]",
                "tx_ipip_segmentation": "off [fixed]",
                "tx_lockless": "on [fixed]",
                "tx_nocache_copy": "off [fixed]",
                "tx_scatter_gather": "on [fixed]",
                "tx_scatter_gather_fraglist": "on [fixed]",
                "tx_sctp_segmentation": "on",
                "tx_sit_segmentation": "off [fixed]",
                "tx_tcp6_segmentation": "on",
                "tx_tcp_ecn_segmentation": "on",
                "tx_tcp_mangleid_segmentation": "on",
                "tx_tcp_segmentation": "on",
                "tx_udp_tnl_csum_segmentation": "off [fixed]",
                "tx_udp_tnl_segmentation": "off [fixed]",
                "tx_vlan_offload": "off [fixed]",
                "tx_vlan_stag_hw_insert": "off [fixed]",
                "udp_fragmentation_offload": "on",
                "vlan_challenged": "on [fixed]"
            },
            "hw_timestamp_filters": [],
            "ipv4": {
                "address": "127.0.0.1",
                "broadcast": "",
                "netmask": "255.0.0.0",
                "network": "127.0.0.0",
                "prefix": "8"
            },
            "ipv6": [
                {
                    "address": "::1",
                    "prefix": "128",
                    "scope": "host"
                }
            ],
            "mtu": 65536,
            "promisc": false,
            "timestamping": [
                "rx_software",
                "software"
            ],
            "type": "loopback"
        },
        "ansible_loadavg": {
            "15m": 0.05,
            "1m": 0.0,
            "5m": 0.04
        },
        "ansible_local": {},
        "ansible_locally_reachable_ips": {
            "ipv4": [
                "127.0.0.0/8",
                "127.0.0.1",
                "172.17.0.1",
                "192.168.2.52"
            ],
            "ipv6": [
                "::1",
                "fe80::a157:95cb:e63c:10dc"
            ]
        },
        "ansible_lsb": {},
        "ansible_lvm": {
            "lvs": {
                "home": {
                    "size_g": "141.12",
                    "vg": "centos"
                },
                "root": {
                    "size_g": "50.00",
                    "vg": "centos"
                },
                "swap": {
                    "size_g": "7.88",
                    "vg": "centos"
                }
            },
            "pvs": {
                "/dev/sda2": {
                    "free_g": "0.00",
                    "size_g": "199.00",
                    "vg": "centos"
                }
            },
            "vgs": {
                "centos": {
                    "free_g": "0.00",
                    "num_lvs": "3",
                    "num_pvs": "1",
                    "size_g": "199.00"
                }
            }
        },
        "ansible_machine": "x86_64",
        "ansible_machine_id": "8f493910db044b7badeae1143229a5f7",
        "ansible_memfree_mb": 7275,
        "ansible_memory_mb": {
            "nocache": {
                "free": 7492,
                "used": 471
            },
            "real": {
                "free": 7275,
                "total": 7963,
                "used": 688
            },
            "swap": {
                "cached": 0,
                "free": 0,
                "total": 0,
                "used": 0
            }
        },
        "ansible_memtotal_mb": 7963,
        "ansible_mounts": [
            {
                "block_available": 224504,
                "block_size": 4096,
                "block_total": 259584,
                "block_used": 35080,
                "device": "/dev/sda1",
                "fstype": "xfs",
                "inode_available": 523962,
                "inode_total": 524288,
                "inode_used": 326,
                "mount": "/boot",
                "options": "rw,relatime,attr2,inode64,noquota",
                "size_available": 919568384,
                "size_total": 1063256064,
                "uuid": "8dffff29-d37b-4980-8be6-c531a832b9b7"
            },
            {
                "block_available": 12295926,
                "block_size": 4096,
                "block_total": 13100800,
                "block_used": 804874,
                "device": "/dev/mapper/centos-root",
                "fstype": "xfs",
                "inode_available": 26140015,
                "inode_total": 26214400,
                "inode_used": 74385,
                "mount": "/",
                "options": "rw,relatime,attr2,inode64,noquota",
                "size_available": 50364112896,
                "size_total": 53660876800,
                "uuid": "c49578c1-a5ed-4f02-b6aa-fb84c9adba87"
            },
            {
                "block_available": 36966713,
                "block_size": 4096,
                "block_total": 36974961,
                "block_used": 8248,
                "device": "/dev/mapper/centos-home",
                "fstype": "xfs",
                "inode_available": 73986045,
                "inode_total": 73986048,
                "inode_used": 3,
                "mount": "/home",
                "options": "rw,relatime,attr2,inode64,noquota",
                "size_available": 151415656448,
                "size_total": 151449440256,
                "uuid": "47c77545-e92a-4057-b348-c43e12402268"
            }
        ],
        "ansible_nodename": "node1",
        "ansible_os_family": "RedHat",
        "ansible_pkg_mgr": "yum",
        "ansible_proc_cmdline": {
            "BOOT_IMAGE": "/vmlinuz-3.10.0-1160.el7.x86_64",
            "LANG": "en_US.UTF-8",
            "quiet": true,
            "rd.lvm.lv": [
                "centos/root",
                "centos/swap"
            ],
            "rhgb": true,
            "ro": true,
            "root": "/dev/mapper/centos-root"
        },
        "ansible_processor": [
            "0",
            "GenuineIntel",
            "Intel(R) Xeon(R) CPU E5-2670 v2 @ 2.50GHz",
            "1",
            "GenuineIntel",
            "Intel(R) Xeon(R) CPU E5-2670 v2 @ 2.50GHz",
            "2",
            "GenuineIntel",
            "Intel(R) Xeon(R) CPU E5-2670 v2 @ 2.50GHz",
            "3",
            "GenuineIntel",
            "Intel(R) Xeon(R) CPU E5-2670 v2 @ 2.50GHz"
        ],
        "ansible_processor_cores": 2,
        "ansible_processor_count": 2,
        "ansible_processor_nproc": 4,
        "ansible_processor_threads_per_core": 1,
        "ansible_processor_vcpus": 4,
        "ansible_product_name": "VMware Virtual Platform",
        "ansible_product_serial": "VMware-56 4d 0c d2 13 5b 0b d8-d3 c8 5d c7 45 1d c2 4f",
        "ansible_product_uuid": "D20C4D56-5B13-D80B-D3C8-5DC7451DC24F",
        "ansible_product_version": "None",
        "ansible_python": {
            "executable": "/usr/bin/python",
            "has_sslcontext": true,
            "type": "CPython",
            "version": {
                "major": 2,
                "micro": 5,
                "minor": 7,
                "releaselevel": "final",
                "serial": 0
            },
            "version_info": [
                2,
                7,
                5,
                "final",
                0
            ]
        },
        "ansible_python_version": "2.7.5",
        "ansible_real_group_id": 0,
        "ansible_real_user_id": 0,
        "ansible_selinux": {
            "status": "disabled"
        },
        "ansible_selinux_python_present": true,
        "ansible_service_mgr": "systemd",
        "ansible_ssh_host_key_ecdsa_public": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBClI+DooIWu08pKeb4gYBiMEWcKAbi8cpu32+A9lBmcRBpAKqLz8/uO3L9chG6XFSOU02qCdkzGdZ3bapmI6I5A=",
        "ansible_ssh_host_key_ecdsa_public_keytype": "ecdsa-sha2-nistp256",
        "ansible_ssh_host_key_ed25519_public": "AAAAC3NzaC1lZDI1NTE5AAAAIGMoseg2ywDbDKCDS4h6IMVspZnBe1xP0AB5+mKzQAjj",
        "ansible_ssh_host_key_ed25519_public_keytype": "ssh-ed25519",
        "ansible_ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAADAQABAAABAQC9zlBHycpjLSIoqYJrZrqr0n/r04/YM4YXjkZ84aXfAEiM25t2lbMf1wt3gnCoT0YHTv727h13GQMpQFB1wpZKWh2+L2KGEp9EfbZU6IBRdsxZvtsJ1LhBfMSLKQlZF3CxrfAmkdS9D1LI/5CWfHeFTZ1nzq7BIv0++tJ3gLliHth9VXLBL0x1c8Qimrir8OC2wYMujl9EwVI8/CW3EYAKHulr6PxVvBhyWfcs2KKApId/dewBOUaIaeexvEYC17hvCwK9sBZdN+APK+GLShoAo7baa0eikdc64cF0uQlvjwvpH1FdQ9TIq+/dAN+2/4hQQRLVeauFfVWbg9HT8U+3",
        "ansible_ssh_host_key_rsa_public_keytype": "ssh-rsa",
        "ansible_swapfree_mb": 0,
        "ansible_swaptotal_mb": 0,
        "ansible_system": "Linux",
        "ansible_system_capabilities": [
            "cap_chown",
            "cap_dac_override",
            "cap_dac_read_search",
            "cap_fowner",
            "cap_fsetid",
            "cap_kill",
            "cap_setgid",
            "cap_setuid",
            "cap_setpcap",
            "cap_linux_immutable",
            "cap_net_bind_service",
            "cap_net_broadcast",
            "cap_net_admin",
            "cap_net_raw",
            "cap_ipc_lock",
            "cap_ipc_owner",
            "cap_sys_module",
            "cap_sys_rawio",
            "cap_sys_chroot",
            "cap_sys_ptrace",
            "cap_sys_pacct",
            "cap_sys_admin",
            "cap_sys_boot",
            "cap_sys_nice",
            "cap_sys_resource",
            "cap_sys_time",
            "cap_sys_tty_config",
            "cap_mknod",
            "cap_lease",
            "cap_audit_write",
            "cap_audit_control",
            "cap_setfcap",
            "cap_mac_override",
            "cap_mac_admin",
            "cap_syslog",
            "35",
            "36+ep"
        ],
        "ansible_system_capabilities_enforced": "True",
        "ansible_system_vendor": "VMware, Inc.",
        "ansible_uptime_seconds": 587,
        "ansible_user_dir": "/root",
        "ansible_user_gecos": "root",
        "ansible_user_gid": 0,
        "ansible_user_id": "root",
        "ansible_user_shell": "/bin/bash",
        "ansible_user_uid": 0,
        "ansible_userspace_architecture": "x86_64",
        "ansible_userspace_bits": "64",
        "ansible_virtualization_role": "guest",
        "ansible_virtualization_tech_guest": [
            "VMware"
        ],
        "ansible_virtualization_tech_host": [],
        "ansible_virtualization_type": "VMware",
        "discovered_interpreter_python": "/usr/bin/python",
        "gather_subset": [
            "all"
        ],
        "module_setup": true
    },
    "changed": false,
    "deprecations": [],
    "warnings": []
}

3、模块的返回值

返回值

含义

changed

几乎所有 Ansible 模块都会返回该变量,表示模块是否对远程主机执行了修改操作

failed

如果模块未能执行完成,返回 failed 为 true

msg

模块执行失败的原因,常见的错误如 ssh 连接失败,没有权限执行模块等

rc

与命令行相关的模块会返回 rc,表示执行 linux 命令的返回码

stdout

与 rc 类似,返回的是标准输出的结果

stderr

与 rc 类似,返回的是标准错误的结果

backup_file

所有存在 backup 选项的模块,用来返回备份文件的路径

results

应用在 Playbook 中存在循环的情况,返回多个结果

五、ansible变量

1、变量定义的方式:

通过命令行传递变量参数定义

1.1、在playbook中定义变量

  • 通过vars定义变量

cat test.yaml
---
- hosts: node
  vars:
  - web_packages: nginx
  tasks:
    - name: Installed web
      yum: "{{ web_packages }}"
  • 通过var_files定义变量,创建一个yml文件专门创建变量,属于公用变量

cat test.yaml
---
- hosts: node
  vars_file:
  - ./var.yml
  tasks:
    - name: Installed web
      yum: "{{ web_packages }}"

1.2、通过inventory在主机组或单个主机中设置变量

  • 通过host_vars对主机进行定义

  • 通过group_vars对主机组进行定义

cat /etc/ansible/hosts
# 主机变量
[web]
192.168.10.2 myid=1 state=master
192.168.10.3 myid=2 state=backup

# 组变量
[web:vars]
port=80
  • 为主机单独创建变量

mkdir host_vars
vim host_vars/192.168.10.2
state: master
  • 为主机组创建变量,方式类似,文件名要与主机组名一致

mkdir host_vars
vim host_vars/web
  • 外置传递变量,可以在执行playbook时定义变量

ansible-playbook test.yml -e "route_id=8888"

2、ansible变量优先级:

外置传参——>playbook(vars_file——>vars)——>主机变量——>group_vars——>inventory_group

3、Register Variables

Ansible的register变量是一种变量类型,用于在运行任务时存储命令、模块或脚本的输出。它们通常用于条件语句或后续任务中,以根据输出结果采取特定的操作。

注册变量可在任务执行完成后访问,以检查命令、模块或脚本执行的输出或结果。您可以使用register变量来存储远程主机上测试的结果,或者正则表达式的匹配结果,甚至是命令的输出。

Register可以将task执行的任务结果存储至某个变量中,便于后续引用

---
- hosts: all
  tasks:
    
    - name: Get network port
      shell: netstat -lntp
      register: System_port
 
    - name: Debug
      debug: 
        msg: "{{ System_port }}"

这段代码的含义是将netstat -lntp的执行结果注入到System_port变量中。

ok: [192.168.10.2] => {
    "msg": {
        "changed": true, 
        "cmd": "netstat -lntp", 
        "delta": "0:00:00.033419", 
        "end": "2023-03-12 08:44:38.655001", 
        "failed": false, 
        "rc": 0, 
        "start": "2023-03-12 08:44:38.621582", 
        "stderr": "", 
        "stderr_lines": [], 
        "stdout": "Active Internet connections (only servers)\nProto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    \ntcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1055/sshd           \ntcp        0      0 127.0.0.1:40663         0.0.0.0:*               LISTEN      11868/containerd    \ntcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1166/master         \ntcp6       0      0 :::9100                 :::*                    LISTEN      1053/node_exporter  \ntcp6       0      0 :::22                   :::*                    LISTEN      1055/sshd           \ntcp6       0      0 :::3000                 :::*                    LISTEN      1054/grafana-server \ntcp6       0      0 ::1:25                  :::*                    LISTEN      1166/master         \ntcp6       0      0 :::9090                 :::*                    LISTEN      1058/prometheus     ", 
        "stdout_lines": [
            "Active Internet connections (only servers)", 
            "Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    ", 
            "tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1055/sshd           ", 
            "tcp        0      0 127.0.0.1:40663         0.0.0.0:*               LISTEN      11868/containerd    ", 
            "tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1166/master         ", 
            "tcp6       0      0 :::9100                 :::*                    LISTEN      1053/node_exporter  ", 
            "tcp6       0      0 :::22                   :::*                    LISTEN      1055/sshd           ", 
            "tcp6       0      0 :::3000                 :::*                    LISTEN      1054/grafana-server ", 
            "tcp6       0      0 ::1:25                  :::*                    LISTEN      1166/master         ", 
            "tcp6       0      0 :::9090                 :::*                    LISTEN      1058/prometheus     "
        ]
    }
}

如果要选用其中的某个参数,只需要在变量名后加入即可:

    - name: Debug
      debug: 
        msg: "{{ System_port.stdout_lines }}"

3.1、示例

# 示例:批量修改主机名
将192.168.10.2-3两台主机名修改为指定格式:
---
- hosts: all

  tasks:
    - name: String
      shell: echo $RANDOM | md5sum | cut -c 2-10
      register: system_sj

    - name: Chanage hostname
      hostname:
        name: "centos_7.9_{{ system_sj.stdout }}"

# 执行结果分别在两台主机查看:
# 192.168.10.2
centos_7.9_1348277e0
# 192.168.10.3
centos_7.9_e08760762

4、Facts Variables

# Ansible中的facts是由Ansible在目标机器上运行的“setup”模块生成的系统和环境信息。这些信息存储在变量中,可以通过Ansible playbook和模板使用。

# Facts变量包括:
  系统信息:操作系统、主机名、内核参数、网络接口、CPU信息等。
  硬件信息:服务器制造商、BIOS版本、物理内存、磁盘容量等。
  网络信息:IP地址、MAC地址、路由列表等。
  环境变量:PATH、PYTHONPATH等环境变量。

# 在使用场景中:
  检查CPU信息,生成不同的nginx配置文件
  检查内存信息。生成不同的memcached配置文件
  检查主机名信息,生成不同的zabbix配置文件
  检查IP信息,生成不同的redis配置文件

# 可以使用下面这条命令查看可用信息:
ansible all -m setup

4.1、示例: 基于IP生成redis配置文件

# playbook.yml
---
- hosts: all
  tasks:
    - name: Installed redis
      yum:
        name: redis
        state: present

    - name: Configure redis server
      template:
        src: ./redis.conf.j2
        dest: /etc/redis.conf
      notify: Restart redis server

    - name: Started redis server
      systemd:
        name: redis
        state: started
        enabled: yes
  handlers:
    - name: Restart redis server
      service:
        name: redis
        state: restarted
        
# redis.conf.j2
bind 127.0.0.1 {{ ansible_ens33.ipv4.address }}

# 查看结果
[root@centos_7 ~]# netstat -utpln | grep 6379
tcp        0      0 192.168.10.2:6379       0.0.0.0:*               LISTEN      30584/redis-server  
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      30584/redis-server  

[root@centos_7 ~]#  netstat -utpln | grep 6379
tcp        0      0 192.168.10.3:6379       0.0.0.0:*               LISTEN      32967/redis-server  
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      32967/redis-server  

4.2、facts优化

# 使用gather_facts: no关闭facts
- hosts: all
  gather_facts: no

# 使用redis进行缓存vim ansible.cfg
gathering = smart
fact_caching_timeout = 86400
fact_caching = redis
fact_caching_connection = 192.168.10.3:6379
# 如果redis有密码
fact_caching_connection = 192.168.10.3:6379:0:passwd

六、Playbook

  • YAML 语法

YAML 文件的第一行为 “---”,表示这是一个 YAML 文件

YAML 中的字段大小写敏感

YAML 与 Python 一样,使用缩进表示层级关系

YAML 的缩进不允许使用 Tab 键,只允许使用空格,且空格的数目不重要,只要相同层级的元素左侧对齐即可

“#” 表示注释,从这个字符一直到行尾都会被解析器忽略

# YAML 支持三种格式的数据:
		对象:键值对的集合,又称为映射,类似于 Python 中的字典
		数组:一组按次序排列的值,又称为序列,类似于 Python 中的列表
		纯量:单个的、不可再分的值,如字符串、布尔值和数字

1、定义

Playbook 的功能强大,可以实现各种高级功能,如指定任务的执行顺序,委派其他主机来执行某一个任务,与监控服务器和负载均衡组件进行交互等。Ansible 中的模块类似 linux 下的命令,Playbook 类似于 linux 下的 Shell 脚本文件。Playbook 将各个模块组合起来实现复杂的部署功能。

# 在 Ansible 中,一个 Play 必须包含以下两项
hosts:需要对哪些远程服务器执行操作
tasks:需要在这些服务器上执行的任务列表

# 举个例子:
---

- hosts: dbservers
  become: yes
  become_method: sudo
  tasks:
  - name: install mongodb
    apt: name=mongodb-server state=present

- hosts: webservers
  tasks:
  - name: copy file
    copy: src=/tmp/data.txt dest=/tmp/data.txt
  - name: change mode
    file: dest=/tmp/data.txt mode=655 owner=abc group=abc

# tasks 的格式是:
tasks:
  - name: task1
    module1: args1
  - name: task2
    module2: args2
    ...
    也可以折叠换行:

- name: install apache
  apt: >
    name=apache2
    update_cache=yes
    state=present
- name: install apache
  apt:
    name: apache2
    update_cache: yes
    state: present
    
# name 是可选的,所以可以不写。建议写上,方便使用者知道当前执行到哪一步。

# 在上边的例子中展示的 Playbook,可以拆分成两个 Playbook(db.yml 和 web.yml)。可以编写一个 all.yml:
---

- include: db.yml
- include: web.yml
  在执行 all.yml 时,db.yml 和 web.yml 会依次执行。

2、使用 ansible-playbook 执行 Playbook

# ansible-playbook 的命令行选项:
		-T --timeout:建立 ssh 连接的超时时间
		--key-file --private-key:建立 ssh 连接的私钥文件
		-i --inventory-file:指定 Inventory 文件,默认是 /etc/ansible/hosts
		-f --forks:并发执行的进程数,默认为 5
		--list-hosts:匹配的服务器列表
		--list-tasks:列出任务列表
		--step:每执行一个任务后停止,等待用户确认
		--syntax-check:检查 Playbook 的语法
		-C --check:预测 Playbook 的执行结果

3、详细语法

3.1、权限

# 在 Ansible 中,默认以当前用户连接远程服务器执行操作。可以在 ansible.cfg 文件中配置默认用户,也可以在 Play 定义中配置:
---
- hosts: webservers
  remote_user: root

# 可以细分 task 对应的用户:
---
- hosts: webservers
  remote_user: root
  tasks:
    - name: test connection
      ping:
      remote_user: abc

# 可以使用管理员身份执行操作:
---
- hosts: webservers
  remote_user: abc
  tasks:
    - service: name=nginx state=started
      become: yes
      become_method: sudo

3.2、通知

# 通过 notify 和 handler 机制来实现。handler 是 Ansible 提供的条件机制,与 task 类似。但是 handler 只有在被 notify 触发后才会执行:
---
- hosts: webservers
  tasks:
  - name: ensure apache is at the latest version
    yum: name=httpd state=latest
  - name: write the apache config file
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf
    notify:
    - restart apache
  - name: ensure apache is running
    service: name=httpd state=started
  handlers:
    - name: restart apache
      service: name=httpd state=restarted

# handler 只会在 task 执行完之后执行,即使一个 handler 被触发多次,也只会执行一次。
		handler 是按照定义顺序执行。官方文档提到 handler 的唯一用途就是重启服务与服务器。

3.3、变量

# 最直接的定义变量的方式是定义在 Playbook 的 vars 选项中:
- hosts: dbservers
  vars:
    mysql_port: 3306
    
# 在 Playbook 中定义的变量,可以在模板渲染时使用,例如,官方例子:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
port={{ mysql_port }}

# 当变量比较多时,可以将变量保存在一个独立的文件中,通过 vars_files 引用该文件:
---
- hosts: all
  vars:
    favcolor: blue
  vars_files:
    - /vars/external_vars.yml
  tasks:
  - name: this is just a placeholder
    command: /bin/echo foo

# 保存变量的文件是一个 YAML 格式的字典:
---
somevar: somevalue
password: magic

# 在 Ansible 中,可以获取任务的执行结果,将执行结果保存在一个变量中。这样的变量使用 register 进行定义,也称为注册变量。
- hosts: webservers
  tasks:
    - shell: /usr/bin/foo
      register: foo_result
      ignore_errors: True
    - shell: /usr/bin/bar
      when: foo_result.rc == 5
      
# ignore_errors 表示忽略当前 task 中的错误,when 是一个条件语句,条件为真时才会执行这个 task。

3.4、Facts 变量

# 在 Ansible 中,有一些特殊的变量,这些变量不需要进行任何设置就可以直接使用,这样的变量称为 Facts 变量。
		Facts 变量是 Ansible 执行远程部署之前从远程服务器中获取的系统信息。
		在 Playbook 中,可以通过 gather_facts 选项控制是否收集远程服务器的信息,默认值为yes。

---
- hosts: all
  tasks:
    - shell: echo {{ansible_os_family}}
      ...
      when: ansible_os_family == "Debian"

# 要访问复杂变量的子属性时,需要使用嵌套结构:
ansible_eth0["ipv4"]["address"]
ansible_eth0.ipv4.address 
# 常见内置变量

# 一般连接
ansible_host #用于指定被管理的主机的真实IP
ansible_port #用于指定连接到被管理主机的ssh端口号,默认是22
ansible_user #ssh连接时默认使用的用户名
# 特定ssh连接
ansible_connection #SSH连接的类型:local, ssh, paramiko,在ansible 1.2 之前默认是
paramiko,后来智能选择,优先使用基于ControlPersist的ssh(如果支持的话)
ansible_ssh_pass #ssh连接时的密码
ansible_ssh_private_key_file #秘钥文件路径,如果不想使用ssh‐agent管理秘钥文件时可以使用此选项
ansible_ssh_executable #如果ssh指令不在默认路径当中,可以使用该变量来定义其路径
# 特权升级
ansible_become #相当于ansible_sudo或者ansible_su,允许强制特权升级
ansible_become_user #通过特权升级到的用户,相当于ansible_sudo_user或者ansible_su_user
ansible_become_pass # 提升特权时,如果需要密码的话,可以通过该变量指定,相当于
ansible_sudo_pass或者ansible_su_pass
ansible_sudo_exec #如果sudo命令不在默认路径,需要指定sudo命令路径
# 远程主机环境参数
ansible_shell_executable # 设置目标机上使用的shell,默认为/bin/sh
ansible_python_interpreter #用来指定python解释器的路径,默认为/usr/bin/python 同样可以指
定ruby 、perl 的路径
ansible_*_interpreter #其他解释器路径,用法与ansible_python_interpreter类似,这里"*"可以
是ruby或才perl等其他语

3.5、循环

# 举例:
- name: Install Mysql package
  yum: name={{ item }} state=installed
  with_items:
    - mysql-server
    - MySQL-python
    - libselinux-python
    - libsemanage-python

3.6、条件判断

# 使用 when
tasks:
  - name: shut down Debian flavored systems
    command: /sbin/shutdown -t now
    when: ansible_os_family == "Debian"

# 多个条件语句:
...
when:
  - ansible_distribution == "CentOS"
  - ansible_distribution_major_version == "6"

# 使用 and or:
...
when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6") or
      (ansible_distribution == "CentOS" and ansible_distribution_major_version == "7")

# 使用 jinja2 的过滤器:
...
when: result|failed

# 可以读取变量的取值:
...
epic: true
...
when: epic

# 可以和循环一起使用:
tasks:
  - command: echo {{ item }}
    with_items: [ 0, 2, 4, 6, 8, 10 ]
    when: item > 5

3.7、任务执行策略

# 从 Ansible 2.0 开始,支持 free 的任务执行策略,允许执行较快的远程服务器提前完成 Play 的部署:
- hosts: all
  strategy: free
  ...

4、高级语法

4.1、线性更新服务器

# 使用 Ansible 的 serial 选项,可以取值为一个数字,表示一次更新多少台服务器,也可以取值为一个百分比,例如:
- name: test play
  hosts: webservers
  serial: 1
- name: test play
  hosts: webservers
  serial: "30%"

# 下面的配置表示先更新 1 台,再更新 5 台,最后更新 10 台服务器:
- name: test play
  hosts: webservers
  serial:
  - 1
  - 5
  - 10

4.2、使用 delegate_to 实现任务委派功能

name: take out of load balancer pool
command: /usr/bin/take_out_of_pool {{ inventory_hostname }}
delegate_to: 127.0.0.1

4.3、使用 local_action 在控制服务器执行操作

tasks:
- name: take out of load balancer pool
  local_action: command /usr/bin/take_out_of_pool {{ inventory_hostname }}

4.4、使用 run_once 保证任务只执行一次

...
run_once: true

4.5、高级循环结构

# 除了 with_items 之外,还包含以下循环:
with_lines
with_fileglob
with_first_found
with_dict
with_flattened
with_indexed_items
with_nested
with_random_choice
with_sequence
with_together
with_subelements
with_file 

# with_items 的每一项都可以是字典,通过 item.key 的方式引用字典:
- name: Add several users
  ansible.builtin.user:
    name: "{{ item.name }}"
    state: present
    groups: "{{ item.groups }}"
  with_items:
    - { name: 'testuser1', groups: 'wheel' }
    - { name: 'testuser2', groups: 'root' }

# 如果循环的元素是一个嵌套字典,需要使用 with_dict 遍历元素:
---
users:
  alice:
    name: Alice Appleworth
    telephone: 123-456-7890
  bob:
    name: Bob Bananarama
    telephone: 987-654-3210
tasks:
  - name: Print phone records
    debug:
      msg: "User {{ item.key }} is {{ item.value.name }} ({{ item.value.telephone }})"
    with_dict: "{{ users }}"

# 如果循环的每一项是列表,可以使用 with_nested 遍历,通过下标的方式访问列表中的元素:
- name: give users access to multiple databases
  mysql_user:
    name: "{{ item[0] }}"
    priv: "{{ item[1] }}.*:ALL"
    append_privs: yes
    password: "foo"
  with_nested:
    - [ 'alice', 'bob' ]
    - [ 'clientdb', 'employeedb', 'providerdb' ]

# 可以使用 with_sequence 产生数字列表,指定起点、终点和步长:
- user:
  name: "{{ item }}"
  state: present
  groups: "evens"
  with_sequence: start=0, end=32, format=testuser%02x

# with_random_choice 随机选择一项:
- debug:
  msg: "{{ item }}"
  with_random_choice:
    - "go through the door"
    - "drink from the goblet"
    - "press the red button"
    - "do nothing"

4.6、使用标签灵活控制执行

- name: install packages
  yum: name={{ item }} state=installed
  with_items:
     - httpd
     - memcached
  tags:
     - packages
- name: uploading config file
  template: src=templates/src.j2 dest=/etc/foo.conf
  tags:
     - configuration
- name: be sure ntpd is running and enabled
  service: name=ntpd state=started enabled=yes
  tags: ntp

# 在这个例子中,用 tags 为每个任务打上了标签,使用下边的方法可以控制标签执行:
ansible-playbook example.yml --tags "configuration,packages"
ansible-playbook example.yml --skip-tags "ntp"

4.7、使用 changed_when 控制对 changed 字段的定义

# 在使用 shell 模块时,往往会根据自己的判断报告是否对远程服务器进行了修改。
tasks:
  - shell: /usr/bin/billybass --mode="take me to the river"
    register: bass_result
    changed_when: "bass_result.rc != 2"

4.8、使用 failed_when 控制对 failed 字段的定义

# 对于一些特殊的命令,无法通过返回码判断命令是否执行成功,可以使用 failed_when 自定义命令执行失败的标准:
- name: this command prints FAILED when it fails
  command: /usr/bin/example-command -x -y -z
  register: command_result
  failed_when: "'FAILED' in command_result.stderr"

5、Ansible Handlers 自动化中的关键组件

在现代的IT环境中,自动化已经成为提高效率和减少错误的关键。Ansible作为一款流行的自动化工具,通过使用Playbooks来定义和执行任务。而Handlers作为Ansible的组件之一,在自动化过程中发挥着重要的作用。本文将深入探讨Handlers的概念、作用和使用方法,帮助读者更好地理解和应用Ansible中的Handlers。

5.1、Handlers概述

Handlers是Ansible Playbooks中的一种特殊任务类型。它们类似于事件处理程序,用于在特定条件下触发和执行任务。Handlers通常与任务关联,当任务的状态发生变化时,Handlers会被触发执行。Handlers可以用于执行各种操作,如重启服务、重新加载配置文件等。

5.2、Handlers的工作原理

Handlers的触发和执行是基于事件驱动的。当一个任务执行完成后,Ansible会检查与该任务关联的Handlers,并将其添加到一个队列中。当Playbook的所有任务执行完毕时,Ansible会遍历Handlers队列,并按顺序执行队列中的Handlers任务。这种机制确保了Handlers的执行顺序和可靠性。

5.3、Handlers的关联和触发

Handlers与任务之间的关联是通过名称来实现的。在Playbooks中,可以使用notify关键字将Handlers与任务关联起来。当任务的状态发生变化时,可以使用notify关键字通知Handlers执行。Handlers只有在被通知时才会执行,这样可以避免不必要的执行和资源浪费。

5.4、使用Handlers的示例

下面是一个使用Handlers的示例,演示了如何在Ansible Playbook中定义和使用Handlers:

- name: Install and configure Nginx
  hosts: web_servers
  tasks:
    - name: Install Nginx
      apt:
        name: nginx
        state: present
      notify: Restart Nginx
    - name: Copy Nginx configuration file
      copy:
        src: nginx.conf
        dest: /etc/nginx/nginx.conf
      notify: Reload Nginx
  handlers:
    - name: Restart Nginx
      service:
        name: nginx
        state: restarted
    - name: Reload Nginx
      service:
        name: nginx
        state: reloaded在上述示例中,当安装Nginx和复制配置文件的任务执行完成后,分别使用notify关键字通知了两个Handlers:Restart Nginx和Reload Nginx。这两个Handlers会在Playbook的所有任务执行完毕后被触发执行,分别重启和重新加载Nginx服务。

5.5、最佳实践和注意事项

在使用Handlers时,有一些最佳实践和注意事项需要考虑。

  • 首先,Handlers的命名应具有描述性,以便于理解和维护。

  • 其次,Handlers的关联应与任务的关联一致,确保正确触发和执行。

  • 此外,Handlers的执行顺序也需要仔细规划和测试,以避免意外的行为。

Handlers作为Ansible自动化工具中的重要组件,为自动化任务的触发和响应提供了强大的功能。通过Handlers,可以实现任务的自动执行和响应,提高自动化的效率和可靠性。

七、role 的定义与使用

1、role 的概念

# role 是一种将复杂的 Playbook 分割成多个文件的机制,简化了 Playbook 的编写,使 Playbook 的复用变得简单。
	每个 role 都会有一个名字,比如 mongodb,与 mongodb role 相关的文件都存放在 /etc/ansible/roles/mongodb 目录中:

$ tree mongodb
mongodb
|-----defaults
|     └----main.yml
|-----files
|-----handlers
|     └----main.yml
|-----meta
|     └----main.yml
|-----README.md
|-----tasks
|     └----main.yml
|-----templates
└-----vars
      └----main.yml

defaults/main.yml:			可以被覆盖的默认变量
files:						目录,保存了需要同步到远程服务器的文件
handlers/main.yml:			与 Playbook 中的 handlers 选项类似,包含了所有 handler
meta/main.yml:				role 的依赖信息
README.md:					role 的说明文件
tasks/main.yml:				包含了任务列表
templates:					目录,保存了 jinja2 模板文件
vars/main.yml:				不应该被覆盖的变量,与 Playbook 中的 vars 或 vars_file 类似

# 注意:这里的文件都是可选的。templates 和 files 目录中的文件都是相对引用,不需要写路径。

2、使用 ansible-galaxy 管理 role

ansible-galaxy 的用法:
# 初始化一个 roles 的目录结构:
ansible-galaxy init /etc/ansible/roles/role_name

# 安装别人写好的 role:
ansible-galaxy install -p /etc/ansible/roles role_name

# 安装到指定目录
ansible-galaxy -p ./roles install role_name
Ansible 中,默认将 role 下载到 /etc/ansible/roles 目录,也可以在 ansible.cfg 中配置 role_path。 

# 列出已安装的 roles:
ansible-galaxy list

# 查看已安装的 role 的信息:
ansible-galaxy info role_name

# 卸载 role
ansible-galaxy remove role_name

3、使用 role

# 在使用 role 之前需要编写一个 Playbook,例如:
---
- hosts: webservers
  become: yes
  become_method: sudo
  roles:
  - role: role_name

# 执行时使用以下格式:
ansible-playbook -i hosts role_name.yml

0

评论区