Ansible自动化运维工具

目录

一、什么是Ansible

1、简介

Ansible是一款自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统部署、批量程序部署,批量运行命令等功能。

Ansible是基于模块工作的,本身没有批量部署的能力,真正具有批量部署能力的是Ansible运行的模块,Ansible只是提供一个框架。Ansible不需要在远程主机上安装client/agents,因为它们是基于ssh来和远程主机通讯的。

2、架构

2Q==

  • ansbile:核心程序
  • modules:包括ansible自带的核心模块以及自定义模块
  • plugins:完成模块功能的补充,包括连接插件,邮箱插件
  • palybooks:剧本,定义ansbile多任务配置文件,由ansible自动执行
  • inventory:定义ansbile管理的主机清单
  • connection plugins:负责和被监控端实现通信

3、工作流程

  1. 加载配置文件: Ansible 默认查找 /etc/ansible/ansible.cfg 配置文件,这个文件包含了Ansible运行时的行为设定,如连接方式、插件路径等。
  2. 解析Inventory: Ansible 使用 Inventory 文件(默认是 /etc/ansible/hosts)来确定需要操作的目标主机或主机组。
  3. 编译Playbook或命令: Ansible 准备执行的Playbook或直接执行的Ad-Hoc命令,并解析其中的任务和模块调用。
  4. 模块加载与执行策略准备: 对于每个任务,Ansible 加载相应的模块(如 command 模块),并准备执行上下文,包括变量、环境等。
  5. 生成并传输临时脚本: Ansible 会根据任务和模块生成一个或多个临时的Python脚本,并通过SSH连接传输到目标主机的临时目录,通常位于目标用户的 ~/.ansible/tmp/ansible-tmp-<UNIQUE_ID>/ 目录下。
  6. 赋予执行权限: 在目标主机上,Ansible 会给这个临时Python脚本加上执行权限,以便能够运行。
  7. 执行远程脚本: Ansible 通过SSH在目标主机上执行这个临时脚本,并收集执行结果。
  8. 结果收集与处理: 执行完毕后,各个主机的执行结果被收集并汇总,Ansible根据这些结果决定是否继续执行后续任务,或是根据Playbook中的错误处理逻辑(如 rescuealways 块)进行操作。
  9. 清理: 一旦任务执行完成,无论成功还是失败,Ansible 会清理目标主机上的临时文件,包括删除之前上传的Python脚本。
  10. 退出与报告: 清理完成后,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安装版本

image-20240514193101699

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

image-20240514194147934

过程中需要输入受管节点的密码

3.4、测试免密登录

ssh root@host1
ssh root@host2
ssh root@host3

image-20240514195408504

4、定义主机清单

4.1、ansible常见的配置文件

  • /etc/ansible/ansible.cfg:主配置文件
  • /etc/ansible/hosts:主机清单文件
  • /etc/ansible/roles:角色目录

4.2、备份主机清单文件

cp -f hosts hosts.bak

image-20240515154201487

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

image-20240516112421403

三、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

image-20240515175627840

image-20240516111257062

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'

image-20240516121432943

2.3、查看磁盘空间

#查看mysql_test组中所有主机的磁盘空间
ansible mysql_test -m command -a 'df -h'

#查看web_test组中所有主机的磁盘空间
ansible web_test -m command -a 'df -h'

image-20240516115223289

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'

image-20240516204041385

3.3、查看远程主机防火墙状态

#查看mysql_test组中所有的主机防火墙firewalld和selinux的状态
ansible mysql_test -m shell -a 'systemctl status firewalld ; getenforce'

这里验证了command模块不能使用命令别名、管道、重定向以及逻辑运算符(如;, &&, ||

由于command模块直接将整个字符串传递给系统执行,分号;以及随后的getenforce命令被视为命令的一部分,而不是独立的指令。这导致系统尝试查找名为类似\x3b.service(分号;的ASCII转义序列)的服务状态,以及尝试将getenforce当作一个服务单元来查找,由于这两个都不是有效的服务单元名称,因此返回了错误信息。

image-20240516210703587

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"

image-20240516221926779

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'"

image-20240516232453569

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}'\'''

image-20240516233345659

