Ansible剧本介绍
什么是剧本
playbook(剧本)是一个持久化的批量执行方法的模型,它要求使用yaml语法,具有简介明了,流程结构清晰明确等特点.playbook的配置文件类似于shell脚本,能持久化保存针对特殊需求的任务列表.单使用ansible命令,它虽然可以完成各种任务和需求,单丝配置复杂任务的时候,使用ansible命令就特别繁琐,而且效率特别低下,最有效的办法就是根据playbook给出的规范搭建剧本环境,并写入任务流程,最后使用ansible-playbook执行命令.
playbook剧本的优势
1,减少重复的书写指令: ansible backup -m file -a
2,看起来简洁清晰
3,功能强大,可以控制流程,比如:判断,循环,变量,标签
4,其他剧本可以复用
5,提供语法检查以及模拟执行
剧本的格式书写要求
playbook的语法,即yaml的语法,ansible采用了jinja2样式模版引擎来渲染yaml文件,我们不仅可以使用变量,也可以使用简单的结构化语句.
YAML格式特点
1,严格的缩进表示层级关系
2,不要使用tab缩进
3,:后面一定要有空格
4,-后面一定要有空格
5,YAML文件内容和Linux系统大小写判断方式保持一致,是区分大小写的,k/v的值均需大小写敏感
6,k/v的值可同行写也可以换行写,同行使用:分隔;
7,v可以是个字符,也可以是一个列表;
8,一个完整的代码块功能需要最少元素包括name: task;
9,文件后缀名需要改为yaml或yml,vim可以只能高亮提示
剧本的组成
hosts: 需要执行的主机
tasks: 需要执行的任务
name: 任务名称
playbook项目目录结构
以下是一个完整的playbook项目目录结构,图片中的一些概念术语,我们先介绍下.
- role: 从1.2版本开始,ansible加入role(角色)的概念,可以将role看成单独一个服务的概念,在执行流程中,我们即可执行多个role的任务,也可以单独使用一个role的信息;
- files: 该目录应该存放软件包,通用的文件等不用再流程需要更改的文件.在yaml文件中,我们可以不用指明这些文件的具体路径,只使用文件名即可传输;
- tasks: 该目录会存放我们任务的具体流程语句,当playbook执行该角色时会执行tasks下的main.yml文件,所以tasks必须存在main.yml文件;
- vars: 该目录会用于存全局变量,当一个值存在复用的情况,我们可以在vars的main.yml中定义变量,方便后面的扩展和修改;
- meta: meta文件可以引用其他role的流程,并先于当前流程执行.
- default:默认变量,在1.3版本添加中的特性,如果一个变量没有被定义,但在default中被定义了,那就会使用default中的变量,但如果被定义了过,则不会使用,意思就是说,default的变量的优先级别为最低.
- templates:该目录可以存放文本文件,但跟files不同的是,它可以使用jinja2语法.
- handlers: 存放一些额外的方法,但是这些方法不会被自动执行,只有tasks里触发该方法时才可以.
简单编写一个nginx安装剧本
- hosts: "{{ server }}"
remote_user: root
gather_facts: True
tasks:
- name: Gather the service facts
ansible.builtin.service_facts:
- name: yum安装nginx
yum:
name: [ "nginx" ]
state: latest
when: "'nginx.service' not in ansible_facts.services"
- name: 配置服务启动
service:
name: nginx
state: started
enabled: yes
hosts: "{{ server }}"
: 这指定了该剧本将在哪些主机上运行,{{ server }}
是一个变量,表示目标主机的列表。在这里,剧本将在指定的主机上执行。remote_user: root
: 这指定了远程主机上用于连接的用户。在这里,剧本将使用 root 用户连接到远程主机。gather_facts: True
: 这指定了是否在执行任务之前收集远程主机的事实信息。在这里,将会收集有关主机的信息,如操作系统、IP 地址等。tasks
: 这部分包含了具体的任务列表。
Gather the service facts
: 这是一个任务,它使用ansible.builtin.service_facts
模块收集远程主机上的服务信息。yum安装nginx
: 这是一个任务,它使用yum
模块安装 Nginx 软件包。条件when
指定了只有当 Nginx 服务未安装时才执行此任务。配置服务启动
: 这是一个任务,它使用service
模块配置 Nginx 服务。它将确保 Nginx 服务已启动并设置为开机自启动。
模拟执行
ansible-playbook -C nginx_install.yml -e "server=10.10.10.236"
用-C 或者--check都行
剧本高级特性-循环
官方文档
https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_loops.html
应用场景
安装多个软件
创建多个目录
复制多个目录
复制多个文件到不同的目录
不同的文件权限不一样
循环书写风格:单行模式
- name: create_data
file: path=/data state=directory owner=www group=www
- name: create_backup
file: path=/backup state=directory owner=www group=www
循环书写风格:缩进模式
以前的写法:
- name: create_data
file:
path: /data
state: directory
owner: www
group: www
- name: create_backup
file:
path: /backup
state: directory
owner: www
group: www
循环实现:
- name: create_dir
file:
path: {{ item }}
state: directory
owner: www
group: www
loop:
- /data
- /backup
循环书写风格:多参数循环模式
- name: create_dir
file:
path: {{ item.path }}
state: directory
owner: www
group: www
mode: "{{ item.mode }}"
loop:
- { path: '/data', mode: '755'}
- { path: '/backup', mode: '644'}
循环写法之with_items
- name: 创建nginx日志目录
file: name={{ item }} state=directory owner=www group=www mode: 0755 recurse=yes
with_items:
- "{{ NGINX_DIR }}/logs/admin"
- "{{ NGINX_DIR }}/logs/adminapi"
是不是见过这种with_items,目前的话已经被loop所替代了
另类写法达到和循环一样的效果
- hosts: "{{ server }}"
remote_user: root
gather_facts: True
tasks:
- name: yum安装php环境依赖包
yum:
name: "{{ packages }}"
state: latest
vars:
packages:
- pcre
- pcre-devel
- zlib
- zlib-devel
- gd
- gd-devel
循环配合条件when使用
- hosts: "{{ server }}"
remote_user: root
gather_facts: True
tasks:
- name: check if /data directory does not exist
ansible.builtin.stat:
path: "/data"
register: data_dir_stat
- name: check if /backup directory does not exist
ansible.builtin.stat:
path: "/backup"
register: backup_dir_stat
- name: create_dir
ansible.builtin.file:
path: "{{ item.path }}"
state: directory
owner: www
group: www
mode: "{{ item.mode }}"
loop:
- { path: '/data', mode: '755'}
- { path: '/backup', mode: '644'}
when: data_dir_stat.stat.exists == false and backup_dir_stat.stat.exists == false
当然根据官方文档还有其他更多的用法,这个具体我们查看官方文档好了,还是比较有趣的
剧本高级特性-变量
应用场景
自定义某个变量,在任务中被多次引用
从主机收集到系统信息里提取某个变量,比如ip地址,主机名
自定义变量并引用
- hosts: backup
vars:
data_path: /data/
dest_path: /etc/
file_path: /etc/rsync.passwd
tasks:
- name: 01mkdir
file:
path: "{{ data_path }}"
state: directory
- name: 02copy
copy:
src: "{{ file_path }}"
dest: "{{ dest_path }}"
使用内置变量获取主机信息
比如我们需要获取主机的ip和主机名信息来修改配置,这种需求场景也是较常见
- hosts: "{{ server }}"
remote_user: root
gather_facts: True
tasks:
- name: gen info
ansible.builtin.debug:
msg: "{{ ansible_hostname }}: {{ ansible_default_ipv4.address }}"
剧本高级特性-注册变量
应用场景
调式,回显命令执行的内容
把状态保存成变量,其他任务可以进行判断或引用
比较常见的是,当我们安装一个服务时先判断服务是否已经被安装了,如果被安装了那就跳过不执行
- hosts: "{{ server }}"
remote_user: root
gather_facts: False
tasks:
- name: Gather the package facts
ansible.builtin.package_facts:
manager: auto
- name: filebeat_install
ansible.builtin.debug:
msg: "start filebat_install step"
when: "'filebeat' not in ansible_facts.packages"
剧本高级特性-服务状态管理
应用场景
有时我们希望仅在计算机上发生更改时运行,例如,如果任务更新了服务的配置,我们希望重新启动该服务,但如果配置未更改,则不需要重新启动,ansible使用handlers来处理这个问题
官方文档:https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html
通知处理程序
任务可以使用关键字指示一个或多个处理程序执行notify,该notify关键字可以应用于任务并接受在任务更改时收到通知的处理程序名称列表,或者也可以提供包含单个处理程序名称的字符串
tasks:
- name: Template configuration file
ansible.builtin.template:
src: template.j2
dest: /etc/foo.conf
notify:
- Restart apache
- Restart memcached
handlers:
- name: Restart memcached
ansible.builtin.service:
name: memcached
state: restarted
- name: Restart apache
ansible.builtin.service:
name: apache
state: restarted
剧本高级特性-选择标签
应用场景
调试,选择性执行任务
打印出playbook里要执行的所有标签
ansible-playbook --list-tags rsync_install.yaml
指定运行某个标签
ansible-playbook -t '03-install nfs service' rsync_install_tag.yaml
指定运行多个标签
ansible-playbook -t 01-add-group,02-add-user,05-create-data-dir rsync_install_tag.yaml
指定不运行某个标签
ansible-playbook --skip-tags 01-add-group rsync_install_tag.yaml
指定不运行多个标签
ansible-playbook --skip-tags 01-add-group,02-add-user,04-copy-nfs-exports rsync_install_tag.yaml
剧本高级特性-选择tasks
应用场景
调式任务,从某个任务开始往下执行
查看task列表
ansible-playbook --list-tasks php.yml -e "server=10.10.10.236"
选择从哪一个task开始运行
ansible-playbook --start-at-task 'Gather the service facts' php.yml -e "server=10.10.10.236"
Ansible角色介绍
为什么需要使用角色
写成一个yaml不太灵活,臃肿
全部写在一起,修改不太方便
配置文件随便放,不标准
角色解决了什么问题
把剧本拆分
解耦,结构更清晰,调试更方便
编写角色的最佳实践
初级阶段,不要直接写就角色,先写好剧本,然后拆分
一开始不要想一步到位,不用拆的很细,尤其是变量
角色目录规划
官方说明
https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.html
目录说明
注意,这里的目录结构必须按照官方定义的要求来做,不要自己随便乱起,可以看我最上面发的
我们还可以在某些目录中添加其yaml文件,例如你可以将特定于平台的任务放在单独的文件中,并在tasks/main.yml文件中引用它们
如何使用角色
可以通过三种方式使用角色:
- 在剧本级别,可以使用roles,这是在剧本中使用角色的经典方式
- 在任务级别可以使用include_role, 可以动态地在任务剧本部分的任何地方使用include_role
- 在任务级别还可以使用import_role,可以静态地在任务剧本中的任何位置使用import_role
这在企业运维中使用剧本是非常常见的
未来规划
目前有个任务中心的子系统,分为系统调用公共部分和平时处理工作的特殊部分,大概脑图是这样,大佬只给了图,没有具体源码
这个让新手练练手我觉得还是不错的