Ansible
一款自动化运维工具,基于Python开发
批量系统配置
批量程序部署
批量运行命令等功能
特色:基于SSH架构,所以不需要在被管端安装任何软件
模块丰富
支持自定义模块
部署简单,容易上手
社区活跃
支持异构IT架构
配置ansible管理环境
一、软件包安装
[root@pubserver ~]# yum -y install ansible
二、配置名称解析 /etc/hosts
[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
三、配置ansible到被管机的免密登录
[root@pubserver ~]# ssh-keygen #三个问题都直接回车,使用默认值
[root@pubserver ~]# for i in web{1..2} db1
> do
> ssh-copy-id $i
> done #
四、创建工作目录
[root@pubserver ~]# mkdir ansible #创建ansible工作目录,目录名自己定义
[root@pubserver ~]# cd ansible
[root@pubserver ansible]# touch ansible.cfg inventory #创建配置文件。默认的配置文件是/etc/ansible/ansible.cfg,但是一般不使用它,而是在工作目录下创建自己的配置文件
[root@pubserver ansible]# vim ansible.cfg #文件名必须是ansible.cfg
[defaults]
inventory = inventory #定义主机清单文件为当前目录的inventory
host_key_checking = false #不检查主机密钥,=号两边空格可有可无
[root@pubserver ansible]# vim inventory #创建主机清单文件。写在[]里的是组名,[]下面的是组内的主机名
[webservers]
web[1:2] #web1和web2的简化写法,表示从1到2
[dbs]
db1
[cluster:children] #cluster是组名,自定义的;children是固定写法,表示下面的组名是cluster的子组
webservers
dbs
[root@pubserver ansible]# ansible all --list-hosts #查看被管理的所有主机。注意:一定在工作目录下执行命令
hosts (3):
web1
web2
db1
[root@pubserver ansible]# ansible webservers --list-hosts #查看webservers组中所有的主机
hosts (2):
web1
web2
ansible进行远程管理的两个方法
无论哪种方式,都是通过模块加参数进行管理。
一、adhoc临时命令。就是在命令行上执行管理命令。
语法:
ansible 主机或组列表 -m 模块 -a "参数"
帮助指令:
[root@pubserver ansible]# ansible-doc -l #列出全部可用模块
[root@pubserver ansible]# ansible-doc -l | grep yum #查看包含yum的模块名
[root@pubserver ansible]# ansible-doc yum #查看yum模块的帮助文档
ping模块
通过ping模块测试到远程主机的连通性
[root@pubserver ansible]# ansible all -m ping
该命令检查是否可以管理远程主机。如果结果为绿色的SUCCESS,则表示成功。
如果是红色的UNREACHABLE,则检查网络是否可通,是否已经可以免密登录。
command模块
ansible默认模块,用于在远程主机上执行任意命令
command不支持shell特性,如管道、重定向
[root@pubserver ansible]# ansible all -m command -a "mkdir /tmp/demo"
[root@pubserver ansible]# ansible web1 -a "ip a s"
[root@pubserver ansible]# ansible web1 -a "ip a s | head" #报错
shell模块
与command模块类似,但是支持shell特性,如管道、重定向
[root@pubserver ansible]# ansible web1 -m shell -a "ip a s | head" #成功
script模块
用于在远程主机上执行脚本
[root@pubserver ansible]# vim test.sh #在控制端创建脚本即可
#!/bin/bash
for user in user{1..5}
do
useradd $user
echo '123456' | passwd --stdin $user
done
[root@pubserver ansible]# ansible webservers -m script -a "test.sh" #在webservers组的主机上执行脚本
file模块
可以创建文件、目录、链接等,还可以修改权限、属性等
常用的选项:
path:指定文件路径
owner:设置文件所有者
group:设置文件所属组
state:状态。touch表示创建文件,directory表示创建目录,link表示创建软链接,absent表示删除
mode:设置权限
src:source的简写,源
dest:destination的简写,目标
[root@pubserver ansible]# ansible-doc file #查看使用帮助
[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/file.txt state=touch" #touch是指如果文件不存在则创建;如果存在则改变它的时间戳
[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/demo state=directory" #在webservers组的主机上创建/tmp/demo目录
[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/file.txt owner=sshd group=adm mode='0777'" #将webservers组的主机上/tmp/file.txt的属主改为sshd,属组改为adm,权限改为0777
[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/file.txt state=absent" #删除webservers组的主机上/tmp/file.txt
[root@pubserver ansible]# ansible webservers -m file -a "path=/tmp/demo state=absent" #删除webservers组的主机上/tmp/demo
[root@pubserver ansible]# ansible webservers -m file -a "src=/etc/hosts dest=/tmp/hosts.txt state=link" #在webservers组的主机上创建/etc/hosts的软链接,目标是/tmp/hosts.txt
copy模块
用于将文件从控制端拷贝到被控端
可以上传目录,但不能上传空目录
常用选项:
src:源。控制端的文件路径
dest:目标。被控端的文件路径
content:内容。需要写到文件中的内容
[root@pubserver ansible]# echo AAA > test.txt
[root@pubserver ansible]# ansible webservers -m copy -a "src=test.txt dest=/root"
[root@pubserver ansible]# ansible webservers -m copy -a "dest=/tmp/mytest.txt content='Hello World\n'"
fetch模块
与copy模块相反,copy是上传,fetch是下载
不能下载目录
常用选项:
src:源。被控制端的文件路径
dest:目标。控制端的文件路径
[root@pubserver ansible]# ansible webservers -m fetch -a "src=/etc/hostname dest=/root"
lineinfile模块
用于确保目标文件中有某一行内容
常用选项:
path:待修改的文件路径
line:写入文件的一行内容
regexp:正则表达式,用于查找文件中的内容
#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:正则表达式,用于查找文件中的内容
#把webservers组中主机上/etc/issue文件中的chi,替换成he
[root@pubserver ansible]# ansible webservers -m replace -a "path=/etc/issue regexp='chi' replace='he'"
user模块
实现linux用户管理
常用选项:
name:待创建的用户名
uid:用户ID
group:设置主组
groups:设置附加组
home:设置家目录
password:设置用户密码
state:状态。present表示创建,它是默认选项;absent表示删除
remove:删除家目录、邮箱等。值为yes或true都可以
#在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表示删除
#在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:指定文件名
#在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@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
yum模块
用于rpm软件包管理、如安装、升级、卸载
常用选项:
name:包名
state:状态。present表示安装,如果已安装则忽略;latest表示安装或升级到最新版本;absent表示卸载
#在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表示设置开机不要自启
#在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可以像普通分区一样,进行格式化、挂载
lvg模块
创建、删除卷组,修改卷组大小
常用选项:
vg:定义卷组名
pvs:由哪些物理卷构成
#在web1上安装lvm2,state不写,默认是present
[root@pubserver ansible]# ansible web1 -m yum -a "name=lvm2"
#手工在web1上对vdb进行分区
[root@web1 ~]# fdisk /dev/vdb
Command (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被分出来了两个分区
#在web1上创建名为myvg的卷组,该卷组由/dev/vdb1组成
[root@pubserver ansible]# ansible web1 -m lvg -a "vg=myvg pvs=/dev/vdb1"
#在web1上查看卷组
[root@web1 ~]# vgs
#扩容卷组。卷组由PV构成,只要向卷组中加入新的PV,即可实现扩容
[root@pubserver ansible]# ansible web1 -m lvg -a "vg=myvg pvs=/dev/vdb1,/dev/vdb2"
#在web1上查看卷组
[root@web1 ~]# vgs
lvol模块
创建、删除逻辑卷,修改逻辑卷大小
常用选项:
vg:指定在哪个卷组上创建逻辑卷
lv:创建的逻辑卷名
size:逻辑卷的大小,不写单位,以M为单位
#在web1上创建名为mylv的逻辑卷,大小为2GB
[root@pubserver ansible]# ansible web1 -m lvol -a "vg=myvg lv=mylv size=2G"
#在web1上查看逻辑卷
[root@web1 ~]# lvs
#mylv扩容至4GB
[root@pubserver ansible]# ansible web1 -m lvol -a "vg=myvg lv=mylv size=4G"
filesystem模块
用于格式化,也就是创建文件系统
常用选项:
fstype:指定文件系统类型
dev:指定要格式化的设备,可以是分区,可以是逻辑卷
#在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
mount模块
用于挂载文件系统
常用选项:
path:挂载点。如果挂载点不存在,自动创建
src:待挂载的设备
fstype:文件系统类型
state:mounted 写入自动挂载并直接挂载
#在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
[root@web1 ~]# df -h /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文件的文件名,一般以yml或yaml作为扩展名
文件一般以---作为第一行,不是必须的,但是常用
键值对使用冒号:表示,冒号后面必须有空格
数组使用-表示,-后面必须有空格
相同的层级必须有相同的缩进。如果缩进不对,则有语法错误。每一级缩进,建议2个空格
全文不能使用tab,必须使用空格
配置vim适应yaml语法
#文件位置和名字是固定的,用于设置vim的格式
[root@pubserver ansible]# cat ~/.vimrc
set ai #设置自动缩进
set et #将tab转换成相应个数的空格
set ts=2 #设置按tab键,缩进2个空格
set cursorcolumn
编写playbook
一个剧本(即playbook),可以包含多个play
每个play用于在指定的主机上,通过模块和参数执行相应的任务
每个play可以包含多个任务
任务由模块和参数构成
#编写用于测试连通性的playbook,相当于执行ansible all -m ping
[root@pubserver ansible]# cat ping.yml
---
- name: test netwok
hosts: all
tasks:
- name: test ping
ping:
[root@pubserver ansible]# ansible-playbook ping.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/
[root@pubserver ansible]# ansible-playbook fileop.yml #执行playbook
#在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\n"
[root@pubserver ansible]# ansible-playbook two.yml #执行playbook
| 和 > 的区别
| 保留换行符
> 把多行合并为一行
#通过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@web1 ~]# cat /tmp/1.txt
Hello World!
ni hao.
#通过copy模块创建/tmp/2.txt,文件中有一行内容,分别是Hello World! ni hao
[root@pubserver ansible]# vim f1.yml
---
- name: play 1
hosts: webservers
tasks:
- name: mkfile 2.txt
copy:
dest: /tmp/2.txt
content: >
Hello World!
ni hao.
[root@web1 ~]# cat /tmp/2.txt
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')}}"
#在webservers组中的主机上删除用户john
[root@pubserver ansible]# vim del_john.yml
---
- name: remove user
hosts: webservers
tasks:
- name: remove user john
user:
name: john
state: absent
硬盘管理
常用的分区表类型有:MBR(主引导记录)、GPT(GUID分区表)
MBR最多支持4个主分区,或3个主分区加1个扩展分区。最大支持2.2TB左右的硬盘
GPT最多支持128个主分区。支持大硬盘
parted模块
用于硬盘分区管理
常用选项:
device:待分区的设备
number:分区编号
state:present表示创建,absent表示删除
part_start:分区的起始位置,不写表示从开头
part_end:表示分区的结束位置,不写表示到结尾
#在web1主机上,对/dev/vdc进行分区,创建1个1GB的主分区
[root@pubserver ansible]# vim disk.yml
---
- name: disk manager
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 /dev/vdc
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的主分区
......
- 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 /dev/vdc
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构成
......
- name: create my_vg
lvg:
vg: my_vg
pvs: /dev/vdc1,/dev/vdc2
#继续编辑disk.yml,在my_vg卷组上创建名为my_lv的逻辑卷,大小1G
......
- name: create my_lv
lvol:
vg: my_vg
lv: my_lv
size: 1G
#继续编辑disk.yml,格式化my_lv为ext4
......
- name: mkfs my_lv
filesystem:
dev: /dev/my_vg/my_lv
fstype: ext4
#继续编辑disk.yml,将my_lv挂载到/data
......
- name: mount my_lv
mount:
path: /data
src: /dev/my_vg/my_lv
fstype: ext4
state: mounted
playbook 安装软件
#在webservers组中的主机上,安装httpd、php、php-mysqlnd
[root@pubserver ansible]# vim pkg.yml
---
- 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
#安装多个软件包,还可以写为:
---
- 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
ansible变量
一、facts变量
facts翻译过来就是事实
facts变量是ansible自带的预定义变量,用于描述被控端软硬件信息
facts变量通过setup模块获得
#通过setup模块查看所有facts变量
[root@pubserver ansible]# ansible webservers -m setup
facts变量是一个大的由{}
构成的键值对字典。在{}
中,有很多层级的嵌套。可以通过参数过滤出第一个层级的内容。
#查看所有的IPV4地址,filter是过滤的意思
[root@pubserver ansible]# ansible web1 -m setup -a "filter=ansible_all_ipv4_addresses"
#查看可用内存
[root@pubserver ansible]# ansible web1 -m setup -a "filter=ansible_memfree_mb"
常用的facts变量:
ansible_all_ipv4_addresses:所有的IPV4地址
ansible_bios_version:BIOS版本信息
ansible_memtotal_mb:总内存大小
ansible_hostname:主机名
在playbook中使用变量
[root@pubserver ansible]# ansible webservers -m setup | less
#在ansible中,变量使用{{}}表示
#debug模块用于输出信息,常用的参数是msg,用于输出指定内容
[root@pubserver ansible]# vim debug.yml
---
- name: display host info
hosts: webservers
tasks:
- name: display host info
debug:
msg: "hostname:{{ansible_hostname}},mem:{{ansible_memtotal_mb}}MB,IP:{{ansible_eth0.ipv4.address}},vda1 size{{ansible_devices.vda.partitions.vda1.size}}"
二、自定义变量
引入变量,可以方便playbook重用。比如装包的playbook,包名使用变量。多次执行playbook,只要改变变量名即可,不用编写新的playbook
ansible支持10种以上的变量定义方式。常用的变量来源如下:
inventory变量。变量来自于主机清单文件
facts变量。
playbook变量。变量在playbook中定义。
变量文件。专门创建用于保存变量的文件。推荐变量写入单独的文件。
#使用inventory变量。
[root@pubserver ansible]# vim inventory
[webservers]
web1
web2
[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
#上述两个play也可以合并为一个,如下:
[root@pubserver ansible]# vim var1.yml
---
- name: webservers create user
hosts: dbs,webservers # 指定执行的目标是dbs组和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]# vim vars.yml #文件名自定义
---
yonghu: rose
mima: 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')}}"
cw
r改
ctrl+n
ctrl+r
光标放到需要缩进的第一行
ctrl + v
向下到需要缩进的最后一行
大I
4个空格
Esc
补充模块
一、firewalld模块
用于配置防火墙的模块
常用选项:
port:声明端口
permanent:永久生效,但不会立即生效
immediate:立即生效,临时生效
state:enabled,放行;disabled拒绝
防火墙一般默认拒绝,明确写入允许的服务。
有一些服务有名字,有些服务没有名字。但是最终都是基于TCP或UDP的某些端口。比如http服务基于TCP80端口。服务名和端口号对应关系的说明文件是:
/etc/services
配置服务器的防火墙,一般来说只要配置开放哪些服务或端口即可。没有明确开放的,都默认拒绝。
应用:
在webservers组中的主机上安装并启动nginx
客户端访问服务器的nginx服务
在webservers组中的主机上安装并启动firewalld
客户端访问服务器的nginx服务
在webservers组中的主机上开放nginx服务
#配置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模块启firewalld服务
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:目标文件路径
#使用template模块将含有变量的文件上传到webservers组中的主机
[root@pubserver ansible]# vim index.html
Welcome 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.12
Welcome to web2 on 192.168.88.12
[root@web1 ~]# cat /usr/share/nginx/html/index.html
Welcome to web1 on 192.168.88.11
[root@web2 ~]# cat /usr/share/nginx/html/index.html
Welcome to web2 on 192.168.88.12
进阶语法
一、错误处理
当Playbook中包含很多任务时,当某一个任务遇到错误,它将崩溃,终止执行
#在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
#到web1上查看,因为第2个任务没有执行,所以文件不会创建
[root@web1 ~]# ls /tmp/service.txt
ls: cannot access '/tmp/service.txt': No such file or directory
可以指定某一个任务如果出现错误,则忽略它
#编辑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
通过全局设置,无论哪个任务出现问题,都要忽略
[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才会进行通知。
#下载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
#第二次执行trigger.yml,上传文件的任务状态是绿色的ok,重启服务任务的状态是黄色changed
#既然配置文件没有改变,那么服务就不应该重启
#修改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中的任务也被触发执行
#第二次运行Playbook,因为第1个任务是绿色的OK,也就不会再触发执行其他任务了
三、when条件
只有满足某一条件时,才执行任务
常用的操作符:
==:相等
!=:不等
>
:大于
<
:小于
<=
:小于等于
>=
:大于等于多个条件或以使用and或or进行连接
when表达式中的变量,可以不使用
{{}}
#当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
#多条件。系统发行版是Rocky8才执行任务
#/etc/motd中的内容,将会在用户登陆时显示在屏幕上
[root@pubserver ansible]# yum -y install cowsay
[root@pubserver ansible]# cowsay Hello World > motd
[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.yml
[root@pubserver ansible]# echo 'nocows = 1' >> ansible.cfg
[root@pubserver ansible]# ansible-playbook when2.yml
四、regitster注册变量
Ansible的“register”模块是用于捕获和保存任务执行结果的,它允许将其他任务的输出作为变量使用。register是一个关键字,可以将任务执行的结果赋值给指定的变量名称。这个变量可以在后续任务中使用。 register模块可以捕获各种类型的输出,包括stdout、stderr、rc、changed等。它可以与其他模块一起使用,例如“when”条件、“loop”循环等。
#在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
#
---
- name: create file /tmp/ademo/abc
hosts: webservers
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 == True
#
---
- name: create file /tmp/ademo/abc
hosts: webservers
ignore_errors: yes
tasks:
- name: create file
file:
path: /tmp/abc
state: touch
register: result
- name: debug output
debug:
msg: "create failed"
when: result.failed == True
关于cowsay
# 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 -l
Cow files in /usr/share/cowsay:
beavis.zen blowfish bud-frogs bunny cheese cower default dragon
dragon-and-cow elephant elephant-in-snake eyes flaming-sheep fox
ghostbusters head-in hellokitty kiss kitty koala kosh luke-koala
mech-and-cow meow milk moofasa moose mutilated ren sheep skeleton small
stegosaurus stimpy supermilker surgery telebears three-eyes turkey turtle
tux 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