一、Ansible playbook 简单概述

playbook 是 ansible 用于配置,部署,和管理被控节点的剧本。通过 playbook 的详细描述,执行其中的一系列 tasks ,可以让远端主机达到预期的状态。playbook 就像 Ansible 控制器给被控节点列出的的一系列 to-do-list ,而被控节点必须要完成。也可以这么理解,playbook 字面意思,即剧本,现实中由演员按照剧本表演,在 Ansible 中,这次由计算机进行表演,由计算机安装,部署应用,提供对外服务,以及组织计算机处理各种各样的事情。

二、Ansible playbook 使用场景

执行一些简单的任务,使用 ad-hoc 命令可以方便的解决问题,但是有时一个设施过于复杂,需要大量的操作时候,执行的 ad-hoc 命令是不适合的,这时最好使用 playbook。就像执行 shell 命令与写 shell 脚本一样,也可以理解为批处理任务,不过 playbook 有自己的语法格式。使用 playbook 你可以方便的重用这些代码,可以移植到不同的机器上面,像函数一样,最大化的利用代码。在你使用 Ansible 的过程中,你也会发现,你所处理的大部分操作都是编写 playbook。可以把常见的应用都编写成 playbook,之后管理服务器会变得十分简单。

三、Ansible playbook 格式

1、书写格式

playbook 由 YMAL 语言编写。YAML( /ˈjæməl/ ) 参考了其他多种语言,包括:XML、C 语言、Python、Perl 以及电子邮件格式 RFC2822,Clark Evans 在 2001 年 5 月在首次发表了这种语言,另外 Ingy döt Net 与 OrenBen-Kiki 也是这语言的共同设计者。YMAL 格式是类似于 JSON 的文件格式,便于人理解和阅读,同时便于书写。首先学习了解一下 YMAL 的格式,对我们后面书写 playbook 很有帮助。以下为 playbook 常用到的YMAL格式:

1、文件的第一行应该以  "---"  (三个连字符)开始,表明 YMAL 文件的开始。
2、在同一行中,# 之后的内容表示注释,类似于 shell,python 和 ruby。
3、YMAL 中的列表元素以 ”-” 开头然后紧跟着一个空格,后面为元素内容。
4、同一个列表中的元素应该保持相同的缩进。否则会被当做错误处理。
5、play 中 hosts,variables,roles,tasks 等对象的表示方法都是键值中间以 ":" 分隔表示,":" 后面还要增加一个空格。

下面是一个举例:

---
#安装与运行mysql服务
- hosts: node1remote_user: roottasks:- name: install mysql-server packageyum: name=mysql-server state=present- name: starting mysqld serviceservice: name=mysql state=started

我们的文件名称应该以 .yml 结尾,像我们上面的例子就是 mysql.yml。其中,有三个部分组成:

hosts :使用 hosts 指示使用哪个主机或主机组来运行下面的 tasks ,每个 playbook 都必须指定 hosts ,hosts 也可以使用通配符格式。主机或主机组在 inventory 清单中指定,可以使用系统默认的 /etc/ansible/hosts,也可以自己编辑,在运行的时候加上 -i 选项,指定清单的位置即可。在运行清单文件的时候,–list-hosts 选项会显示那些主机将会参与执行 task 的过程中。

remote_user:指定远端主机中的哪个用户来登录远端系统,在远端系统执行 task 的用户,可以任意指定,也可以使用 sudo,但是用户必须要有执行相应 task 的权限。

tasks:指定远端主机将要执行的一系列动作tasks 的核心为 ansible 的模块,前面已经提到模块的用法。tasks 包含 name 和要执行的模块,name 是可选的,只是为了便于用户阅读,不过还是建议加上去,模块是必须的,同时也要给予模块相应的参数

使用 ansible-playbook 运行 playbook 文件,得到如下输出信息,输出内容为 JSON 格式。并且由不同颜色组成,便于识别。一般而言:

