前言
上篇介绍了 Ansible 单模块(AD-Hoc)的相关内容Ansible自动化运维工具单模块介绍-CSDN博客,Ad-Hoc 命令是一次性的、即时执行的命令,用于在远程主机上执行特定任务,这些命令通常用于快速执行简单的任务。当需要在执行多个任务、配置复杂场景或需要可重复使用操作时,就需要用到任务剧本(Playbook)来定义复杂的任务流程和处理重复执行的操作。
Playbook 也通常被大家翻译成剧本。可以认为它是 Ansible 自定义的一门语言(可以将 Playbook 比作 Linux 中的 shell,而 Ansible 中的 Module 可以比作为 Linux 中的各种命令。
目录
一、主机清单
1. 概述
2. 主机定义
2.1 inventory 中的变量
2.2 主机变量
2.3 组变量
2.4 组嵌套
二、YAML 非标记语言
1. 概述
2. Yaml 特点
3. 基本语法
3.1 字符串
3.2 列表
3.3 字典
3.4 混合结构
三、任务剧本 Playbook
1. 概述
2. 组成
3. Play 常用属性
4. tasks 属性中任务的多种写法
5. Playbook 校验与执行
5.1 语法检验
5.2 列出任务
5.3 列出主机
5.4 单步跟重调试
5.5 测试运行
5.6 执行
6. 编写一个 Playbook
6.1 定义主机清单
6.2 编写 Yaml 文件
7. 定义、引用变量
7.1 定义剧本
7.2 执行剧本
8. 指定远程主机 sudo 切换用户
8.1 通过 visudo 来管理用户权限
8.2 sudo提权操作
9. when 条件判断
10. 迭代
11. Templates 模块
11.1 概述
11.2 示例
12. Tags 模块
12.1 概述
12.2 示例
13. Roles 模块
13.1 概述
13.2 目录介绍
13.2.1 在一个 playbook 中使用 roles 的步骤
13.3 示例:简单的LNMP
13.3.1 定义 nginx 角色变量
13.3.2 编写 nginx 模块
13.3.3 定义 mysql 角色变量
13.3.4 编写 mysql 模块
13.3.5 定义 php 角色变量
13.3.6 编写 php 模块
13.3.7 定义主机清单
13.3.8 编写 roles
13.3.9 启动剧本
13.3.10 查看服务
一、主机清单
1. 概述
在 Ansible 中,inventory 主机清单是一个关键概念,用于定义 Ansible 将要管理的主机和主机组。主机清单可以包含主机的 IP 地址、主机名、主机组等信息,以便 Ansible 可以根据清单中的定义来执行任务。
2. 主机定义
一般情况下,可以修改 /etc/ansible/hosts 文件内容,来对主机进行分组,每个组内可以定义多个主机,每个主机都可以定义在任何一个或多个主机内。示例如下:
[root@control ~]# vim /etc/ansible/hosts
[webs]
192.168.190.100:2222 # 冒号后定义远程连接端口,默认是ssh的22端口
192.168.190.20[0:9] # 代表200~209
[dbs]
db-[a:d].example.org # 支持匹配a~d,支持域名
2.1 inventory 中的变量
Inventory变量名 | 含义 |
ansible_host | ansible连接节点时的IP地址 |
ansible_port | 连接对方的端口号,ssh连接时默认为22 |
ansible_user | 连接对方主机时使用的主机名。不指定时,将使用执行ansible或ansible-playbook命令的用户 |
ansible_password | 连接时的用户的ssh密码,仅在未使用密钥对验证的情况下有效 |
ansible_ssh_private_key_file | 指定密钥认证ssh连接时的私钥文件 |
ansible_ssh_common_args | 提供给ssh、sftp、scp命令的额外参数 |
ansible_become | 允许进行权限提升 |
ansible_become_method | 指定提升权限的方式,例如可使用sudo/su/runas等方式 |
ansible_become_user | 提升为哪个用户的权限,默认提升为root |
ansible_become_password | 提升为指定用户权限时的密码 |
2.2 主机变量
[webs]
192.168.190.100 ansible_port=2222 ansible_user=root ansible_password=123456
# ansible_port=2222:指定 SSH 连接的端口号为 2222。
# ansible_user=root:指定 SSH 连接的用户名为 root。
# ansible_password=123456:指定 SSH 连接的密码为 123456。
2.3 组变量
[webs:vars] # 表示为webs组内所有主机定义变量
ansible_user=root
ansible_password=123456
[all:vars] # 表示为所有组内的所有主机定义变量
ansible_port=22
# vars是一个关键字,用于定义变量。在主机清单文件中,可以使用vars关键字为主机组或单个主机定义变量
2.4 组嵌套
[nginx]
192.168.190.100
192.168.190.101
192.168.190.102
[apache]
192.168.190.20[0:2]
[webs:children] #表示为webs主机组中包含了nginx组和apache组内的所有主机
nginx
apache
# children是一个特殊的关键字,用于定义主机组之间的父子关系
# 当你在主机清单中使用[webs:children]这样的语法时,表示webs主机组是一个父组,包含了nginx组和apache组内的所有主机。
二、YAML 非标记语言
1. 概述
YAML 是一种人类可读的数据序列化格式,常用于配置文件和数据传输。它以缩进、换行和符号结构来表示数据,具有简洁、清晰的特点。YAML 旨在成为一个易于阅读和编写的数据格式,同时也适合机器解析和生成。它使用空格缩进来表示层级关系,不需要显式的标记符号(如 XML 或 JSON 中的尖括号或大括号),这使得它更加直观和易读。
2. Yaml 特点
YAML文件
- 以 #为注释符
- 以 .yml 或者 .yaml 结尾
- 以 --- 开始,以 ... 结束,但开始和结束标志都是可选的
3. 基本语法
- 大小写敏感
- 使用缩进表示层级关系
- 缩进时是使用Tab键还是使用空格一定要达到统一,建议使用空格
- 相同层级的元素必须左侧对齐即可
YAML 支持的数据结构有三种:
- 字符串
- 列表
- 字典
3.1 字符串
---
# YAML 中的字符串可以不使用引号,即使里面存在空格的时候,当然了使用单引号和双引号也可以
this is a string
'this is a string'
"this is a string"
# YAML 中若一行写不下要表述的内容,可以进行折行。写法如下:
long line: |
Example 1
Example 2
Example 3
# 或者
long line: >
Example 1
Example 2
Example 3
...
3.2 列表
在 YAML 中,列表使用短横线 - 表示,后面跟着一个空格。列表可以包含任意类型的元素,例如字符串、数字、布尔值或者其他嵌套的列表。
---
#可以认为它就是 python 中的 List,可以认为它是 c 语言中的数组。
# 如何定义:以短横线开头 + 空格 + 具体的值
- red
- green
- blue
# 以上的值假如转换成 python 的 List 会是这样:
# ['red', 'green', 'blue']
...
3.3 字典
字典在 YAML 中使用键值对的形式表示,使用冒号 : 将键和值分隔开,键值之间需要有一个空格。字典可以包含嵌套的字典或者列表作为值。
---
# 可以认为它就是 python 中的 Dict (字典)
# 如何定义:key + 冒号(:) + 空格 + 值(value),即 key: value
name: Using Ansible
code: D1234
#转换为 python 的 Dict
#{'name': 'Using Ansibel','code': 'D1234'}
...
3.4 混合结构
但在日常生产中,往往需要的数据结构会特别复杂,有可能会是字符串、列表、字典的组合形式。这里举一个例子:学校里是以班级为单位。使用列表和字典的形式去描述一个班级的组成:
---
class:
- name: stu1
num: 001
- name: stu2
num: 002
- name: stu3
num: 003
#{'class': [{'name': 'stul, 'num': 1},{'name': 'stu2', 'num': 2), ...]}
...
三、任务剧本 Playbook
1. 概述
Ansible playbook 是一个用 YAML 格式编写的文件,其中包含了一系列任务(tasks)和其他配置信息,用于描述 Ansible 在远程主机上执行的自动化任务和操作步骤;是一种通过 YAML 语言方式编写的一种策略。
2. 组成
- Tasks:任务,即通过 task 调用 ansible 的模板将多个操作组织在一个 playbook 中运行
- Variables:变量
- Templates:模板
- Handlers:处理器,当changed状态条件满足时,(notify)触发执行的操作
- Roles:角色
3. Play 常用属性
- name 属性:每个play的名字
- hosts 属性:每个play涉及的被管理服务器,同 ad-hoc 中的资产选择器
- tasks 属性:每个play 中具体要完成的任务,以列表的形式表达
- become 属性:如果需要提权,则加上become相关属性
- becomekuser 属性:若提权的话,提权到哪个用户上
- remote_user 属性:指定连接到远程节点上的用户,即远程服务器上执行操作的用户。若不指定,则默认使用当前执行 ansible Playbook 的用户
4. tasks 属性中任务的多种写法
# 以启动 apache 服务,并增加开机启动为例
#一行的形式:
service: name=apache enabled=true state=started
#多行的形式:
sefvice: name=apache
enabled=true
state=started
#多行写成字典的形式:
service:
name: apache
enabled: true
state: started
5. Playbook 校验与执行
5.1 语法检验
ansible-playbook example.yaml --syntax-check
5.2 列出任务
ansible-playbook example.yaml --list-tasks
5.3 列出主机
ansible-playbook example.yaml --list-hosts
5.4 单步跟重调试
指定从某个 task 开始运行,需要手动确认是否往下执行。
ansible-playbook example.yaml --step
示例:
ansible-playbook example.yaml --start-at-task='install httpd'
5.5 测试运行
会执行完整的 Playbook,但是所有 task 中的行为都不会在远程被管理节点服务器上执行,所有的操作都是模拟。
ansible-playbook apache.yaml --C #大写的C
5.6 执行
ansible-playbook example.yaml
补充参数:
# -k(–ask-pass):用来交互输入ssh密码
# -K(-ask-become-pass):用来交互输入sudo密码
# -u:指定用户
6. 编写一个 Playbook
6.1 定义主机清单
[root@control ~]# vim /etc/ansible/hosts
[webs]
192.168.190.104
[dbs]
192.168.190.105
[servers:children]
webs
dbs
6.2 编写 Yaml 文件
批量安装apache
① 准备工作,卸载目标主机网站服务
管理节点:
[root@control ~]# ansible all -m yum -a "name=httpd state=removed"
#在Ansible中,all是一个用于指代所有主机的特殊关键字。当你在使用Ansible命令时,使用all会将命令应用到所有已定义的主机上。卸载httpd相关服务。
被管理节点:
[root@managed1 ~]# yum list | grep httpd | grep @
httpd-tools.x86_64 2.4.6-99.el7.centos.1 @updates
#检查是否还有安装httpd相关包。
管理节点:
[root@control ~]# ansible all -m yum -a "name=httpd-tools state=removed"
#卸载httpd工具包,避免影响安装httpd。
管理节点:
[root@control ~]# yum install -y httpd
#Ansible服务器安装网站服务
[root@control ~]# cp -rf /etc/httpd/conf/httpd.conf /opt/
② 编写剧本
--- # #yaml文件以---开头,以表明这是一个yaml文件,可省略
- name: install apache # 定义一个play的名称,可省略
gather_facts: false # 设置不进行facts信息收集,这可以加快执行速度,可省略
hosts: servers # 指定要执行任务的被管理主机组,如多个主机组用冒号分隔,不可省略
remote_user: root # 指定被管理主机上执行任务的用户,默认root,可选择省略
tasks: # 定义任务列表,任务列表中的各任务按次序逐个在hosts中指定的主机上执行
- name: ping # 自定义任务名称
ping: # 使用module: [options]格式来定义一个任务
- name: disable firewalld
service: name=firewalld state=stopped # 使用module: options格式来定义任务,option使用key=value格式
- name: disable selinux
command: '/sbin/setenforce 0' # command模块和shell模块无需使用key=value格式
ignore_errors: True # 如执行命令的返回值不为0,就会报错,tasks停止,可使用ignore_errors忽略失败的任务
- name: install httpd
yum: name=httpd state=latest
- name: copy apache conf
copy: src=/opt/httpd.conf dest=/etc/httpd/conf/httpd.conf # 这里需要一个事先准备好的/opt/httpd.conf文件
notify: "restart httpd" # 如以上操作后为changed的状态时,会通过notify指定的名称触发对应名称的handlers操作
- name: start http service
service: enabled=true name=httpd state=started
handlers: # handlers中定义的就是任务,此处handlers中的任务使用的是service模块
- name: restart httpd # notify和handlers中任务的名称必须一致
service: name=httpd state=restarted
...
Ansible 在执行完某个任务之后并不会立即去执行对应的 handler,而是在当前 play 中所有普通任务都执行完后再去执行 handler,这样的好处是可以多次触发 notify,但最后只执行一次对应的handler,从而避免多次重启。
③ 检查测试
[root@control ~]# ansible-playbook apache.yml --syntax-check # 检查语法
playbook: apache.yml
[root@control ~]# ansible-playbook apache.yml --list-tasks # 列出任务
playbook: apache.yml
play #1 (servers): install apache TAGS: []
tasks:
ping TAGS: []
disable firewalld TAGS: []
disable selinux TAGS: []
install apache TAGS: []
copy apache conf TAGS: []
start http service TAGS: []
[root@control ~]# ansible-playbook apache.yml --list-hosts # 列出主机
playbook: apache.yml
play #1 (servers): install apache TAGS: []
pattern: [u'servers']
hosts (2):
192.168.190.105
192.168.190.104
④ 执行剧本
[root@control ~]# ansible-playbook apache.yml
[root@control ~]# ansible all -a 'systemctl status httpd'
192.168.190.105 | CHANGED | rc=0 >>
Main PID: 51200 (httpd)
192.168.190.104 | CHANGED | rc=0 >>
Main PID: 8465 (httpd)
7. 定义、引用变量
是一种定义的任务方式,在编写 playbook 时,可以使用变量来传输数据;playbook 引用变量值的是在 playbook 中使用变量代理静态常量值,来实现动态的配置过程;通过引用变量,可以使 playbook 更具有灵活性和可重复性。
7.1 定义剧本
[root@control ~]# vim vars.yml
- hosts: webs
vars: # 定义变量
- username: zhangsan # 格式为 key: value
- groupname: student
tasks:
- name: create group
group: name={{groupname}} system=yes gid=1500 # 使用 {{key}} 引用变量的值
- name: create user
user: name={{username}} uid=1500 group={{groupname}}
- name: copy file
copy: content="{{ansible_default_ipv4}}" dest=/opt/1.txt
# 在setup模块中可以获取facts变量信息
7.2 执行剧本
由此可见,在命令行里定义变量,优先级大于 playbook 中的。
8. 指定远程主机 sudo 切换用户
8.1 通过 visudo 来管理用户权限
在 managed1 操作:
[root@managed1 opt]# su - lisi
[lisi@managed1 ~]$ cd /opt/
[lisi@managed1 opt]$ ls
1.txt a.txt rh script.txt
[lisi@managed1 opt]$ rm -rf a.txt
rm: 无法删除"a.txt": 权限不够
[lisi@managed1 opt]$ exit
登出
[root@managed1 ~]# visudo
lisi ALL=(ALL) ALL
[root@managed1 ~]# passwd lisi
123456
8.2 sudo提权操作
在 control 节点操作:
① 编写剧本
[root@control ~]# vim sudo.yml
- hosts: webs
remote_user: lisi
become: yes
become_user: root
tasks:
- name: rm
command: /usr/bin/rm -f /opt/a.txt
[root@control ~]# ansible-playbook sudo.yml --syntax-check
playbook: sudo.yml
或者:
- hosts: webs
remote_user: lisi
become: yes
become_user: root
tasks:
- name: rm
file: name=a.txt state=absent
② 执行剧本
[root@control ~]# sshpass -p '123456' ssh-copy-id lisi@192.168.190.104
[root@control ~]# ansible-playbook sudo.yml -K
BECOME password: 123456
PLAY [webs] ***************************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [192.168.190.104]
TASK [rm] *****************************************************************************************
ok: [192.168.190.104]
PLAY RECAP ****************************************************************************************
192.168.190.104 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
9. when 条件判断
在 Ansible 中,提供的唯一一个通用的条件判断是 when 指令,当 when 指令的值为 true 时,则该任务执行,否则不执行该任务。
when 是一个比较常见的应用场景是实现跳过某个主机不执行任务或者只有满足条件的主机执行任务。
① 编写剧本
[root@control ~]# vim when.yml
- hosts: all
tasks:
- name: shutdown host
command: /usr/sbin/shutdown -r now
when: ansible_default_ipv4.address == "192.168.190.105"
或者:
when: inventory_hostname == "主机名"
# when指令中的变量名不需要手动加上 {{}}
[root@control ~]# ansible-playbook when.yml --syntax-check
playbook: when.yml
② 执行剧本
[root@control ~]# ansible-playbook when.yml
查看 105 机器已重启:
10. 迭代
Ansible提供了很多种循环结构,一般都命名为with_items,作用等同于 loop 循环。loop 是一种用于循环执行任务的结构,它允许在 playbook 中遍历一个列表,并对每个元素执行相同的任务。
① 编写剧本
示例:同时创建多个文件夹、同时创建多个用户
[root@control ~]# vim items.yml
- hosts: dbs
tasks:
- name: mkdir
file: path="{{item}}" state=directory
with_items:
- /opt/a1
- /opt/a2
- name: useradd
user: name={{item.name}} state=present groups={{iteam.groups}}
with_items:
- name: a1
groups: root
- name: a2
groups: root
或者:
with_items:
- {name:'a1', groups:'root'}
- {name:'a2', groups:'root'}
[root@control ~]# ansible-playbook items.yml --syntax-check
playbook: items.yml
② 执行剧本
[root@control ~]# ansible-playbook items.yml
PLAY [dbs] ****************************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [192.168.190.105]
TASK [mkdir] **************************************************************************************
ok: [192.168.190.105] => (item=/opt/a1)
ok: [192.168.190.105] => (item=/opt/a2)
TASK [useradd] ************************************************************************************
changed: [192.168.190.105] => (item={u'name': u'a1', u'groups': u'root'})
changed: [192.168.190.105] => (item={u'name': u'a2', u'groups': u'root'})
PLAY RECAP ****************************************************************************************
192.168.190.105 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
③ 查看结果
[root@control ~]# ansible dbs -a 'ls -l /opt/'
192.168.190.105 | CHANGED | rc=0 >>
总用量 4
drwxr-xr-x 2 root root 6 5月 7 18:54 a1
drwxr-xr-x 2 root root 6 5月 7 18:54 a2
-rwxrwxrwx 1 fql fql 465 5月 6 22:03 fstab.bak
lrwxrwxrwx 1 root root 14 5月 6 22:14 fstab.link -> /opt/fstab.bak
drwxr-xr-x. 2 root root 6 3月 26 2015 rh
# a1、a2文件夹已创建
[root@control ~]# ansible dbs -a 'id a1'
192.168.190.105 | CHANGED | rc=0 >>
uid=2001(a1) gid=2001(a1) 组=2001(a1),0(root)
[root@control ~]# ansible dbs -a 'id a2'
192.168.190.105 | CHANGED | rc=0 >>
uid=2002(a2) gid=2002(a2) 组=2002(a2),0(root)
# 用户已创建
11. Templates 模块
11.1 概述
是一种创建配置文件的工具,在配置文件中,会有一些数据(如:ip 地址、主机名、端口、用户、页面路径等)会动态的改变,需要使用变量来表示;
template 模块就是将变量和动态文件结合起来,最终生成一个配置文件(需要动态改变)。文件使用 jinjia2 模块语言来编写,结尾(后缀)一定是 j2(xxx.j2)。
11.2 示例
使用 template 模块配置相关变量,通过 playbook 安装 apache。
① 先准备一个以 .j2 为后缀的 template 模板文件,设置引用的变量
[root@control yml]# cp /etc/httpd/conf/httpd.conf /opt/httpd.conf.j2
[root@control yml]# vim /opt/httpd.conf.j2
42 Listen {{http_port}}
96 ServerName {{server_name}}
120 DocumentRoot "{{html_path}}"
125 <Directory "{{html_path}}">
② 修改主机清单文件,使用主机变量定义一个变量名相同,而值不同的变量
[root@control yml]# vim /etc/ansible/hosts
[apache1]
192.168.190.104 http_port=666 server_name=www.abc.com html_path=/opt/
[apache2]
192.168.190.105 http_port=888 server_name=www.efg.com html_path=/opt/
③ 编写 playbook
[root@control yml]# pwd
/root/yml
[root@control yml]# vim httpd.yml
---
- hosts: apache1,apache2
vars:
- {package: httpd, service: httpd}
tasks:
- name: install package
yum: name={{package}} state=latest
- name: copy configure j2
template: src=/opt/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify: restart httpd
- name: copy html file
copy: src=/root/yml/index.html dest=/opt/ mode=644
notify: restart httpd
- name: start httpd server
service: name={{service}} enabled=true state=started
handlers:
- name: restart httpd
service: name={{service}} state=restarted
...
[root@control yml]# ansible-playbook httpd.yml --syntax-check
playbook: httpd.yml
④ 准备工作,卸载目标主机网站服务
管理节点:
[root@control ~]# ansible all -m yum -a "name=httpd state=removed"
#在Ansible中,all是一个用于指代所有主机的特殊关键字。当你在使用Ansible命令时,使用all会将命令应用到所有已定义的主机上。卸载httpd相关服务。
被管理节点:
[root@managed1 ~]# yum list | grep httpd | grep @
httpd-tools.x86_64 2.4.6-99.el7.centos.1 @updates
#检查是否还有安装httpd相关包。
管理节点:
[root@control ~]# ansible all -m yum -a "name=httpd-tools state=removed"
#卸载httpd工具包,避免影响安装httpd。
管理节点:
[root@control ~]# yum install -y httpd
#Ansible服务器安装网站服务
[root@control ~]# cp -rf /etc/httpd/conf/httpd.conf /opt/
⑤ 执行 playbook
[root@control yml]# echo welcome apache > index.html
[root@control yml]# ansible-playbook httpd.yml
[root@control yml]# ansible all -a 'systemctl status httpd'
192.168.190.105 | CHANGED | rc=0 >>
Main PID: 9400 (httpd)
192.168.190.104 | CHANGED | rc=0 >>
Main PID: 18585 (httpd)
⑥ 访问域名及对应端口
[root@control yml]# vim /etc/hosts
192.168.190.104 managed1 www.abc.com
192.168.190.105 managed2 www.efg.com
[root@control yml]# curl www.abc.com:666/index.html
welcome apache
[root@control yml]# curl www.efg.com:888/index.html
welcome apache
12. Tags 模块
12.1 概述
可以在一个 playbook 中为某个或某些任务定义“标签”,在执行此 playbook 时通过 ansible-playbook 命令使用 --tags 选项能实现仅运行指定的 tasks。playbook 还提供了一个特殊的 tags 为 always。作用就是当 tasks 中的 tags 为 always 时,无论执行哪一个 tags 时,定义有 always 的 tags 都会执行。且执行顺序从上往下。
是一种标记任务或一系列的任务的功能,通过任务或一个命令的任务列表上定义标记,可以在运行 playbook 时去选择你需要执行的任务或列表。
12.2 示例
① 编写 playbook
[root@control yml]# vim tag.yml
- hosts: apache2
tasks:
- name: copy file
copy: src=/etc/hosts dest=/opt/1.txt
tags:
- a
- name: touch file
file: path=/opt/2 state=touch
tags:
- always
- name: mkdir
file: path=/opt/3 state=directory
tags:
- b
[root@control yml]# ansible-playbook tag.yml --syntax-check
playbook: tag.ym
② 执行 playbook
[root@control yml]# ansible-playbook tag.yml --tags="b"
[root@control yml]# ansible apache2 -a 'ls -l /opt/'
192.168.190.105 | CHANGED | rc=0 >>
-rw-r--r-- 1 root root 0 5月 8 16:15 2
drwxr-xr-x 2 root root 6 5月 8 16:15 3
13. Roles 模块
13.1 概述
Ansible 为了层次化、结构化地组织 Playbook,使用了角色(roles),roles 可以根据层次型结构自动装载变量文件、task 以及 handlers 等。简单来讲,roles 就是通过分别将变量、文件、任务、模块及处理器放置于单独的目录中,并可以便捷地 include 它们。roles 一般用于基于主机构建服务的场景中,但也可以用于构建守护进程等场景中。
13.2 目录介绍
13.2.1 在一个 playbook 中使用 roles 的步骤
① 创建以 roles 命名的目录
mkdir /etc/ansible/roles/ -p # yum装完默认就有
② 创建全局变量目录(可选)
mkdir /etc/ansible/group_vars/ -p
touch /etc/ansible/group_vars/all # 文件名自己定义,引用的时候注意
③ 在 roles 目录中分别创建以各角色名称命令的目录,如 nginx、mysql
[root@control ~]# mkdir /etc/ansible/roles/nginx
[root@control ~]# mkdir /etc/ansible/roles/mysql
[root@control ~]# mkdir /etc/ansible/roles/php
④ 在每个角色命令的目录中分别创建files、handlers、tasks、templates、meta、defaults和vars目录,用不到的目录可以创建为空目录,也可以不创建
[root@control ~]# mkdir /etc/ansible/roles/nginx/{files,templates,tasks,handlers,vars,defaults,meta}
[root@control ~]# mkdir /etc/ansible/roles/mysql/{files,templates,tasks,handlers,vars,defaults,meta}
[root@control ~]# mkdir /etc/ansible/roles/php/{files,templates,tasks,handlers,vars,defaults,meta}
⑤ 在每个角色的 handlers、tasks、meta、defaults、vars 目录下创建 main.yml 文件,千万不能自定义文件名
[root@control ~]# touch /etc/ansible/roles/nginx/{defaults,vars,tasks,meta,handlers}/main.yml
[root@control ~]# touch /etc/ansible/roles/mysql/{defaults,vars,tasks,meta,handlers}/main.yml
[root@control ~]# touch /etc/ansible/roles/php/{defaults,vars,tasks,meta,handlers}/main.yml
⑥ 查看 roles 的目录结构
[root@control ~]# tree /etc/ansible/roles/
/etc/ansible/roles/
├── mysql
│ ├── defaults
│ │ └── main.yml
│ ├── files
│ ├── handlers
│ │ └── main.yml
│ ├── meta
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ ├── templates
│ └── vars
│ └── main.yml
├── nginx
│ ├── defaults
│ │ └── main.yml
│ ├── files
│ ├── handlers
│ │ └── main.yml
│ ├── meta
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ ├── templates
│ └── vars
│ └── main.yml
└── php
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── tasks
│ └── main.yml
├── templates
└── vars
└── main.yml
roles 内各目录含义解释:
files:
- 用来存放由 copy 模块或 script 模块调用的文件
templates:
- 用来存放 jinjia2 模板,template 模块会自动在此目录中寻找 jinjia2 模板文件
tasks:
- 此目录应当包含一个 main.yml 文件,用于定义此角色的任务列表,此文件可以使用 include 包含其它的位于此目录的 task 文件
handlers:
- 此目录应当包含一个 main.yml 文件,用于定义此角色中触发条件时执行的动作
vars:
- 此目录应当包含一个 main.yml 文件,用于定义此角色用到的变量
defaults:
- 此目录应当包含一个 main.yml 文件,用于为当前角色设定默认变量
meta:
- 此目录应当包含一个 main.yml 文件,用于定义此角色的特殊设定及其依赖关系
⑦ 编辑 yml 剧本针对不同主机去调用不同的角色
vim /etc/ansible/example.yml
⑧ 运行 ansible-playbook
cd /etc/ansible
ansible-playbook example.yml
13.3 示例:简单的LNMP
13.3.1 定义 nginx 角色变量
定义变量:可以定义在全局变量中,也可以定义在roles角色变量中,一般定义在角色变量中
[root@control ansible]# vim /etc/ansible/roles/nginx/vars/main.yml
epel:
- epel-release.noarch
page:
- nginx
service: nginx
13.3.2 编写 nginx 模块
[root@control ansible]# vim /etc/ansible/roles/nginx/tasks/main.yml
- name: install epel-release.noarch
yum: name={{epel}} state=latest
- name: install nginx
yum: name={{page}}
- name: start nginx
service: enabled=true name={{service}} state=started
13.3.3 定义 mysql 角色变量
[root@control ansible]# vim /etc/ansible/roles/mysql/vars/main.yml
page:
- mariadb
- mariadb-server
service: mariadb
13.3.4 编写 mysql 模块
[root@control ansible]# vim /etc/ansible/roles/mysql/tasks/main.yml
- name: install mysql
yum: name={{page}} state=latest
- name: start mysql
service: enabled=true name={{service}} state=started
13.3.5 定义 php 角色变量
[root@control ansible]# vim /etc/ansible/roles/php/vars/main.yml
page:
- php
- php-fpm
service: php-fpm
13.3.6 编写 php 模块
[root@control ~]# vim /etc/ansible/roles/php/tasks/main.yml
- name: install php
yum: name={{page}} state=latest
- name: start php-fpm
service: enabled=true name={{service}} state=started
13.3.7 定义主机清单
[root@control ~]# vim /etc/ansible/hosts
[nginx]
192.168.190.104
[mysql]
192.168.190.105
[php]
192.168.190.106
[lnmp:children]
nginx
mysql
php
13.3.8 编写 roles
[root@control ~]# cd /etc/ansible/
[root@control ansible]# vim roles.yml
- hosts: nginx
roles:
- nginx
- hosts: mysql
roles:
- mysql
- hosts: php
roles:
- php
[root@control ansible]# ls
ansible.cfg hosts roles roles.yml
13.3.9 启动剧本
所有机器添加DNS解析域名加速:
vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.190.103 control
192.168.190.104 managed1 www.abc.com
192.168.190.105 managed2 www.efg.com
192.168.190.106 managed3
[root@control ansible]# ssh 192.168.190.106
[root@control ansible]# sshpass -p '123' ssh-copy-id root@192.168.190.106
[root@control ansible]# ansible-playbook roles.yml
13.3.10 查看服务
[root@control ansible]# ansible nginx -a 'systemctl status nginx'
192.168.190.104 | CHANGED | rc=0 >>
Main PID: 26243 (nginx)
[root@control ansible]# ansible mysql -a 'systemctl status mariadb'
192.168.190.105 | CHANGED | rc=0 >>
Main PID: 16321 (mysqld_safe)
[root@control ansible]# ansible php -a 'systemctl status php-fpm'
192.168.190.106 | CHANGED | rc=0 >>
Main PID: 2772 (php-fpm)