Ansible自动化运维工具
- 一、什么是Ansible
- 二、部署Ansible批量管理
- 三、Ansible参数说明及执行状态
- 四、Ansible常用模块
- 五、Ansible playbook
一、什么是Ansible
1、简介
Ansible是一款自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统部署、批量程序部署,批量运行命令等功能。
Ansible是基于模块工作的,本身没有批量部署的能力,真正具有批量部署能力的是Ansible运行的模块,Ansible只是提供一个框架。Ansible不需要在远程主机上安装client/agents,因为它们是基于ssh来和远程主机通讯的。
2、架构
- ansbile:核心程序
- modules:包括ansible自带的核心模块以及自定义模块
- plugins:完成模块功能的补充,包括连接插件,邮箱插件
- palybooks:剧本,定义ansbile多任务配置文件,由ansible自动执行
- inventory:定义ansbile管理的主机清单
- connection plugins:负责和被监控端实现通信
3、工作流程
- 加载配置文件: Ansible 默认查找
/etc/ansible/ansible.cfg
配置文件,这个文件包含了Ansible运行时的行为设定,如连接方式、插件路径等。 - 解析Inventory: Ansible 使用 Inventory 文件(默认是
/etc/ansible/hosts
)来确定需要操作的目标主机或主机组。 - 编译Playbook或命令: Ansible 准备执行的Playbook或直接执行的Ad-Hoc命令,并解析其中的任务和模块调用。
- 模块加载与执行策略准备: 对于每个任务,Ansible 加载相应的模块(如
command
模块),并准备执行上下文,包括变量、环境等。 - 生成并传输临时脚本: Ansible 会根据任务和模块生成一个或多个临时的Python脚本,并通过SSH连接传输到目标主机的临时目录,通常位于目标用户的
~/.ansible/tmp/ansible-tmp-<UNIQUE_ID>/
目录下。 - 赋予执行权限: 在目标主机上,Ansible 会给这个临时Python脚本加上执行权限,以便能够运行。
- 执行远程脚本: Ansible 通过SSH在目标主机上执行这个临时脚本,并收集执行结果。
- 结果收集与处理: 执行完毕后,各个主机的执行结果被收集并汇总,Ansible根据这些结果决定是否继续执行后续任务,或是根据Playbook中的错误处理逻辑(如
rescue
和always
块)进行操作。 - 清理: 一旦任务执行完成,无论成功还是失败,Ansible 会清理目标主机上的临时文件,包括删除之前上传的Python脚本。
- 退出与报告: 清理完成后,Ansible 进程在目标主机上退出,并向控制机报告最终的执行状态和结果。
二、部署Ansible批量管理
1、涉及主机
主机名 | 角色 | IP地址 |
---|---|---|
server | 控制节点 | 192.168.112.10 |
host1 | 受管节点 | 192.168.112.20 |
host2 | 受管节点 | 192.168.112.30 |
host3 | 受管节点 | 192.168.112.40 |
2、安装部署Ansible
控制节点
2.1、yum安装
yum install -y epel-release #Centos需要安装EPEL仓库
yum install -y ansible #yum包管理安装Ansible
ansible --version #查看Ansible安装版本
2.2、其他方式
3、设置免密登录
3.1、控制节点设置hosts解析
[root@server ~]# vim /etc/hosts
192.168.112.10 server
192.168.112.20 host1
192.168.112.30 host2
192.168.112.40 host3
3.2、生成密钥对
[root@server ~]# ssh-keygen -P "" -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:eSgh2wm7WxXS8n61UI4wKK0yEl3mLlzwIFBdOQSAgag root@server
The key's randomart image is:
+---[RSA 2048]----+
|B+=o++o. |
|+o B..oo |
|o . B *.= . |
|Eo o O * * + |
|. = = + S + o |
| . + . + . o . |
| . . . . . |
| o . |
| . |
+----[SHA256]-----+
-P ""
:设置空密码-t rsa
: 指定生成密钥的类型为RSA- 简化后续实验输密码操作
3.3、将公钥发送给受管节点
ssh-copy-id -i /root/.ssh/id_rsa.pub root@host1
ssh-copy-id -i /root/.ssh/id_rsa.pub root@host2
ssh-copy-id -i /root/.ssh/id_rsa.pub root@host3
过程中需要输入受管节点的密码
3.4、测试免密登录
ssh root@host1
ssh root@host2
ssh root@host3
4、定义主机清单
4.1、ansible常见的配置文件
- /etc/ansible/ansible.cfg:主配置文件
- /etc/ansible/hosts:主机清单文件
- /etc/ansible/roles:角色目录
4.2、备份主机清单文件
cp -f hosts hosts.bak
4.3、修改主机清单,设置分组
vim /etc/ansible/hosts
[all-servers]
server
host1
host2
host3
[node1]
host1
[node2]
host2
[node3]
host3
[mysql_test]
host1
host2
[web_test]
host2
host3
[manager]
server
三、Ansible参数说明及执行状态
1、参数说明
参数 | 说明 |
---|---|
-h |
显示帮助信息,包含可用的命令和选项。 |
-i |
指定Inventory文件的路径,默认为/etc/ansible/hosts 。 |
-l |
限制playbook或命令的作用范围,仅对匹配的主机执行。 |
-u |
指定连接远程主机时使用的用户名。 |
-b |
在远程主机上执行操作时临时提升权限,相当于使用sudo 。 |
--become-user=USER |
提升权限后切换到的用户。 |
-m |
用于ad-hoc命令,指定要使用的模块名。 |
-a |
指定模块的参数。 |
-f |
指定并发进程数,默认为5。 |
-v |
增加输出的详细程度,多次使用可获得更多调试信息。 |
-vvv |
设置更详细的输出级别,有助于调试。 |
--check |
执行模拟运行,不实际改变系统状态,用以预览操作效果。 |
--diff |
修改文件时,显示修改前后的差异。 |
-C |
检查执行结果 |
-e |
指明变量名 |
--syntax-check |
检查执行命令是否存在语法错误 |
2、Ansible的执行状态
- 绿色:执行成功并且不需要做改变的操作
- 黄色:执行成功并且对目标主机做变更
- 红色:执行失败
- 粉色:警告信息
- 蓝色:显示ansible命令执行的过程
四、Ansible常用模块
1、ping模块
主机连通性测试
#一个一个测试
ansible -m ping node1
ansible -m ping node2
ansible -m ping node3
ansible -m ping manager
#以组为单位测试
ansible -m ping all-servers
2、command模块
ansible的默认模块,用于在远程主机上执行简单的Linux命令,并将结果返回主机
不支持管道,变量及重定向等
2.1、选项及描述
ansible-doc -s command
选项 | 描述 |
---|---|
argv | 将命令作为列表而非字符串传递。使用argv 可避免对原本会被误解的值(例如用户名中带空格的情况)进行引用。只能提供字符串或列表形式之一,不能同时提供。 |
chdir | 在执行命令前切换到此目录。 |
cmd | 要执行的命令。 |
creates | 如果该文件已经存在,此步骤不会执行。 |
removes | 如果该文件存在,此步骤将会执行。 |
stdin | 直接将指定的值设置为命令的stdin。 |
stdin_add_newline | 如果设置为yes ,在stdin数据末尾追加换行符。 |
strip_empty_ends | 从stdout/stderr结果的结尾去除空行。 |
warn | 启用或禁用任务警告。 |
2.2、结合chdir和removes、creates列出指定目录下内容
#node1组先切换到root目录下aliyun.sh文件存在不执行ls
ansible node1 -m command -a 'chdir=/root/ creates=aliyun.sh ls'
#node1组先切换到root目录下aliyun.sh文件存在就执行ls
ansible node1 -m command -a 'chdir=/root/ removes=aliyun.sh ls'
2.3、查看磁盘空间
#查看mysql_test组中所有主机的磁盘空间
ansible mysql_test -m command -a 'df -h'
#查看web_test组中所有主机的磁盘空间
ansible web_test -m command -a 'df -h'
3、shell模块
shell模块可以在远程主机上调用shell解释器运行命令,支持shell的各种功能,例如管道等。
3.1、选项及参数
ansible-doc -s command
选项 | 描述 |
---|---|
chdir | 在执行命令前切换到此目录。 |
cmd | 要执行的命令及其可选参数。 |
creates | 当指定的文件已存在时,此步骤将不执行。 |
executable | 更改用于执行命令的shell。这需要shell可执行文件的绝对路径。 |
free_form | 要执行的Linux指令,一般使用Ansible的-a参数代替。 |
removes | 当指定的文件存在时,此步骤将执行。 |
stdin | 直接将指定的值设置为命令的stdin。 |
stdin_add_newline | 是否在stdin数据末尾添加换行符。 |
warn | 是否启用任务警告。 |
3.2、检查远程主机的系统版本
#查看mysql_test组远程主机的系统版本
ansible mysql_test -m shell -a 'cat /etc/os-release | grep PRETTY_NAME | cut -d "=" -f2'
#查看web_test组远程主机的系统版本
ansible web_test -m shell -a 'cat /etc/os-release | grep PRETTY_NAME | cut -d "=" -f2'
3.3、查看远程主机防火墙状态
#查看mysql_test组中所有的主机防火墙firewalld和selinux的状态
ansible mysql_test -m shell -a 'systemctl status firewalld ; getenforce'
这里验证了
command
模块不能使用命令别名、管道、重定向以及逻辑运算符(如;
,&&
,||
)由于
command
模块直接将整个字符串传递给系统执行,分号;
以及随后的getenforce
命令被视为命令的一部分,而不是独立的指令。这导致系统尝试查找名为类似\x3b.service
(分号;
的ASCII转义序列)的服务状态,以及尝试将getenforce
当作一个服务单元来查找,由于这两个都不是有效的服务单元名称,因此返回了错误信息。
3.4、创建、查看指定目录
#在mysql_test组下的主机循环创建/root/tmp_1/NOW+当前时间的目录
ansible mysql_test -m shell -a "mkdir -p /root/tmp_1/NOW-$(date +'%H:%M:%S')"
#find查找是否正确创建
ansible mysql_test -m shell -a "find /root/tmp_1 -mmin -5"
4、user模块
主要用于管理远程系统上的用户账户,包括创建、修改和删除用户。
它允许你设置用户的密码、shell、主目录、权限等属性
4.1、选项及描述
ansible-doc -s user
选项 | 描述 |
---|---|
comment | 用户的描述信息 |
createhom | 是否创建家目录 |
force | 在使用state=absent时, 行为与userdel –force一致 |
group | 指定基本组 |
groups | 指定附加组,如果指定为(groups=)表示删除所有组 |
home | 指定用户家目录 |
move_home | 如果设置为home=时, 试图将用户主目录移动到指定的目录 |
name | 指定用户名 |
non_unique | 该选项允许改变非唯一的用户ID值 |
password | 指定用户密码 |
remove | 在使用state=absent时, 行为是与userdel –remove一致 |
shell | 指定默认shell |
state | 设置帐号状态,默认为present表示新建用户,指定值为absent表示删除 |
system | 当创建一个用户,设置这个用户是系统用户。这个设置不能更改现有用户 |
uid | 指定用户的uid |
update_password | 更新用户密码 |
expires | 指明密码的过期时间 |
append | 添加一个新的组 |
4.2、添加系统用户,指定uid、家目录及注释
#给web_test组中添加一个系统用户zhangsan家目录为/home/zhangsan,用户id为111,注释信息为hello zhangsan
ansible web_test -m user -a "system=yes name=zhangsan home=/home/zhangsan uid=111 comment='hello zhangsan'"
4.3、查看新创建的用户
#id zhangsan验证用户是否正确创建,使用grep+awk截取/etc/passwd上关于zhangsan的注释信息
ansible web_test -m shell -a 'id zhangsan ; grep ^zhangsan: /etc/passwd | awk -F ":" '\''{print $5}'\'''
4.4、删除新创建的用户
#删除用户zhangsan
ansible web_test -m user -a "name=zhangsan state=absent remove=yes"
5、group模块
用于管理Linux系统中的用户组。
这个模块允许你添加或删除用户组,并且可以设置组ID(GID)。
5.1、选项及描述
ansible-doc -s group
选项 | 描述 |
---|---|
gid | 用于设置用户组的GID(组ID)。 |
local | 强制使用平台提供的本地命令替代品(如lgroupadd 代替groupadd ),适用于需要操作本地组的集中认证环境。此选项要求目标主机上存在这些命令,否则会导致致命错误。 |
name | (必需)指定组的名称。 |
non_unique | 允许将组ID更改为非唯一值。需要与gid 一起使用。不支持macOS或BusyBox发行版。 |
state | 指定用户组在远程主机上应有的状态,可以是present (存在)或absent (不存在)。 |
system | 如果设置为yes ,表示创建的用户组是系统组。 |
5.2、创建或更新组
#在web_test组的所有主机上创建一个系统组web_test,组id为1010
ansible web_test -m group -a "name=web_test gid=1010 system=yes"
#通过/etc/group查看系统组web_test信息
5.3、删除组
#删除web_test组所有主机上的系统组web_test
ansible web_test -m group -a "name=web_test gid=1010 state=absent"
6、copy模块
用于将本地文件或目录复制到远程主机上
支持文件、目录、权限、用户组功能
6.1、选项及描述
ansible-doc -s copy
选项 | 描述 |
---|---|
backup | 在覆盖之前,将源文件备份,备份文件包含时间信息。 |
content | 用于替代“src”,可以直接设定指定文件的值 |
dest | 必选项。要将源文件复制到的远程主机的绝对路径 |
directory_mode | 递归设定目录的权限,默认为系统默认权限 |
force | 当目标主机包含该文件,但内容不同时,设为"yes",表示强制覆盖;设为"no",表示目标主机的目标位置不存在该文件才复制。默认为"yes" |
follow | 支持link文件拷贝 |
others | 所有file模块里的选项都可以在这里使用 |
src | 被复制到远程主机的本地文件。可以是绝对路径,也可以是相对路径。如果路径是一个目录,则会递归复制,用法类似于"rsync" |
6.2、给定内容生成文件,并修改权限信息
#将copy内容为copy test复制到node3主机的/root/copy.txt并设置权限666
ansible node3 -m copy -a 'content="copy test" dest=/root/copy.txt mode=666'
6.3、修改文件内容,选择覆盖备份
#修改node3主机上copy.txt文件内容,并选择备份
ansible node3 -m copy -a 'content="copy test_1\n" backup=yes dest=/root/copy.txt mode=666'
7、fetch模块
Ansible 的
fetch
模块用于从远程节点抓取文件并存储到Ansible控制器(执行Ansible任务的机器)上的指定目录
7.1、选项及描述
ansible-doc -s fetch
选项 | 描述 |
---|---|
dest | 必选项,用来存放文件的目录 |
src | 必选项,在远程拉取的文件,并且必须是一个file,不能是目录 |
flat | 当设置为yes 时,即使src 是一个目录,也会将所有内容扁平化存储到指定的dest 目录下,而不是保留目录结构。( 默认no ) |
validate_checksum | 当设置为yes 时,在下载完成后校验文件的校验和,确保文件完整无误。这可以用来防止因网络问题导致的文件损坏。(默认no ) |
fail_on_missing | 当设置为yes 时,如果远程文件不存在,则标记任务失败,否则只是简单地跳过该文件。(默认no ) |
size | 限制要抓取的文件大小,可以使用后缀如k 、M 、G 来指定单位(千字节、兆字节、吉字节)。如果远程文件超过指定大小,抓取操作将不会执行。 |
timeout | 设置超时时间(秒),用于等待文件传输完成。默认情况下,Ansible使用其内部的连接超时设置。 |
force | 即使本地文件已经存在,也强制重新抓取。如果设置为no ,则只有当远程文件比本地文件新或不同才执行抓取。(默认yes ) |
unarchive | 如果src 是指向一个归档文件(如.zip或.tar.gz),并且设置了此选项为yes ,Ansible将在抓取后尝试解压该归档文件。(默认no ) |
list_files | 当设置为yes 时,模块将只列出远程目录下的文件而不实际抓取它们,可用于预览目的。(默认no ) |
7.2、从远程主机抓取文件
#从mysql_test组的主机中抓取aliyun.sh文件到本机的/tmp/data目录下
ansible mysql_test -m fetch -a "src=/root/aliyun.sh dest=/tmp/data"
#通过检查/tmp/data下的目录结构可知文件已完整获取
ansible manager -m shell -a "tree -L 5 /tmp/data"
7.3、限制抓取文件的大小、添加文件存在检测
#从mysql_test组的主机中抓取install.sh文件,限制最大抓取大小20kb,传输中校验文件完整性,添加文件存在检测(不存在任务失败)
ansible mysql_test -m fetch -a "src=/root/install.sh dest=/tmp/data/ verify_checksum=yes fail_on_missing=yes size=20k"
8、file模块
file模块主要用于对文件的创建、删除、修改、权限、属性
8.1、选项及描述
ansible-doc -s file
选项 | 描述 |
---|---|
path | 必选项,定义文件/目录的路径 |
mode | 定义文件/目录的权限 |
force | 需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes |
group | 定义文件/目录的属组,后面可以加上mode :定义文件/目录的权限 |
owner | 定义文件/目录的属主。后面必须跟上path :定义文件/目录的路径 |
recurse | 递归设置文件的属性,只对目录有效,后面跟上src :被链接的源文件路径,只应用于state=link 的情况 |
dest | 被链接到的路径,只应用于state=link 的情况 |
src | 被链接的源文件路径,只应用于state=link的情况 |
state | 状态,有以下选项:directory 、file 、link 、hard 、touch 、absent |
8.2、在指定路径下创建目录
#在mysql_test组所有主机在/tmp/路径下创建权限都是只读、属主属组都是root的file1目录
ansible mysql_test -m file -a "path=/tmp/file1 mode=444 owner=root group=root state=directory"
#查看创建好的目录
ansible mysql_test -m shell -a "ls -l /tmp/ | grep file1"
8.3、创建软链接文件
#给mysql_test组的所有主机创建软链接文件test1指向/root/aliyun.sh
ansible mysql_test -m file -a "path=/tmp/test1 src=/root/aliyun.sh state=link"
8.4、创建硬链接文件
#给mysql_test组的所有主机创建硬链接文件test1指向/root/aliyun.sh
ansible mysql_test -m file -a "path=/tmp/test2 src=/root/aliyun.sh state=hard"
8.5、删除文件
#删除mysql_test组中所有主机/tmp/目录下test1
ansible mysql_test -m file -a "path=/tmp/test1 state=absent"
9、yum模块
主要用于在基于 RPM 的 Linux 系统上管理软件包。
它允许用户安装、更新、卸载软件包,并可配置额外的选项以控制操作的具体行为。
9.1、选项及描述
ansible-doc -s yum
选项 | 描述 |
---|---|
name | 必选项,所安装的包的名称 |
state | 安装-> present ; 安装最新版本的-> latest ;absent-> 卸载包 |
update_cache | 强制更新yum的缓存 |
conf_file | 指定远程yum安装时所依赖的配置文件(安装本地已有的包)。 |
disable_pgp_check | 是否禁止GPG checking,只用于present or latest 。 |
disablerepo | 临时禁止使用yum库。 只用于安装或更新时。 |
enablerepo | 临时使用的yum库。只用于安装或更新时。 |
skip_borken | 跳过异常软件节点 |
autoremove | 当设置为yes 且状态为absent 时,自动移除不再被任何已安装包依赖的包。 |
9.2、安装httpd服务
#给web_test组的所有主机安装httpd服务
ansible web_test -m yum -a "name=httpd state=present"
#远程启动httpd服务
ansible web_test -m shell -a "systemctl start httpd"
#远程查看http服务进程
ansible web_test -m shell -a "ps aux | grep httpd"
#远程停止httpd服务
ansible web_test -m shell -a "systemctl stop httpd"
#远程卸载httpd服务
ansible web_test -m yum -a "name=httpd state=absent"
安装 |
---|
查看进程 |
卸载 |
9.3、更新所有的软件包
#给所有主机更新所有的软件包
ansible all-servers -m yum -a "name=* state=latest"
10、cron模块
用于添加、删除、更新操作系统的Crontab计划任务
10.1、选项及描述
ansible-doc -s cron
选项 | 描述 |
---|---|
backup | 如果设置,会在修改crontab前创建备份。备份文件的位置通过backup_file 变量返回。 |
cron_file | 如果指定,将使用此文件而非用户个人的crontab。如果是相对路径,则相对于/etc/cron.d/ 。绝对路径通常为/etc/crontab 。为了使用cron_file 参数,必须同时指定user 。 |
day | 任务应运行的月份中的日期 (1-31, *, */2, 等)。 |
disabled | 如果任务应在crontab中被禁用(注释掉)。仅当state=present 时有效。 |
env | 如果设置,管理crontab的环境变量。新变量会被添加到crontab的顶部。name 和value 参数分别为环境变量的名称和值。 |
hour | 任务应运行的小时 (0-23, *, */2, 等)。 |
insertafter | 与state=present 和env 一起使用。如果指定,环境变量将在指定环境变量声明之后插入。 |
insertbefore | 与state=present 和env 一起使用。如果指定,环境变量将在指定环境变量声明之前插入。 |
job | 要执行的命令,或者如果设置了env ,则是环境变量的值。命令不应包含换行符。当state=present 时必需。 |
minute | 任务应运行的分钟 (0-59, *, */2, 等)。 |
month | 任务应运行的年份中的月份 (1-12, *, */2, 等)。 |
name | crontab条目的描述,或者如果设置了env ,则是环境变量的名称。当state=absent 时必需。注意,如果不设置name,且state=present ,则总是会创建新的crontab条目,不管已有条目如何。此参数在未来的版本中将始终是必需的。 |
special_time | 特殊的时间范围,参数:reboot(重启时),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小时) |
state | 确保任务或环境变量存在或不存在的状态。 |
user | 应修改其crontab的具体用户。未设置时,默认为使用root 。 |
weekday | 任务应运行的星期几 (0-6 表示周日-周六,*, 等)。 |
10.2、添加计划任务
#给mysql_test组中的所有主机添加一个以root用户每天三点执行/root/aliyun.sh脚本的计划任务
ansible mysql_test -m cron -a "name='Daily Task' minute=0 hour=3 job='/root/aliyun.sh &> /dev/null' user=root"
10.3、删除指定计划任务
#删除名为Daily Task的计划任务(没有明确的计划任务名称写完整的计划任务也可以删除)
ansible mysql_test -m cron -a "name='Daily Task' state=absent"
11、service模块
Ansible的
service
模块用于管理系统服务(如启动、停止、重启服务等)。这个模块与特定的系统服务管理工具(如systemd、sysvinit、upstart等)兼容,能够跨不同的Linux发行版和系统管理框架工作
11.1、选项及描述
ansible-doc -s service
选项 | 描述 |
---|---|
arguments | 额外的命令行参数,提供给服务管理命令。 |
enabled | 服务是否应该在系统启动时自动启动。至少需要指定state 或enabled 中的一个。 |
name | (必需)服务的名称。 |
pattern | 如果服务不响应状态查询命令,可以指定一个子字符串作为查找依据,该子字符串应能在ps 命令的输出中找到,作为服务状态的替代判断。如果找到该字符串,服务将被认为已启动。 |
runlevel | 仅针对OpenRC初始化脚本(如Gentoo)使用。指定该服务属于哪个运行级别。 |
sleep | 当服务处于restarted 状态时,停止与启动命令之间暂停的秒数。有助于解决那些在发出停止信号后立即退出的不良行为初始化脚本问题。并非所有服务管理器都支持此设置,例如使用systemd时,此设置会被忽略。 |
state | 有四种状态,分别为:started --->启动服务, stopped --->停止服务, restarted --->重启服务, reloaded --->重载配置 |
use | 服务模块通常通过自动检测使用系统特定的模块,此设置可以强制使用特定模块。默认情况下,它使用ansible_service_mgr 事实的值,并且在找不到匹配项时回退到旧的service 模块。 |
11.2、远程开启/关闭防火墙
#给web_test组中的所有主机重启firewalld服务
ansible web_test -m service -a "name=firewalld state=restarted"
#查看web_test组中所有主机的firewalld服务运行状态
ansible web_test -m shell -a "systemctl status firewalld"
#给web_test组中的所有主机关闭firewalld服务
ansible web_test -m service -a "name=firewalld state=stopped"
开启firewalld服务 |
---|
查看firewalld服务状态 |
关闭firewalld服务 |
12、script模块
Ansible的
script
模块允许你在远程主机上执行位于Ansible控制节点上的本地脚本
12.1、选项及描述
ansible-doc -s script
选项 | 描述 |
---|---|
chdir | 在远程节点上执行脚本之前切换到的目录路径。 |
cmd | 要在远程节点上运行的本地脚本的路径,后面可以跟上可选的参数。注意,这个选项与free_form 二选一使用。 |
creates | 指定远程节点上的一个文件名,如果该文件已存在,则此步骤将不执行,可用于防止重复执行脚本。 |
decrypt | 控制是否自动解密使用Vault加密的源文件。 |
executable | 用于调用脚本的可执行文件的名称或路径,例如如果脚本是Python脚本,可以设置为/usr/bin/python 。 |
free_form | 直接提供本地脚本文件的路径以及可选的参数,与cmd 选项作用相似但格式不同,两者选其一使用。 |
removes | 指定远程节点上的一个文件名,如果该文件不存在,则此步骤将不执行,可以作为执行脚本的另一个条件。 |
12.2、编辑并部署脚本
1、控制节点本地编辑脚本并添加执行权限
vim /tmp/df.sh
#!/bin/bash
date >> /tmp/data/df.log
df -lh >> /tmp/data/df.log
[root@server ~]# chmod +x /tmp/df.sh
2、通过script模块部署到远程主机执行
#给web_test组的所有主机执行控制节点上的df.sh脚本文件
ansible web_test -m script -a "/tmp/df.sh”
13、setup模块
Ansible的
setup
模块用于收集远程主机的信息,并将这些信息以facts的形式返回给Ansible控制节点。这些facts可以包括系统变量(如操作系统类型、架构、网络配置、已安装软件包等),并且在Playbook执行期间可以被其他任务使用。
13.1、选项及描述
ansible-doc -s setup
选项 | 描述 |
---|---|
fact_path | 用于存放本地Ansible事实(*.fact 文件)的路径。此目录下的文件如果可执行,将被执行,其结果会被添加到ansible_local 事实中;如果文件不可执行,则会被读取。适用于从2.1版本开始。文件/结果格式可以是JSON或INI格式。默认的fact_path 可以在ansible.cfg 中为自动调用setup 作为gather_facts 一部分时指定。Windows环境下有特定选项,请查看注释。 |
filter | 如果提供,仅返回匹配此shell风格(fnmatch通配符)的变量。这允许筛选出特定的facts进行查看或使用。 |
gather_subset | 如果提供,限制收集的额外事实子集。可能的值包括:all (全部)、min (最小集合)、hardware (硬件信息)、network (网络信息)、virtual (虚拟化信息)、ohai (类似Chef Ohai的扩展信息)、facter (使用Facter收集的信息)。可以指定值的列表来定义更大的子集。值前可加! 来排除特定子集的收集,例如:!hardware,!network,!virtual,!ohai,!facter 。如果指定!all ,则只收集最小集合。要避免收集最小集合,可以指定!all,!min 。要仅收集特定事实,使用!all,!min 并指定特定的事实子集。如果只想隐藏某些收集到的事实,使用filter 参数。 |
gather_timeout | 设置单个事实收集的默认超时时间(以秒为单位)。这有助于控制事实收集过程,避免因个别慢速收集导致整个任务超时。 |
13.2、查看内存信息
#查看mysql_test组所有主机的内存信息
ansible mysql_test -m setup -a "filter='*mem*'"
通过free -m命令查看内存大小是否一致
#通过free -m命令查看mysql_test组主机的内存信息
ansible mysql_test -m shell -a "free -m"
13.3、保存信息
#将筛选的信息保存到控制节点的/tmp/data目录下
ansible web -m setup -a 'filter="*mem*"' --tree /tmp/data
14、synchronize模块
Ansible的
synchronize
模块提供了使用rsync进行文件和目录同步的功能。rsync是一个快速且高效的文件传输工具,支持增量更新,特别适合在远程主机之间同步大量文件或保持文件夹内容的一致性。
14.1、选项及描述
ansible-doc synchronize
选项 | 描述 |
---|---|
archive | 镜像rsync的归档标志,启用递归、链接、权限、时间戳、所有者、组标志及-D。默认开启。 |
checksum | 基于校验和而非修改时间和大小来跳过同步,注意“archive”选项默认仍启用,"checksum"选项不会禁用它。默认关闭。从1.6版本起可用。 |
compress | 在传输过程中压缩文件数据。大多数情况下应保持启用状态,除非引起问题。默认开启。从1.7版本起可用。 |
copy_links | 将符号链接作为它们指向的对象(被链接项)复制,而不是复制符号链接本身。默认关闭。 |
delete | 删除目标路径中不存在于源路径的文件(在传输之后,不是之前)。此选项要求recursive=yes 。表现得像rsync的--delete-excluded 选项,忽略被排除的文件。默认关闭。 |
dest | 同步的目的地主机路径,将从源路径同步而来。路径可以是绝对或相对的。此选项是必须的。 |
dest_port | 目标主机SSH端口。在Ansible 2.0之前,ansible_ssh_port库存变量优先于这个值。此参数默认为ansible_ssh_port 或ansible_port 的值、remote_port 配置设置的值,或如果没有设置前者,则使用SSH客户端配置的值。从1.5版本起可用。 |
dirs | 仅传输目录而不递归进入。默认关闭。 |
existing_only | 跳过在接收端创建新文件。默认关闭。从1.5版本起可用。 |
group | 保留组信息。默认值取决于archive选项。 |
link_dest | 添加一个硬链接目标,在rsync期间与之关联。默认为无。从2.5版本起可用。 |
links | 作为符号链接复制符号链接。默认值取决于archive选项。 |
mode | 指定同步的方向。推模式下,本地主机或代理是源;拉模式下,上下文中的远程主机是源。(可选值:pull, push)默认为push。 |
owner | 保留所有者(仅超级用户)。默认值取决于archive选项。 |
partial | 告诉rsync保留部分文件,这应该会使后续传输文件剩余部分快得多。默认关闭。从2.0版本起可用。 |
perms | 保留权限信息。默认值取决于archive选项。 |
private_key | 为基于SSH的rsync连接指定私钥(如~/.ssh/id_rsa )。默认为无。从1.6版本起可用。 |
recursive | 递归进入目录。默认值取决于archive选项。 |
rsync_opts | 通过传递数组来指定额外的rsync选项。注意,rsync_opts 中的空字符串最终会传输当前工作目录。默认为无。从1.6版本起可用。 |
rsync_path | 指定在远程主机上运行的rsync命令。参见rsync手册页上的--rsync-path 。要指定在本地主机上运行的rsync命令,你需要设置任务变量ansible_rsync_path 。默认为无。 |
rsync_timeout | 为rsync命令指定一个超时时间(秒)。默认为0。 |
set_remote_user | 为远程路径添加user@。如果你有自定义的ssh配置来为与库存用户不匹配的主机定义远程用户,应将此参数设为no 。默认为True。 |
src | 源主机上的路径,将同步到目的地。路径可以是绝对或相对的。此选项是必须的。 |
times | 保留修改时间。默认值取决于archive选项。 |
use_ssh_args | 使用ansible.cfg中指定的ssh_args。默认关闭。从2.0版本起可用。 |
verify_host | 验证目标主机密钥。默认关闭。从2.0版本起可用。 |
14.2、将源目录同步至目标目录(增量同步)
#既然是基于rsync那么所有主机安装rsync
ansible all-servers -m shell -a "yum install -y rsync"
#将本地的/tmp/目录同步到node1组的host1主机上
ansible node1 -m synchronize -a "src=/tmp/ dest=/tmp/"
#查看node1组的host1主机的/tmp/目录结构
ansible node1 -m shell -a "tree -L 5 /tmp/"
所有主机安装rsync |
---|
同步本地/tmp/到host1主机上 |
查看目录结构 |
14.3、将源目录同步至目标目录(完全同步)
#删除目标路径中不存在于源路径的文件(在传输之后)
ansible node1 -m synchronize -a "src=/tmp/ dest=/tmp/ delete=yes"
五、Ansible playbook
1、简介
Ansible Playbook 是Ansible用于定义和执行自动化任务的配置、部署和编排的主要方式。它是一种使用YAML语言编写的剧本文件,允许用户以简洁、可读性强的方式描述一系列步骤,这些步骤可以跨多台主机执行,以实现系统的配置管理和应用程序部署。
playbook是由一个或者多个play组成的列表,可以让这些列表按事先编排的机制执行;所谓task是调用ansible的具体模块,在模块参数中可以使用变量。模块执行是幂等性的,意味着多次执行结果相同。使用yaml语言编写playbook,后缀名一般为.yml
2、playbook的YAML格式
- 文件的第一行应该以 "---" (三个连字符)开始,表明YMAL文件的开始。
- 在同一行中,#之后的内容表示注释,类似于shell,python和ruby。
- YMAL中的列表元素以”-”开头然后紧跟着一个空格,后面为元素内容。
- 同一个列表中的元素应该保持相同的缩进。否则会被当做错误处理。
- play中hosts,variables,roles,tasks等对象的表示方法都是键值中间以":"分隔表示,":"后面还要增加一个空格。
- 缩进:使用空格缩进(而非Tab),通常使用2个空格
2.1、示例:
---
- name: update web servers
hosts: node1
remote_user: root
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
- name: ensure that htppd is started
service:
name: httpd
state: started
- name: update db servers
hosts: node1
remote_user: root
tasks:
- name: ensure mariadb is at the latest version
yum:
name: mariadb-server
state: latest
- name: ensure that mariadb is started
service:
name: mariadb
state: started
2.2、解析
Play 1: 更新Web服务器
- Play标题:"update web servers",表明本Play的目标是更新Web服务器配置。
- hosts:
node1
,指定该Play作用于名为node1
的主机。 - remote_user:
root
,指定执行任务的远程用户为root。 - tasks:
- task 1: 确保Apache是最新的版本。使用
yum
模块安装httpd
包至最新版。 - task 2: 写入Apache配置文件。使用
template
模块将模板文件/srv/httpd.j2
渲染后复制到/etc/httpd.conf
,允许动态配置生成。 - task 3: 确保Apache服务已启动。使用
service
模块设置httpd
服务的状态为started
,如果服务未运行则启动。
- task 1: 确保Apache是最新的版本。使用
Play 2: 更新数据库服务器
- Play标题:"update db servers",目标是更新数据库服务器配置。
- hosts:同样为
node1
,指定该Play作用于名为node1
的主机。 - remote_user:
root
,指定执行任务的远程用户为root。 - tasks:
- task 1: 确保MariaDB是最新的版本。使用
yum
模块安装mariadb-server
至最新版。 - task 2: 确保MariaDB服务已启动。使用
service
模块设置mariadb
服务的状态为started
。
- task 1: 确保MariaDB是最新的版本。使用
3、playbook的执行与语法检查
#执行playbook
ansible-playbook playbook.yml
#语法检查
ansible-playbook --syntax-check playbook.yml
4、playbook的核心元素
- Hosts(主机组):定义了Playbook将要操作的目标机器集合。可以是单个主机名、IP地址,也可以是主机组名。
- Tasks(任务列表):构成Play的主要部分,定义了在目标主机上执行的具体操作序列。每个任务通常关联一个特定的Ansible模块及参数。
- Variables(变量):用于在Playbook中传递和管理配置信息,支持多种设置方式(如直接赋值、变量文件、环境变量、角色默认变量等),增加了Playbook的灵活性和可重用性。
- Templates(模板):使用Jinja2模板引擎动态生成配置文件。允许根据变量插入动态内容,适用于需要根据不同环境定制配置的情况。
- Handlers(处理程序):特殊类型的任务,仅当被其他任务通过
notify
属性明确告知时才会执行。常用于服务重启等需要在特定条件满足时进行的操作。
5、基本组件及格式
-
remote_user:指定执行Ansible任务的远程用户名。
-
sudo_user:定义需要临时提升权限执行任务时的目标用户。
-
Tasks格式:
tasks: - name: 简短任务描述 module: 模块名称 arguments: 参数列表 notify: 通知的处理程序名称(可选)
-
Handlers格式:
handlers: - name: 处理程序描述 module: 模块名称 arguments: 参数列表
- Handlers触发条件:
- 当某任务状态变为
changed
时,可以触发一个或多个预先定义好的处理程序。 - 使用
tags
为任务和处理程序打标签,可以在执行Playbook时通过--tags
或-t
选项选择性地执行带有特定标签的任务。
- 当某任务状态变为
- Handlers触发条件:
-
模块与模块参数:Ansible通过各种模块执行具体操作,模块后跟随的是该模块接受的参数。对于
shell
和command
这类直接执行系统命令的模块,参数直接是命令字符串,而不是键值对形式。
6、安装nginx并修改配置文件
6.1、准备文件存放目录
[root@server ~]# mkdir -p /root/ansible/{conf,bin}
6.2、编写yaml文件
[root@server ~]# cd ansible/bin/
[root@server bin]# cat nginx.yml
---
- name: Update web servers
hosts: node1
remote_user: root
tasks:
- name: Install epel
yum:
name: epel-release.noarch
state: latest
- name: Install nginx
yum:
name: nginx
state: present
- name: Copy nginx configure file
copy:
src: /root/ansible/conf/nginx.conf
dest: /etc/nginx/nginx.conf
backup: yes
- name: Start nginx
service:
name: nginx
state: restarted
- name: Create index.html
shell: echo "hello playbook_nginx" > /usr/share/nginx/html/index.html
6.3、编写conf文件
[root@server conf]# cat site.conf
events {
worker_connections 1024;
}
http {
server {
listen 8080;
server_name 192.168.112.20:8080;
location / {
index index.html;
}
}
}
6.4、检查语法错误,执行playbook
#语法检查
ansible-playbook nginx.yml --syntax-check
#执行playbook
ansible-playbook nginx.yml
6.5、验证nginx启动状态
#ps aux|grep nginx显示nginx的进程,curl -s 查看实际的响应体内容
ansible node2 -m shell -a "ps aux | grep nginx ; curl -s 192.168.112.30:8080"
7、安装nginx,并添加handlers和notify
7.1、修改对应的nginx.yml和nginx.conf文件
nginx2.yml
---
- name: Update web servers
hosts: node2
remote_user: root
tasks:
- name: Install epel
yum:
name: epel-release.noarch
state: latest
- name: Install nginx
yum:
name: nginx
state: present
- name: Copy nginx configure file
copy:
src: /root/ansible/conf/nginx2.conf
dest: /etc/nginx/nginx2.conf
backup: yes
notify: reload #当nginx.conf发生改变时,通知给相应的handlers
tags: reloadnginx #打标签
- name: Start nginx
service:
name: nginx
state: restarted
tags: startnginx #打标签
- name: Create index.html
shell: echo "hello playbook_nginx_2" > /usr/share/nginx/html/index.html
handlers: #注意,前面没有-,是两个空格
- name: reload
service:
name: nginx
state: restarted
nginx2.conf
[root@server conf]# cat nginx2.conf
events {
worker_connections 1024;
}
http {
server {
listen 8080;
server_name 192.168.112.30:8080;
location / {
index index.html;
}
}
}
7.2、验证nginx进程信息
#验证端口和响应内容
ansible node2 -m shell -a "ss -tunlp | grep nginx ; curl -s 192.168.112.30:8080"
7.3、测试标签
#先关闭node3上的nginx服务以便测试
ansible node3 -m shell -a "systemctl stop nginx"
#再运行剧本并引用标签startnginx
ansible-playbook nginx2.yml -t startnginx
7.4、测试notify
7.4.1、notify的触发条件是配置文件被改变
#修改监听的端口号
[root@server conf]# cat nginx2.conf
events {
worker_connections 1024;
}
http {
server {
listen 8848;
server_name 192.168.112.30:8080;
location / {
index index.html;
}
}
}
7.4.2、重新执行剧本
#语法检查
ansible-playbook nginx2.yml --syntax-check
#再运行剧本并引用标签reloadnginx
ansible-playbook nginx2.yml -t reloadnginx
7.4.3、重新查看端口号
ansible node2 -m shell -a "ss -tnulp | grep nginx"
端口号变为8848
8、变量(variables)
在Ansible剧本中,
vars
是用来定义变量的一个关键字,它允许你为任务、play或整个剧本设定变量值。这些变量可以在后续的任务中被引用,以提高剧本的灵活性和重用性。
8.1、定义变量的方式
1. Facts(Facts变量)
-
描述:Facts是Ansible自动收集的目标主机信息,如系统类型、网络配置等。它们不是直接定义的变量,而是通过执行
setup
模块获取的。尽管不能直接定义Facts,但它们可以在剧本中像其他变量一样使用。 -
使用方式
- name: Display hostname using a fact debug: msg: "The hostname is {{ ansible_hostname }}"
-
查看所有可以使用的变量:
ansible node1 -m setup > variables
2. 用户自定义变量
-
直接在Playbook中定义
-
可以在play或tasks级别定义变量。
- hosts: web_test vars: my_var: "Hello, World!" tasks: - name: Use playbook-defined variable debug: msg: "{{ my_var }}"
-
-
通过命令行参数(
-e
/--extra-vars
)传入-
在运行Ansible命令时动态添加变量。
ansible-playbook my_playbook.yml -e "my_var=ValueFromCommandLine"
-
3. 通过Roles传递变量
-
简介:Roles是Ansible组织和复用任务的一种方式。变量可以通过角色的
defaults
,vars
,environment
目录下的文件来定义,或者在角色的tasks/main.yml
等文件中直接定义。-
例子:
-
在
roles/my_role/defaults/main.yml
中定义:my_role_variable: default_value
-
然后在使用该角色的playbook中,该变量自动可用,也可被更高优先级的变量覆盖。
-
-
4. Host Inventory(主机清单)中定义变量
-
向不同主机传递不同变量
[webservers] host1.example.com my_var=value1 host2.example.com my_var=value2
-
向组中的所有主机传递相同变量
[webservers:vars] group_variable=value_for_all_hosts_in_group
8.2、优先级
- 通过命令行指定变量优先级最高
- /etc/ansible/hosts定义变量(针对单个主机定义,针对主机组进行定义)
- playbook中定义的变量
8.3、案例:使用变量安装keepalived
1、编写剧本
#先复制一份
[root@server bin]# cp nginx2.yml keepalived.yml
#再通过vim的替换将nginx替换为变量并优化一下src地址
[root@server bin]# cat keepalived.yml
---
- name: Update web servers
hosts: node2
remote_user: root
tasks:
- name: Install epel
yum:
name: epel-release.noarch
state: latest
- name: Install {{ rpmname }}
yum:
name: "{{ rpmname }}"
state: present
- name: Copy {{ rpmname }} configure file
copy:
src: /root/ansible/conf/{{ rpmname }}.conf
dest: /etc/{{ rpmname }}/{{ rpmname }}.conf
backup: yes
notify: reload
tags: reload{{ rpmname }}
- name: Start {{ rpmname }}
service:
name: "{{ rpmname }}"
state: restarted
tags: start{{ rpmname }}
handlers:
- name: reload
service:
name: "{{ rpmname }}"
state: restarted
全局替换并添加确认动作 |
---|
输入y确认替换 |
替换好的剧本 |
2、拷贝配置文件
我们想要在被监管的机器上安装什么服务的话,就直接在我们的server端上把该服务的配置文件拷贝到我们定义剧本的
src
目录下。这样我们的剧本才能正常运行。
cp /etc/keepalived/keepalived.conf /root/ansible/conf/keepalived.conf
3、运行剧本,变量由命令行传入
#语法检查
ansible-playbook keepalived.yml --syntax-check
#执行剧本-e 接变量
ansible-playbook keepalived.yml -e rpmname=keepalived
4、或者直接再剧本里定义变量
我们可以直接在剧本中把变量定义好,这样就不需要在通过命令行传入了。
以后想要安装不同的服务,直接在剧本里把变量修改一下即可。
[root@server bin]# vim keepalived.yml
---
- name: Update web servers
hosts: node2
remote_user: root
vars:
- rpmname: keepalived
tasks:
- name: Install epel
yum:
name: epel-release.noarch
state: latest
- name: Install {{ rpmname }}
yum:
name: "{{ rpmname }}"
state: present
- name: Copy {{ rpmname }} configure file
copy:
src: /root/ansible/conf/{{ rpmname }}.conf
dest: /etc/{{ rpmname }}/{{ rpmname }}.conf
backup: yes
notify: reload
tags: reload{{ rpmname }}
- name: Start {{ rpmname }}
service:
name: "{{ rpmname }}"
state: restarted
tags: start{{ rpmname }}
handlers:
- name: reload
service:
name: "{{ rpmname }}"
state: restarted
5、运行定义过变量的剧本
#语法检查
ansible-playbook keepalived.yml --syntax-check
#执行剧本
ansible-playbook keepalived.yml
9、模板(templates)
9.1、简介
Templates主要用于自动生成和管理服务器上的配置文件,如nginx的配置、数据库配置等。这有助于实现基础设施的配置标准化和自动化。
- 文本文件,内部嵌套有模板语言的脚本
- jinja2是由python编写的,在使用模板文件时jinja2是很好的解决方案
- 功能:将模板文件中的变量转换成对应的本地主机的确定值\
9.2、基本数据类型和操作符
- 字符串:在Jinja2模板中,无论是单引号还是双引号,都可以用来定义字符串。例如,
{{ "Hello, World!" }}
或{{ 'Hello, World!' }}
。 - 数字:Jinja2直接支持整数和浮点数的使用,无需特别的标记,如
{{ 42 }}
或{{ 3.14 }}
。 - 列表(List) 和 元组(Tuple):虽然Jinja2原生支持列表(使用方括号
[]
),但元组的直接表示不如Python中常见,因为模板更倾向于动态输出而不是静态结构。列表示例:{% for item in [1, 2, 3] %}...{% endfor %}
。 - 字典(Dictionary):与Python类似,使用花括号
{}
定义,键值对之间用冒号:
分隔。例如,{{ {"key": "value", "another_key": 42} }}
。 - 布尔型(Booleans):在Jinja2中,可以直接使用
true
和false
(全部小写),用于条件判断。 - 算术运算:Jinja2支持所有基本的算术运算符,包括
+
,-
,*
,/
,//
,%
,**
。例如,{{ 5 + 3 }}
或{{ 10 // 2 }}
。 - 比较操作:与Python相同,包括
==
,!=
,>
,>=
,<
,<=
。用于条件判断,如{% if variable > 10 %}...{% endif %}
。 - 逻辑运算:
and
,or
,not
用于逻辑条件组合。例如,{% if condition1 and condition2 %}...{% endif %}
或{% if not condition %}...{% endif %}
。
模板都是通过引用变量来引用的
9.3、案例:生成hosts解析文件
使用模板替远程主机生成hosts解析文件(先把原来的hosts解析都去掉,在ansible配置文件里面替换为ip)
1、修改Ansible主机清单
[root@server1 ~]# egrep -v "^$|^#" /etc/ansible/hosts
[all-servers]
server1
server2
server3
server4
[all_ip]
192.168.112.10
192.168.112.20
192.168.112.30
192.168.112.40
2、修改主机名
hostnamectl set-hostname server1
hostnamectl set-hostname server2
hostnamectl set-hostname server3
hostnamectl set-hostname server4
3、准备模板文件
[root@server1 ~]# vim hosts.j2
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for host in groups.all_ip %}
{{hostvars[host].ansible_ens33.ipv4.address}} {{hostvars[host].ansible_hostname}}
{% endfor %}
4、编写剧本
[root@server1 ~]# vim hosts.yml
---
- name: Config hosts file
hosts: all_ip
remote_user: root
tasks:
- name: copy hosts.j2 to group servers
template:
src: hosts.j2
dest: /etc/hosts
5、执行剧本
ansible-playbook hosts.yml --syntax-check
ansible-playbook hosts.yml
6、验证
ansible all-servers -m shell -a "tail -4 /etc/hosts"
10、条件判断
when语句:在task中使用,jinja2的语法格式。
10.1、举例
tasks:
- name: install conf file to centos7
template: src=files/nginx.conf.c7.j2
when: ansible_distribution_major_version == "7"
- name: install conf file to centos6
template: src=files/nginx.conf.c6.j2
when: ansible_distribution_major_version == "6"
11、循环迭代
循环:迭代,需要重复执行的任务;
对迭代项的引用,固定变量名为"item",而后,要在task中使用with_items给定要迭代的元素列表;
11.1举例
#基于字符串列表
tasks:
‐ name: create rsyncd file
copy: src={{ item }} dest=/tmp/{{ item }}
with_items:
‐ a
‐ b
‐ c
‐ d
*with_itmes 嵌套子变量*
#基于字典列表
‐ hosts: eagleslab
remote_user: root
tasks:
‐ name: add several users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
‐ { name: 'testuser1' , groups: 'wheel'}
‐ { name: 'testuser2' , groups: 'root' }
11.2、案例:循环创建用户
1、循环创建以下用户信息
zhangsan | xsb | /home/xsb/zhangsan | /bin/bash | 销售 |
---|---|---|---|---|
lisi | xsb | /home/xsb/lisi | /bin/bash | 销售 |
wangwu | jsb | /home/jsb/wangwu | /bin/sh | java工程师 |
maliu | jsb | /home/jsb/maliu | /bin/sh | linux工程师 |
zhaoqi | cwb | /home/cwb/zhaoqi | /bin/sh | 会计 |
2、循环创建出以上用户并指定用户信息
[root@server1 ~]# vim user_manage.yml
---
- name: Manage user
hosts: all-servers
remote_user: root
tasks:
- name: ensure group xsb/jsb/cwb exists
group:
name={{ item.group }}
with_items:
- { group: 'xsb' }
- { group: 'cwb' }
- { group: 'jsb' }
- name: create users zhangsan/lisi/wangwu/maliu/zhaoqi
user:
name={{ item.name }}
group={{ item.group }}
shell={{ item.shell }}
comment={{ item.comment }}
home={{ item.home }}
with_items:
- { name: 'zhangsan', group: 'xsb',home: '/home/xsb/zhangsan',shell: '/bin/bash',comment: '销售'}
- { name: 'lisi', group: 'xsb',home: '/home/xsb/zhangsan',shell: '/bin/bash',comment: '销售'}
- { name: 'wangwu', group: 'jsb',home: '/home/jsb/wangwu',shell: '/bin/sh',comment: 'java工程师'}
- { name: 'maliu', group: 'jsb',home: '/home/jsb/maliu',shell: '/bin/sh',comment: 'linux工程师'}
- { name: 'zhaoqi', group: 'cwb',home: '/home/cwb/zhaoqi',shell: '/bin/sh',comment: '会计'}
3、执行剧本
#语法检查
ansible-playbook user_manage.yml --syntax-check
#执行剧本
ansible-playbook user_manage.yml
4、验证
ansible all-servers -m shell -a "id zhangsan ; id lisi ; id wangwu ; id maliu ; id zhaoqi"
12、字典
ansible playbook 还支持字典这种数据类型
12.1、举例
- name: install some packages
yum: name={{ item }} state=present
with_items:
- nginx
- memcached
- php-fpm
- name: add some groups
group: name={{ item }} state=present
with_items:
- group11
- group12
- group13
- name: add some users
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: 'user11', group: 'group11' }
- { name: 'user12', group: 'group12' }
- { name: 'user13', group: 'group13' }
13、角色(role)
13.1、简介
Ansible的角色(Roles)是用于组织和复用配置任务的一种方式,它提供了一种结构化的方法来编写和管理Playbooks,使得大型项目和重复使用的配置任务变得更加易于管理和维护。
角色设计的初衷是为了促进Playbooks的层次化和模块化,使得不同功能组件能够清晰分离。
13.2、角色的目录结构
角色集合:roles/
- mysql/
- httpd/
- nginx/
- files/:存储由copy或script等模块调用的文件;
- tasks/:此目录中至少应该有一个名为main.yml的文件,用于定义各task;其它的文件需要由main.yml进行“包含”调用;、
- handlers/:此目录中至少应该有一个名为main.yml的文件,用于定义各handler;其它的文件需要由main.yml进行“包含”调用;
- vars/:此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其它的文件需要由main.yml进行“包含”调用;
- templates/:存储由template模块调用的模板文本;
- meta/:此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要由main.yml进行“包含”调用;
- default/:此目录中至少应该有一个名为main.yml的文件,用于设定默认变量;
14、案例:使用角色安装nginx
14.1、创建对应的目录结构
[root@server1 ~]# cd /etc/ansible/roles/
[root@server1 roles]# ls
[root@server1 roles]# mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}
14.2、定义配置文件
需要修改的配置文件为
/tasks/main.yml
[root@server1 roles]# cat /etc/ansible/roles/nginx/tasks/main.yml
---
- name: cp
copy: src=nginx-1.10.2-1.el7.ngx.x86_64.rpm dest=/tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm
- name: install
yum: name=/tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm state=present
- name: conf
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
tags: nginxconf
notify: new conf to reload
- name: start service
service: name=nginx state=started enabled=true
14.3、放置文件到指定目录
#rpm包放在files目录下
cp /tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm /etc/ansible/roles/nginx/files/
#模板放在templates目录下
cp /tmp/nginx.conf.j2 /etc/ansible/roles/nginx/templates/
#查看目录结构
[root@server1 nginx]# tree
14.4、修改变量文件
[root@server1 nginx]# cat /etc/ansible/roles/nginx/vars/main.yml
nginxport: 6666
14.5、定义handlers文件
[root@server1 nginx]# cat /etc/ansible/roles/nginx/handlers/main.yml
---
- name: new conf to reload
service: name=nginx state=restarted
14.6定义剧本文件
[root@server1 ansible]# cat /etc/ansible/roles.yml
---
- hosts: all-servers
remote_user: root
roles:
- nginx
14.7、剩余的配置文件
- nginx.conf.j2
events {
worker_connections 1024;
}
http {
server {
listen {{ nginxport }};
}
}
14.8、启动服务
#语法检查
ansible-playbook roles.yml --syntax-check
#执行剧本
ansible-playbook roles.yml
14.9、验证端口号
ansible all-servers -m shell -a "ss -tunlp | grep nginx"
15、案例:使用角色安装httpd
15.1、创建对应的目录结构
[root@server1 ~]# cd /etc/ansible/roles/
[root@server1 roles]# ls
[root@server1 roles]# mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}
#创建一个名为apache的新角色
[root@server1 roles]# ansible-galaxy init apache
- Role apache was created successfully
15.2、编写site.yaml文件
[root@server1 roles]# cat /etc/ansible/roles/site.yml
---
- hosts: all-servers
remote_user: root
roles:
- apache
15.3、编写tasks里的main.yml文件
[root@server1 roles]# cat /etc/ansible/roles/apache/tasks/main.yml
---
- name: Install httpd
yum:
name: httpd
state: present
- name: Start httpd
service:
name: httpd
state: restarted
- name: Write index file
shell: echo "http" > /var/www/html/index.html
15.4、执行剧本
#语法验证
ansible-playbook site.yml --syntax-check
#执行剧本
ansible-playbook site.yml
15.5、验证
ansible all-servers -m shell -a "curl -s server1 ; curl -s server2 ; curl -s server3 ; curl -s server4"
16、案例:使用角色安装java+nginx+halo
16.1、准备角色
[root@server1 roles]# ansible-galaxy init halo
- Role halo was created successfully
[root@server1 roles]# ansible-galaxy init java
- Role java was created successfully
[root@server1 roles]# ansible-galaxy init nginx
- Role nginx was created successfully
16.2、编写site.yml
- pre_tasks为运行play之前执行的任务
- post_tasks为运行play之后执行的任务
[root@server1 roles]# cat site.yml
---
- hosts: node1
remote_user: root
strategy: free
pre_tasks:
- name: config nginx repo for centos 7
yum_repository:
name: nginx
description: nginx
baseurl: http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck: no
when: ansible_distribution_major_version == "7"
- name: Disable SELinux
selinux: state=disabled
roles:
- nginx
post_tasks:
- shell: echo 'Deplay halo finished.'
register: ret
- debug: var=ret.stdout
16.3、编写nginx角色
nginx/tasks/main.yml
[root@server1 roles]# cat nginx/tasks/main.yml
---
# tasks file for nginx
- name: make sure nginx state is installed
yum: name=nginx state=installed
- name: copy halo to nginx config file
template: src=halo.conf dest="/etc/nginx/conf.d/halo.conf"
- name: make sure nginx service is running
service: name=nginx state=started
- name: make sure port is open
wait_for: port="{{ nginx_port }}"
meta/main.yml为role的依赖关系,要先运行这里面的内容才会运行自己的nginx这个role。
[root@server1 roles]# cat nginx/meta/main.yml #要修改的是dependencies部分
dependencies:
- role: java
- role: halo
nginx/templates/halo.conf
[root@server1 roles]# cat nginx/templates/halo.conf
upstream halo {
server 127.0.0.1:8090;
}
server {
listen 80;
listen [::]:80;
server_name {{ halo_domain }};
client_max_body_size 1024m;
location / {
proxy_pass http://halo;
proxy_set_header HOST $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
16.4、编写java角色
为了安装java
[root@server1 roles]# cat java/tasks/main.yml
---
# tasks file for java
- name: install java
yum: name=java-11-openjdk state=installed
16.5、编写halo角色
[root@server1 roles]# cat halo/tasks/main.yml
---
# tasks file for halo
- name: get halo
get_url: url=https://dl.halo.run/release/halo-1.4.11.jar dest={{ halopath }}
- name: add halo service file
template: src=halo.service dest=/etc/systemd/system/halo.service
- name: touch ~/.halo directory
file: path=~/.halo state=directory
- name: copy halo config file
template: src=application.yaml dest="~/.halo/application.yaml"
- name: restart halo
systemd:
daemon_reload: yes
name: halo
state: started
enabled: yes
- name: wait to start halo
wait_for: port={{ halo_port }}
修改变量文件halo/vars/main.yml
[root@server1 roles]# cat halo/vars/main.yml
---
# vars file for halo
memory: 512m
halo_port: 8090
halopath: /root/halo.jar
halo_domain: 192.168.112.10
nginx_port: 80
下载servers文件并编辑
[root@server1 roles]# wget https://dl.halo.run/config/halo.service -O halo/templates/halo.service
[root@server1 roles]# cat halo/templates/halo.service
[Unit]
Description=Halo Service
Documentation=https://docs.halo.run
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root #修改
ExecStart=/usr/bin/java -server -Xms256m -Xmx256m -jar /root/halo.jar #修改
ExecStop=/bin/kill -s QUIT $MAINPID
Restart=always
StandOutput=syslog
StandError=inherit
[Install]
WantedBy=multi-user.target
[root@server1 roles]# wget https://dl.halo.run/config/application-template.yaml -O halo/templates/application.yaml
16.6、执行剧本
#语法检查
ansible-playbook site.yml --syntax-check
#执行剧本
ansible-playbook site.yml
16.7、验证
通过IP+端口访问
192.168.112.10:8090
至此ansible的学习就告一段落啦