| 绿色代表执行成功,系统保持原样

| 黄色代表系统代表系统状态发生改变

| 红色代表执行失败,显示错误输出

执行有三个步骤:

1、收集 facts

2、执行 tasks

3、报告结果

2、核心元素

Playbook 的核心元素:

Hosts:主机组;
Tasks:任务列表;
Variables:变量,设置方式有四种;
Templates:包含了模板语法的文本文件;
Handlers:由特定条件触发的任务;

3、基本条件

Playbooks 配置文件的基础组件:

Hosts:运行指定任务的目标主机
remoute_user:在远程主机上执行任务的用户;
sudo_user:
tasks:任务列表

a、tasks 格式

tasks:
– name: TASK_NAMEmodule: argumentsnotify: HANDLER_NAMEhandlers:
– name: HANDLER_NAMEmodule: arguments

b、模块,模块参数

(1) action: module arguments

(2) module: arguments

注意:shell 和 command 模块后面直接跟命令,而非 key=value 类的参数列表;

c、handlers:任务,在特定条件下触发或者接收到其它任务的通知时被触发

(1) 某任务的状态在运行后为 changed 时,可通过 “notify” 通知给相应的 handlers;

(2) 任务可以通过 “tags“ 打标签,而后可在 ansible-playbook 命令上使用 -t 指定进行调用;

c、举例

① 定义 playbook

[root@server ~]# cd /etc/ansible[root@server ansible]# vim nginx.yml---- hosts: webremote_user: roottasks:- name: install nginxyum: name=nginx state=present- name: copy nginx.confcopy: src=/tmp/nginx.conf dest=/etc/nginx/nginx.conf backup=yesnotify: reload #当nginx.conf发生改变时,通知给相应的 handlerstags: reloadnginx #打标签- name: start nginx serviceservice: name=nginx state=startedtags: startnginx #打标签handlers: #注意,前面没有-,是两个空格- name: reloadservice: name=nginx state=restarted #为了在进程中能看出来

② 测试运行结果

写完了以后,我们就可以运行了:

[root@server ansible]# ansible-playbook nginx.yml

现在我们可以看看两台机器的端口是否开启:

[root@server ansible]# ansible web -m shell -a 'ss -nutlp |grep nginx'192.168.37.122 | SUCCESS | rc=0 >>
tcp    LISTEN     0      128       *:80                    *:*                   users:(("nginx",pid=8304,fd=6),("nginx",pid=8303,fd=6))
192.168.37.133 | SUCCESS | rc=0 >>
tcp    LISTEN     0      128       *:80                    *:*                   users:(("nginx",pid=9671,fd=6),("nginx",pid=9670,fd=6))

③ 测试标签

我们在里面已经打上了一个标签,所以可以直接引用标签。但是我们需要先把服务关闭,再来运行剧本并引用标签:

[root@server ansible]# ansible web -m shell -a 'systemctl stop nginx'
[root@server ansible]# ansible-playbook nginx.yml -t startnginx

④ 测试 notify

我们还做了一个 notify,来测试一下。首先,它的触发条件是配置文件被改变,所以我们去把配置文件中的端口改一下:

[root@server ansible]# vim /tmp/nginx.conf
listen       8080;

然后我们重新加载一下这个剧本:

发现我们执行的就是 reload 段以及我们定义的 notify 部分。我们来看一看我们的端口号:

 [root@server ansible]# ansible web -m shell -a 'ss -ntlp | grep nginx'192.168.37.122 | SUCCESS | rc=0 >>
LISTEN     0      128          *:8080                     *:*                   users:(("nginx",pid=2097,fd=6),("nginx",pid=2096,fd=6))
192.168.37.133 | SUCCESS | rc=0 >>
LISTEN     0      128          *:8080                     *:*                   users:(("nginx",pid=3061,fd=6),("nginx",pid=3060,fd=6))

可以看出,我们的 nginx 端口已经变成了 8080。

4、variables 部分

