- 依赖
- ansible-6.3.0-1.el8.noarch
ansible-core-2.13.3-1.el8.x86_64
git-core-2.31.1-2.el8.x86_64
- python3-jmespath-0.9.0-11.el8.noarch
python39-3.9.7-1.module+el8.6.0+795+de4edbcc.x86_64
python39-cffi-1.14.3-2.module+el8.4.0+574+843c4898.x86_64
- python39-cryptography-3.3.1-2.module+el8.5.0+673+10283621.x86_64
python39-idna-2.10-3.module+el8.4.0+574+843c4898.noarch
python39-libs-3.9.7-1.module+el8.6.0+795+de4edbcc.x86_64
- python39-pip-20.2.4-7.module+el8.6.0+795+de4edbcc.noarch python39-pip-wheel-20.2.4-7.module+el8.6.0+795+de4edbcc.noarch python39-ply-3.11-10.module+el8.4.0+574+843c4898.noarch
- python39-pycparser-2.20-3.module+el8.4.0+574+843c4898.noarch python39-pyyaml-5.4.1-1.module+el8.5.0+673+10283621.x86_64 python39-setuptools-50.3.2-4.module+el8.5.0+673+10283621.noarch
- python39-setuptools-wheel-50.3.2-4.module+el8.5.0+673+10283621.noarch python39-six-1.15.0-3.module+el8.4.0+574+843c4898.noarch sshpass-1.09-4.el8.x86_64
### 免密登入
# 配置名称解析
[root@pubserver ~]# echo -e "192.168.88.240\tpubserver" >> /etc/hosts
[root@pubserver ~]# for i in 1 2
> do
> echo -e "192.168.88.1$i\tweb$i" >> /etc/hosts
> done
[root@pubserver ~]# echo -e "192.168.88.13\tdb1" >> /etc/hosts
[root@pubserver ~]# tail -4 /etc/hosts
192.168.88.240 pubserver
192.168.88.11 web1
192.168.88.12 web2
192.168.88.13 db1
# 配置免密登陆
[root@pubserver ~]# ssh-keygen # 三个问题都直接回车,使用默认值
# 执行以下命令时,可能需要回答yes和远程用户的密码,请按提示操作
[root@pubserver ~]# for i in web{1..2} db1
> do
> ssh-copy-id $i
> done
## ansible管理环境
使用一套ansible软件,有可能需要管理多种环境。如在同一台管理主机上管理开发环境和生产环境。
通过创建不同的工作目录,来实现相应的管理需求。
将某一环境下的主机写入到对应工作目录的主机清单文件。
进入对应的工作目录执行管理任务,就可以管理相应环境的主机。
### 工作目录
- 配置文件
- 创建配置文件。默认的配置文件是/etc/ansible/ansible.cfg,但是一般不使用它,而是在工作目录下创建自己的配置文件ansible.cfg
[defaults]
host_key_checking = false # 不检查主机密钥,=号两边空格可有可无。
inventory = inventory # 定义主机清单文件为当前目录的
- 主机清单
- 创建主机清单文件inventory。写在[]里的是组名,[]下面的是组内的主机名
web[1:2] # web1和web2的简化写法,表示从1到2
[dbs]
db1
# cluster是组名,自定义的;:children是固定写法,表示下面的组名是cluster的子组。
[cluster:children]
webservers
dbs
## ansible管理方式
### adhoc #临时命令,模块化管理
ansible 主机或组列表 -m 模块 -a "参数" # -a是可选的
ansible-doc -l # 列出全部可用模块
ansible all --list-hosts # 查看被管理的所有的主机
模块的作用
在ansible中,通过模块来完成某一特定任务。
学习模块,主要知道实现某种功能,需要哪个模块。
模块的使用方式都一样。主要是查看该模块有哪些参数。
- command #默认模块,不支持管道重定向,后台进程
- shell #支持管道重定向
# 查看web1的ip地址,只显示前10行
[root@pubserver ansible]# ansible web1 -m shell -a "ip a s | head"
- script #支持脚本
原理是先上传脚本到指定主机,bash执行脚本,随后删除
# 在控制端创建脚本即可
[root@pubserver ansible]# vim test.sh
#!/bin/bash
for user in user{1..5}
do
useradd $user
echo '123456' | passwd --stdin $user
done
# 在webservers组的主机上执行脚本
[root@pubserver ansible]# ansible webservers -m script -a "test.sh"
- ping
- file #创建文件
# 在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"
- path #指定路径
- owner #指定文件/目录属主
- group #指定文件/目录属组
- mode='0755' #指定文件属性
- state
- touch #指定文件创建类型为普通文件
- directory #指定文件创建类型为目录
- link #指定文件类型为链接
- absent #删除
- src #源文件(链接)
- dest #目标文件
- copy #上传文件
[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"
- src #源,控制端
- dest #目标,被控制端
- content='hello dcc' #将内容输入到文件内,可以同时创建文件
- fetch #下载
# 将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/
hostname
- src/***/*** #源,被控制端
- dest=/root/*** #目标,控制端
- flat=yes/no #下载时会连带目录下载,falt是下载时忽略路径目录
# 下载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 # 直接下载文件,不要目录
- lineinfile #对被控制端的文件确定有某一行,注意替换时只能整行替换
# 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'"
- path #路径
- regexp=‘hello’ #匹配正则
- line ='hello dcc' #内容
- replace #对文件内容关键词替换,全文替换
# 把webservers组中主机上/etc/issue文件中的chi,替换成he
[root@pubserver ansible]# ansible webservers -m replace -a "path=/etc/issue regexp='chi' replace='he'"
- path #修改的路径
- regexp=‘hello’ #匹配正则
- replace=‘修改的内容’
- user #用户管理模块
# 在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"
- name #用户名
- uid #指定uid
- group #指定基本组
- groups #指定附加组
- password #密码
{{'123456'|password_hash('sha512')}}
- home #家目录
- state
- present
- absent
- remove #删除家目录{{慎用}}
- group #组管理
- name
- gid
- state
- present
- absent
- yum_repository #软件仓库配置文件
# 在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 = 1
baseurl = ftp://192.168.88.240/dvd/AppStream
enabled = 1
gpgcheck = 0
name = 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 = 1
baseurl = ftp://192.168.88.240/dvd/AppStream
enabled = 1
gpgcheck = 0
name = My App
[BaseOS]
async = 1
baseurl = ftp://192.168.88.240/dvd/BaseOS
enabled = 1
gpgcheck = 0
name = Base OS
- file #指定文件名(会自动添加.repo后缀)
- name #仓库唯一标识
- description #仓库描述信息
- baseurl
- enabled=yes
- gpgcheck=no
- yum #yum安装管理
# 在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"
- name #软件包名
name=nginx,httpd,firewalld
在playbook中
name: nginx,httpd,firewalld
name: [nginx,httpd,firewalld]
name:
- xxx
- xxx
- xxx
- state #状态
- present
- latest
- absent
- service #服务管理
# 在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"
- name #服务名
- state #服务状态
- started
- stopped
- restarted
- enabled=yes #是否开机自启
- 逻辑卷相关
逻辑卷可以动态管理存储空间。可以对逻辑卷进行扩容或缩减。
可以把硬盘或分区转换成物理卷PV;再把1到多个PV组合成卷组VG;然后在VG上划分逻辑卷LV。LV可以像普通分区一样,进行格式化、挂载。
关闭虚拟机web1,为其添加2块20GB的硬盘
LINUX下KVM虚拟机新加的硬盘,名称是/dev/vdb和/dev/vdc
vmware虚拟机新加的硬盘,名称是/dev/sdb和/dev/sdc
如果选nvme硬盘,名称可能是/dev/nvme0n1和/dev/nvme0n2
- parted #磁盘分区
- device #磁盘名称,vdb,vdc等
- number #第几快分区
- state
- present
- absent
- part_start #分区的起始大小
- part_end #这块分区结束大小的位置
- lvg #创建卷组
创建名为myvg的卷组,该卷组由/dev/vdb1组成
]# ansible web1 -m lvg -a "vg=myvg pvs=/dev/vdb1"
# 扩容卷组。卷组由PV构成,只要向卷组中加入新的PV,即可实现扩容
]# ansible web1 -m lvg -a "vg=myvg pvs=/dev/vdb1,/dev/vdb2"
- pvs=/dev/vdb1 #物理卷
- lv #卷组名
- lvol #逻辑卷
# 在web1上创建名为mylv的逻辑卷,大小为2GB
[root@pubserver ansible]# ansible web1 -m lvol -a "vg=myvg lv=mylv size=2G"
# mylv扩容至4GB
[root@pubserver ansible]# ansible web1 -m lvol -a "vg=myvg lv=mylv size=4G"
# 格式化后mylv扩容至4GB
[root@pubserver ansible]# ansible web1 -m lvol -a "vg=myvg lv=mylv size=4G resizefs=yes"
- lv #逻辑卷名
- vg #卷组名
- size #逻辑卷大小,单位一般用G,M,不写默认是M
- resizefs #如果逻辑卷是格式化过了的需要新增,resizefs=yes,表示需要刷新文件系统
- filesystem #文件系统/格式化
# 在web1上,把/dev/myvg/mylv格式化为xfs
[root@pubserver ansible]# ansible web1 -m filesystem -a "fstype=xfs dev=/dev/myvg/mylv"
- fstype=文件系统类型
- dev=逻辑卷设备名(/dev/卷组名/逻辑卷名或者)
- mount #挂载
# 在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"
- fstype=文件系统类型
- path #挂载目录,没有会自动创建,但不支持递归
- state
- mounted #启用永久挂载
- absent #卸载
- src #源,逻辑卷设备名
- 磁盘相关综合习题
# 在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
- setup # facts变量相关,键值对字典相关
常用的facts变量
ansible_all_ipv4_addresses:所有的IPV4地址
ansible_bios_version:BIOS版本信息
ansible_memtotal_mb:总内存大小
ansible_hostname:主机名
# 查看所有的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"
- filter=facts变量 #filter过滤
- debug #屏显输出
---
- name: display host info
hosts: webservers
tasks:
- name:
debug:
msg: "hostname: {{ansible_hostname}}; mem: {{ansible_memtotal_mb}} MB"
- msg= ‘需要输出的信息’ #屏显输出
- firewalld #防火墙相关
- name: set firewalld rules # 通过firewalld模块开放80端口
firewalld:
port: 80/tcp
permanent: yes
immediate: yes
state: enabled
- port=80/tcp #协议端口
- permanent #永久生效
- immediate #临时生效,立即生效
- state=enabled/disabled #允许或者拒绝
- template #上传变量相关文件
copy模块可以上传文件,但是文件内容固定
template模块可以上传具有特定格式的文件(如文件中包含变量)
当远程主机接收到文件之后,文件中的变量将会变成具体的值
template模块上传的文件,使用的语法叫Jinja2。
--------------------------------------------
---
- name: upload index
hosts: webservers
tasks:
- name: create web index
template:
src: index.html
dest: /usr/share/nginx/html/index.html
- src=源地址
- dest=目标地址
- systcl #修改系统内核参数
---
- name: config sysctl
hosts: lb
tasks:
- name: set ip_forward
sysctl: # 用于修改内核参数的模块
name: net.ipv4.ip_forward # 内核模块名
value: '1' # 内核模块的值
sysctl_set: yes # 立即设置生效
sysctl_file: /etc/sysctl.conf # 配置写入文件
- name: 内核参数名称 可以用sysctl -a查看对应参数
- value #内核模块布尔值 1表示启用,0 表示关闭
- systcl_set: yes #表示是否立即生效
- sysctl_file: # 配置需要写入的文件
- archive 压缩
- path
- dest ***.gz
- format=gz 压缩格式
- mode 权限
- unarchive
- src=***.gz 源
- dest 目标目录
### playbook
- yaml
YAML不是一个标记语言
- yml或yaml的语法规范
yaml文件的文件名,一般以yml或yaml作为扩展名
文件一般以---作为第一行,不是必须的,但是常用
键值对使用冒号:表示,冒号后面必须有空格。
数组使用-表示,-后面必须有空格。
相同的层级必须有相同的缩进。如果缩进不对,则有语法错误。每一级缩进,建议2个空格。
全文不能使用tab,必须使用空格。
- 修改vim适合yml语法规范
[root@pubserver ansible]# vim ~/.vimrc
set ai # 设置自动缩进
set ts=2 # 设置按tab键,缩进2个空格
set et # 将tab转换成相应个数的空格
set cursorcolumn
- 编写playbook
一个剧本(即playbook),可以包含多个play
每个play用于在指定的主机上,通过模块和参数执行相应的任务
每个play可以包含多个任务。
任务有模块和参数构成。
---
- name:
hosts: 主机组名或主机名
tasks:
- name:
模块名:
选项参数
- name:
模块名:
选项参数
- name:
hosts:
tasks:
- name:
模块名:
选项参数
- name:
模块名:
选项参数
- # 在dbs组的主机和web1上创建/tmp/demo目录,权限是0755。将控制端/etc/hosts拷贝到目标主机的/tmp/demo中
[root@pubser
[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
- # 在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
- |和>的区别:|它保留换行符,>把多行合并为一行
- # 通过copy模块创建/tmp/1.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]# vim f1.yml
---
- name: play 1
hosts: webservers
tasks:
- name: mkfile 1.txt
copy:
dest: /tmp/1.txt
content: |
Hello World!
ni hao.
- # 在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
- 执行playbook
ansible-playbook ***.yml
- 变量
格式 {{变量名}}
注意在plabook中如果变量是在开头
如:
- name:
debug:
msg: "{{ansible_hostname}}"
必须加引号,否则报错
- facts变量
- 作用及定义
facts翻译过来就是事实。
facts变量是ansible自带的预定义变量,用于描述被控端软硬件信息。
facts变量通过setup模块获得。
facts变量是一个大的由{}构成的键值对字典。在{}中,有很多层级的嵌套。可以通过参数过滤出第一个层级的内容
- 常用的facts变量
ansible_all_ipv4_addresses:所有的IPV4地址
ansible_bios_version:BIOS版本信息
ansible_memtotal_mb:总内存大小
ansible_hostname:主机名
- facts变量的查看方式
ansible web1 -m setup | less #用于查看词典
- 列题 显示远程主机的主机名和内存大小。在ansible中,变量使用{{}}表示
---
- name:
hosts: webservers
tasks:
- name:
debug:
msg: "hostname: {{ansible_hostname}}; mem: {{ansible_mentotal_mb}} MB"
- 自定义变量
- 主机清单变量 #在主机清单内建立变量
[webservers]
web1 变量名=值
web2 变量名=值
web1 ansible_host=192.168.88.240
web2 dcc='123'
[all:vars] #固定格式
变量名=值
ansible_ssh_user=root
ansible_ssh_pass=123
- playbook变量
---
- name:
hosts: webservers
vars:
username: "dcc"
pass: "123456" #注意如果值是数字需要加双引号,表示数字类型的字符
tasks:
- name:
user:
name: "{{username}}"
password: "{{pass|password_hash('sha512')}}"
state: present
- 文件变量
---
- name:
hosts:
vars_files: vars.yml
tasks:
- name:
.........
- 注册变量
---
- 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
- Ansible的“register”模块是用于捕获和保存任务执行结果的,它允许将其他任务的输出作为变量使用。register是一个关键字,可以将任务执行的结果赋值给指定的变量名称。这个变量可以在后续任务中使用。 register模块可以捕获各种类型的输出,包括stdout、stderr、rc、changed等。它可以与其他模块一起使用,例如“when”条件、“loop”循环等。
- 进阶语法
- 错误处理
- 当Playbook中包含很多任务时,当某一个任务遇到错误,它将崩溃,终止执行,我们需要忽视错误并继续执行时可以用ignore_errors: yes
- 单独任务忽视错误
- 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
- 全局错误忽视
---
- 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
- 触发任务
---
- 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
- 通过handlers定义触发执行的任务
- handlers中定义的任务,不是一定会执行的
- 在tasks中定义的任务,通过notify关键通知handlers中的哪个任务要执行
- 只有tasks中的任务状态是changed才会进行通知。
- when判断
---
- 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"
- 只有满足某一条件时,才执行任务
- 常用的操作符:
- ==:相等
- !=:不等
- >:大于
- <:小于
- <=:小于等于
- >=:大于等于
- 多个条件或以使用and或or进行连接
- when表达式中的变量,可以不使用{{}}
- 任务块
- block
- name: block tasks
hosts: webservers
tasks:
- name: define a group of tasks
block:
- name: install nginx
yum:
name: nginx
state: present
- name: start nginx
service:
name: nginx
state: started
enabled: yes
- 可以通过block关键字,将多个任务组合到一起
- 可以将整个block任务组,一起控制是否要执行
- rescue
- block中的任务都成功,rescue中的任务不执行
- block中的任务出现失败(failed),rescue中的任务执行
- always
- block中的任务不管怎么样,always中的任务总是执行
- loop循环
---
- 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
- 相当于shell中for循环
- ansible中循环用到的变量名是固定的,叫item
- 复杂循环
# 使用复杂变量。创建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"}
### 角色
- 定义及作用
为了实现playbook重用,可以使用role角色
角色role相当于把任务打散,放到不同的目录中
再把一些固定的值,如用户名、软件包、服务等,用变量来表示
role角色定义好之后,可以在其他playbook中直接调用
playbook重复调用,代码重用
- 目录
- defaults
- 定义变量目录,优先级最低
- vars
- 定义变量的目录
- files
- 储存上传文件目录,copy模块使用
- handlers
- 触发任务所在位置
- tasks
- 正常任务所在位置
- meta
- 保存数据说明,如角色作者,版本信息等
- templates
- 储存上传文件目录,template模块使用
- tests
- 保存测试用的playbook
- 角色使用流程
- 1.声明角色存储的目录
# 1. 声明角色存放的位置
[root@pubserver ansible]# vim ansible.cfg
[defaults]
inventory = hosts
roles_path = roles # 定义角色存在当前目录的roles子目录中
- 2.创建存储角色的目录
mkdir roles
- 3.在角色目录创建角色
ansible-galaxy init roles/xtt
- 4.创建变量和任务
- 5.调用角色
[root@pubserver ansible]# vim role_motd.yml
---
- name: modify motd with role
hosts: webservers
roles:
- motd
- 练习
创建名为pkgs的角色。用于装包。包名使用变量pkg代表
创建inst_nginx.yml,调用pkgs角色,安装nginx
创建inst_mysql.yml,调用pkgs角色,安装mysql
# 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/pkgs
pkg: 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.yml
### ansible加密文件
- ansible-vault encrypt hello.txt #对文件加密
- ansible-vault decrypt hello.txt #对文件解密
- ansible-vault rekey hello.txt #对文件改密
- ansible-vault view hello.txt #对文件不揭密查看
- 使用文件内容做密码
# 使用密码文件进行加解密
# 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.txt
Encryption successful
[root@pubserver ansible]# cat data.txt # 文件已加密
# 4. 使用pass.txt中的内容作为密码解密文件
[root@pubserver ansible]# ansible-vault decrypt --vault-id=pass.txt data.txt
Decryption successful
[root@pubserver ansible]# cat data.txt
hello world
### 特殊的主机清单
[root@pubserver myansible]# vim inventory
[group1]
web1 ansible_ssh_user=root ansible_ssh_pass=a ansible_ssh_port=220
web2 ansible_ssh_user=root ansible_ssh_pass=a
db1 ansible_ssh_user=root ansible_ssh_pass=a
【all:vars】
- ansible_ssh_user:指定登陆远程主机的用户名
- ansible_ssh_pass:指定登陆远程主机的密码
- ansible_ssh_port:指定登陆远程主机的端口号
*XMind - Trial Version*