1 Ansible Playbook简介
前面我们都是通过ansible命令形式管理被控节点:
- 此方式适合执行一些临时性的简单任务
Playbook剧本:
- 将需要执行的任务写入剧本文件,看起来简洁清晰
- 剧本文件中可以包含多个任务
- 剧本能够实现流程控制,比如:判断、循环、变量、标签
- 剧本写好后,随时调用剧本,执行相关的任务
- 适用于经常执行的复杂任务
- 剧本提供语法检查以及模拟执行功能
电影剧本:
电影名
场景
演员
事件
事件1
事件2
事件3
Ansible剧本:
剧本名
被控节点
管理被控节点时使用的用户
任务(事件)
任务1
任务2
任务3
2 Playbook书写格式
2.1 YAML简介
YAML是一个可读性高、用来表达数据序列的格式语言;YAML以数据为中心,重点描述数据的关系和结构。
2.2 YAML格式特点
YAML语法官方文档:https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html
1."#"代表注释,第一行一般为三个横杠表示开头
2.严格的缩进表示层级关系,缩进一般为2个空格
3.缩进必须使用空格,不能使用tab键
4.字符串通常不需要放在引号里,即使字符串中包含空格
5.支持字典,字典以简单的形式表示 key: value;字典也可以使用{}括起来
6.支持列表,列表的内容使用"-"表示;列表也可用[]括起来
7.":"和"-"后面必须要有一个空格
8.跨行数据可以使用">"来换行
9.剧本文件后缀名必须为yaml或yml
2.3 剧本编写格式
Playbook剧本必不可少的三个部分:name,hosts,tasks。
name 剧本名称
hosts 被控节点,主机或主机组
tasks 要执行的任务
become:表示是否要以特权用户(通常是root)身份执行任务。如果设置为yes,则任务会以特权身份执行。
playbook: 由一个或多个play组成,一个play可以包含多个task任务
--- #第一行一般为三个横杠,可以省略
- name: Update web servers #剧本名称
hosts: webservers #被控节点,主机或主机组
remote_user: root #管理被控节点时使用哪个用户
tasks: #要执行的任务
- name: apache_install #第一个任务的名称
tags: t1 #该任务的标签
yum: #该任务使用的模块,也就是该任务要做的事情
name: httpd #yum模块的参数,表示httpd包
state: latest #yum模块的参数,表示安装最新版
- name: apache_config_file #第二个任务的名称
tags: t2 #该任务的标签
template: #该任务使用的模块,也就是该任务要做的事情
src: /srv/httpd.j2 #模块参数
dest: /etc/httpd.conf #模块参数
- name: Update db servers #第二个剧本名称,第二种格式
hosts: databases
remote_user: root
tasks:
- name: Ensure postgresql is at the latest version
yum: name=postgresql state=latest
- name: Ensure that postgresql is started
service: name=postgresql state=started
示例:安装host1节点 httpd 服务并且在host3节点上重启nginx并且检查他们的服务状态
[root@server ~]# vi httpd.yml
[root@server ~]# cat httpd.yml
---
- hosts: node1
become: yes
tasks:
# 使用yum模块在node1主机上安装httpd服务
- name: Install httpd Server
yum:
name: httpd
state: present
name:定义一个Playbook的名称,用于标识Playbook的用途;
hosts:指定要在哪个主机上执行,也是写主机或主机组名,
需要提前在/etc/ansible/hosts中配置好;
become:yes表示使用特权用户;
tasks:属于是一个任务列表,主要写具体执行什么的(可以有多个);
name:每个任务的名称,用于描述干什么的;上述yml中则是安装httpd服务;
yum:表示使用哪个模块来进行操作;
name:要安装的服务名称,我们这里是httpd:
state:要进行的操作,可以是安装、卸载、更新;
其实tasks就是Ansible的模块以YAML语法写入到playbook中。
生产环境中为了可读性与可维护性通常一个playbook中只编写一个play,如果某些主机需要执行多个play,那么可以使用include关键字在一个playbook中导入其他的playbook。
3 剧本执行命令
#命令格式
ansible-playbook [选项] 剧本文件
#选项
-C #模拟执行
-i #指定主机清单hosts文件路径,默认是/etc/ansible/hosts
-v #显示过程,-vv、-vvv更详细
--list-hosts #查看哪些主机会执行该剧本
--list-tasks #列出剧本中所有任务
--start-at-task #指定从剧本中某个任务开始运行
--list-tags #列出剧本文件中任务中定义的所有tags
-t #只运行剧本文件中定义的某些tags任务,多个标签用逗号隔开
--skip-tags #跳过剧本中某些标签的任务
#示例
#执行某剧本
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook Rsync_configure_project.yaml
#模拟执行某剧本
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook -C Rsync_configure_project.yaml
#查看哪些主机会执行该剧本
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook --list-hosts Rsync_configure_project.yaml
playbook: Rsync_configure_project.yaml
play #1 (backup): Rsync configure TAGS: []
pattern: [u'backup']
hosts (1):
10.0.0.16
#列出剧本中所有任务
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook --list-tasks Rsync_configure_project.yaml
playbook: Rsync_configure_project.yaml
play #1 (backup): Rsync configure TAGS: []
tasks:
01 install rsync TAGS: [t1]
02 copy config file TAGS: [t2]
03 rsync groupadd TAGS: [t3]
04 rsync useradd TAGS: [t4]
05 make backup directory TAGS: [t5]
06 copy password file TAGS: [t6]
07 stop firewalld service TAGS: [t7]
08 close the selinux TAGS: [t8]
09 start rsyncd service TAGS: [t9]
#指定从剧本中第7个任务开始运行
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook --start-at-task "07 stop firewalld service" Rsync_configure_project.yaml
#列出剧本文件中任务中定义的所有tags
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook --list-tags Rsync_configure_project.yaml
playbook: Rsync_configure_project.yaml
play #1 (backup): Rsync configure TAGS: []
TASK TAGS: [t1, t2, t3, t4, t5, t6, t7, t8, t9]
#只运行剧本文件中定义的tags为t2,t6,t9的任务
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook -t t2,t6,t9 Rsync_configure_project.yaml
#跳过剧本中标签为t3,t4,t5的任务
[root@manager-18 ~/projects/Rsync_configure_project]# ansible-playbook --skip-tags t3,t4,t5 Rsync_configure_project.yaml
3.1 权限
remote_user指定playbook运行时的用户身份,可以写在hosts下,也可以每个tasks做定义;
become 该选项为布尔值,当等于yes表示以管理员身份通常与become_method一起使用;
become_method:su或sudo
# 指定使用哪个用户执行此任务
remote_user: root
# 是否使用特权用户
become: yes
3.2 通知与触发
notify: 如果指定的操作执行了,会触发handlers的操作,指定的是handler的名称;
handlers和notify指定的名称必须相同,否则无法触发。
handlers 中需要- name指定名称 ,handlers只会在所有的tasks执行完后执行,
并且,即便一个handlers被触发多次,也只会执行一次。 handlers是一种特殊的tasks。
使用上场景:一般都是修改配置文件时
正常情况时handlers是不会执行的,除非触发任务,才会执行
任务导致系统状态发生变化(例如,配置文件被修改),则将触发名为restart的处理器。
- hosts: node1
tasks:
- name: installredis
yum: name=redis
- name: copyfile
template: src=redis.conf dest=/etc/redis.conf
tags: copyfile
notify: restart # 触发:触发名称
- name: start
service:
name: redis
state: started
enabled: yes
handlers: # 触发动作
- name: restart
service:
name: redis
state: restarted
例:下载nginx并启动,启动成功后会自动执行关闭防火墙并且检查运行状态
[root@server ~]# cat nginx3.yml
---
- hosts: node3
become: yes
tasks:
- name: install_nginx
yum:
name: nginx
state: present
- name: Start_nginx
service:
name: nginx
state: started
notify:
- stop_firewalld
- check_status_nginx
- display nginx status
changed_when: true # 强制标记任务为已改变
handlers:
- name: stop_firewalld
service:
name: firewalld
state: stopped
enabled: no
- name: check_status_nginx
command: systemctl status nginx
register: nginx_status
changed_when: false
- name: display nginx status
debug:
var: nginx_status.stdout_lines
在Ansible中,处理器(handlers)只有在任务状态发生变化时才会被触发。例如,如果Nginx服务之前已经是运行状态,那么Start_nginx任务不会被视为“改变”系统状态,因此不会触发处理器。
为了确保处理器能够被触发,你可以使用changed_when参数来强制标记任务为已改变,或者使用meta: flush_handlers来强制执行所有处理器。
4 Ansible变量应用
Ansible支持很多种定义变量的方式;在此简单列举几种,根据优先级排序:
1.Inventory变量
2.Host Facts变量
3.Register变量
4.Playbook变量
5.变量文件
除了以上变量之外还有"命令行定义的变量"和ansible内置的"magic魔法变量"
变量的调用方式:
通过 {{ variable_name }} 调用变量,且变量名前后建议加空格,有时使用 "{{ variable_name }}" 才能生效
4.1 变量的定义方式
1.通过命令行进行变量定义
2.在play文件中进行变量定义
3.通过Inventory主机信息文件中进行变量定义
变量读取的优先级为: 命令行 > playbook文件 > Inventory文件
4.1.1 通过vars定义变量
---
- name: LAMP
hosts: node1
vars:
packages_name:
- httpd
- mariadb-server
- php
- php-mysql
tasks:
- name: install LAMP
yum:
name: "{{packages_name}}"
state: present
4.1.2 通过vars_files定义变量
当变量较少时,使用vars定义没有问题,当变量较多时,可以将变量保存到一个独立的文件中;
需要多个yml文件,一个主文件,需要调用其他yml独立文件,主要是最后运行的;其他是定义包名的yml文件。
[root@server ansible]# cat rzc.yml
---
httpd_package: httpd
mariadb_package: mariadb-server
[root@server ansible]# vi nginx4.yml
[root@server ansible]# cat nginx4.yml
---
- name: nginx
hosts: node3
become: yes
vars_files:
- rzc.yml
tasks:
- name: Install httpd
yum:
name: "{{ httpd_package }}"
state: present
- name: Install mariadb-server
yum:
name: "{{ mariadb_package }}"
state: present
4.1.3 命令行定义变量
ansible-playbook命令提供-e选项,用于在命令行定义变量,命令行定义变量的优先级最高
# 执行:命令行定义变量
[root@localhost yml]# vi test.yml
---
- name: apache
hosts: web
become: yes
vars:
httpd_package:
- httpd
tasks:
- name: install httpd service
yum:
name: "{{ httpd_package }}"
state: present
#定义阶段
[root@ansible ~]# ansible-playbook test.yml -e "httpd_package=httpd"
命令行指定多个变量
ansible-playbook test.yml -e "file=command" -e "file2=command2"
4.1.4 官方推荐的定义变量方法(推荐)
之前的几种变量定义都不是很好用,比较好用的是在Ansible项目目录下创建两个变量目录:
host_vars
group_vars
目录名字一定要一致,不能做任何修改。
理解如何设置和使用host_vars和group_vars可以使你的Ansible管理更加灵活和有组织。以下是更详细的步骤,从设置目录结构到创建Playbook的执行:
1.目录结构
your_ansible_project/
├── group_vars/
│ └── web-servers.yml
├── host_vars/
│ └── web-server.yml
├── playbook.yml
└── inventory.ini
group_vars目录用于存放组级别的变量定义。
host_vars目录用于存放主机级别的变量定义。
playbook.yml是你的Ansible Playbook。
inventory.ini是Ansible的主机清单文件,其中列出了你的主机和主机组。
2.清单文件(inventory.ini):
在这里添加你的主机和主机组
[root@server ~]# cat /etc/ansible/inventory.ini
[node1]
host1
[node2]
host2
[node3]
host3
[node4]
host1
host3
3.组级别变量
group_vars/web-servers.yml
[root@server ~]# cd /etc/ansible/
[root@server ~]# mkdir -p /etc/ansible/group_vars
[root@server group_vars]# vi node4.yml
[root@server group_vars]# cat node4.yml
---
httpd_package: httpd
mariadb_package: mariadb-server
nginx_package: nginx
4.主机级别变量
host_vars/web-server.yml
在host_vars目录下创建一个YAML文件,例如node1.yml,并在其中定义主机级别的变量,如:
[root@server ~]# cd /etc/ansible/
[root@server ~]# mkdir -p /etc/ansible/host_vars
[root@server ansible]# cd host_vars/
[root@server host_vars]# vi node3.yml
[root@server host_vars]# cat node3.yml
---
nginx_package= nginx
5.Playbook(playbook.yml)
创建你的Ansible Playbook,例如:
[root@server ansible]# vi nginx4.yml
[root@server ansible]# cat nginx4.yml
---
- name: nginx
hosts: node3
become: yes
tasks:
- name: Install nginx
yum:
name: "{{ nginx_package }}"
state: present
6.运行playbook:
格式:
ansible-playbook -i inventory.ini playbook.yml
inventory.ini : 这里面表示你设置的主机分组
playbook.yml:你创造的脚本名称
此时,Ansible会自动加载group_vars和host_vars目录中的变量,你的Playbook将使用这些变量来配置主机。
通过这种方式,你可以更加有组织地管理变量,特别是对于多主机和多组的环境。你可以为不同的组或主机设置特定的变量,而不必在Playbook中硬编码这些值,提高了可维护性和可读性。
4.2 Host Facts变量
#事实变量就是setup模块获取到的被控节点的主机信息
#示例一
[root@manager-18 ~]# vim facts_variable_test.yml
---
- name: facts variable test
hosts: backup
tasks:
- name: print
debug:
msg: "the backup host ip address is {{ ansible_ens33.ipv4.address }}"
[root@manager-18 ~]# ansible-playbook facts_variable_test.yml
PLAY [facts variable test] **********************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [10.0.0.16]
TASK [test01] ***********************************************************************************************************************
ok: [10.0.0.16] => {
"msg": "the backup host ip address is 172.16.1.16"
}
PLAY RECAP **************************************************************************************************************************
10.0.0.16 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
#示例二
[root@manager-18 ~]# vim facts_variable_test.yml
---
- name: facts variable test
hosts: backup
tasks:
- name: test01
shell: echo "{{ ansible_ens33.ipv4.address }}" > /tmp/{{ ansible_ens33.ipv4.address }}
[root@manager-18 ~]# ansible-playbook facts_variable_test.yml
PLAY [facts variable test] **********************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [10.0.0.16]
TASK [test01] ***********************************************************************************************************************
changed: [10.0.0.16]
PLAY RECAP **************************************************************************************************************************
10.0.0.16 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@backup-16 ~]# cat /tmp/172.16.1.16
172.16.1.16
#注意:若使用不到事实变量,可以关闭获取被控主机的事实变量
# 配置如下:
---
- name: facts variable test
hosts: backup
gather_facts: false
4.3 Register变量
#register语句可以将某个命令的执行结果保存至某变量中,该变量就是注册变量
#示例
[root@manager-18 ~]# vim register_variable_test.yml
---
- name: register variable test
hosts: backup
tasks:
- name: test01
shell: echo "hello world"
register: hi #将此任务的结果保存到一个名为"hi"的变量中
- name: print
debug:
var: hi #在此使用debug模块,输出hi变量内容
#var: hi.stdout #输出hi变量中stdout该部分内容
[root@manager-18 ~]# ansible-playbook register_variable_test.yml
PLAY [register variable test] *******************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [10.0.0.16]
TASK [test01] ***********************************************************************************************************************
changed: [10.0.0.16]
TASK [debug] ************************************************************************************************************************
ok: [10.0.0.16] => {
"hi": {
"changed": true,
"cmd": "echo \"hello world\"",
"delta": "0:00:00.002149",
"end": "2021-12-03 11:12:50.385688",
"failed": false,
"rc": 0,
"start": "2021-12-03 11:12:50.383539",
"stderr": "",
"stderr_lines": [],
"stdout": "hello world",
"stdout_lines": [
"hello world"
]
}
}
PLAY RECAP **************************************************************************************************************************
10.0.0.16 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
评论区