上文中,我们说到了 variables 是变量,有四种定义方法,现在我们就来说说这四种定义方法:

① facts :可直接调用

setup 这个模块就是通过调用 facts 组件来实现的。我们这里的 variables 也可以直接调用 facts 组件。具体的 facters 我们可以使用 setup 模块来获取,然后直接放入我们的剧本中调用即可。

② 用户自定义变量

我们也可以直接使用用户自定义变量,想要自定义变量有以下两种方式:

通过命令行传入:ansible-playbook 命令的命令行中的 -e VARS, --extra-vars=VARS,这样就可以直接把自定义的变量传入。

在 playbook 中定义变量:我们也可以直接在 playbook 中定义我们的变量。示例如下:

vars:
- var1: value1
- - var2: value2

5、variables 举例

① 定义剧本

我们就使用全局替换把我们刚刚编辑的文件修改一下:

[root@server ansible]# vim nginx.yml

这样一来,我们的剧本就定义完成了。

② 拷贝配置文件

我们想要在被监管的机器上安装什么服务的话,就直接在我们的 server 端上把该服务的配置文件拷贝到我们的/tmp/目录下。这样我们的剧本才能正常运行。我们就以 keepalived 服务为例:

[root@server ansible]# cp /etc/keepalived/keepalived.conf /tmp/keepalived.conf

③ 运行剧本,变量由命令行传入

[root@server ansible]# ansible-playbook nginx.yml -e rpmname=keepalived

④ 修改剧本,直接定义变量

同样的,我们可以直接在剧本中把变量定义好,这样就不需要在通过命令行传入了。以后想要安装不同的服务,直接在剧本里把变量修改一下即可。

[root@server ansible]# vim nginx.yml

⑤ 运行定义过变量的剧本

我们刚刚已经把变量定义在剧本里面了。现在我们来运行一下试试看:

[root@server ansible]# ansible-playbook nginx.yml

发现这样也是可以的。

a、通过 roles 传递变量

b、Host Inventory

我们也可以直接在主机清单中定义。

1、向不同的主机传递不同的变量:

IP/HOSTNAME varaiable=value var2=value2

2、向组中的主机传递相同的变量:

[groupname:vars]variable=value

6、模板 templates

模板是一个文本文件,嵌套有脚本(使用模板编程语言编写)。Jinja2:Jinja2 是 python 的一种模板语言,以 Django 的模板语言为原本。模板支持:

  字符串:使用单引号或双引号;
  数字:整数,浮点数;
  列表:[item1, item2, ...]
  元组:(item1, item2, ...)
  字典:{key1:value1, key2:value2, ...}
  布尔型:true/false
  算术运算:+, -, *, /, //, %, **
  比较操作:==, !=, >, >=, <, <=
  逻辑运算:and, or, not

通常来说,模板都是通过引用变量来运用的。

举例

① 定义模板

我们直接把之前定义的 /tmp/nginx.conf 改个名,然后编辑一下,就可以定义成我们的模板文件了:

[root@server ansible]# cd /tmp[root@server tmp]# mv nginx.conf nginx.conf.j2[root@server tmp]# vim nginx.conf.j2worker_processes  {{ ansible_processor_vcpus }};listen       {{ nginxport }};

② 修改剧本

我们现在需要去修改剧本来定义变量:

[root@server ansible]# vim nginx.yml

需要修改的部分如图所示。

③ 运行剧本

上面的准备工作完成后,我们就可以去运行剧本了:

[root@server ansible]# ansible-playbook nginx.yml -t reloadnginxPLAY [web] *********************************************************************
TASK [setup] *******************************************************************
ok: [192.168.37.122]
ok: [192.168.37.133]
TASK [copy nginx.conf] *********************************************************
ok: [192.168.37.122]
ok: [192.168.37.133]
PLAY RECAP *********************************************************************
192.168.37.122             : ok=2    changed=0    unreachable=0    failed=0
192.168.37.133             : ok=2    changed=0    unreachable=0    failed=0

