Ansible playbook(剧本)
详情请参考[Ansible实践笔记]自动化运维工具Ansible(一):初探ansible&ansible的点对点模式
文章目录
- Ansible playbook(剧本)
- 介绍
- 核心字段
- 环境配置
- 案例:配置apache虚拟主机
- 准备配置文件
- 准备playbook剧本
- 利用ansible语法检查工具检查yaml文件(不加语法检查也会检查语法)
- 执行playbook
- 测试虚拟主机的功能
- 案例:安装并修改nginx配置文件
- 创建nginx文件存放目录
- 编写nginx配置文件
- 编写yaml文件
- 检查playbooky语法并执行
- 测试功能
- 变量
- Ansible中jinja2模板
- 语法
- 变量
- 控制语句
- 案例:批量生成hosts解析文件
- 准备模板文件
- 编写playbook剧本
- 执行剧本
- Role(角色)
- 角色的生成(初始化自定义Role)
- Role目录结构
- 例:用Role安装httpd
- 初始化角色httpd
- 为httpd配置虚拟主机及根目录
- 当前role目录状态
- 到上级目录创建剧本
- 执行剧本
- 检验效果
介绍
-
playbook是一个task组成的列表,可以让这些列表按照事先编排的机制执行
-
task是指调用ansible的具体模块,在模块参数中可以使用变量
-
模块的执行是幂等性的,意味着多次执行的结果相同
-
使用yaml语言编写playbook,后缀名为.yaml
核心字段
字段 | 含义 |
---|---|
hosts | 执行的远程主机列表 |
tasks | 任务,由模块定义操作列表 |
variables | 内置变量或自定义变量 |
templates | 模板文件(一般用jinjia2语言编写) |
handlers | 为条件触发操作,满足条件则执行(通常与nogity结合使用) |
roles | 角色 |
环境配置
为了下面的实验更加直观,对ansible的主机清单进行修改
tail -n 10 -f /etc/ansible/hosts
我们先把之前下载安装的httpd服务卸载了
ansible -m service -a "name=httpd state=stopped" node2
ansible -m yum -a "name=httpd state=absent" node2
案例:配置apache虚拟主机
准备配置文件
mkdir -p /root/playbook/file # 递归创建playbook配置文件目录
cd /root/playbook/file&&touch site.conf
# cat site.conf
Listen 8080
Listen 9090
<Directory "/data/web">
Require all granted
</Directory>
<VirtualHost *:8080>
DocumentRoot "/data/web/site1/"
</VirtualHost>
<VirtualHost *:9090>
DocumentRoot "/data/web/site2/"
</VirtualHost>
准备playbook剧本
vim apache_playbook.yaml
- name: virtual web servers
hosts: node3
remote_user: root
tasks:
- name: install httpd
yum:
name: httpd
state: latest
- name: create dir site1
file:
name: /data/web/site1
state: directory
- name: create dir site2
file:
name: /data/web/site2
state: directory
- name: create web index
shell: echo "site1" > /data/web/site1/index.html && echo "site2" > /data/web/site2/index.html
- name: create apache conf
copy:
src: /root/playbook/file/site.conf
dest: /etc/httpd/conf.d/site.conf
- name: enable and start apache
service:
name: httpd
enabled: yes
state: started
利用ansible语法检查工具检查yaml文件(不加语法检查也会检查语法)
ansible-playbook apache_playbook.yaml --syntax-check
执行playbook
ansible-playbook apache_playbook.yaml
报错server3不可达,检查了一下,小case,server3没开机
再来一遍发现前几个任务都是可以正常执行的
到了启动apache这一步就报错了
检查后发现是没有禁用selinux
setenforce 0 # 临时禁用selinux
再执行一次
测试虚拟主机的功能
elinks 192.168.28.100:8080
elinks 192.168.28.100:9090
案例:安装并修改nginx配置文件
创建nginx文件存放目录
mkdir -p /root/nginx/{conf,bin}
编写nginx配置文件
vim /root/nginx/conf/site.conf
server {
listen 8848;
server_name localhost;
location /{
root /data;
index index.html
}
}
编写yaml文件
- name: nginx install && configuration
hosts: node1
remote_user: root
tasks:
- name: install epel
yum:
name: epel-release.noarch
state: latest
- name: install nginx
yum:
name: nginx
state: present
- name: ensure /data directory exists
file:
path: /data
state: directory
mode: '0755'
- name: copy configure file
copy:
src: /root/nginx/conf/site.conf
dest: /etc/nginx/conf.d/site.conf
- name: create index
shell: echo "this is nginx_yaml test web!" > /data/index.html
- name: set correct permissions for index.html
file:
path: /data/index.html
owner: nginx
group: nginx
mode: '0644'
- name: start nginx
service:
name: nginx
state: restarted
检查playbooky语法并执行
为了避免因为防火墙导致的问题,直接禁用selinux
ansible -m selinux -a "policy=targeted state=disabled" all_servers
ansible-playbook nginx.yaml --syntax-check
ansible-playbook nginx.yaml
nginx启动失败了,检查一下配置文件语法发现是第八行的{
附近出了问题
# 看看配置文件
cat /etc/nginx/nginx.conf
句柄末尾少了一个分号,那我们得根治源头的/root/nginx/conf/site.conf文件
vim /root/nginx/conf/site.conf
# 加上分号应该就可以了
server1卡住了,我们先用server2看看到底行不行
vim /playbook/nginx.yaml
# 把node1改成node2
完美
测试功能
elinks 192.168.28.77:8848
变量
ansible中变量的来源
- 主机清单里配置的 ip 、主机名 、主机组的对应关系
- 自定义变量
优先级
- 通过命令行指定的变量优先级最高
- /etc/ansible/hosts中定义的变量
- playbook中定义的变量
Ansible中jinja2模板
-
由python编写,在使用模板文件时jinja2是很好的解决方案
-
功能是将模板文件中的变量转换成对应主机的确定值
语法
数据类型 | 表示 |
---|---|
字符串 | 用双引号或单引号代表字符串 |
列表 | [] |
元组 | () |
字典 | {} |
算术表达式 | ±*/等 |
比较操作 | ==、!=、<、>等等 |
逻辑运算 | and或者or |
变量
{{name}}
控制语句
{% if 条件 %}
{{ name1 }}
{% else %}
{{ name2 }}
{% endif %}
# 如果条件成立,渲染name1,条件不成立,渲染name2
案例:批量生成hosts解析文件
先看看之前创建的主机清单
cat /etc/ansible/hosts
[all_servers]
server1
server2
server3
[node1]
server1
[node2]
server2
[node3]
server3
准备模板文件
mkdir jinja2 &&cd jinja2
vim hosts.j2
因为前一段对本机解析都是一样的,所以我们随便从一台复制都可以
ssh root@server1
cat /etc/hosts
exit
echo "127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
" > hosts.j2
看看有没有成功
cat hosts.j2
由于是模板,所以我们要向hosts.j2写入一些通用的代码段
循环遍历一个服务器列表(all_servers
),并打印出每个服务器的IPv4地址和主机名。这段代码假设您已经使用Ansible的事实收集功能获取了关于ens33网络接口的信息
{% for host in all_servers %}
{{hostvars[host].ansible_ens33.ipv4.address}} {{hostvars[host].ansible_hostname}}
{% endfor %}
# 常见变量
主机名: "{{ ansible_hostname }}"
操作系统版本: "{{ ansible_distribution }}" "{{ ansible_distribution_version }}"
内核版本: "{{ ansible_kernel }}"
系统位数: "{{ ansible_userspace_bits }}"
网卡:"{{ ansible_eth0["device"] }}"
IP地址: "{{ ansible_eth0["ipv4"]["address"] }}"
子网掩码: "{{ ansible_eth0["ipv4"]["netmask"] }}"
总内存: "{{ ansible_memory_mb["real"]["total"] }}"
内存空闲: "{{ ansible_memfree_mb }}"
cat /root/jinja2/hosts.j2
编写playbook剧本
vim /root/playbook/hosts.yaml
- name: config hosts file
hosts: all_servers
remote_user: root
tasks:
- name: copy hosts.j2 to all_servers
template:
src: /root/jinja2/hosts.j2
dest: /etc/hosts
执行剧本
ansible-playbook /root/playbook/hosts.yaml
成功
再检查一下
ansible -m shell -a "cat /etc/hosts" all_servers
ssh root@server1
ssh root@server2
Role(角色)
- 在角色中,将tasks、files、handles、templates等内容分开存放,在playbook中可以直接调用角色
- 通过
ansible-galaxy
工具初始化角色
角色的生成(初始化自定义Role)
ansible-galaxy init apache
Role目录结构
apache/
├── defaults # 定义角色的默认变量
│ └── main.yml
├── files
├── handlers # 定义角色的默认处理程序
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks # 定义角色的主要任务
│ └── main.yml
├── templates # 存放角色使用的模板文件
├── tests # 存放角色测试相关文件
│ ├── inventory
│ └── test.yml
└── vars # 定义角色变量
└── main.yml
例:用Role安装httpd
初始化角色httpd
规定角色httpd要执行的任务
ansible-galaxy init httpd
tree httpd/
vim /httpd/tasks/main.yml
- name: install httpd
yum:
name: httpd
state: present
- name: copy site.conf to httpd/conf.d/
copy:
src: site.conf
dest: /etc/httpd/conf.d/site.conf
- name: create dir /data/site1 site2
file:
name: "{{ item }}"
state: directory
loop:
- /data/site1
- /data/site2
- name: create web index
shell: echo "<h1>in site1<h1>" > /data/site1/index.html && echo "<h1>in site2<h1>" > /data/site2/index.html
- name: start service
service:
name: httpd
state: started
为httpd配置虚拟主机及根目录
vim file/site.conf
Listen 8080
Listen 9090
<Directory "/data/">
require all granted
</Directory>
<VirtualHost *:8080>
DocumentRoot "/data/site1/"
</VirtualHost>
<VirtualHost *:9090>
DocumentRoot "/data/site2/"
</VirtualHost>
当前role目录状态
到上级目录创建剧本
我这里统一把剧本放在了playbook文件夹下
vim playbook/httpd_role.yaml
- name: install httpd
hosts: node3
roles:
- httpd
执行剧本
ansible-playbook playbook/httpd_role.yaml
检验效果
elinks 192.168.28.100:8080
# elinks 192.168.28.100:9090