自动化运维实践 | Ansible playbook重用
今天我们讲讲如何重用ansible的playbook。
playbook支持两种重用机制,一种是重用静态的单个playbook脚本,另外一种是重用实现特定功能的文件夹,类似于python等编程语言中的包。
- include语句:重用单个playbook脚本,使用起来简单、直接
- role语句:重用实现特定功能的playbook文件夹,使用方法稍复杂,功能强大。Ansible 还为role创建了一个共享平台AnsibleGalaxy,role是Ansible最为推荐的重用和分享Playbook的方式。
Include语句
include语句是最基本的Ansible代码重用机制,主要重用任务,同时,include还可将任务分割成多个文件,避免playbook过于臃肿,使用户更关注于整体的架构,而不是实现的细节上。
- 基本的include用法
与其他语言的include一样,直接include即可
tasks:
- include: tasks/add_firewalld_rule.yml
- 在include语句中使用参数
这里有两个知识点,一个是如何在被include的yml文件中定义参数,而是如何向include文件中传入参数。
1)被include的add_firewalld_rule.yml文件定义如下:
---
- name: insert the firewalld rule
firewalld: port={{ port }}/tcp permanent=true state=enabled immediate=yes
2)使用include, 并在使用时像include的文件中传入参数
tasks:
- include tasks/add_firewalld_rule.yml port=80
- include tasks/add_firewalld_rule.yml port=3260
- include tasks/add_firewalld_rule.yml port=8080
或者直接在playbook中定义参数,就不需要传入值了
vars:
port: 3260
remote_user: root
tasks:
- include tasks/add_firewalld_rule.yml
Role - Playbook中的"Package"
role比include有更强大的代码重用和分享机制。include类似于编程语言中的include,是重用单个文件的,重用的功能有限。
而role类似于编程语言中的"Package",可以重用一组文件,形成完整的功能。
- roles说明
roles意为角色,主要用于封装playbook实现复用性。在ansible中,roles通过文件的组织结构来展现。
首先需要有一个roles目录。同时,在roles目录所在目录中,还要有一个playbook文件,以下示例为nginx.yml,nginx.yml文件是ansible-playbook需要执行的文件,在此文件中定义了角色,当执行到角色时,将会到roles中对应的角色目录中寻找相关文件。
roles目录中的子目录是即是各个role。例如,此处只有一个名为halo的role,在role目录中,有几个固定名称的目录(如果没有则忽略)。在这些目录中,还要有一些固定名称的文件,除了固定名称的文件,其他的文件可以随意命名。以下是各个目录的含义:
- tasks目录:存放task列表。若role要生效,此目录必须要有一个主task文件main.yml,在main.yml中可以使用include包含同目录(即tasks)中的其他文件。
- handlers目录:存放handlers的目录,若要生效,则文件必须名为main.yml文件。
- files目录:在task中执行copy或script模块时,如果使用的是相对路径,则会到此目录中寻找对应的文件。
- templates目录:在task中执行template模块时,如果使用的是相对路径,则会到此目录中寻找对应的模块文件。
- vars目录:定义专属于该role的变量,如果要有var文件,则必须为main.yml文件。
- defaults目录:定义角色默认变量,角色默认变量的优先级最低,会被任意其他层次的同名变量覆盖。如果要有var文件,则必须为main.yml文件。
- meta目录:用于定义角色依赖,如果要有角色依赖关系,则文件必须为main.yml。
所以,相对完整的role的文件组织结构如下图。
├── roles
│ ├── halo
│ │ ├── defaults
│ │ ├── files
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── meta
│ │ │ └── main.yml
│ │ ├── tasks
│ │ │ └── main.yml
│ │ ├── templates
│ │ └── vars
│ │ └── main.yml
└── site.yml
举例:
使用role的方式来安装halo,相对来说,结构会比较清晰明了。还是使用ansible去自动部署halo博客系统。功能很简单,就是在一台机器上面自动部署java+halo+nginx服务。目录如下:
├── roles
│ ├── halo
│ │ ├── tasks
│ │ │ └── main.yml
│ │ ├── templates
│ │ │ ├── application.yaml
│ │ │ └── halo.service
│ │ └── vars
│ │ └── main.yml
│ ├── java
│ │ └── tasks
│ │ └── main.yml
│ └── nginx
│ ├── meta
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ └── templates
│ └── halo.conf
└── site.yml
主要分为3个role,由site.yml引入,内容如下:
# cat site.yml
---
- hosts: 192.168.1.61
remote_user: root
strategy: free
pre_tasks:
- name: config nginx repo for centos
yum_repository:
name: nginx
description: nginx
baseurl: http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck: no
when: ansible_distribution_major_version == "7"
- name: Disable SELinux
selinux: state=disabled
roles:
- nginx
post_tasks:
- shell: echo 'Deplay halo finished.'
register: ret
- debug: var=ret.stdout
pre_tasks为运行play之前的操作,post_tasks为运行完play之后的操作。主要是看nginx这个role的内容:
[root@localhost nginx]# cat tasks/main.yml
---
- name: make sure nginx state is installed
yum: name=nginx state=installed
- name: copy halo to nginx config file
template: src=halo.conf dest="/etc/nginx/conf.d/halo.conf"
- name: make sure nginx service is running
service: name=nginx state=started
- name: make sure port is open
wait_for: port="{{ nginx_port }}"
[root@localhost nginx]# cat meta/main.yml
---
dependencies:
- role: java
- role: halo
[root@localhost nginx]# cat templates/halo.conf
server {
listen ;
server_name {{ halo_domain }};
client_max_body_size m;
location / {
proxy_set_header HOST $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0..:{{halo_port}}/;
}
}
meta/main.yml为role的依赖关系,要先运行这里面的内容才会运行自己的nginx这个role。
java这个role很简单,只需要安装jdk即可。
[root@localhost java]# cat tasks/main.yml
---
- name: install java
yum: name=java-1.8.0-openjdk state=installed
而halo的内容如下:
[root@localhost halo]# cat tasks/main.yml
---
- name: get halo
get_url: url=http://halo.ryanc.cc/release/halo-latest.jar dest={{ halopath }}
- name: add halo service file
template: src=halo.service dest=/etc/systemd/system/halo.service
- name: touch ~/.halo directory
file: path=~/.halo state=directory
- name: copy halo config file
template: src=application.yaml dest="~/.halo/application.yaml"
- name: restart halo
systemd:
daemon_reload: yes
name: halo
state: started
enabled: yes
- name: wait to start halo
wait_for: port={{ halo_port }}
[root@localhost halo]# cat vars/main.yml
---
memory: m
halo_port:
halopath: /root/halo.jar
今天我们先介绍到这里,未完待续!
参考资料:
Ansible快速入门, 技术原理与实战。
https://www.wumingx.com/linux/ansible-roles.html
- Oracle 12c 多租户专题|CDB元数据内幕
- 深入分析golang多值返回以及闭包的实现
- Hadoop3.0扩展Yarn资源模型详解2:资源Profiles说明
- hdu------(1525)Euclid's Game(博弈决策树)
- Go语言指针访问结构体的方法
- Spring Boot & Spring Cloud 应用内存管理
- hdu----(1849)Rabbit and Grass(简单的尼姆博弈)
- 10分钟让你明白MySQL是如何利用索引的
- 扩展Yarn资源模型详解1
- hdu-------(1848)Fibonacci again and again(sg函数版的尼姆博弈)
- go语言实现将重要数据写入图片中
- poj-----(2528)Mayor's posters(线段树区间更新及区间统计+离散化)
- poj---(2886)Who Gets the Most Candies?(线段树+数论)
- Hadoop3.0通用版集群安装高可靠详细教程
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- CodePen vue SFC 、flutter 在线玩耍来袭
- [重拾CSS]一道面试题来看伪元素、包含块和高度坍塌
- webpack 拍了拍你,给了你一份图解指南(模块化部分)
- 深入探究Immutable.js的实现机制(一)
- 深入探究immutable.js的实现机制(二)
- ES6 Promise 的最佳实践
- 「 Map最佳实践」什么时候适合使用 Map 而不是 Object
- ES2017 异步函数的最佳实践(`async` /`await`)
- React Hooks中这样写HTTP请求可以避免内存泄漏
- 用了这 7 个 VS Code 插件,想写一辈子代码
- 听说你还不知道Promise的allSettled()和all()的区别?
- React 条件渲染最佳实践(7 种方法)
- 一文带你层层解锁「文件下载」的奥秘
- Android实现简单C/S聊天室应用
- Android仿IOS回弹效果 支持任何控件