7、条件测试

when 语句:在 task 中使用,jinja2 的语法格式。举例如下:

tasks:
- name: install conf file to centos7template: src=files/nginx.conf.c7.j2when: ansible_distribution_major_version == "7"
- name: install conf file to centos6template: src=files/nginx.conf.c6.j2when: ansible_distribution_major_version == "6"

循环:迭代,需要重复执行的任务;对迭代项的引用,固定变量名为"item",而后,要在task中使用with_items给定要迭代的元素列表。举例如下:

tasks:- name: unstall web packagesyum: name={{ item }} state=absentwith_items:- httpd- php- php-mysql

8、字典

ansible playbook 还支持字典功能。举例如下:

- name: install some packagesyum: name={{ item }} state=presentwith_items:- nginx- memcached- php-fpm
- name: add some groupsgroup: name={{ item }} state=presentwith_items:- group11- group12- group13
- name: add some usersuser: name={{ item.name }} group={{ item.group }} state=presentwith_items:- { name: 'user11', group: 'group11' }- { name: 'user12', group: 'group12' }- { name: 'user13', group: 'group13' }

9、角色定制:roles

① 简介

对于以上所有的方式有个弊端就是无法实现复用假设在同时部署 Web、db、ha 时或不同服务器组合不同的应用就需要写多个 yml 文件。很难实现灵活的调用。roles 用于层次性、结构化地组织 playbook。roles 能够根据层次型结构自动装载变量文件、tasks 以及 handlers 等。要使用 roles 只需要在 playbook 中使用 include 指令即可。简单来讲,roles 就是通过分别将变量 (vars)、文件 (file)、任务 (tasks)、模块 (modules) 及处理器 (handlers) 放置于单独的目录中,并可以便捷地 include 它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。

② 角色集合

角色集合:roles/
mysql/
httpd/
nginx/
files/:存储由 copy 或 script 等模块调用的文件;
tasks/:此目录中至少应该有一个名为 main.yml 的文件,用于定义各 task;其它的文件需要由 main.yml 进行“包含”调用;
handlers/:此目录中至少应该有一个名为 main.yml 的文件,用于定义各 handler;其它的文件需要由 main.yml 进行“包含”调用;
vars/:此目录中至少应该有一个名为 main.yml 的文件,用于定义各variable;其它的文件需要由 main.yml 进行“包含”调用;
templates/:存储由 template 模块调用的模板文本;
meta/:此目录中至少应该有一个名为 main.yml 的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要由 main.yml 进行“包含”调用;
default/:此目录中至少应该有一个名为 main.yml 的文件,用于设定默认变量;

③ 角色定制实例

1. 在 roles 目录下生成对应的目录结构

[root@server ansible]# cd roles/
[root@server roles]# ls
[root@server roles]# mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}
[root@server roles]# tree
.
├── httpd
│   ├── default
│   ├── files
│   ├── handlers
│   ├── meta
│   ├── tasks
│   ├── templates
│   └── vars
├── mysql
│   ├── default
│   ├── files
│   ├── handlers
│   ├── meta
│   ├── tasks
│   ├── templates
│   └── vars
└── nginx├── default├── files├── handlers├── meta├── tasks├── templates└── vars
24 directories, 0 files

2. 定义配置文件

我们需要修改的配置文件为 /tasks/main.yml,下面,我们就来修改一下:

[root@server roles]# vim nginx/tasks/main.yml- name: cpcopy: src=nginx-1.10.2-1.el7.ngx.x86_64.rpm dest=/tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm
- name: installyum: name=/tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm state=latest
- name: conftemplate: src=nginx.conf.j2 dest=/etc/nginx/nginx.conftags: nginxconfnotify: new conf to reload
- name: start serviceservice: name=nginx state=started enabled=true

3. 放置我们所需要的文件到指定目录

