python自动化运维九:Playbook

playbook:
playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’ 为元素的列表.
在 play 之中,一组机器被映射为定义好的角色.在 ansible 中,play 的内容,被称为 tasks,即任务.在基本层次的应用中,一个任务是一个对 ansible 模块的调用
Playbooks 的格式是YAML,语法做到最小化. 首先来介绍下YAML语法
YAML:
每一个 YAML 文件都是从一个列表开始. 列表中的每一项都是一个键值对, 通常它们被称为一个 “哈希” 或 “字典”. 所以, 我们需要知道如何在 YAML 中编写列表和字典. YAML 还有一个比较奇怪的地方. 所有的 YAML 文件(无论和 Ansible 有没有关系)开始行都应该是 ---. 这是 YAML 格式的一部分, 表明一个文件的开始.
列表中的所有成员都开始于相同的缩进级别, 并且使用一个 "- " 作为开头(一个横杠和一个空格):
---
#一个关于变成语言的列表
- python
- c++
- java
对应的Python 结果为:[‘python’,’c++’,’java’]
再来看一个块结构的表示方法
-
- python
- c++
- java
-
- mysql
- mongodb
对应的python结果:
[[‘python’,’c++’,’java’],[‘mysql’,’mongodb’]]
一个字典是由一个简单的 键: 值 的形式组成(这个冒号后面必须是一个空格):
---
# 一个出版书籍的记录
publish:
 name: Publisher
 city: chengdu
 province: sichuan
author:
 name: zhf
 age: 32
对应的python结果:
{‘publish’:{‘name’: ’Publisher’,’city’: ’chengdu’,’province’: ’sichuan’},’author’:{‘name’: ‘zhf’,’age’: 32}}
字典也可以使用缩进形式来表示, 如果你喜欢这样的话:
{name: Publisher,city: chengdu,province: sichuan}
从上面这些可以看出,YAML其实和JSON的格式很接近

 

回到playbook我们来看下tasks列表

每一个 play 包含了一个 task 列表(任务列表).一个 task 在其所对应的所有主机上(通过 host pattern 匹配的所有主机)执行完毕之后,下一个 task 才会执行.有一点需要明白的是(很重要),在一个 play 之中,所有 hosts 会获取相同的任务指令,这是 play 的一个目的所在,也就是将一组选出的 hosts 映射到 task

在运行 playbook 时(从上到下执行),如果一个 host 执行 task 失败,这个 host 将会从整个 playbook rotation 中移除. 如果发生执行失败的情况,请修正 playbook 中的错误,然后重新执行即可.

下面我们来看一个task的具体例子:

---

- hosts: webservers

  remote_user: root

tasks:

- name: for playbook test

  apt: name=curl state=latest

在这个例子中,host的地址为webservers中定义的主机IPremote_user: root代表已root用户执行

tasks:就是具体的任务 其中name为任务的名称, apt 就是ansible的远程命令模块 其中包含2个参数。name=curl代表要下载的软件名称,state=latest表示下载最新的

运行结果如下:任务成功执行并且在192.168.0.9上安装了curl软件包。其中TASK[for playbook test]就是我们这个任务的名称

root@zhf-linux:/home/zhf/zhf/python_prj/auto_manintance# ansible-playbook test.yml -f 10



PLAY ***************************************************************************



TASK [setup] *******************************************************************

ok: [192.168.0.9]



TASK [for playbook test] *******************************************************

changed: [192.168.0.9]



PLAY RECAP *********************************************************************

192.168.0.9 : ok=2 changed=1 unreachable=0 failed=0

我们再来看另外一个例子:在这个yml文件中。task中采用了command模块。command模块和shell模块比较特殊,它们不使用key=value的格式 而是直接使用命令。但是还是带有自有的一些参数。比如chdi/home/zhf/zhf就是指定切换到的目录。后面直接跟上rm tcpdumpresult.txt的命令删除文件

---

- hosts: webservers

  remote_user: root

tasks:

- name: for playbook test

  command: chdir=/home/zhf/zhf rm tcpdumpresult.txt

运行结果:

PLAY ***************************************************************************



TASK [setup] *******************************************************************

ok: [192.168.0.9]



TASK [for playbook test] *******************************************************

changed: [192.168.0.9]

[WARNING]: Consider using file module with state=absent rather than running rm





PLAY RECAP *********************************************************************

192.168.0.9 : ok=2 changed=1 unreachable=0 failed=0

在这个提示中,有一个warningConsider using file module with state=absent rather than running rm

这个的意思是让我们使用file模块 然后设置state=absent就可以删除文件。如果改成file模块使用的话yaml改成如下:

file: path=/home/zhf/zhf state=absent

 

 

 

