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.confListen 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 servershosts: node3remote_user: roottasks:- name: install httpdyum:name: httpdstate: latest- name: create dir site1file:name: /data/web/site1state: directory- name: create dir site2file:name: /data/web/site2state: directory- name: create web indexshell: echo "site1" > /data/web/site1/index.html && echo "site2" > /data/web/site2/index.html- name: create apache confcopy:src: /root/playbook/file/site.confdest: /etc/httpd/conf.d/site.conf- name: enable and start apacheservice:name: httpdenabled: yesstate: 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 && configurationhosts: node1remote_user: roottasks:- name: install epelyum:name: epel-release.noarchstate: latest- name: install nginxyum:name: nginxstate: present- name: ensure /data directory existsfile:path: /datastate: directorymode: '0755'- name: copy configure filecopy:src: /root/nginx/conf/site.confdest: /etc/nginx/conf.d/site.conf- name: create indexshell: echo "this is nginx_yaml test web!" > /data/index.html- name: set correct permissions for index.htmlfile:path: /data/index.htmlowner: nginxgroup: nginxmode: '0644'- name: start nginxservice:name: nginxstate: 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 filehosts: all_serversremote_user: roottasks:- name: copy hosts.j2 to all_serverstemplate:src: /root/jinja2/hosts.j2dest: /etc/hosts
执行剧本
ansible-playbook /root/playbook/hosts.yaml
成功
再检查一下
ansible -m shell -a "cat /etc/hosts" all_servers
ssh root@server1ssh 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 httpdyum:name: httpdstate: present- name: copy site.conf to httpd/conf.d/copy:src: site.confdest: /etc/httpd/conf.d/site.conf- name: create dir /data/site1 site2file:name: "{{ item }}"state: directoryloop:- /data/site1- /data/site2- name: create web indexshell: echo "<h1>in site1<h1>" > /data/site1/index.html && echo "<h1>in site2<h1>" > /data/site2/index.html- name: start serviceservice:name: httpdstate: 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 httpdhosts: node3roles:- httpd
执行剧本
ansible-playbook playbook/httpd_role.yaml
检验效果
elinks 192.168.28.100:8080
# elinks 192.168.28.100:9090