一、ansible入门
1、简介
Ansible是一个自动化统一配置管理工具,自动化主要体现在Ansible集成了丰富模块以及功能组件,可以通过一个命令完成一系列的操作,进而能减少重复性的工作和维护成本,可以提高工作效率。
2、组成
1.连接插件connection plugins用于连接主机 用来连接被管理端
2.核心模块core modules连接主机实现操作, 它依赖于具体的模块来做具体的事情
3.自定义模块custom modules根据自己的需求编写具体的模块
4.插件plugins完成模块功能的补充
5.剧本playbookansible的配置文件,将多个任务定义在剧本中,由ansible自动执行
6.主机清单inventor定义ansible需要操作主机的范围
最重要的一点是 ansible是模块化的 它所有的操作都依赖于模块
3、执行流程
1.Ansible读取playbook剧本,剧本中会记录对哪些主机执行哪些任务。 #web 安装nginx
2.首先Ansible通过主机清单找到要执行的主机,然后调用具体的模块。 #web 是谁
3.其次Ansible会通过连接插件连接对应的主机并推送对应的任务列表。 #使用yum模块安装nginx
4.最后被管理的主机会将Ansible发送过来的任务解析为本地Shell命令执行。 #受控端执行yum install -y nginx
二、ansible的使用
1、环境准备
2、控制端安装
#1.安装epel源
[root@m01 ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
#2.安装Ansible
[root@m01 ~]# yum install -y ansible
3、参数解释
# ansible <host-pattern> [options]
#不常用参数
--version #ansible版本信息
-v #显示详细信息
-i #主机清单文件路径,默认是在/etc/ansible/hosts
-k #提示输入ssh密码,而不使用基于ssh的密钥认证
-C #模拟执行测试,但不会真的执行
-T #执行命令的超时
#常用参数
-m #使用的模块名称,默认使用command模块
-a #使用的模块参数,模块的具体动作
--syntax-check #验证语法
[root@m01 ~]# ansible --version
ansible 2.9.15
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Oct 30 2018, 23:45:53) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
4、配置文件
[root@m01 ~]# rpm -qc ansible
/etc/ansible/ansible.cfg
/etc/ansible/hosts
[root@m01 ~]# cat /etc/ansible/ansible.cfg
#inventory = /etc/ansible/hosts #主机列表配置文件
#library = /usr/share/my_modules/ #库文件存放目录
#remote_tmp = ~/.ansible/tmp #临时py文件存放在远程主机目录
#local_tmp = ~/.ansible/tmp #本机的临时执行目录
#forks = 5 #默认并发数
#sudo_user = root #默认sudo用户
#ask_sudo_pass = True #每次执行是否询问sudo的ssh密码
#ask_pass = True #每次执行是否询问ssh密码
#remote_port = 22 #远程主机端口
host_key_checking = False #跳过检查主机指纹
log_path = /var/log/ansible.log #ansible日志
#普通用户提权操作
[privilege_escalation]
#become=True
#become_method=sudo
#become_user=root
#become_ask_pass=False
5、主机清单配置
1)、基于密码的方式
1、单主机配置
#方式一: ip + 端口 + 用户名 + 用户密码
[root@m01 ~]# vim /etc/ansible/hosts
[web01]
10.0.0.7 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
[web02]
10.0.0.8 ansible_ssh_user=root ansible_ssh_port=22 ansible_ssh_pass='1'
#测试
[root@m01 ~]# ansible web01 -m ping
10.0.0.7 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
#方式二: ip + 用户密码
[root@m01 ~]# vim /etc/ansible/hosts
[web01]
10.0.0.7 ansible_ssh_pass='1'
[web02]
10.0.0.8 ansible_ssh_pass='1'
[root@m01 ~]# ansible web02 -m ping
10.0.0.8 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
#方式三: ip + 变量密码
[root@m01 ~]# vim /etc/ansible/hosts
[web01]
10.0.0.7
[web02]
10.0.0.8
[web01:vars]
ansible_ssh_pass='1'
2、多主机配置
[root@m01 ~]# vim /etc/ansible/hosts
[web_group]
10.0.0.7 ansible_ssh_pass='1'
10.0.0.8 ansible_ssh_pass='1'
[root@m01 ~]# ansible 'web_group' -m ping
10.0.0.8 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
10.0.0.7 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
2)、基于秘钥的方式
1.生成密钥对
[root@m01 ~]# ssh-keygen
2.推送公钥
[root@m01 ~]# ssh-copy-id 10.0.0.7
[root@m01 ~]# ssh-copy-id 10.0.0.8
3、配置主机清单
[root@m01 ~]# vim /etc/ansible/hosts
[web_group]
10.0.0.7
10.0.0.8
4、修改host配置主机清单
#配置主机清单
[root@m01 ~]# vim /etc/ansible/hosts
[web_group]
web01
web02
#配置hosts
[root@m01 ~]# vim /etc/hosts
10.0.0.7 web01
10.0.0.8 web02
#测试
[root@m01 ~]# ansible 'web_group' -m ping
web02 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
web01 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
6、定义整合组
1)、定义
[root@m01 ~]# vim /etc/ansible/hosts
[web_group]
web01
web02
[nfs_server]
nfs ansible_ssh_pass='1'
[rsync_server]
backup ansible_ssh_pass='1'
[db_server]
db01 ansible_ssh_pass='1'
#定义整合组,下面包含多个组
[www:children]
web_group
nfs_server
rsync_server
#配置hosts
[root@m01 ~]# vim /etc/hosts
10.0.0.7 web01
10.0.0.8 web02
10.0.0.31 nfs
10.0.0.41 backup
10.0.0.51 db01
2)、查看
[root@m01 ~]# ansible www --list-host
hosts (4):
web01
web02
nfs
backup
7、测试
#单主机
[root@m01 ~]# ansible 'web01' -m ping
#所有主机
[root@m01 ~]# ansible '*' -m ping
#所有主机
[root@m01 ~]# ansible 'all' -m ping
#主机组
[root@m01 ~]# ansible 'web_group' -m ping
#整合组
[root@m01 ~]# ansible 'www' -m ping
三、ansible ad-hoc
1、简介
ad-hoc简而言之就是"临时命令",执行完即结束,并不会保存
[root@m01 ~]# ansible web01 -m command -a 'df -h'
web01 | CHANGED | rc=0 >>
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 18G 1.6G 17G 9% /
devtmpfs 476M 0 476M 0% /dev
tmpfs 487M 0 487M 0% /dev/shm
tmpfs 487M 7.7M 479M 2% /run
tmpfs 487M 0 487M 0% /sys/fs/cgroup
/dev/sda1 1014M 127M 888M 13% /boot
tmpfs 98M 0 98M 0% /run/user/0
[root@m01 ~]# ansible web_group -m command -a 'free -m'
web01 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 972 128 481 7 362 658
Swap: 1023 0 1023
web02 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 972 111 551 7 309 691
Swap: 1023 0 1023
绿色: 代表被管理端主机没有被修改
黄色: 代表被管理端主机发现变更
红色: 代表出现了故障,注意查看提示
2、ad-hoc常用模块
command # 执行shell命令(不支持管道等特殊字符)
shell # 执行shell命令
scripts # 执行shell脚本
yum_repository # 配置yum仓库
yum # 安装软件
copy # 变更配置文件
file # 建立目录或文件
service # 启动与停止服务
systemd # 启动与停止服务
mount # 挂载设备
cron # 定时任务
get_url #下载软件
firewalld #防火墙
selinux #selinux
setup #获取主机信息
注意:查看帮助
#1.查看所有模块
[root@m01 ~]# ansible-doc -l
#2.查看指定模块的用法
[root@m01 ~]# ansible-doc yum
#3.查看模块参数
[root@m01 ~]# ansible-doc -s yum
3、命令模块
1、command
#默认模块,远程执行命令
[root@m01 ~]# ansible web01 -m command -a 'free -m'
web01 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 972 128 479 7 364 658
Swap: 1023 0 1023
#不支持特殊字符
[root@m01 ~]# ansible web01 -m command -a "ifconfig eth0 | awk 'NR==2 {print \$2}'"
web01 | FAILED | rc=1 >>
|: Unknown host
ifconfig: `--help' gives usage information.non-zero return code
2、shell
[root@m01 ~]# ansible web01 -m shell -a 'free -m'
web01 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 972 128 479 7 364 658
Swap: 1023 0 1023
#支持特殊字符
[root@m01 ~]# ansible web01 -m shell -a "ifconfig eth0 | awk 'NR==2 {print \$2}'"
web01 | CHANGED | rc=0 >>
10.0.0.7
4、文件管理模块
1、copy
[root@m01 ~]# ansible-doc copy
EXAMPLES:
- name: Copy file with owner and permissions
copy:
src: /srv/myfiles/foo.conf
dest: /etc/foo.conf
owner: foo
group: foo
mode: '0644'
backup: yes
content: '# This file was moved to /etc/other.conf'
follow: yes
src #文件的源地址
dest #目标地址或文件
owner #文da件属主
group #文件属组
mode #文件的权限
backup #替换的文件是否备份
content #直接将内容写入文件
follow #处理软连接
例子:
#推送文件并备份
[root@m01 ~]# ansible web_group -m copy -a 'src=/root/index.html dest=/root/ owner=adm group=adm backup=yes'
注意:buckup参数不是用来回滚的,需要回滚的话要备份原来m01上推送的文件
#直接将内容写入文件
[root@m01 ~]# ansible web_group -m copy -a 'content="rsync_backup:123456" dest=/tmp/rsync.password mode=600'
2、file模块
[root@m01 ~]# ansible-doc file
EXAMPLES:
- name: Change file ownership, group and permissions
file:
src: /file/to/link/to
path: /etc/foo.conf
owner: foo
group: foo
mode: '0644'
state: link
recurse: yes
path #创建的文件或目录的地址
owner #文件或目录的属主
group #文件或目录的属组
mode #文件或目录的权限
state
link #创建软链接
src #源文件
dest #软链接的名字
touch #创建文件
directory #创建目录
absent #删除,目录,文件,软链接
recurse #递归授权
例子:#单纯的创建目录
[root@m01 ~]# ansible web01 -m file -a 'path=/code state=directory'
相当于在远程机器上执行:mkdir /code
#创建目录并授权
[root@m01 ~]# ansible web01 -m file -a 'path=/code state=directory owner=nginx group=nginx'
相当于在远程机器上执行:mkdir /code && chown nginx.nginx /code
#递归创建目录,不需要加任何参数
[root@m01 ~]# ansible web01 -m file -a 'path=/code/wordpress/wp-content/pic state=directory'
#递归授权目录
[root@m01 ~]# ansible web01 -m file -a 'path=/code/ state=directory owner=nginx group=nginx recurse=yes'
#注意:
1.当创建的目录不存在时,递归创建会递归授权
2.当创建的目录已经存在,递归授权只授权最后一层目录下的内容
#创建文件
[root@m01 ~]# ansible web01 -m file -a 'path=/tmp/1.txt state=touch'
#创建文件并授权
[root@m01 ~]# ansible web01 -m file -a 'path=/tmp/1.txt state=touch owner=nginx group=nginx'
#创建软链接
[root@m01 ~]# ansible web01 -m file -a 'src=/tmp/1.txt dest=/tmp/1.ln state=link'
3、get_url 模块
[root@m01 ~]# ansible-doc get_url
EXAMPLES:
- name: Download foo.conf
get_url:
url: http://example.com/path/file.conf
dest: /etc/foo.conf
mode: '0440'
checksum: sha256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c
url #文件下载地址
dest #文件存放路径
mode #文件下载后授权
checksum #验证文件
sha256 #加密方式
例子:#下载网站上的文件
[root@m01 ~]# ansible web01 -m get_url -a 'url=http://10.0.0.7/1.txt dest=/tmp'
#下载时验证文件
[root@m01 ~]# ansible web01 -m get_url -a 'url=http://10.0.0.7/1.txt dest=/tmp checksum=md5:d8e8fca2dc0f896fd7cb4cb0031ba249'
5、服务管理模块
1、server
[root@m01 ~]# ansible-doc service
EXAMPLES:
- name: Start service httpd, if not started
service:
name: httpd
state: started
name: nginx #服务名字
state:
started #启动服务
stopped #停止服务
restarted #重启服务
reloaded #重载服务
enabled: yes #开机自启
2、systemd
[root@m01 ~]# ansible-doc systemd
EXAMPLES:
- name: Make sure a service is running
systemd:
state: started
name: httpd
name: nginx #服务名字
state:
started #启动服务
stopped #停止服务
restarted #重启服务
reloaded #重载服务
enabled: yes #开机自启
5、用户管理模块
1、group
[root@m01 ~]# ansible-doc group
EXAMPLES:
- name: Ensure group "somegroup" exists
group:
name: somegroup #组名字
state:
present #创建组
absent #删除组
gid: 666 #指定组id
例子:
#创建用户组
[root@m01 ~]# ansible web01 -m group -a 'name=www gid=666 state=present'
#修改用户组
[root@m01 ~]# ansible web01 -m group -a 'name=www gid=666 state=absent'
2、user
[root@m01 ~]# ansible-doc user
EXAMPLES:
- name: Add the user 'johnd' with a specific uid and a primary group of 'admin'
user:
name: johnd
comment: John Doe
uid: 1040
group: admin
shell: /bin/bash
state: absent
remove: yes
create_home: false
name #用户名字
comment #用户备注
uid #用户id
group #用户所在的组名字
shell
/bin/bash #用户可以登录
/sbin/nologin #用户不需要登录
state
absent #删除用户
present #创建用户
remove #移除家目录
create_home #是否创建家目录
true #创建家目录
false #不创建家目录
例子:
#创建用户,不需要登录,有家目录
[root@m01 ~]# ansible web01 -m user -a 'name=www uid=666 group=www shell=/sbin/nologin create_home=true'
#删除用户并移除家目录
[root@m01 ~]# ansible web01 -m user -a 'name=www state=absent remove=yes'
#注意:
1.当组的名字与用户名字相同时,删除用户,组也会被删除
2.当组的名字与用户名字相同时,而组下面还有其他用户,则删除用户时不会删除同名组
6、其他模块
1、cron定时任务模块
[root@m01 ~]# ansible-doc cron
EXAMPLES:
- name: Ensure a job that runs at 2 and 5 exists. Creates an entry like "0 5,2 * * ls -alh > /dev/null"
cron:
name: "check dirs"
minute: "0"
hour: "5,2"
day: "*"
month: "*"
weekday: "*"
job: "ls -alh > /dev/null"
state: absent
disabled: yes
name #定时任务的备注
minute #分钟
hour #小时
day #日
month #月
weekday #周
job #指定的定时任务内容
state
present #新建定时任务
absent #删除定时任务
disabled
yes #注释定时任务
no #取消注释
例子:
#添加定时任务,每五分钟执行一次时间同步(只配置分钟,其他不配置默认是 * )
[root@m01 ~]# ansible web01 -m cron -a 'name="测试ansible配置定时任务" minute=*/5 job="ntpdate time1.aliyun.com"'
#查看配置
[root@web01 html]# crontab -l
#Ansible: 测试ansible配置定时任务
*/5 * * * * ntpdate time1.aliyun.com
#注释定时任务
[root@m01 ~]# ansible web01 -m cron -a 'name="测试ansible配置定时任务" minute=*/5 job="ntpdate time1.aliyun.com" disabled=yes'
#删除定时任务
[root@m01 ~]# ansible web01 -m cron -a 'name="测试ansible配置定时任务" minute=*/5 job="ntpdate time1.aliyun.com" state=absent'
#注意:
1.定时任务添加,是通过名字来区分是否一样的,如果不加name参数,则会添加重复的定时任务
2.定时任务注释是通过 name 参数来注释的,所以一定要加 name 参数
3.定时任务删除是通过 name 参数来删除的,所以一定要加 name 参数
2、mount模块
# 安装NFS
1.安装nfs
[root@m01 ~]# ansible nfs_server -m yum -a 'name=nfs-utils state=present'
2.配置nfs
[root@m01 ~]# ansible nfs_server -m copy -a 'content="/data 172.16.1.0/24(rw,sync,all_squash)" dest=/etc/exports'
3.创建目录
[root@m01 ~]# ansible nfs_server -m file -a 'path=/data state=directory owner=nfsnobody group=nfsnobody'
4.启动服务
[root@m01 ~]# ansible nfs_server -m systemd -a 'name=nfs state=started'
# 挂在模块的语法
[root@m01 ~]# ansible-doc mount
EXAMPLES:
- name: Mount DVD read-only
mount:
path: /mnt/dvd
src: /dev/sr0
fstype: iso9660
opts: ro,noauto
state: present
path #本机准备挂载的目录
src #远端挂载点
fstype #指定挂载类型
opts #挂载参数(/etc/fstab中的内容)
state
present #配置开机挂载,将配置写入自动挂载文件,并没有直接挂载
unmounted #取消挂载,但是没有删除自动挂载配置
#常用配置
mounted #配置开机挂载,并且直接挂载上
absent #取消挂载,并且删除自动挂载配置
例子:
#配置开机挂载,将配置写入自动挂载文件,并没有直接挂载
[root@m01 ~]# ansible web01 -m mount -a 'path=/data src=172.16.1.31:/data fstype=nfs opts=defaults state=present'
#配置开机挂载,并且直接挂载上
[root@m01 ~]# ansible web01 -m mount -a 'path=/data src=172.16.1.31:/data fstype=nfs opts=defaults state=mounted'
#取消挂载,但是没有删除自动挂载配置
[root@m01 ~]# ansible web01 -m mount -a 'path=/data src=172.16.1.31:/data fstype=nfs opts=defaults state=unmounted'
#取消挂载,并且删除自动挂载配置
[root@m01 ~]# ansible web01 -m mount -a 'path=/data src=172.16.1.31:/data fstype=nfs opts=defaults state=absent
3、selinux模块
- name: Disable SELinux
selinux:
state: disabled
#关闭selinux
[root@m01 ~]# ansible web02 -m selinux -a 'state=disabled'
web02 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"configfile": "/etc/selinux/config",
"msg": "",
"policy": "targeted",
"reboot_required": false,
"state": "disabled"
}
4、firewalld模块
[root@m01 ~]# ansible-doc firewalld
EXAMPLES:
- firewalld:
service: https #指定服务
permanent: #是否永久生效
yes #永久生效
no #临时生效
state:
enabled #允许通过
port:
8081/tcp #指定端口
zone: dmz #指定区域
rich_rule: rule service name="ftp" audit limit value="1/m" accept #配置富规则
source: 192.0.2.0/24 #指定网段
interface: eth2 #帮定网卡
masquerade: yes #开启IP伪装
例子:
#允许访问http服务,永久生效
[root@m01 ~]# ansible web01 -m firewalld -a 'service=http permanent=yes state=enabled'
[root@m01 ~]# ansible web01 -m firewalld -a 'service=http state=enabled'
#允许访问80端口,临时生效
[root@m01 ~]# ansible web01 -m firewalld -a 'port=80/tcp state=enabled'
#配置允许10.0.0.0网段访问22端口
[root@m01 ~]# ansible web01 -m firewalld -a 'rich_rule="rule family=ipv4 source address=10.0.0.0/24 port port=22 protocol=tcp accept" state=enabled'
#配置网段白名单
[root@m01 ~]# ansible web01 -m firewalld -a 'source=10.0.0.0/24 zone=trusted state=enabled permanent=yes'
[root@m01 ~]# ansible web01 -m firewalld -a 'source=10.0.0.0/24 zone=trusted state=enabled permanent=no'
4、unachive模块
[root@m01 ~]# ansible-doc unarchive
EXAMPLES:
- name: Extract foo.tgz into /var/lib/foo
unarchive:
src: foo.tgz
dest: /var/lib/foo
remote_src: no #默认是no
src #包的路径
dest #解压后的目标路径
remote_src
yes #包在受控端服务器上
no #包在控制端服务器上
例子:
#解压包到受控端,包在控制端上
[root@m01 ~]# ansible web01 -m unarchive -a 'src=/root/php.tar.gz dest=/tmp'
:
#在受控端解压包,包在受控端
[root@m01 ~]# ansible web01 -m unarchive -a 'src=/tmp/php.tar.gz dest=/tmp remote_src=yes'
5、archive压缩模块
[root@m01 ~]# ansible-doc archive
EXAMPLES:
- name: Compress directory /path/to/foo/ into /path/to/foo.tgz
archive:
path: /path/to/foo #要打包的内容
dest: /path/to/foo.tgz #打好的包与存放位置
format:gz #打包的类型 bz2, gz, tar, xz, zip
#打包实例
[root@m01 ~]# ansible web01 -m archive -a 'path=/tmp dest=/opt/php.tar.gz'
四、ansible主机学习模块
1、setup模块
#1.获取web01主机所有信息
[root@m01 ~]# ansible web01 -m setup
#2.获取主机IP
[root@m01 ~]# ansible web01 -m setup -a 'filter=ansible_default_ipv4'
#3.获取主机名
[root@m01 ~]# ansible web01 -m setup -a 'filter=ansible_fqdn'
web01 | SUCCESS => {
"ansible_facts": {
"ansible_fqdn": "www.baidu.com",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
#4.获取内存信息
[root@m01 ~]# ansible web01 -m setup -a 'filter=ansible_memory_mb'
web01 | SUCCESS => {
"ansible_facts": {
"ansible_memory_mb": {
"nocache": {
"free": 720,
"used": 252
},
"real": {
"free": 276,
"total": 972,
"used": 696
},
"swap": {
"cached": 0,
"free": 1023,
"total": 1023,
"used": 0
}
},
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
#5.常用参数
ansible_all_ipv4_addresses:仅显示ipv4的信息。
ansible_devices:仅显示磁盘设备信息。
ansible_distribution:显示是什么系统,例:centos,suse等。
ansible_distribution_major_version:显示是系统主版本。
ansible_distribution_version:仅显示系统版本。
ansible_machine:显示系统类型,例:32位,还是64位。
ansible_eth0:仅显示eth0的信息。
ansible_hostname:仅显示主机名(不准确)
ansible_fqdn:仅显示主机名。
ansible_kernel:仅显示内核版本。
ansible_lvm:显示lvm相关信息。
ansible_memtotal_mb:显示系统总内存。
ansible_memfree_mb:显示可用系统内存。
ansible_memory_mb:详细显示内存情况。
ansible_swaptotal_mb:显示总的swap内存。
ansible_swapfree_mb:显示swap内存的可用内存。
ansible_mounts:显示系统磁盘挂载情况。
ansible_processor:显示cpu个数(具体显示每个cpu的型号)。
ansible_processor_vcpus:显示cpu个数(只显示总的个数)。
五、ansible剧本playbook
1、简介
[root@m01 ~]# vim touch.yml
#定义要执行动作的主机或主机组
- hosts: web_group
#定义操作的用户
remote_user: root
#定义变量
vars:
#变量:变量的值
file_name: lhd
#指定主机的动作
tasks:
#动作的注释
- name: Touch New File
#使用shell模块执行动作
shell: touch /tmp/{{ file_name }}
#模拟执行
[root@m01 ~]# ansible-playbook -C touch.yml
#验证语法
[root@m01 ~]# ansible-playbook --syntax-check touch.yml
#注意:只能验证语法,验证不了逻辑
2、变量
1.通过命令行进行变量定义
2.在play文件中进行变量定义
3.通过Inventory主机清单中进行变量定义
4.通过vars_file定义变量
5.通过hosts_vars和group_vars定义变量
#变量的优先级
如果在定义变量时,变量冲突了
在上述的三个地方分别设置了:
1.命令行中:age=11
2.play文件中:age=12
3.Inventory中:age=13
那么,最终的age结果一定是 11
变量的读取优先级:命令行 > playbook文件 > Inventory文件
#变量设置:命名时,应该由字母,数字,下划线组成,必须由字母开头
方式一:在模块下方定义
[root@m01 project]# vim yum.yml
- hosts: db01
tasks:
- name: Installed http Server
yum:
name: "{{ packages }}"
vars:
packages:
- httpd
- httpd-tools
#问题:
1.如果将变量设置到模块下,那么其他的name是不识别的
方式二:在hosts下定义
[root@m01 project]# vim yum.yml
- hosts: db01
vars:
packages:
- httpd
- httpd-tools
tasks:
- name: Installed http Server
yum:
name: "{{ packages }}"
- name: Mkdir Dir
file:
path: /tmp/{{ packages }}
state: directory
#问题:
1.创建目录时可能会出现格式转换问题
2.如果将变量设置到hosts下,那么其他的hosts是不识别的
# 刚才我们学到在playbook中使用vars定义变量,有一个缺陷,就是其他的playbook无法使用该变量。所以我们可以采取第二种定义变量的方式,在vars_file中定义变量。
[root@m01 project]# mkdir vars
[root@m01 project]# cd vars/
[root@m01 vars]# vim vars.yml
packages: httpd
dbs: mariadb-server
# 调用变量
[root@m01 project]# vim yum.yml
- hosts: db01
vars_files: /project/vars/vars.yml
tasks:
- name: Installed http Server
yum:
name: "{{ packages }}"
- hosts: db01
vars_files: /project/vars/vars.yml
tasks:
- name: Installed http Server
yum:
name: "{{ dbs }}"
#通过inventory主机清单中进行变量定义
[root@m01 project]# vim /etc/ansible/hosts
... ...
[db_server]
db01 ansible_ssh_pass='1'
[db_server:vars]
web=suibianshezhideneirong
调用变量:
[root@m01 project]# vim yum.yml
- hosts: db_server
tasks:
- name: Touch File
file:
path: /tmp/{{ web }}
state: touch
#注意:
1.主机清单中定义变量,只要hosts配置的是主机清单中设置变量的组,可以直接使用变量
2.如果hosts配置的不是主机清单中设置变量的组,变量不可识别
3.主机组定义的变量优先级高于整合组定义的变量
4.主机定义的变量优先级高于主机组定义的变量
# 命令行定义变量
[root@m01 project]# ansible-playbook test.yml -e "file=command" -e "file2=command2"
# 直接使用内置变量
#使用内置变量创建目录,目录格式为 主机名_IP_时间
[root@m01 project]# vim test.yml
- hosts: web_group
tasks:
- name: Touch File
file:
path: /backup/{{ ansible_fqdn }}_{{ ansible_eth1.ipv4.address }}_{{ ansible_date_time.date }}
state: directory
六、流程控制
1、实例
[root@m01 project]# vim startserver.yml
- hosts: web_group
tasks:
- name: Start CentOS 6 Server
shell: "/etc/init.d/httpd start"
when:
- ansible_distribution == "CentOS"
- ansible_distribution_major_version == "6"
- name: Start CentOS 7 Server
shell: "systemctl start httpd"
when:
- ansible_distribution == "CentOS"
- ansible_distribution_major_version == "7"
[root@m01 project]# vim startserver.yml
- hosts: web_group
tasks:
- name: Start CentOS 6 Server
shell: "/etc/init.d/httpd start"
when: (ansible_distribution == "CentOS") and (ansible_distribution_major_version == "6")
- name: Start CentOS 7 Server
shell: "systemctl start httpd"
when: (ansible_distribution == "CentOS") and (ansible_distribution_major_version == "7")
- hosts: web_group
tasks:
- name: Check Httpd Server
command: systemctl is-active httpd
ignore_errors: yes
register: check_httpd
- name: debug outprint
debug: var=check_httpd
- name: Httpd Restart
service:
name: httpd
state: restarted
when: check_httpd.rc == 0
七、循环语句
1、实例
#错误写法
[root@m01 project]# vim start.yml
- hosts: web_group
tasks:
- name: Start Server
systemd:
name: "{{ package }}"
state: started
vars:
package:
- redis
- httpd
#正确写法
[root@m01 project]# vim start.yml
- hosts: web_group
tasks:
- name: Start Server
systemd:
name: "{{ item }}"
state: started
with_items:
- redis
- httpd
[root@m01 project]# cat user.yml
- hosts: lb01
tasks:
- name: Create Some Group
group:
name: "{{ item.name }}"
gid: "{{ item.gid }}"
state: present
with_items:
- { name: "lhd", gid: "777" }
- { name: "test", gid: "888" }
- { name: "egon", gid: "999" }
- name: Create Some User
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
group: "{{ item.group }}"
shell: "{{ item.shell }}"
create_home: "{{ item.create_home }}"
with_items:
- { name: "lhd", uid: "777", group: "lhd", shell: "/sbin/nologin", create_home: "false" }
- { name: "test", uid: "888", group: "test", shell: "/bin/bash", create_home: "false" }
- { name: "egon", uid: "999", group: "egon", shell: "/bin/bash", create_home: "true" }
八、playbook handle触发器
1、实例
handler用来执行某些条件下的任务,比如当配置文件发生变化的时候,通过notify触发handler去重启服务。
在saltstack中也有类似的触发器,写法相对Ansible简单,只需要watch,配置文件即可。
[root@m01 project]# cat nginx.yml
- hosts: nginx
tasks:
- name: Config Nginx Server
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
notify: restart_nginx
- name: Start Nginx Server
systemd:
name: nginx
state: started
handlers:
- name: restart_nginx
systemd:
name: nginx
state: restarted
1.无论多少个task通知了相同的handlers,handlers仅会在所有tasks结束后运行一次。
2.Handlers只有在其所在的任务被执行时,才会被运行;如果一个任务中定义了notify调用Handlers,但是由于条件判断等原因,该任务未被执行,那么Handlers同样不会被执行。
3.Handlers只会在每一个play的末尾运行一次;如果想在一个playbook中间运行Handlers,则需要使用meta模块来实现。例如: -meta: flush_handlers。
4.如果一个play在运行到调用Handlers的语句之前失败了,那么这个Handlers将不会被执行。我们可以使用meta模块的--force-handlers选项来强制执行Handlers,即使Handlers所在的play中途运行失败也能执行。
5.不能使用handlers替代tasks
九、playbook任务标签
1、对一个任务打一个标签
- hosts: nginx
- name: Config Nginx Server
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
notify: restart_nginx
tags: reconf_nginx
2、对一个任务打多个标签
- hosts: nginx
- name: Config Nginx Server
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
notify: restart_nginx
tags:
- reconf_nginx
- reconfig_nginx
3、对多个任务打一个标签
- hosts: nginx
- name: Config Nginx Server
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
notify: restart_nginx
tags: reconf_nginx
- name: Config Nginx wordpress
copy:
src: /project/conf/linux.wp.com.conf
dest: /etc/nginx/conf.d/
notify: reload_nginx
when: (ansible_fqdn == "web01") or (ansible_fqdn == "web02")
tags: reconf_nginx
4、使用标签的方式
1、查看标签
[root@m01 project]# ansible-playbook wp.yml --list-tags
playbook: wp.yml
play #1 (nginx): nginx TAGS: []
TASK TAGS: [reconf_nginx, reconfig_nginx]
2、执行制定标签的内容
[root@m01 project]# ansible-playbook wp.yml -t reconfig_nginx
[root@m01 project]# ansible-playbook wp.yml -t reconf_nginx,reconfig_nginx
[root@m01 project]# ansible-playbook wp.yml --skip-tags reconfig_nginx # 跳过标签内容
十、playbook的复用
1、实例
[root@m01 project]# cat play1.yml
- name: Install Nginx Server
yum:
name: nginx
state: present
[root@m01 project]# cat play2.yml
- name: Config Nginx Server
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
[root@m01 project]# vim main.yml
- hosts: web_group
tasks:
- include_tasks: /project/play1.yml
- include_tasks: /project/play2.yml
[root@m01 project]# cat main.yml
- import_playbook: ./base.yml
- import_playbook: ./nginx.yml
- import_playbook: ./php.yml
- import_playbook: ./wordpress.yml
- import_playbook: ./mariadb.yml
十一、playbook忽略错误
1、使用
- hosts: web_group
tasks:
- name: Check Httpd Server
#使用命令检查服务启动状态时,如果服务没有启动则会得到错误结果,剧本会停止运行
command: systemctl is-active httpd
#配置忽略错误可以继续执行剧本
ignore_errors: yes
register: check_httpd
- name: debug outprint
debug:
msg: "{{ check_httpd }}"
- name: Httpd Restart
service:
name: httpd
state: restarted
when: check_httpd.rc == 0
# 强制执行handle的内容
[root@m01 ~]# cat handler.yml
- hosts: web_group
vars:
- http_port: 8080
force_handlers: yes
tasks:
- name: config httpd server
template:
src: ./httpd.j2
dest: /etc/httpd/conf
notify:
- Restart Httpd Server
- Restart PHP Server
- name: Install Http Server
yum:
name: htttpd
state: present
- name: start httpd server
service:
name:httpd
state: started
enabled: yes
handlers:
- name: Restart Httpd Server
systemd:
name: httpd
state: restarted
- name: Restart PHP Server
systemd:
name: php-fpm
state: restarted
十二、ansible role
1、简介
roles不管是Ansible还是saltstack,我在写一键部署的时候,都不可能把所有的步骤全部写入到一个'剧本'文件当中,我们肯定需要把不同的工作模块,拆分开来,解耦,那么说到解耦,我们就需要用到roles官方推荐,因为roles的目录结构层次更加清晰。
例如:我们之前推荐大家写一个base.yml里面写所有基础优化的项目,其实把所有东西摞进去也是很鸡肋的,不如我们把这些功能全部拆分开,谁需要使用,就调用即可。
建议:每个roles最好只使用一个tasks这样方便我们去调用,能够很好的做到解耦。(SOA)
2、目录介绍
production # inventory file for production servers
staging # inventory file for staging environment
group_vars/
group1.yml # here we assign variables to particular groups
group2.yml
host_vars/
hostname1.yml # here we assign variables to particular systems
hostname2.yml
library/ # if any custom modules, put them here (optional)
module_utils/ # if any custom module_utils to support modules, put them here (optional)
filter_plugins/ # if any custom filter plugins, put them here (optional)
site.yml # master playbook
webservers.yml # playbook for webserver tier
dbservers.yml # playbook for dbserver tier
roles/
common/ # this hierarchy represents a "role"
tasks/ #
main.yml # <-- tasks file can include smaller files if warranted
handlers/ #
main.yml # <-- handlers file
templates/ # <-- files for use with the template resource
ntp.conf.j2 # <------- templates end in .j2
files/ #
bar.txt # <-- files for use with the copy resource
foo.sh # <-- script files for use with the script resource
vars/ #
main.yml # <-- variables associated with this role
defaults/ #
main.yml # <-- default lower priority variables for this role
meta/ #
main.yml # <-- role dependencies
library/ # roles can also include custom modules
module_utils/ # roles can also include custom module_utils
lookup_plugins/ # or other types of plugins, like lookup in this case
webtier/ # same kind of structure as "common" was above, done for the webtier role
monitoring/ # ""
fooapp/ # ""
3、创建语法
[root@m01 roles]# ansible-galaxy init nginx
- Role nginx was created successfully
[root@m01 roles]# tree nginx
nginx #项目目录名称
├── defaults #默认的变量(优先级很低)
│ └── main.yml
├── files #存放文件,使用copy模块时自动获取
├── handlers #存放触发器的配置
│ └── main.yml
├── meta #依赖的服务,执行该项目时先执行其他的项目
│ └── main.yml
├── README.md
├── tasks #默认执行的playbook
│ └── main.yml
├── templates #存放jinja2模板,使用template模块时自动获取
├── tests
│ ├── inventory
│ └── test.yml
└── vars #存放变量
└── main.yml
4、role的依赖关系
`roles`允许你再使用roles时自动引入其他的roles。role依赖关系存储在roles目录中meta/main.yml文件中。
例如:推送wordpress并解压,前提条件,必须要安装nginx和php,把服务跑起来,才能运行wordpress的页面,此时我们就可以在wordpress的roles中定义依赖nginx和php的roles
[root@m01 roles]# vim /etc/ansible/roles/wordpress/meta/main.yml
dependencies:
- { role: nginx }
- { role: php }
如果编写了meta目录下的main.yml文件,那么Ansible会自动先执行meta目录中main.yml文件中的dependencies文件,如上所示,就会先执行nginx和php的安装。