因为我们定义的角色已经有了新的组成方式,所以我们需要把文件都放到指定的位置,这样,才能让配置文件找到这些并进行加载。rpm 包放在 files 目录下,模板放在 templates 目录下:

[root@server nginx]# cp /tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm ./files/
[root@server nginx]# cp /tmp/nginx.conf.j2 ./templates/
[root@server nginx]# tree
.
├── default
├── files
│   └── nginx-1.10.2-1.el7.ngx.x86_64.rpm
├── handlers
├── meta
├── tasks
│   └── main.yml
├── templates
│   └── nginx.conf.j2
└── vars
7 directories, 3 files

4. 修改变量文件

我们在模板中定义的变量,也要去配置文件中加上:

[root@server nginx]# vim vars/main.ymlnginxprot: 9999

5. 定义handlers文件

我们在配置文件中定义了 notify,所以我么也需要定义 handlers,我们来修改配置文件:

[root@server nginx]# vim handlers/main.yml- name: new conf to reloadservice: name=nginx state=restarted

6. 定义剧本文件

接下来,我们就来定义剧本文件,由于大部分设置我们都单独配置在了 roles 里面,所以,接下来剧本就只需要写一点点内容即可:

[root@server ansible]# vim roles.yml - hosts: webremote_user: rootroles:- nginx

7. 启动服务

剧本定义完成以后,我们就可以来启动服务了:

[root@server ansible]# ansible-playbook roles.ymlPLAY [web] *********************************************************************TASK [setup] *******************************************************************
ok: [192.168.37.122]
ok: [192.168.37.133]TASK [nginx : cp] **************************************************************
ok: [192.168.37.122]
ok: [192.168.37.133]TASK [nginx : install] *********************************************************
changed: [192.168.37.122]
changed: [192.168.37.133]TASK [nginx : conf] ************************************************************
changed: [192.168.37.122]
changed: [192.168.37.133]TASK [nginx : start service] ***************************************************
changed: [192.168.37.122]
changed: [192.168.37.133]RUNNING HANDLER [nginx : new conf to reload] ***********************************
changed: [192.168.37.122]
changed: [192.168.37.133]PLAY RECAP *********************************************************************
192.168.37.122             : ok=6    changed=4    unreachable=0    failed=0
192.168.37.133             : ok=6    changed=4    unreachable=0    failed=0   

启动过后照例查看端口号:

[root@server ansible]# ansible web -m shell -a "ss -ntulp |grep 9999"192.168.37.122 | SUCCESS | rc=0 >>
tcp    LISTEN     0      128       *:9999                  *:*                   users:(("nginx",pid=7831,fd=6),("nginx",pid=7830,fd=6),("nginx",pid=7829,fd=6))192.168.37.133 | SUCCESS | rc=0 >>
tcp    LISTEN     0      128       *:9999                  *:*                   users:(("nginx",pid=9654,fd=6),("nginx",pid=9653,fd=6),("nginx",pid=9652,fd=6))

可以看出我们的剧本已经执行成功。