4.4、删除新创建的用户

#删除用户zhangsan
ansible web_test -m user -a "name=zhangsan state=absent remove=yes"

image-20240516233919793

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信息

image-20240517084145750

5.3、删除组

#删除web_test组所有主机上的系统组web_test
ansible web_test -m group -a "name=web_test gid=1010 state=absent"

image-20240517084723135

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'

image-20240517092416076

6.3、修改文件内容,选择覆盖备份

#修改node3主机上copy.txt文件内容,并选择备份
ansible node3 -m copy -a 'content="copy test_1\n" backup=yes dest=/root/copy.txt mode=666'

image-20240517093301639

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 限制要抓取的文件大小,可以使用后缀如kMG来指定单位(千字节、兆字节、吉字节)。如果远程文件超过指定大小,抓取操作将不会执行。
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"

image-20240518153051479

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"

image-20240518154431410

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 状态,有以下选项:directoryfilelinkhardtouchabsent

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"

image-20240517104101964

8.3、创建软链接文件

#给mysql_test组的所有主机创建软链接文件test1指向/root/aliyun.sh
ansible mysql_test -m file -a "path=/tmp/test1 src=/root/aliyun.sh state=link"

image-20240517135611145

8.4、创建硬链接文件

#给mysql_test组的所有主机创建硬链接文件test1指向/root/aliyun.sh
ansible mysql_test -m file -a "path=/tmp/test2 src=/root/aliyun.sh state=hard"

image-20240517140146609

8.5、删除文件

#删除mysql_test组中所有主机/tmp/目录下test1
ansible mysql_test -m file -a "path=/tmp/test1 state=absent"

image-20240517141327165

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,只用于presentor 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"
安装
image-20240518102615952
查看进程
image-20240518102905585
卸载
image-20240518102701842

9.3、更新所有的软件包

#给所有主机更新所有的软件包
ansible all-servers -m yum -a "name=* state=latest"

image-20240518110821977

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的顶部。namevalue参数分别为环境变量的名称和值。
hour 任务应运行的小时 (0-23, *, */2, 等)。
insertafter state=presentenv一起使用。如果指定,环境变量将在指定环境变量声明之后插入。
insertbefore state=presentenv一起使用。如果指定,环境变量将在指定环境变量声明之前插入。
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"

image-20240518162626709

10.3、删除指定计划任务

#删除名为Daily Task的计划任务(没有明确的计划任务名称写完整的计划任务也可以删除)
ansible mysql_test -m cron -a "name='Daily Task' state=absent"

image-20240518163214996

11、service模块

Ansible的service模块用于管理系统服务(如启动、停止、重启服务等)。

这个模块与特定的系统服务管理工具(如systemd、sysvinit、upstart等)兼容,能够跨不同的Linux发行版和系统管理框架工作

11.1、选项及描述

ansible-doc -s service
选项 描述
arguments 额外的命令行参数,提供给服务管理命令。
enabled 服务是否应该在系统启动时自动启动。至少需要指定stateenabled中的一个。
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服务
image-20240518165922943
查看firewalld服务状态
image-20240518170027529
关闭firewalld服务
image-20240518170142857

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

image-20240518173032713

2、通过script模块部署到远程主机执行
#给web_test组的所有主机执行控制节点上的df.sh脚本文件
ansible web_test -m script -a "/tmp/df.sh”

image-20240518173943581

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*'"

image-20240518180334853

通过free -m命令查看内存大小是否一致
#通过free -m命令查看mysql_test组主机的内存信息
ansible mysql_test -m shell -a "free -m"

image-20240518180649443

13.3、保存信息

#将筛选的信息保存到控制节点的/tmp/data目录下
ansible web -m setup -a 'filter="*mem*"' --tree /tmp/data

image-20240518181607518

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_portansible_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
image-20240518202630013
同步本地/tmp/到host1主机上
image-20240518202725638
查看目录结构
image-20240518202919470

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服务器配置。
  • hostsnode1,指定该Play作用于名为node1的主机。
  • remote_userroot,指定执行任务的远程用户为root。
  • tasks
    • task 1: 确保Apache是最新的版本。使用yum模块安装httpd包至最新版。
    • task 2: 写入Apache配置文件。使用template模块将模板文件/srv/httpd.j2渲染后复制到/etc/httpd.conf,允许动态配置生成。
    • task 3: 确保Apache服务已启动。使用service模块设置httpd服务的状态为started,如果服务未运行则启动。

