知识点思维导图:https://flowus.cn/share/7875c0e1-ebbd-4dad-aa7e-f40e6ed6c6d3
什么是andsble?
ansible是一款自动化运维工具,基于Python开发,可以实现
–批量系统配置
–批量程序部署
–批量运行命令等功能
ansible进行远程管理的两个方法:
adhoc临时命令。就是在命令行上执行管理命令。
playbook剧本。把管理任务用特定格式写到文件中。
无论哪种方式,都是通过模块加参数进行管理。
ansible产品特色
基于SSH架构 模块丰富
社区活跃 支持自定义模块
支持异构IT架构 部署简单,容易上手
ansible环境部署
1.修改/etc/hosts
控制节点ip 主机名
被控节点ip 被控节点主机名
如:
]# tail -4 /etc/hosts192.168.88.240 pubserver192.168.88.11 web1192.168.88.12 web2192.168.88.13 db12.配置ssh密钥
ssh-keygen ssh-copy-id
主机A :
ssh-keygen
ssh-copy-id 主机B 输入主机B的密码
主机A即可免密ssh连接主机B
使用一套ansible软件,有可能需要管理多种环境。如在同一台管理主机上管理开发环境和生产环境。
通过创建不同的工作目录,来实现相应的管理需求。
将某一环境下的主机写入到对应工作目录的主机清单文件。
进入对应的工作目录执行管理任务,就可以管理相应环境的主机。
3.创建ansible工作目录,目录名自己定义,不是固定的。
xxxxxxxxxx[root@pubserver ~]# mkdir ansible[root@pubserver ~]# cd ansible4.创建配置文件。默认的配置文件是/etc/ansible/ansible.cfg,但是一般不使用它,而是在工作目录下创建自己的配置文件
xxxxxxxxxx[root@pubserver ansible]# vim ansible.cfg # 文件名必须是ansible.cfg[defaults]host_key_checking = false # 不检查主机密钥,=号两边空格可有可无。inventory = inventory # 定义主机清单文件为当前目录的inventory5.创建主机清单文件。写在[]里的是组名,[]下面的是组内的主机名
xroot@pubserver ansible]# vim inventory[webservers]web[1:2] # web1和web2的简化写法,表示从1到2
[dbs]db1
# cluster是组名,自定义的;:children是固定写法,表示下面的组名是cluster的子组。[cluster:children]webserversdbs
# 查看被管理的所有的主机。注意,一定在工作目录下执行命令。[root@pubserver ansible]# ansible all --list-hosts hosts (3): web1 web2 db1
# 查看webservers组中所有的主机[root@pubserver ansible]# ansible webservers --list-hosts hosts (2): web1 web2ansible配置文件
xxxxxxxxxx修改主配置文件·主配置文件ansib|e.cfg-参考/etc/ansible/ansible.cfgansible配置文件查找顺序-首先检测ANSIBLE CONFIG变量定义的配置文件-其次检查当前目录下的./ansible.cfg文件-再次检查当前用户家目录下/ansible.cfg文件-最后检查/etc/ansible/ansible.cfg文件adhocl临时命令
语法
xxxxxxxxxxansible 主机或组列表 -m 模块 -a "参数" # -a是可选的
通过ping模块测试到远程主机的连通性。ansible all -m pingansible模块
在ansible中,通过模块来完成某一特定任务。
学习模块,主要知道实现某种功能,需要哪个模块。
模块的使用方式都一样。主要是查看该模块有哪些参数。
xxxxxxxxxx# 列出全部可用模块,按空格键向下翻页,按q退出[root@pubserver ansible]# ansible-doc -l
# 列出模块数量[root@pubserver ansible]# ansible-doc -l | wc -l # 如有WARNING提示,可忽略7214
# 查看包含yum的模块名[root@pubserver ansible]# ansible-doc -l | grep yum
# 查看yum模块的帮助文档,按空格键向下翻页,按q退出[root@pubserver ansible]# ansible-doc yumcommand模块
ansible默认模块,用于在远程主机上执行任意命令
command不支持shell特性,如管道、重定向。
xxxxxxxxxx# 在所有被管主机上创建目录/tmp/demo[root@pubserver ansible]ansible all -a "mkdir /tmp/demo"# 查看we1的ip地址[root@pubserver ansible]ansible web1 -a "ip a s"[root@pubserver ansible]ansible web1 -a "ip a s | head" # 报错shell模块
与command模块类似,但是支持shell特性,如管道、重定向。
xxxxxxxxxx# 查看web1的ip地址,只显示前10行[root@pubserver ansible]ansible web1 -m shell -a "ip a s | head"script模块
用于在远程主机上执行脚本
xxxxxxxxxx# 在控制端创建脚本即可[root@pubserver ansible] vim test.shfor user in user{1..5}do useradd $user echo '123456' | passwd --stdin $userdone# 在webservers组的主机上执行脚本[root@pubserver ansible] ansible webservers -m script -a "test.sh"file模块
可以创建文件、目录、链接等,还可以修改权限、属性等
常用的选项:
path:指定文件路径
owner:设置文件所有者
group:设置文件所属组
state:状态。touch表示创建文件,directory表示创建目录,link表示创建软链接,absent表示删除
mode:设置权限
src:source的简写,源
dest:destination的简写,目标
xxxxxxxxxx# 查看使用帮助[root@pubserver ansible]# ansible-doc file... ...EXAMPLES:
- name: Change file ownership, group and permissions # 忽略 ansible.builtin.file: # 模块名。以下是它的各种参数 path: /etc/foo.conf # 要修改的文件的路径 owner: foo # 文件所有者 group: foo # 文件的所有组 mode: '0644' # 权限... ...# 根据上面的example,-m file -a的内容就是doc中把各参数的冒号换成=号
# 在webservers组的主机上创建/tmp/file.txt[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/file.txt state=touch" # touch是指如果文件不存在,则创建;如果存在则改变它的时间戳
# 在webservers组的主机上创建/tmp/demo目录[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/demo state=directory"
# 将webservers组的主机上/tmp/file.txt的属主改为sshd,属组改为adm,权限改为0777[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/file.txt owner=sshd group=adm mode='0777'"[root@pubserver ansible]# ansible webservers -a "ls -l /tmp/file.txt"
# 删除webservers组的主机上/tmp/file.txt[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/file.txt state=absent" # absent英文缺席的、不存在的
# 删除webservers组的主机上/tmp/demo[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/demo state=absent"
# 在webservers组的主机上创建/etc/hosts的软链接,目标是/tmp/hosts.txt[root@pubserver ansible]# ansible webservers -m file -a "src=/etc/hosts dest=/tmp/hosts.txt state=link"copy模块
用于将文件从控制端拷贝到被控端
常用选项:
src:源。控制端的文件路径
dest:目标。被控制端的文件路径
content:内容。需要写到文件中的内容
xxxxxxxxxx[root@pubserver ansible]# echo "AAA" > a3.txt# 将a3.txt拷贝到webservers主机的/root/[root@pubserver ansible]# ansible webservers -m copy -a "src=a3.txt dest=/root/"
# 在目标主机上创建/tmp/mytest.txt,内容是Hello World[root@pubserver ansible]# ansible webservers -m copy -a "content='Hello World' dest=/tmp/mytest.txt"fetch模块
与copy模块相反,copy是上传,fetch是下载
常用选项:
src:源。被控制端的文件路径
dest:目标。控制端的文件路径
xxxxxxxxxx# 将webservers主机上的/etc/hostname下载到本地用户的家目录下[root@pubserver ansible]# ansible webservers -m fetch -a "src=/etc/hostname dest=~/"[root@pubserver ansible]# ls /root/web1/etc/ # web1是webservers组中的主机hostname[root@pubserver ansible]# ls /root/web2/etc/hostnamelineinfile模块
用于确保存目标文件中有某一行内容
常用选项:
path:待修改的文件路径
line:写入文件的一行内容
regexp:正则表达式,用于查找文件中的内容
xxxxxxxxxx# webservers组中的主机,/etc/issue中一定要有一行Hello World。如果该行不存在,则默认添加到文件结尾[root@pubserver ansible]# ansible webservers -m lineinfile -a "path=/etc/issue line='Hello World'"
# webservers组中的主机,把/etc/issue中有Hello的行,替换成chi le ma[root@pubserver ansible]# ansible webservers -m lineinfile -a "path=/etc/issue line='chi le ma' regexp='Hello'"replace模块
lineinfile会替换一行,replace可以替换关键词
常用选项:
path:待修改的文件路径
replace:将正则表达式查到的内容,替换成replace的内容
regexp:正则表达式,用于查找文件中的内容
xxxxxxxxxx# 把webservers组中主机上/etc/issue文件中的chi,替换成he[root@pubserver ansible]# ansible webservers -m replace -a "path=/etc/issue regexp='chi' replace='he'"文件操作综合练习
所有操作均对webservers组中的主机生效
在目标主机上创建/tmp/mydemo目录,属主和属组都是adm,权限为0777
将控制端的/etc/hosts文件上传到目标主机的/tmp/mydemo目录中,属主和属组都是adm,权限为0600
替换目标主机/tmp/mydemo/hosts文件中的db1为database1
将目标主机/tmp/mydemo/hosts文件下载到控制端的当前目录
xxxxxxxxxx# 在目标主机上创建/tmp/mydemo目录,属主和属组都是adm,权限为0777[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/mydemo owner=adm group=adm mode='0777' state=directory"
# 将控制端的/etc/hosts文件上传到目标主机的/tmp/mydemo目录中,属主和属组都是adm,权限为0600[root@pubserver ansible]# ansible webservers -m copy -a "src=/etc/hosts dest=/tmp/mydemo owner=adm group=adm mode='0600'"
# 替换目标主机/tmp/mydemo/hosts文件中的db1为database1[root@pubserver ansible]# ansible webservers -m replace -a "path=/tmp/mydemo/hosts regexp='db1' replace='database1'"
# 将目标主机/tmp/mydemo/hosts文件下载到控制端的当前目录。[root@pubserver ansible]# ansible webservers -m fetch -a "src=/tmp/mydemo/hosts dest=."user模块
实现linux用户管理
常用选项:
name:待创建的用户名
uid:用户ID
group:设置主组
groups:设置附加组
home:设置家目录
password:设置用户密码
state:状态。present表示创建,它是默认选项。absent表示删除
remove:删除家目录、邮箱等。值为yes或true都可以。
xxxxxxxxxx# 在webservers组中的主机上,创建zhangsan用户[root@pubserver ansible]# ansible webservers -m user -a "name=zhangsan"
# 在webservers组中的主机上,创建lisi用户。设置其uid为1010,主组是adm,附加组是daemon和root,家目录是/home/lisi[root@pubserver ansible]# ansible webservers -m user -a "name=lisi uid=1010 group=adm groups=daemon,root home=/home/lisi"
# 设置zhangsan的密码是123456# {{}}是固定格式,表示执行命令。password_hash是函数,sha512是加密算法,则password_hash函数将会把123456通过sha512加密变成zhangsan的密码[root@pubserver ansible]# ansible webservers -m user -a "name=zhangsan password={{'123456'|password_hash('sha512')}}"
# 删除zhangsan用户,不删除家目录[root@pubserver ansible]# ansible webservers -m user -a "name=zhangsan state=absent"
# 删除lisi用户,同时删除家目录[root@pubserver ansible]# ansible webservers -m user -a "name=lisi state=absent remove=yes"group模块
创建、删除组
常用选项:
name:待创建的组名
gid:组的ID号
state:present表示创建,它是默认选项。absent表示删除
xxxxxxxxxx# 在webservers组中的主机上创建名为devops的组[root@pubserver ansible]# ansible webservers -m group -a "name=devops"
# 在webservers组中的主机上删除名为devops的组[root@pubserver ansible]# ansible webservers -m group -a "name=devops state=absent"yum_repository
用于配置yum
常用选项:
file: 指定文件名
其他选项,请与文件内容对照
xxxxxxxxxx# 在webservers组中的主机上,配置yum[root@pubserver ansible]# ansible webservers -m yum_repository -a "file=myrepo name=myApp description='My App' baseurl=ftp://192.168.88.240/dvd/AppStream gpgcheck=no enabled=yes"
[root@web1 ~]# cat /etc/yum.repos.d/myrepo.repo [myApp]async = 1baseurl = ftp://192.168.88.240/dvd/AppStreamenabled = 1gpgcheck = 0name = My App
[root@pubserver ansible]# ansible webservers -m yum_repository -a "file=myrepo name=BaseOS description='Base OS' baseurl=ftp://192.168.88.240/dvd/BaseOS gpgcheck=no enabled=yes"
[root@web1 ~]# cat /etc/yum.repos.d/myrepo.repo [myApp]async = 1baseurl = ftp://192.168.88.240/dvd/AppStreamenabled = 1gpgcheck = 0name = My App
[BaseOS]async = 1baseurl = ftp://192.168.88.240/dvd/BaseOSenabled = 1gpgcheck = 0name = Base OSyum模块
用于rpm软件包管理,如安装、升级、卸载
常用选项:
name:包名
state:状态。present表示安装,如果已安装则忽略;latest表示安装或升级到最新版本;absent表示卸载。
xxxxxxxxxx# 在webservers组中的主机上安装tar[root@pubserver ansible]# ansible webservers -m yum -a "name=tar state=present"
# 在webservers组中的主机上安装wget、net-tools[root@pubserver ansible]# ansible webservers -m yum -a "name=wget,net-tools"
# 在webservers组中的主机上卸载wget[root@pubserver ansible]# ansible webservers -m yum -a "name=wget state=absent"service模块
用于控制服务。启动、关闭、重启、开机自启。
常用选项:
name:控制的服务名
state:started表示启动;stopped表示关闭;restarted表示重启
enabled:yes表示设置开机自启;no表示设置开机不要自启。
xxxxxxxxxx# 在test主机上安装nginx[root@pubserver ansible]# ansible webservers -m yum -a "name=nginx state=latest"
# 在test主机上启动nginx,并设置它开机自启[root@pubserver ansible]# ansible webservers -m service -a "name=nginx state=started enabled=yes"逻辑卷相关模块
逻辑卷可以动态管理存储空间。可以对逻辑卷进行扩容或缩减。
可以把硬盘或分区转换成物理卷PV;再把1到多个PV组合成卷组VG;然后在VG上划分逻辑卷LV。LV可以像普通分区一样,进行格式化、挂载。
关闭虚拟机web1,为其添加2块20GB的硬盘
LINUX下KVM虚拟机新加的硬盘,名称是
/dev/vdb和/dev/vdcvmware虚拟机新加的硬盘,名称是
/dev/sdb和/dev/sdc如果选nvme硬盘,名称可能是
/dev/nvme0n1和/dev/nvme0n2
xxxxxxxxxx[root@web1 ~]# lsblk # 可以查看到新加的硬盘vdb和vdcNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTsr0 11:0 1 1024M 0 rom vda 253:0 0 30G 0 disk `-vda1 253:1 0 20G 0 part /vdb 253:16 0 20G 0 disk vdc 253:32 0 20G 0 disk lvg模块
创建、删除卷组,修改卷组大小
常用选项:
vg:定义卷组名。vg:volume group
pvs:由哪些物理卷构成。pvs:physical volumes
xxxxxxxxxx# 在web1上安装lvm2,state不写,默认是present[root@pubserver ansible]# ansible web1 -m yum -a "name=lvm2"
# 手工在web1上对vdb进行分区[root@web1 ~]# fdisk /dev/vdbCommand (m for help): g # 创建GPT分区表Command (m for help): n # 新建分区Partition number (1-128, default 1): # 回车,使用1号分区First sector (2048-41943006, default 2048): # 起始位置,回车Last sector, +sectors or +size{K,M,G,T,P} (2048-41943006, default 41943006): +5G # 结束位置+5G
Command (m for help): n # 新建分区Partition number (2-128, default 2): # 回车,使用2号分区First sector (10487808-41943006, default 10487808): # 起始位置,回车Last sector, +sectors or +size{K,M,G,T,P} (10487808-41943006, default 41943006): # 结束位置,回车,分区到结尾Command (m for help): w # 存盘
[root@web1 ~]# lsblk # vdb被分出来了两个分区NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTsr0 11:0 1 1024M 0 rom vda 253:0 0 30G 0 disk `-vda1 253:1 0 20G 0 part /vdb 253:16 0 20G 0 disk |-vdb1 253:17 0 5G 0 part `-vdb2 253:18 0 15G 0 part vdc 253:32 0 20G 0 disk
# 在web1上创建名为myvg的卷组,该卷组由/dev/vdb1组成[root@pubserver ansible]# ansible web1 -m lvg -a "vg=myvg pvs=/dev/vdb1"
# 在web1上查看卷组[root@web1 ~]# vgs VG #PV #LV #SN Attr VSize VFree myvg 1 0 0 wz--n- <5.00g <5.00g
# 扩容卷组。卷组由PV构成,只要向卷组中加入新的PV,即可实现扩容[root@pubserver ansible]# ansible web1 -m lvg -a "vg=myvg pvs=/dev/vdb1,/dev/vdb2"
[root@web1 ~]# vgs # 在web1上查看卷组 VG #PV #LV #SN Attr VSize VFree myvg 2 0 0 wz--n- 19.99g 19.99glvol模块
创建、删除逻辑卷,修改逻辑卷大小
常用选项:
vg:指定在哪个卷组上创建逻辑卷
lv:创建的逻辑卷名。lv:logical volume
size:逻辑卷的大小,不写单位,以M为单位
xxxxxxxxxx# 在web1上创建名为mylv的逻辑卷,大小为2GB[root@pubserver ansible]# ansible web1 -m lvol -a "vg=myvg lv=mylv size=2G"
# 在web1上查看逻辑卷[root@web1 ~]# lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert mylv myvg -wi-a----- 2.00g # mylv扩容至4GB[root@pubserver ansible]# ansible web1 -m lvol -a "vg=myvg lv=mylv size=4G"
[root@web1 ~]# lvs # 在web1上查看逻辑卷 LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert mylv myvg -wi-a----- 4.00g filesystem模块
用于格式化,也就是创建文件系统
常用选项:
fstype:指定文件系统类型
dev:指定要格式化的设备,可以是分区,可以是逻辑卷
xxxxxxxxxx# 在web1上,把/dev/myvg/mylv格式化为xfs[root@pubserver ansible]# ansible web1 -m filesystem -a "fstype=xfs dev=/dev/myvg/mylv"
# 在web1上查看格式化结果[root@web1 ~]# blkid /dev/myvg/mylv/dev/myvg/mylv: UUID="46c0af72-e517-4b15-9e53-ec72fbe1d96e" TYPE="xfs"mount模块
用于挂载文件系统
常用选项:
path:挂载点。如果挂载点不存在,自动创建。
src:待挂载的设备
fstype:文件系统类型
state:mounted,表示永久挂载
xxxxxxxxxx# 在web1上,把/dev/myvg/mylv永久挂载到/data[root@pubserver ansible]# ansible web1 -m mount -a "path=/data src=/dev/myvg/mylv state=mounted fstype=xfs"
# 在web1上查看[root@web1 ~]# tail -1 /etc/fstab /dev/myvg/mylv /data xfs defaults 0 0[root@web1 ~]# df -h /data/Filesystem Size Used Avail Use% Mounted on/dev/mapper/myvg-mylv 4.0G 61M 4.0G 2% /data
# 在web1上,卸载/dev/myvg/mylv[root@pubserver ansible]# ansible web1 -m mount -a "path=/data state=absent"
# 在web1上,强制删除/dev/myvg/mylv[root@pubserver ansible]# ansible web1 -m lvol -a "lv=mylv state=absent vg=myvg force=yes" # force是强制
# 在web1上,删除myvg卷组[root@pubserver ansible]# ansible web1 -m lvg -a "vg=myvg state=absent"Playbook剧本
常用于复杂任务的管理,以及管理经常要完成的任务
playbook也是通过模块和它的参数,在特定主机上执行任务
playbook是一个文件,该文件中需要通过yaml格式进行书写
YAML
YAML Ain't a Markup Language:YAML不是一个标记语言
yaml语法规范
yaml文件的文件名,一般以yml或yaml作为扩展名
文件一般以
---作为第一行,不是必须的,但是常用键值对使用冒号
:表示,冒号后面必须有空格。数组使用
-表示,-后面必须有空格。相同的层级必须有相同的缩进。如果缩进不对,则有语法错误。每一级缩进,建议2个空格。
全文不能使用tab,必须使用空格。
配置vim适应yaml语法
xxxxxxxxxx# 文件位置和名字是固定的,用于设置vim的格式[root@pubserver ansible]# vim ~/.vimrcset ai # 设置自动缩进set ts=2 # 设置按tab键,缩进2个空格set et # 将tab转换成相应个数的空格编写playbook
一个剧本(即playbook),可以包含多个play
每个play用于在指定的主机上,通过模块和参数执行相应的任务
每个play可以包含多个任务。
任务有模块和参数构成。
xxxxxxxxxx---- 名字: 猴王初问世 职员表: 猴哥, 大马猴 场景: - 名字: 石头裂开了 - 名字: 天宫震颤了
- 名字: 官封弼马温 职员表: 猴哥, 玉皇大帝 场景: - 名字: 太白金星骗猴哥 - 名字: 猴哥天宫放马
xxxxxxxxxx# 编写用于测试连通性的playbook,相当于执行ansible all -m ping[root@pubserver ansible]# vim test.yml---- hosts: all tasks: - ping:
[root@pubserver ansible]# ansible-playbook test.yml # 执行playbook
# 以上更规范的写法如下:[root@pubserver ansible]# vim test.yml---- name: test network # play的名字,可选项 hosts: all # 作用于所有的主机 tasks: # 任务 - name: test via ping # 第1个任务的名字,可选项 ping: # 第1个任务使用的模块
[root@pubserver ansible]# ansible-playbook test.yml # 执行playbook
# 在dbs组的主机和web1上创建/tmp/demo目录,权限是0755。将控制端/etc/hosts拷贝到目标主机的/tmp/demo中[root@pubserver ansible]# vim fileop.yml---- name: create dir and copy file hosts: dbs,web1 # 这里的名称,必须出现在主机清单文件中 tasks: - name: create dir file: path: /tmp/demo state: directory mode: '0755' - name: copy file copy: src: /etc/hosts dest: /tmp/demo/hosts
# 执行playbook[root@pubserver ansible]# ansible-playbook fileop.yml
# 在webservers组中的主机上,创建用户bob,附加组是adm;在db1主机上,创建/tmp/hi.txt,其内容为Hello World.[root@pubserver ansible]# vim two.yml---- name: create user hosts: webservers tasks: - name: create bob user: name: bob groups: adm
- name: create file hosts: db1 tasks: - name: make file copy: dest: /tmp/hi.txt content: "Hello World"
[root@pubserver ansible]# ansible-playbook two.yml|和>的区别:|它保留换行符,>把多行合并为一行
xxxxxxxxxx# 通过copy模块创建/tmp/1.txt,文件中有两行内容,分别是Hello World和ni hao[root@pubserver ansible]# vim f1.yml---- name: play 1 hosts: webservers tasks: - name: mkfile 1.txt copy: dest: /tmp/1.txt content: | Hello World! ni hao.
[root@pubserver ansible]# ansible-playbook f1.yml# 查看结果[root@web1 ~]# cat /tmp/1.txt Hello World!ni hao.
# 通过copy模块创建/tmp/2.txt,文件中有一行内容,分别是Hello World! ni hao[root@pubserver ansible]# vim f2.yml ---- name: play 1 hosts: webservers tasks: - name: mkfile 2.txt copy: dest: /tmp/2.txt content: > Hello World! ni hao.
[root@pubserver ansible]# ansible-playbook f2.yml[root@web1 ~]# cat /tmp/2.txt Hello World! ni hao.playbook示例
xxxxxxxxxx# 在webservers组中的主机上创建john用户,它的uid是1040,主组是daemon,密码为123[root@pubserver ansible]# vim user_john.yml---- name: create user hosts: webservers tasks: - name: create user john user: name: john uid: 1040 group: daemon password: "{{'123'|password_hash('sha512')}}"[root@pubserver ansible]# ansible-playbook user_john.yml
# 在webservers组中的主机上删除用户john[root@pubserver ansible]# vim del_john.yml---- name: delete user hosts: webservers tasks: - name: delete user john user: name: john state: absent[root@pubserver ansible]# ansible-playbook del_john.yml硬盘管理
常用的分区表类型有:MBR(主引导记录)、GPT(GUID分区表)
MBR最多支持4个主分区,或3个主分区加1个扩展分区。最大支持2.2TB左右的硬盘
GPT最多支持128个主分区。支持大硬盘
parted模块
用于硬盘分区管理
常用选项:
device:待分区的设备
number:分区编号
state:present表示创建,absent表示删除
part_start:分区的起始位置,不写表示从开头
part_end:表示分区的结束位置,不写表示到结尾
xxxxxxxxxx# 在web1主机上,对/dev/vdc进行分区,创建1个1GB的主分区[root@pubserver ansible]# vim disk.yml---- name: disk manage hosts: web1 tasks: - name: create a partition parted: device: /dev/vdc number: 1 state: present part_end: 1GiB
[root@pubserver ansible]# ansible-playbook disk.yml
# 在目标主机上查看结果[root@web1 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT.. ...vdc 253:32 0 20G 0 disk `-vdc1 253:33 0 1023M 0 part
# 继续编辑disk.yml,对/dev/vdc进行分区,创建1个新的5GB的主分区[root@pubserver ansible]# vim disk.yml ... ... - name: add a new partition parted: device: /dev/vdc number: 2 state: present part_start: 1GiB part_end: 6GiB
[root@pubserver ansible]# ansible-playbook disk.yml [root@web1 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT... ...vdc 253:32 0 20G 0 disk |-vdc1 253:33 0 1023M 0 part `-vdc2 253:34 0 5G 0 part
# 继续编辑disk.yml,创建名为my_vg的卷组,它由上面创建的vdc1和vdc2构成[root@pubserver ansible]# vim disk.yml ... ... - name: create my_vg lvg: vg: my_vg pvs: /dev/vdc1,/dev/vdc2
# 继续编辑disk.yml,在my_vg卷组上创建名为my_lv的逻辑卷,大小1G[root@pubserver ansible]# vim disk.yml ... ... - name: create my_lv lvol: vg: my_vg lv: my_lv size: 1G
# 继续编辑disk.yml,格式化my_lv为ext4[root@pubserver ansible]# vim disk.yml ... ... - name: mkfs my_lv filesystem: dev: /dev/my_vg/my_lv fstype: ext4
# 继续编辑disk.yml,将my_lv挂载到/data[root@pubserver ansible]# vim disk.yml ... ... - name: mount my_lv mount: path: /data src: /dev/my_vg/my_lv fstype: ext4 state: mounted
# 完整的disk.yml如下---- name: disk manage hosts: web1 tasks: - name: create a partition parted: device: /dev/vdc number: 1 state: present part_end: 1GiB
- name: add a new partition parted: device: /dev/vdc number: 2 state: present part_start: 1GiB part_end: 6GiB
- name: create my_vg lvg: vg: my_vg pvs: /dev/vdc1,/dev/vdc2
- name: create my_lv lvol: vg: my_vg lv: my_lv size: 1G - name: mkfs my_lv filesystem: dev: /dev/my_vg/my_lv fstype: ext4
- name: mount my_lv mount: path: /data src: /dev/my_vg/my_lv fstype: ext4 state: mounted知识点思维导图:https://flowus.cn/share/7875c0e1-ebbd-4dad-aa7e-f40e6ed6c6d3
playbook
模块
xxxxxxxxxx# 在webservers组中的主机上,安装httpd、php、php-mysqlnd[root@pubserver ansible]# vim pkg.yml---- name: install pkgs hosts: webservers tasks: - name: install web pkgs # 此任务通过yum安装三个包 yum: name: httpd,php,php-mysqlnd state: present# 安装多个软件包,还可以写为:---- name: install pkgs hosts: webservers tasks: - name: install web pkgs yum: name: [httpd,php,php-mysqlnd] state: present
# 安装多个软件包,还可以写为:---- name: install pkgs hosts: webservers tasks: - name: install web pkgs yum: name: - httpd - php - php-mysqlnd state: present
# 根据功能等,可以将一系列软件放到一个组中,安装软件包组,将会把很多软件一起安装上。比如gcc、java等都是开发工具,安装开发工具包组,将会把它们一起安装。[root@node1 ~]# yum grouplist # 列出所有的软件包组[root@node1 ~]# yum groupinstall "Development Tools"# 如果列出的组名为中文,可以这样进行:[root@node1 ~]# LANG=C yum grouplist
# 继续编辑pkg.yml,在webservers组中的主机上安装Development tools组[root@pubserver ansible]# vim pkg.yml---- name: install pkgs hosts: webservers tasks: - name: install web pkgs # 此任务通过yum安装三个包 yum: name: - httpd - php - php-mysqlnd state: present
- name: install dev group # 此任务通过yum安装一组包 yum: name: "@Development Tools" # @表示后面的名字是组名 state: present
[root@pubserver ansible]# ansible-playbook pkg.yml
# 系统升级命令[root@pubserver ansible]# yum update# 继续编辑pkg.yml,在webservers组中的主机上升级所有的包到最新版本---- name: install pkgs hosts: webservers tasks: - name: install web pkgs yum: name: - httpd - php - php-mysqlnd state: present
- name: install dev group yum: name: "@Development Tools" state: present
- name: update system # 相当于yum update命令 yum: name: "*" # 表示系统已经安装的所有包 state: latest
[root@pubserver ansible]# ansible-playbook pkg.ymlansible变量
facts变量
facts翻译过来就是事实。
facts变量是ansible自带的预定义变量,用于描述被控端软硬件信息。
facts变量通过setup模块获得。
xxxxxxxxxx# 通过setup模块查看所有facts变量[root@pubserver ansible]# ansible webservers -m setupfacts变量是一个大的由
{}构成的键值对字典。在{}中,有很多层级的嵌套。可以通过参数过滤出第一个层级的内容。
xxxxxxxxxx# 查看所有的IPV4地址,filter是过滤的意思[root@pubserver ansible]# ansible webservers -m setup -a "filter=ansible_all_ipv4_addresses"
# 查看可用内存[root@pubserver ansible]# ansible webservers -m setup -a "filter=ansible_memfree_mb"常用的facts变量
ansible_all_ipv4_addresses:所有的IPV4地址
ansible_bios_version:BIOS版本信息
ansible_memtotal_mb:总内存大小
ansible_hostname:主机名
在playbook中使用变量
xxxxxxxxxx# 显示远程主机的主机名和内存大小。在ansible中,变量使用{{}}表示# debug模块用于输出信息,常用的参数是msg,用于输出指定内容[root@pubserver ansible]# vim debug.yml---- name: display host info hosts: webservers tasks: - name: display hostname and memory debug: # debug是模块,它的选项msg可以输出指定信息 msg: "hostname: {{ansible_hostname}}; mem: {{ansible_memtotal_mb}} MB"
[root@pubserver ansible]# ansible-playbook debug.yml自定义变量
引入变量,可以方便Playbook重用。比如装包的playbook,包名使用变量。多次执行playbook,只要改变变量名即可,不用编写新的playbook。
ansible支持10种以上的变量定义方式。常用的变量来源如下:
inventory变量。变量来自于主机清单文件
facts变量。
playbook变量。变量在playbook中定义。
变量文件。专门创建用于保存变量的文件。推荐变量写入单独的文件。
xxxxxxxxxx# 使用inventory变量。[root@pubserver ansible]# vim inventory[webservers]web1web2
[dbs]db1 username="wangwu" # 定义主机变量的方法
[webservers:vars] # 定义组变量的方法,:vars是固定格式username="zhaoliu"
# 通过变量创建用户[root@pubserver ansible]# vim var1.yml---- name: webservers create user hosts: webservers tasks: - name: create user user: name: "{{username}}" state: present - name: create user in dbs hosts: dbs tasks: - name: create some users user: name: "{{username}}" state: present
[root@pubserver ansible]# ansible-playbook var1.yml
# 上述两个play也可以合并为一个,如下:[root@pubserver ansible]# vim var1.yml---- name: webservers create user hosts: dbs,webservers # 指定执行的目标是webservers组和webservers组 tasks: - name: create user user: name: "{{username}}" state: present
# 在playbook中定义变量# 在webservers组中的主机上创建用户jack,他的密码是123456[root@pubserver ansible]# vim user_jack.yml---- name: create user hosts: webservers vars: # 固定格式,用于声明变量 username: "jack" # 此处引号可有可无 mima: "123456" # 此处引号是需要的,表示数字字符 tasks: - name: create some users user: name: "{{username}}" # {}出现在开头,必须有引号 state: present password: "{{mima|password_hash('sha512')}}"
[root@pubserver ansible]# ansible-playbook user_jack.yml
# 将变量定义在文件中[root@pubserver ansible]# vim vars.yml # 文件名自定义---yonghu: rosemima: abcd[root@pubserver ansible]# vim user_rose.yml ---- name: create user hosts: webservers vars_files: vars.yml # vars_files用于声明变量文件 tasks: - name: create some users user: name: "{{yonghu}}" # 这里的变量来自于vars.yml state: present password: "{{mima|password_hash('sha512')}}"
[root@pubserver ansible]# ansible-playbook user_rose.yml 补充模块
firewalld模块
用于配置防火墙的模块
常用选项:
port:声明端口
permanent:永久生效,但不会立即生效
immediate:立即生效,临时生效
state:enabled,放行;disabled拒绝
防火墙一般默认拒绝,明确写入允许的服务。
有一些服务有名字,有些服务没有名字。但是最终都是基于TCP或UDP的某些端口。比如http服务基于TCP80端口。服务名和端口号对应关系的说明文件是:
/etc/services配置服务器的防火墙,一般来说只要配置开放哪些服务或端口即可。没有明确开放的,都默认拒绝。
应用
在webservers组中的主机上安装并启动nginx
客户端访问服务器的nginx服务
在webservers组中的主机上安装并启动firewalld
客户端访问服务器的nginx服务
在webservers组中的主机上开放nginx服务
xxxxxxxxxx# 配置nginx服务[root@pubserver ansible]# vim firewall.yml---- name: configure webservers hosts: webservers tasks: - name: install nginx pkg # 这里通过yum模块装httpd yum: name: nginx state: present
- name: start nginx service # 这里通过service模块启httpd服务 service: name: nginx state: started enabled: yes [root@pubserver ansible]# ansible-playbook firewall.yml[root@pubserver ansible]# curl http://192.168.88.11/ # 可访问
# 安装并启动firewalld[root@pubserver ansible]# vim firewall.yml---- name: configure webservers hosts: webservers tasks: - name: install nginx pkg # 这里通过yum模块装httpd yum: name: nginx state: present
- name: start nginx service # 这里通过service模块启httpd服务 service: name: nginx state: started enabled: yes - name: install firewalld pkg # 这里通过yum模块装firewalld yum: name: firewalld state: present
- name: start firewalld service # 这里通过service模块启firewalld服务 service: name: firewalld state: started enabled: yes [root@pubserver ansible]# ansible-playbook firewall.yml[root@pubserver ansible]# curl http://192.168.88.11/ # 被拒绝curl: (7) Failed to connect to 192.168.88.11 port 80: 没有到主机的路由
# 配置防火墙规则,放行http协议[root@pubserver ansible]# vim firewall.yml---- name: configure webservers hosts: webservers tasks: - name: install nginx pkg # 这里通过yum模块装httpd yum: name: nginx state: present
- name: start nginx service # 这里通过service模块启httpd服务 service: name: nginx state: started enabled: yes - name: install firewalld pkg # 这里通过yum模块安装firewalld yum: name: firewalld state: present
- name: start firewalld service # 这里通过service模块启service服务 service: name: firewalld state: started enabled: yes - name: set firewalld rules # 通过firewalld模块开放80端口 firewalld: port: 80/tcp permanent: yes immediate: yes state: enabled
[root@pubserver ansible]# ansible-playbook firewall.yml [root@pubserver ansible]# curl http://192.168.88.11/ # 可访问template模块
copy模块可以上传文件,但是文件内容固定
template模块可以上传具有特定格式的文件(如文件中包含变量)
当远程主机接收到文件之后,文件中的变量将会变成具体的值
template模块上传的文件,使用的语法叫Jinja2。
常用选项:
src:要上传的文件
dest:目标文件路径
xxxxxxxxxx# 使用template模块将含有变量的文件上传到webservers组中的主机[root@pubserver ansible]# vim index.htmlWelcome to {{ansible_hostname}} on {{ansible_eth0.ipv4.address}}
[root@pubserver ansible]# vim templ.yml---- name: upload index hosts: webservers tasks: - name: create web index template: src: index.html dest: /usr/share/nginx/html/index.html
[root@pubserver ansible]# ansible-playbook templ.yml[root@pubserver ansible]# curl http://192.168.88.11/Welcome to web1 on 192.168.88.11[root@pubserver ansible]# curl http://192.168.88.12Welcome to web2 on 192.168.88.12[root@web1 ~]# cat /usr/share/nginx/html/index.htmlWelcome to web1 on 192.168.88.11[root@web2 ~]# cat /usr/share/nginx/html/index.htmlWelcome to web2 on 192.168.88.12进阶语法
错误处理
当Playbook中包含很多任务时,当某一个任务遇到错误,它将崩溃,终止执行
xxxxxxxxxx# 在webservers组中的主机上启动mysqld服务,然后创建/tmp/service.txt# 因为目标主机上没有mysqld服务,所以它将崩溃,终止执行。即,不会创建/tmp/service.txt文件[root@pubserver ansible]# vim myerr.yml---- name: my errors hosts: webservers tasks: - name: start mysqld service # 通过service模块启动mysqld服务 service: name: mysqld state: started enabled: yes - name: touch a file # 通过file模块创建文件 file: path: /tmp/service.txt state: touch
# 执行playbook,第1个任务就会失败[root@pubserver ansible]# ansible-playbook myerr.yml# 到node1上查看,因为第2个任务没有执行,所以文件不会创建[root@web1 ~]# ls /tmp/service.txtls: cannot access '/tmp/service.txt': No such file or directory可以指定某一个任务如果出现错误,则忽略它
xxxxxxxxxx# 编辑myerr.yml,如果myslqd服务无法启动,则忽略它[root@pubserver ansible]# vim myerr.yml---- name: my errors hosts: webservers tasks: - name: start mysqld service service: name: mysqld state: started enabled: yes ignore_errors: yes # 即使这个任务失败了,也要继续执行下去
- name: touch a file file: path: /tmp/service.txt state: touch
[root@pubserver ansible]# ansible-playbook myerr.yml[root@web1 ~]# ls /tmp/service.txt # 第2个任务已执行/tmp/service.txt通过全局设置,无论哪个任务出现问题,都要忽略
xxxxxxxxxx[root@pubserver ansible]# vim myerr.yml---- name: my errors hosts: webservers ignore_errors: yes tasks: - name: start mysqld service service: name: mysqld state: started enabled: yes
- name: touch a file file: path: /tmp/mysql.txt state: touch
[root@pubserver ansible]# ansible-playbook myerr.yml[root@web1 ~]# ls /tmp/mysql.txt /tmp/mysql.txt触发执行任务
通过handlers定义触发执行的任务
handlers中定义的任务,不是一定会执行的
在tasks中定义的任务,通过notify关键通知handlers中的哪个任务要执行
只有tasks中的任务状态是changed才会进行通知。
xxxxxxxxxx# 下载web1上的/etc/nginx/nginx.conf[root@pubserver ansible]# vim get_conf.yml---- name: download nginx.conf hosts: web1 tasks: - name: get nginx.conf fetch: src: /etc/nginx/nginx.conf dest: ./ flat: yes # 直接下载文件,不要目录[root@pubserver ansible]# ansible-playbook get_conf.yml
# 修改nginx.conf的端口为变量[root@pubserver ansible]# vim +39 nginx.conf... ... server { listen {{http_port}} default_server; listen [::]:{{http_port}} default_server; server_name _;... ...
# 修改nginx服务的端口为8000,重启nginx[root@pubserver ansible]# vim trigger.yml---- name: configure nginx hosts: webservers vars: http_port: "8000" # 定义nginx.conf中的变量和值 tasks: - name: upload nginx.conf # 上传nginx.conf template: src: ./nginx.conf dest: /etc/nginx/nginx.conf
- name: restart nginx # 重启服务 service: name: nginx state: restarted# 第一次执行trigger.yml,上传文件和重启服务两个任务的状态都是黄色changed[root@pubserver ansible]# ansible-playbook trigger.yml# 第二次执行trigger.yml,上传文件的任务状态是绿色的ok,重启服务任务的状态是黄色changed[root@pubserver ansible]# ansible-playbook trigger.yml
# 既然配置文件没有改变,那么服务就不应该重启# 修改Playbook,只有配置文件变化了,才重启服务[root@pubserver ansible]# vim trigger.yml---- name: configure nginx hosts: webservers vars: http_port: "80" tasks: - name: upload nginx.conf template: src: ./nginx.conf dest: /etc/nginx/nginx.conf notify: restart nginx # 通知restart httpd需要执行
handlers: - name: restart nginx service: name: nginx state: restarted# 第一次运行Playbook,因为第1个任务是黄色的changed,所以handlers中的任务也被触发执行[root@pubserver ansible]# ansible-playbook trigger.yml # 第二次运行Playbook,因为第1个任务是绿色的OK,也就不会再触发执行其他任务了[root@pubserver ansible]# ansible-playbook trigger.yml when条件
只有满足某一条件时,才执行任务
常用的操作符:
\==:相等
!=:不等
>:大于<:小于<=:小于等于>=:大于等于
多个条件或以使用and或or进行连接
when表达式中的变量,可以不使用
{{}}
xxxxxxxxxx# 当dbs组中的主机内存大于2G的时候,才安装mysql-server[root@pubserver ansible]# vim when1.yml---- name: install mysql-server hosts: dbs tasks: - name: install mysql-server pkg yum: name: mysql-server state: present when: ansible_memtotal_mb>2048
# 如果目标主机没有2GB内存,则不会安装mysqld-server[root@pubserver ansible]# ansible-playbook when1.yml
# 多条件。系统发行版是Rocky8才执行任务# /etc/motd中的内容,将会在用户登陆时显示在屏幕上[root@pubserver ansible]# vim motd _____________< hello world > ------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
[root@pubserver ansible]# vim when2.yml---- name: when condition hosts: webservers tasks: - name: modify /etc/motd copy: dest: /etc/motd src: motd when: > # 以下三行合并成一行 ansible_distribution == "Rocky" and ansible_distribution_major_version == "8"
[root@pubserver ansible]# ansible-playbook when2.ymlregitster注册变量
Ansible的“register”模块是用于捕获和保存任务执行结果的,它允许将其他任务的输出作为变量使用。register是一个关键字,可以将任务执行的结果赋值给指定的变量名称。这个变量可以在后续任务中使用。 register模块可以捕获各种类型的输出,包括stdout、stderr、rc、changed等。它可以与其他模块一起使用,例如“when”条件、“loop”循环等。
xxxxxxxxxx# 在web1组的主机上执行任务,创建/tmp/regfile1.txt,并打印创建结果[root@pubserver ansible]# vim reg1.yml---- name: create file /tmp/regfile1.txt hosts: web1 tasks: - name: create file file: path: /tmp/rgefile1.txt state: touch register: result
- name: display output debug: msg: "{{result}}"
# 在web1主机上执行任务,创建文件/tmp/ademo/abc。如果创建不成功,则通过debug输出create failed[root@pubserver ansible]# vim reg2.yml---- name: create file /tmp/ademo/abc hosts: web1 ignore_errors: yes tasks: - name: create file file: path: /tmp/ademo/abc state: touch register: result
- name: debug output debug: msg: "create failed" when: result.failed
cowsay:
xxxxxxxxxx# cowsay是一个软件,可以在以下地址获得# https://rpmfind.net/linux/epel/8/Everything/x86_64/Packages/c/cowsay-3.04-16.el8.noarch.rpm# 使用方式如下:[root@pubserver ansible]# yum install -y /root/cowsay-3.04-16.el8.noarch.rpm[root@pubserver ansible]# cowsay ni hao a__________< ni hao a >----------\ ^__^\ (oo)\_______(__)\ )\/\||----w ||| ||# 查看其他形象[root@pubserver ansible]# cowsay -lCow files in /usr/share/cowsay:beavis.zen blowfish bud-frogs bunny cheese cower default dragondragon-and-cow elephant elephant-in-snake eyes flaming-sheep foxghostbusters head-in hellokitty kiss kitty koala kosh luke-koalamech-and-cow meow milk moofasa moose mutilated ren sheep skeleton smallstegosaurus stimpy supermilker surgery telebears three-eyes turkey turtletux udder vader vader-koala www[root@pubserver ansible]# cowsay -f elephant are you ok?_____________< are you ok? >-------------\ /\ ___ /\\ // \/ \/ \\(( O O ))\\ / \ //\/ | | \/| | | || | | || o || | | ||m| |m|# 如果执行playbook时也会出现奶牛,则可以使用以下方式取消[root@pubserver ansible]# echo 'nocows = 1' >> ansible.cfg
知识点思维导图:https://flowus.cn/share/7875c0e1-ebbd-4dad-aa7e-f40e6ed6c6d3
任务块
可以通过block关键字,将多个任务组合到一起
可以将整个block任务组,一起控制是否要执行
xxxxxxxxxx# 如果webservers组中的主机系统发行版是Rocky,则安装并启动nginx[root@pubserver ansible]# vim block1.yml---- name: block tasks hosts: webservers tasks: - name: define a group of tasks block: - name: install nginx # 通过yum安装nginx yum: name: nginx state: present
- name: start nginx # 通过service启动nginx服务 service: name: nginx state: started enabled: yes
when: ansible_distribution=="Rocky" # 条件为真才会执行上面的任务
[root@pubserver ansible]# ansible-playbook block1.ymlrescue和always
block和rescue、always联合使用:
block中的任务都成功,rescue中的任务不执行
block中的任务出现失败(failed),rescue中的任务执行
block中的任务不管怎么样,always中的任务总是执行
xxxxxxxxxx[root@pubserver ansible]# vim block2.yml---- name: block test hosts: webservers tasks: - name: block / rescue / always test1 block: - name: touch a file file: path: /tmp/test1.txt state: touch rescue: - name: touch file test2.txt file: path: /tmp/test2.txt state: touch always: - name: touch file test3.txt file: path: /tmp/test3.txt state: touch
# 执行playbook web1上将会出现/tmp/test1.txt和/tmp/test3.txt[root@pubserver ansible]# ansible-playbook block2.yml[root@web1 ~]# ls /tmp/test*.txt/tmp/test1.txt /tmp/test3.txt
# 修改上面的playbook,使block中的任务出错[root@web1 ~]# rm -f /tmp/test*.txt[root@pubserver ansible]# vim block2.yml---- name: block test hosts: webservers tasks: - name: block / rescue / always test1 block: - name: touch a file file: path: /tmp/abcd/test11.txt state: touch rescue: - name: touch file test22.txt file: path: /tmp/test22.txt state: touch always: - name: touch file test33.txt file: path: /tmp/test33.txt state: touch# 因为web1上没有/tmp/abcd目录,所以block中的任务失败。但是playbook不再崩溃,而是执行rescue中的任务。always中的任务总是执行[root@pubserver ansible]# ansible-playbook block2.yml[root@web1 ~]# ls /tmp/test*.txt/tmp/test22.txt /tmp/test33.txtloop循环
相当于shell中for循环
ansible中循环用到的变量名是固定的,叫item
xxxxxxxxxx# 在test组中的主机上创建5个目录/tmp/{aaa,bbb,ccc,ddd,eee}[root@pubserver ansible]# vim loop1.yml---- name: use loop hosts: webservers tasks: - name: create directory file: path: /tmp/{{item}} state: directory loop: [aaa,bbb,ccc,ddd,eee]
# 上面写法,也可以改为:---- name: use loop hosts: webservers tasks: - name: create directory file: path: /tmp/{{item}} state: directory loop: - aaa - bbb - ccc - ddd - eee
[root@pubserver ansible]# ansible-playbook loop1.yml
# 使用复杂变量。创建zhangsan用户,密码是123;创建lisi用户,密码是456# item是固定的,用于表示循环中的变量# 循环时,loop中每个-后面的内容作为一个整体赋值给item。# loop中{}中的内容是自己定义的,写法为key:val# 取值时使用句点表示。如下例中取出用户名就是{{item.uname}}[root@pubserver ansible]# vim loop_user.yml---- name: create users hosts: webservers tasks: - name: create multiple users user: name: "{{item.uname}}" password: "{{item.upass|password_hash('sha512')}}" loop: - {"uname": "zhangsan", "upass": "123"} - {"uname": "lisi", "upass": "456"}[root@pubserver ansible]# ansible-playbook loop_user.ymlrole角色
为了实现playbook重用,可以使用role角色
角色role相当于把任务打散,放到不同的目录中
再把一些固定的值,如用户名、软件包、服务等,用变量来表示
role角色定义好之后,可以在其他playbook中直接调用
xxxxxxxxxx# 使用常规playbook,修改/etc/motd的内容# 1. 创建motd模板文件[root@pubserver ansible]# vim motdHostname: {{ansible_hostname}} # facts变量,主机名Date: {{ansible_date_time.date}} # facts变量,日期Contact to: {{admin}} # 自定义变量
# 2. 编写playbook[root@pubserver ansible]# vim motd.yml---- name: modifty /etc/motd hosts: webservers vars: admin: root@tedu.cn # 自定义名为admin的变量 tasks: - name: modify motd template: src: motd dest: /etc/motd
[root@pubserver ansible]# ansible-playbook motd.yml[root@web1 ~]# cat /etc/motd Hostname: web1Date: 2021-11-01Contact to: root@tedu.cn
# 创建角色# 1. 声明角色存放的位置[root@pubserver ansible]# vim ansible.cfg [defaults]inventory = hostsroles_path = roles # 定义角色存在当前目录的roles子目录中
# 2. 创建角色目录[root@pubserver ansible]# mkdir roles
# 3. 创建名为motd的角色[root@pubserver ansible]# ansible-galaxy init roles/motd[root@pubserver ansible]# ls roles/motd # 生成了motd角色目录[root@pubserver ansible]# yum install -y tree[root@pubserver ansible]# tree roles/motd/roles/motd/├── defaults # 定义变量的目录,优先级最低│ └── main.yml├── files # 保存上传的文件(如copy模块用到的文件)├── handlers # handlers任务写到这个目录的main.yml中│ └── main.yml├── meta # 保存说明数据,如角色作者、版本等│ └── main.yml├── README.md # 保存角色如何使用之类的说明├── tasks # 保存任务│ └── main.yml├── templates # 保存template模块上传的模板文件├── tests # 保存测试用的playbook。可选│ ├── inventory│ └── test.yml└── vars # 定义变量的位置,推荐使用的位置 └── main.yml
# 4. 将不同的内容分别写到对应目录的main.yml中# 4.1 创建motd模板文件[root@pubserver ansible]# vim roles/motd/templates/motdHostname: {{ansible_hostname}}Date: {{ansible_date_time.date}}Contact to: {{admin}}
# 4.2 创建变量[root@pubserver ansible]# vim roles/motd/vars/main.yml # 追加一行admin: zzg@tedu.cn
# 4.3 创建任务[root@pubserver ansible]# vim roles/motd/tasks/main.yml # 追加- name: modify motd template: src: motd # 这里的文件,自动到templates目录下查找 dest: /etc/motd
# 5. 创建playbook,调用motd角色[root@pubserver ansible]# vim role_motd.yml---- name: modify motd with role hosts: webservers roles: - motd
# 6. 执行playbook[root@pubserver ansible]# ansible-playbook role_motd.yml role练习
创建名为pkgs的角色。用于装包。包名使用变量pkg代表
创建inst_nginx.yml,调用pkgs角色,安装nginx
创建inst_mysql.yml,调用pkgs角色,安装mysql
xxxxxxxxxx# 1. 创建名为pkgs的角色。# 1.1 创建角色目录[root@pubserver ansible]# ansible-galaxy init roles/pkgs# 1.2 创建装包的任务,包名使用变量pkg代表[root@pubserver ansible]# vim roles/pkgs/tasks/main.yml ---# tasks file for roles/pkgs- name: install rpm pkg yum: name: "{{pkg}}" state: present# 1.3 定义变量[root@pubserver ansible]# vim roles/pkgs/defaults/main.yml ---# defaults file for roles/pkgspkg: nginx
# 2. 创建inst_nginx.yml,调用pkgs角色,安装nginx[root@pubserver ansible]# vim inst_nginx.yml---- name: install nginx pkg hosts: webservers roles: - pkgs[root@pubserver ansible]# ansible-playbook inst_nginx.yml
# 3. 创建inst_mysql.yml,调用pkgs角色,安装mysql-server[root@pubserver ansible]# vim inst_mysql.yml ---- name: install mysql pkg hosts: dbs vars: pkg: mysql-server roles: - pkgs[root@pubserver ansible]# ansible-playbook inst_mysql.ymlansible的公共角色仓库:https://galaxy.ansible.com/
xxxxxxxxxx# 在公共仓库中搜索与nginx相关的角色[root@myhost ~]# ansible-galaxy search nginx# 如果找到相应的角色,如名字为mynginx,可以下载它到roles目录[root@myhost ~]# ansible-galaxy install mynginx -p roles/ansible加解密文件
ansible加解密文件使用ansible-vault命令
xxxxxxxxxx[root@pubserver ansible]# echo "Hi ni hao" > hello.txt [root@pubserver ansible]# cat hello.txtHi ni hao
# 加密文件[root@pubserver ansible]# ansible-vault encrypt hello.txtNew Vault password: 123456Confirm New Vault password: 123456Encryption successful[root@pubserver ansible]# cat hello.txt$ANSIBLE_VAULT;1.1;AES256373733663535663462356137313965666465333933613861313136323065636333363339633734656164323461356130303863633964393339363738653036310a666564313832316263393061616330323731333231623538643164353664393862666166613739363635633736343563653266373361656336636230366564650a3832396362306236333565656234613264313936346566663063306635336235
# 解密[root@pubserver ansible]# ansible-vault decrypt hello.txtVault password: 123456Decryption successful[root@pubserver ansible]# cat hello.txt Hi ni hao
# 加密后更改密码[root@pubserver ansible]# ansible-vault encrypt hello.txt New Vault password: 123456Confirm New Vault password: 123456Encryption successful
[root@pubserver ansible]# ansible-vault rekey hello.txt # 改密码Vault password: 123456 # 旧密码New Vault password: abcd # 新密码Confirm New Vault password: abcdRekey successful
# 不解密文件,查看内容[root@pubserver ansible]# ansible-vault view hello.txt Vault password: abcdHi ni hao
# 使用密码文件进行加解密# 1. 将密码写入文件[root@pubserver ansible]# echo 'tedu.cn' > pass.txt# 2. 创建明文文件[root@pubserver ansible]# echo 'hello world' > data.txt# 3. 使用pass.txt中的内容作为密码加密文件[root@pubserver ansible]# ansible-vault encrypt --vault-id=pass.txt data.txtEncryption successful[root@pubserver ansible]# cat data.txt # 文件已加密# 4. 使用pass.txt中的内容作为密码解密文件[root@pubserver ansible]# ansible-vault decrypt --vault-id=pass.txt data.txtDecryption successful[root@pubserver ansible]# cat data.txt hello world使用ansible管理远程主机,存储敏感数据时(如,文件中包含密码),应该将其加密
执行playbook时,通过
--ask-vault-password选项提示输入密码
xxxxxxxxxx# 1. 编写有密码的playbook[root@pubserver ansible]# vim user_zhangsan.yml---- name: create a user hosts: webservers tasks: - name: create user zhangsan user: name: zhangsan password: "{{'123'|password_hash('sha512')}}"
# 2. 加密playbook[root@pubserver ansible]# ansible-vault encrypt user_zhangsan.ymlNew Vault password: 123456Confirm New Vault password: 123456Encryption successful
# 3. 直接执行playbook,报错[root@pubserver ansible]# ansible-playbook user_zhangsan.ymlERROR! Attempting to decrypt but no vault secrets found
# 4. 使用--ask-vault-password选项[root@pubserver ansible]# ansible-playbook --ask-vault-password user_zhangsan.ymlVault password: 123456
sudo命令
一般用于普通用户执行需要root权限的命令
在web1上配置zhangsan拥有sudo权限
xxxxxxxxxx# 如果没有zhangsan,手工创建[root@web1 ~]# visudo # 将会打开vi,在尾部追加以下一行zhangsan ALL=(ALL) ALL# 中间的ALL=(ALL)在集中认证的域环境中才有效,单机忽略即可# zhangsan是用户名,最后的ALL表示zhangsan可以以管理员的身份执行所有命令
# 切换成zhangsan用户,执行命令[root@web1 ~]# su - zhangsan[zhangsan@web1 ~]$ useradd wangwu # 失败,因为还是张三身份[zhangsan@web1 ~]$ sudo useradd wangwu # 以管理员身份执行... ...[sudo] password for zhangsan: # 输入zhangsan的密码,不是root
# 配置lisi不输入密码可以直接运行sudo[root@web1 ~]# visudo # 在最后追加一行lisi ALL=(ALL) NOPASSWD: ALL
# 切换成lisi运行[root@web1 ~]# su - lisi[lisi@web1 ~]$ ls /root/ # 没权限ls: cannot open directory '/root/': Permission denied[lisi@web1 ~]$ sudo ls /root/ # 成功运行,无需输入密码a3.txt anaconda-ks.cfg特殊的主机清单变量
如果远程主机没有使用免密登陆,如果远程主机ssh不是标准的22端口,可以设置特殊的主机清单变量
ansible_ssh_user:指定登陆远程主机的用户名ansible_ssh_pass:指定登陆远程主机的密码ansible_ssh_port:指定登陆远程主机的端口号
xxxxxxxxxx# 删除远程主机的/root/.ssh/authorized_keys,以便恢复通过密码登陆[root@pubserver ansible]# ansible all -m file -a "path=/root/.ssh/authorized_keys state=absent"
# 创建新的工作目录[root@pubserver ~]# mkdir myansible[root@pubserver ~]# cd myansible[root@pubserver myansible]# vim ansible.cfg[defaults]inventory = inventory[root@pubserver myansible]# vim inventory[group1]web1web2db1[root@pubserver myansible]# ansible all -m ping # 报错,因为无法免密执行
# 修改web1 ssh服务的端口为220[root@web1 ~]# systemctl stop firewalld[root@web1 ~]# echo 'Port 220' >> /etc/ssh/sshd_config[root@web1 ~]# systemctl restart sshd# 退出再登陆时,需要指定端口号[root@myhost ~]# ssh -p220 192.168.88.11
# 配置ssh通过用户名、密码管理远程主机,通过220端口连接web1[root@pubserver myansible]# vim inventory [group1]web1 ansible_ssh_user=root ansible_ssh_pass=a ansible_ssh_port=220web2 ansible_ssh_user=root ansible_ssh_pass=adb1 ansible_ssh_user=root ansible_ssh_pass=a
[root@pubserver myansible]# ansible all -m ping知识点思维导图:https://flowus.cn/share/7875c0e1-ebbd-4dad-aa7e-f40e6ed6c6d3