Ansible 学习总结(2)—— Ansible playbook 入门详解相关推荐

  1. 生成对抗网络入门详解及TensorFlow源码实现--深度学习笔记

    生成对抗网络入门详解及TensorFlow源码实现–深度学习笔记 一.生成对抗网络(GANs) 生成对抗网络是一种生成模型(Generative Model),其背后最基本的思想就是从训练库里获取很多 ...

  2. CNN入门详解及TensorFlow源码实现--深度学习笔记

    CNN入门详解及TensorFlow源码实现–深度学习笔记 ##一.卷积神经网络 ###1.简介 卷积神经网络是一种前馈神经网络,它的人工神经元可以响应一部分覆盖范围内的周围单元,对于大型图像处理有出 ...

  3. 委托(C#入门详解学习笔记)

    委托(C#入门详解学习笔记) 几个概念 什么是委托 委托的声明(自定义委托) 委托的常规使用 通用泛型委托类型的简单使用(Func和Action) 委托的高级使用 多播委托 委托的异步调用 使用接口取 ...

  4. FFmpeg入门详解之92:Live555学习之(一)-------Live555的基本介绍

    Live555学习之(一)-------Live555的基本介绍 前一阵子,因为项目需要,研究了一下Live555开源框架,研究的不是很深入,基本上把Live555当做API用了一下,但是毕竟也是本人 ...

  5. python语言编程基础-Python语言入门详解!快速学成Python!

    原标题:Python语言入门详解!快速学成Python! 很多技能是被职场所需要的,但很可惜... 这些技能在大学中并学习不到. 大学和职场现实存在的横沟对大部分同学来说难以跨越或碰得头破血流... ...

  6. python语言入门m-Python语言入门详解!快速学成Python!

    今日主题 "Python语言入门详解" 近两年来,Python语言借着数据科学和人工智能的"东风"成为了最流行的编程语言--街头巷尾人们口口相传.同时,Pyth ...

  7. python语言入门详解-python初级教程:入门详解

    python初级教程:入门详解 Crifan Li 目录 前言 .................................................................... ...

  8. 【GCN】图卷积网络(GCN)入门详解

    机器学习算法与自然语言处理出品 @公众号原创专栏作者 Don.hub 单位 | 京东算法工程师 学校 | 帝国理工大学 图卷积网络(GCN)入门详解 什么是GCN GCN 概述 模型定义 数学推导 G ...

  9. JDBC学习笔记02【ResultSet类详解、JDBC登录案例练习、PreparedStatement类详解】

    黑马程序员-JDBC文档(腾讯微云)JDBC笔记.pdf:https://share.weiyun.com/Kxy7LmRm JDBC学习笔记01[JDBC快速入门.JDBC各个类详解.JDBC之CR ...

最新文章

  1. linux 远程访问
  2. ES学习笔记之-AvgAggregation的实现过程分析
  3. 8. String to Integer (atoi)
  4. 它抢不走程序员的饭碗,但是会让一部分人瑟瑟发抖
  5. ICML 2020 | 基于连续动态系统学习更加灵活的位置编码
  6. node.js 建立live-server
  7. 量角器中Selenium定位器的完整指南(示例)
  8. 如何使用redis来实现常见的游戏排行榜
  9. 亚洲食品市场挑战:了解亚洲新消费群体
  10. 2017年java教材推荐_干货|2017年最新JavaEE课程大纲分享
  11. 学会asp后再学php,九天学会ASP 之 第二天
  12. 排球积分程序(二)——需求分析
  13. MySQL导入数据出错
  14. oracle 泵备份,Oracle逻辑备份之数据泵(一)
  15. C语言全局变量,局部变量,静态局部变量的区分
  16. Android对话框的使用
  17. 单片机74LS138扩展中断
  18. 扫码点餐系统开通后如何设置桌码和上传菜品?
  19. 安全私人云储存时代 H3C Magic M2脱颖而出
  20. android仿网易云音乐引导页、仿书旗小说Flutter版、ViewPager切换、风扇叶片效果等源码...

热门文章

  1. 列表 list的技巧
  2. 记录linux历史命令,如何将Linux系统的历史操作命令删除,并不再记录
  3. ndnsim r语言 ubuntu_Ubuntu14.04下配置ndnSIM-nom-rapid-car2car
  4. java序列化_今天聊聊 Java 序列化
  5. gitlab CI/CD 知识点查阅
  6. r730服务器内置SD卡位置,已解决: RE: 关于r730xd做存储服务器的疑问 - Dell Community...
  7. java多按钮筛选条件_Excel办公技巧:如何对表格数据进行自定义筛选?
  8. fastjson 序列化 不包括转义字符_fastjson再次发现漏洞,可能发生OOM导致宕机
  9. C语言丨格式化屏幕输出(二)——日历
  10. C++socket编程(五):5.2 tcp编程总结