Play 2: 更新数据库服务器

  • Play标题:"update db servers",目标是更新数据库服务器配置。
  • hosts:同样为node1,指定该Play作用于名为node1的主机。
  • remote_userroot,指定执行任务的远程用户为root。
  • tasks
    • task 1: 确保MariaDB是最新的版本。使用yum模块安装mariadb-server至最新版。
    • task 2: 确保MariaDB服务已启动。使用service模块设置mariadb服务的状态为started

3、playbook的执行与语法检查

#执行playbook
ansible-playbook playbook.yml

#语法检查
ansible-playbook --syntax-check playbook.yml 

4、playbook的核心元素

  1. Hosts(主机组):定义了Playbook将要操作的目标机器集合。可以是单个主机名、IP地址,也可以是主机组名。
  2. Tasks(任务列表):构成Play的主要部分,定义了在目标主机上执行的具体操作序列。每个任务通常关联一个特定的Ansible模块及参数。
  3. Variables(变量):用于在Playbook中传递和管理配置信息,支持多种设置方式(如直接赋值、变量文件、环境变量、角色默认变量等),增加了Playbook的灵活性和可重用性。
  4. Templates(模板):使用Jinja2模板引擎动态生成配置文件。允许根据变量插入动态内容,适用于需要根据不同环境定制配置的情况。
  5. 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选项选择性地执行带有特定标签的任务。
  • 模块与模块参数:Ansible通过各种模块执行具体操作,模块后跟随的是该模块接受的参数。对于shellcommand这类直接执行系统命令的模块,参数直接是命令字符串,而不是键值对形式。

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

image-20240519071818027

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"

image-20240519073818831

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"

image-20240519075156982

7.3、测试标签

#先关闭node3上的nginx服务以便测试
ansible node3 -m shell -a "systemctl stop nginx"

#再运行剧本并引用标签startnginx
ansible-playbook nginx2.yml -t startnginx

image-20240519000329240

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;
        }
    }
}

image-20240519075419174

7.4.2、重新执行剧本
#语法检查
ansible-playbook nginx2.yml --syntax-check

#再运行剧本并引用标签reloadnginx
ansible-playbook nginx2.yml -t reloadnginx

image-20240519001410850

7.4.3、重新查看端口号
ansible node2 -m shell -a "ss -tnulp | grep nginx"

image-20240519075549066

端口号变为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、优先级

  1. 通过命令行指定变量优先级最高
  2. /etc/ansible/hosts定义变量(针对单个主机定义,针对主机组进行定义)
  3. 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
全局替换并添加确认动作
image-20240519085826481
输入y确认替换
image-20240519085933294
替换好的剧本
image-20240519091914865
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

image-20240519093852380

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

image-20240519094357159

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中,可以直接使用truefalse(全部小写),用于条件判断。
  • 算术运算: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

image-20240519103229272

6、验证
ansible all-servers -m shell -a "tail -4 /etc/hosts"

image-20240519104459086

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

image-20240519151508668

4、验证
ansible all-servers -m shell -a "id zhangsan ; id lisi ; id wangwu ; id maliu ; id zhaoqi"

image-20240519152054284

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}

image-20240519155820069

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包

#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

image-20240519162239997

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

image-20240519165513040

14.9、验证端口号

ansible all-servers -m shell -a "ss -tunlp | grep nginx"

image-20240519165645659

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

image-20240519172738160

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

image-20240519173423259

15.5、验证

ansible all-servers -m shell -a "curl -s server1 ; curl -s server2 ; curl -s server3 ; curl -s server4"

image-20240519173703371

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

image-20240519173958985

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

image-20240519181906858

16.7、验证

通过IP+端口访问

192.168.112.10:8090

image-20240519182050796

至此ansible的学习就告一段落啦

posted @ 2024-05-19 18:52  misakivv  阅读(950)  评论(0编辑  收藏  举报