我们再看一个template的模块调用方法。在做很多功能配置的时候,涉及到大量的配置文件的修改和替换。template就是用来完成这一功能的。官方翻译:template使用了Jinjia2格式作为文件模版,进行文档内变量的替换的模块。它的每次使用都会被ansible标记为”changed”状态。

 

例子:这个讲实现将本端的test1.yml文件内容渲染到远端主机的test1.yml文件中去

 

---

 

- hosts: webservers

 

  remote_user: root

 

tasks:

 

- name: use template function

 

  template: src=/home/zhf/zhf/python_prj/auto_manintance/test1.yml dst=/home/zhf/zhf/test1.yml

 


 

其实在task中都是调用ansible中的命令模块来触发操作的。ansible有很多模块。如果在主机上查询的花可以使用ansible-doc -s file的方式进行查询。 ansible-doc是查询命令。 -s后面接的是模块命令

 

或者也可以到网上查询网址是:http://docs.ansible.com/ansible/latest/modules_by_category.html

 

这里面有所有的ansible命令介绍。

 

YAML中还可以使用变量。通过vars:定义变量。在具体使用变量的过程中两个双括号包含变量。例子如下:

 

---

 

- hosts: webservers

 

vars:

 

filename: tcpdumpresult.txt

 

remote_user: root

 

tasks:

 

- name: for playbook test

 

  command: chdir=/home/zhf/zhf rm {{ filename }}

 

 

 

下面将介绍下handlers;

 

当我们再完成一些服务配置的时候往往会重启服务或者进行恢复。所以当远端系统被人改动时,可以重放 playbooks 达到恢复的目的。当发生改动时’notify’ actions 会在 playbook 的每一个 task 结束时被触发

 

下面的这个例子是在安装vsftpd后重启动这个服务。类似的只要执行结果中changed=1的都会触发notify操作。

 

---

 

- hosts: webservers

 

remote_user: root

 

tasks:

 

- name: for notify function test

 

apt: name=vsftpd state=latest

 

notify:

 

- restart vsftpd

 



 

include语句和角色:

 

首先来看下include语句,在用playbook实现一个很复杂的功能的时候,有可能会写一个很大的文件。而且这些文件的某些task在其他yml文件中也是被重用的。这样就没必要在每个yml中都去实现这些功能,这样效率也很低,我们应该想在编写软件代码的时候去组织这些文件。这里就需要用到include语句。include可以引用其他yml文件中的play。这种方式也被称为封装,将某些具体的功能给封装起来。我们来看一个例子,以前面删除文件的play来做示例。

 

首先来看test.yml。在task里面没有实现具体的操作。而是包含了test1.yml文件

 

---

 

- hosts: webservers

 

  remote_user: root

 

tasks:

 

- name: to verify include function

 

  include: test1.yml

 

再来看下test1.yml文件。里面没有了hostsremote_user等配置,而只是由普通的task列表组成。

 

---

 

- name: test1.yml to delete the file

 

command: rm /home/zhf/test2.txt

 

来看下执行结果:

 

root@zhf-linux:/home/zhf/zhf/python_prj/auto_manintance# ansible-playbook test.yml -f 10

 



 

PLAY ***************************************************************************

 



 

TASK [setup] *******************************************************************

 

ok: [192.168.0.9]

 



 

TASK [to verify include function] **********************************************

 

included: /home/zhf/zhf/python_prj/auto_manintance/test1.yml for 192.168.0.9

 



 

TASK [test1.yml to delete the file] ********************************************

 

changed: [192.168.0.9]

 

[WARNING]: Consider using file module with state=absent rather than running rm

 



 



 

PLAY RECAP *********************************************************************

 

192.168.0.9 : ok=3 changed=1 unreachable=0 failed=0

 

taskname来看,先执行test.yml. 然后调用test1.yml文件执行

 

我们在include的时候还可以往里面传递参数

 

tasks:

 

- name: to verify include function

 

  include: test1.yml path=/home/zhf/

 

然后在test1.yml中通过{{ path }}来使用path. 同样的你也可以在handler中去引用文件

 

notify:

 

- include: test1.yml

 



 

Role(角色)

 

现在已经学过 tasks handlers,那怎样组织 playbook 才是最好的方式呢?简单的回答就是:使用 roles ! Roles 基于一个已知的文件结构,去自动的加载某些 vars_filestasks 以及 handlers。基于 roles 对内容进行分组,使得我们可以容易地与其他用户分享 roles

 

我们来看一个例子: 在一个工程里面有2个角色。一个是dele 一个是添加。分别实现删除文件和添加文件。我们建立如下文件目录:

 

1 group_vars: 其中定义全局变量,所有的角色都可以使用

 

2 hosts定义主机的参数,否则默认使用/etc/ansible/hosts的参数。自定义参数通过ansible-playbook -i hosts来调用

 

3 role: 角色文件夹。其中包含2个角色 adddele. 在个2角色下分别有handlers, tasks,templatesvars文件夹。里面包含了各自的yml文件。角色中的vasrs里面的变量优先级高于group_vars中的变量

 

4 test.yml为整个程序的入口。从test.yml中引用具体的角色

 

一 首先我们来定义hosts文件。在里面添加主机IP

[webservers]

192.168.0.9

二 全局配置文件 test.yml. 在里面定义了2个角色分别是adddele. 将分别对这个2角色进行调用

---

- name: add function for role test

hosts: webservers

roles:

- add

- name: dele function for dele test

hosts: webservers

roles:

- dele

三 角色add的定义:

[handers/main.yml]

- name: restart ftp

  service: name=vsftpd state=restarted



[tasks/main.yml]

首先新建一个ftp_confg.conf文件。然后通过template命令将本段的ftp配置渲染到主机上的新建的文件

其中template中的src不用制定路径,默认在上级的templates目录中去寻找. 这里有一点很奇怪templatecommand不能写在同一个任务下面。否则会报错。提示语法错误

- name: add the configration of FTP

  command: chdir=/home/zhf touch ftp_config.conf.j2



- name: to template the file

template: src=ftp.conf.j2 dest=/home/zhf/ftp_config.conf.j2

[vars/main.yml]

定义FTP服务主机IP

---

ftpserver: 192.168.0.9

定义模板文件

[templates/ftp.conf.j2]

server {{ ftpserver }}



四 角色dele的定义:

task中删除掉之前建立的ftp_config.conf.j2

[task/main.yml]

- name: dele the configration of FTP

  command: chdir=/home/zhf rm ftp_config.conf.j2

[handlers/main.yml]

- name: after dele the conf then restart FTP

  service: name=vsftpd state=restarted

运行结果如下:

root@zhf-linux:/home/zhf/zhf/python_prj/role_test# ansible-playbook -i hosts test.yml -f 10



PLAY [add function for role test] **********************************************



TASK [setup] *******************************************************************

ok: [192.168.0.9]



TASK [add : add the configration of FTP] ***************************************

changed: [192.168.0.9]

[WARNING]: Consider using file module with state=touch rather than running

touch





TASK [add : to template the file] **********************************************

changed: [192.168.0.9]



PLAY [dele function for dele test] *********************************************



TASK [setup] *******************************************************************

ok: [192.168.0.9]



TASK [dele : dele the configration of FTP] *************************************

changed: [192.168.0.9]

[WARNING]: Consider using file module with state=absent rather than running rm





PLAY RECAP *********************************************************************

192.168.0.9 : ok=5 changed=3 unreachable=0 failed=0



最后来介绍下playbook的循环和条件执行方法:

通常一个任务会做很多事情。如创建大量的用户和文件。安装很多包等。通过with_items方法可以帮助我们循环执行任务。参考下面的例子:

command: chdir=/home/zhf touch {{ item }}.txt 这句中的item来自与with_items中的变量分别是test4test5

root@zhf-linux:/home/zhf/zhf/python_prj/auto_manintance# cat test2.yml

---

- hosts: webservers

  remote_user: root

tasks:

- name: create file by batch

  command: chdir=/home/zhf touch {{ item }}.txt

with_items:

- test4

- test5

这个示例与下面是等价的:

- name: create file by batch

  command: chdir=/home/zhf touch test4.txt

- name: create file by batch

  command: chdir=/home/zhf touch test5.txt

另外还可以嵌套循环:

- name: create file by batch

  command: chdir=/home/zhf touch {{ item[0] }}.txt rm {{ item[1] }}

with_nested:

- [‘test3’,’test4’]

- [‘test5’]



对哈希使用循环:

假如你有以下变量:

---
users:
  alice:
    name: Alice Appleworth
    telephone: 123-456-7890
  bob:
    name: Bob Bananarama
    telephone: 987-654-3210

你想打印出每个用户的名称和电话号码.你可以使用 with_dict 来循环哈希表中的元素:

tasks:
  - name: Print phone records
    debug: msg="User {{ item.key }} is {{ item.value.name }} ({{ item.value.telephone }})"
    with_dict: "{{users}}"



对文件列表使用循环:

---
- hosts: all

  tasks:

    # first ensure our target directory exists
    - file: dest=/etc/fooapp state=directory

    # copy each file over that matches the given pattern
    - copy: src={{ item }} dest=/etc/fooapp/ owner=root mode=600
      with_fileglob:
        - /playbooks/files/fooapp/*
其他循环方式可以参考:http://ansible-tran.readthedocs.io/en/latest/docs/playbooks_loops.html#looping-over-hashes

 

转载于:https://www.cnblogs.com/zhanghongfeng/p/7852798.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值