第四章、非常重要的playbook剧本编写

当篇文章需要读者细嚼慢咽,在结合实操即可明白。

一、playbook模块初步介绍

以一个简单的playbook为例,说明yaml的基本语法

  1. yaml⽂件以 - - - 开头,以表明这是⼀个yaml语言⽂件,就像常用的shell脚本⽂件在开头使⽤ #!/bin/bash 宣称它是shell脚本文件⼀样。但即使没有使⽤ - - - 开头,也不会有什么影响。
  2. yaml中使⽤"#“作为注释符,可以注释整⾏,也可以注释⾏内从”#"开始的内容。
  3. yaml中的字符串通常不⽤加任何引号,即使它包含了某些特殊字符。但有些情况下,必须加引号" ",最常见的是在引⽤变量的时候。

需要单独调用单个变量时候,必须加引用

4. 关于布尔值的书写格式
(我们一般使用的是yes或NO)也可以用true/false的表达⽅式。其实playbook中的布尔值类型⾮常灵活,可分为两种情况:

(一)、模块的参数(系统自带): 这时布尔值作为字符串直接被ansible解析。接受yes/on/1/true/no/of f /0/false等参数,这时被ansible解析。例如上⾯⽰例中的 update_cache=yes 。

(二)、⾮模块的参数: 这时布尔值被yaml解释器解析,完全遵循yaml语法。接受不区分⼤⼩写的 true/yes/on/y/f alse/no/off /n。例如上⾯的 gpgcheck=no 和 enabled=True 。建议遵循ansible的官⽅规范,模块的布尔参数采⽤yes/no,⾮模块的布尔参数采⽤True/False

5、playbook的内容

  • 每个play操作时都应该包含⼀个hosts(必须存在)和⼀个tasks值(当角色数值有时可以不存在),(除非定义第二play个否则)。

  • hosts定义规则的是inventory(主机清单)中待控制的主机,tasks下定义的是⼀系列task任务列表,⽐如调⽤各个模块。这些task按顺序⼀次执⾏⼀个,直到所有被筛选出来的主机都执⾏了这个task之后才会移动到下⼀个task上进⾏同样的操作。

  • 需要注意的是,虽然只有被筛选出来的主机(默认会读取清单中的)会执⾏对应的task,但是所有主机(此处的所有主机表⽰的是,hosts选项所指定的那些主机)都会收到相同的task指令,所有主机收到指令后,ansible主控端会筛选某些主机并将命令打包为.py的脚本,并通过ssh在远程执⾏任务。

6、判断结果规则
可以通过每次执行命令时可以依据判断

changed=2 受控节点发生改变
unreachable=0 受控制=节点不可达(出现数字)。

YAML字典(常用)
YAML中使用的key/value对也称为字典、散列或关联数组 在key/value对中,键与值通过由冒号和空格组成的分隔符隔开
如:

 name: 
 svcrole 
 svcservice: http 
 svcport: 80  

字典也可以使用内嵌块格式表示,其中多个key/value对用花括号括起,并由逗号和空格隔开

  • {name: svcrole, svcservice: http, svcport: 80}

7、YAML列表

  • 在YAML中,列表类似于其他编程语言中的数组 为表示一组列表项,使用一个短划线加一个空格作为每个列表项的前缀,以一排一排的方法
    hosts: - server1 - server2 列表也可使用内嵌块表示。
    其中多个列表项用方括号括起来并由逗号和空格隔开 hosts: [server1, server2]

8、playbook的预执行使用
ansible-playbook用于运行剧本,-C 测试运行结果,并不是真的执行任务,只是模拟。

[student@server ansible]$ ansible-playbook aa.yml -C

YAML语法和playbook写法
Playbook是通过积累一条一条的模块来运行的

在这里插入图片描述

ansible的playbook采用了yaml语法,它简单地实现了json格式的事件描述。在学习ansible playbook之前,很有必要把yaml的语法格式、引用方式做个梳理。

基本编写的与ansible-doc 帮助文档里面的模板类似

yaml 列表:
需要以yml后缀名为结尾
以yaml字典编写(一般用的最多是这种)

二、playbook操作实例

1、搭建仓库示范

[student@server ansible]$ vim aa.yml
---
- name: test              //某个横杠和冒号都需要接空格
 Hosts : node1           //定义自己的主机名
 tasks:                //任务清单
	- name:  mount cdrom            //自定义子目录中的名字
      mount:
	    src: /dev/cdrom
		dath: /mnt
		fstype: iso9660
		state: mounted


   - name: set repo1    //每个子模块下面需要缩进2字符
     yum_repository:
       file: server
       name: aa
       description: aa1
       baseurl: file:///mnt/BaseOS
       enabled: yes
       gpgcheck: no
       
   - name: set repo2
     yum_repository:
       file: server
       name: bb
       description: bb1
       baseurl: file:///mnt/AppStream
       enabled: yes
       gpgcheck: no
  • 直接输入自动对齐
    每一次: 后面都需要空格在换行输入

//运行命令
需注意的是当中间某个节点出现错误后面的程序则都不会运行

[student@server ansible]$ ansible-playbook aa.yml 

PLAY [test] ********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [node1]

TASK [mount cdrom] *************************************************************
ok: [node1]

TASK [set repo1] ***************************************************************
changed: [node1]

TASK [set repo2] ***************************************************************
changed: [node1]

PLAY RECAP *********************************************************************
node1                      : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

2、安装httpd实例

示例1:
1、 安装httpd

//server本机安装
[root@server html]# systemctl restart httpd
[root@server html]# systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
[root@server html]# ss -antl | grep httpd
[root@server html]# ss -antl | grep 80
LISTEN 0      128          0.0.0.0:80        0.0.0.0:* 
//防火墙处于关闭中
[root@server html]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor>
   Active: inactive (dead) 
[root@node1 www]# cat /var/www/html/index.html 
my name is liutianyang

后映射软连接就有了
[root@node1 www]# pwd
/www
[root@node1 www]# cat index.html 
my name is liutianyang

2、	开机自启
3、	给/var/www/html目录创建软链接/www

[student@server ansible]$ cat aa.yml 
---
- name: test
  hosts: node1
  tasks: 
   - name: mount cdrom
     mount: 
       src: /dev/cdrom
       path: /mnt
       fstype: iso9660
       state: mounted

   - name: set repo1                //定义好第一个yum源
     yum_repository: 
       file: server
       name: aa
       description: aa1
       baseurl: file:///mnt/BaseOS
       enabled: yes
       gpgcheck: no

   - name: set repo2              //定义第二个
     yum_repository: 
       file: server
       name: bb
       description: bb1
       baseurl: file:///mnt/AppStream
       enabled: yes
       gpgcheck: no

   - name: install httpd         //为node1安装httpd
     yum: 
       name: httpd
       statr: present

   - name: create link         //将本机的httpd网页存放目录映射为受控机的/www
     file: 
       src: /var/www/html
       dest: /www
       state: link

name: get file    //定义拉取
     get_url:
       url: http://servera.example.com/index.html
       dest: /www

   - name: set selinux context     //这里由于是映射,需要修改数值
     sefcontext: 
       target: /www/index.html    //受控机绝对路径
       setype: httpd_sys_content_t     //设置的值

   - name: apply context     //在次刷新数值
     shell: 
       cmd: restorecon -Rv /www/index.html

- name: modify apache config     //将其受控主机默认网页访问目录改为自己映射的/www
     replace: 
       path: /etc/httpd/conf/httpd.conf
       regexp: DocumentRoot "/var/www/html" 
       replace: DocumentRoot "/www"     //替换


   - name: modify apache config2
     replace: 
       path: /etc/httpd/conf/httpd.conf
       regexp: <Directory "/var/www">
       replace: <Directory "/www">

   - name: restart httpd      //将apache设为开机自启动
     service: 
       name: httpd
       state: restarted
       enabled: yes

   - name: set firewalld for http     //添加http放行防火墙规则
     firewalld: 
       service: httpd
       state: enabled
       permanent: yes

当运行剧本的时候可能由于我们大意打错了会导致报错
//这时所使用的子目录 -name 就派上用场了(一眼就知道那里错了)
在这里插入图片描述

//原来是配置文件中防火墙规则打成httpd了
在这里插入图片描述

//成功

这里已经替换掉的默认战点,类似于代理模块
[root@node1 html]# vim /etc/httpd/conf/httpd.conf
DocumentRoot “/www”
<Directory “/www”>

4、 从http://server.example.com/index.html下载至/www
5、 能够访问该web站点,documentroot是/www

[student@server ansible]$ curl http://node1
my name is liutianyang

2、条件判断用法

示例2:

notify handlers用法(当完成….任务时,则进行….任务)
[root@server ansible]# cat test.yml 
---
- name: this is a test playbook
hosts: node1
tasks: 
- name: create user1
   user: 
     name: user1
     state: present

  - name: create user2
    user: 
     name: user2
     state: present
    notify:               //当只有创建第二个user2时notify才会触发handlers程序去执行对应的任务
     - file3

 handlers:      //这里需与第一集目录相对应
  - name: file3      //指定file3如果user2创建则触发则执行命令,如果u2不触发则不会运行
    file: 
     path: /tmp/cy1
     state: touch
     mode: 0644

示例3:
1、 写一个剧本runtime.yml,只对node1操作
2、 创建用户aa,该用户不能用于登录,家目录/www
3、 在/www创建一个文件html
4、 每次执行该剧本时,将系统的当前时间输入到html文件中。
5、 如果html中的时间发生变化,那么创建/tmp/kk的文件

[student@ansible ~/ansible]$cat alone.yml
---
- name: time
hosts: node1
tasks:
- name: create user
user:
name: aa
shell: /sbin/nologin
home: /www
- name: create file
file:
path: /www/html
state: touch
- name: date
shell: date > /www/html
notify:
- kk
handlers:
- name: kk
file:
path: /tmp/kk
state: touch
[student@ansible ~/ansible]$ansible-playbook alone.yml
PLAY [time]
********************************************************************************************************
****
TASK [Gathering Facts]
*************************************************************************************************
ok: [node1]
TASK [create user]
*****************************************************************************************************
ok: [node1]
TASK [create file]
*****************************************************************************************************
changed: [node1]
TASK [date]
********************************************************************************************************
****
changed: [node1]
RUNNING HANDLER [kk]
***************************************************************************************************
changed: [node1]
PLAY RECAP
********************************************************************************************************
*****
node1 : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0
ignored=

[root@node1 ~]# ls /tmp/
aa
ansible_setup_payload_d9nvajm5
b
d
ggg
hhh
kk

3、tags标签示例

示例:4:
tags用法:给任务打标签,一个任务可以有多个标签,
参数-t来指定需要指定的任务标签。
tags
l2
l3
一般放在模板命令的最后,运行时可直接调用

注意:
其实ansible还预置了5个特殊的tag,这样可以执行一些命令的时候单独执行
1、always:如果添加此标签,不管是否命令行指定该任务,都执行

tag:
-	 always

2、never:不执行标签

	tag:
-	 never

3、tagged:在执行时使用 -t tagged 只执行带有标签(tags)的任务

[student@server ansible]$ ansible-playbook aa.yml -t tagged

4、 untagged:在执行时使用 -t untagged 只执行不带标签的任务,包含always标签也执行

[student@server ansible]$ ansible-playbook aa.yml -t untagged

5、all:所有任务都执行,默认标签。

6、自定义字典标签:

可以同时使用多个标签,需要用”,”隔开
–tags package,service playbook.yml

查看tag的标签类型
ansible-playbook –list-tags playbook.yml

//示范

[student@server ansible]$ cat test2.yml 
---
 - name: test playbook
  hosts: node1
  tasks: 
    - name: create user3
      user: 
        name: user3
        state: present
      tags: 
        - l1
        - l2 
    
    - name: create user4
      user:
        name: user4
        state: present
      tags: 
        - l2
        - l3

    - name: create user5
      user: 
        name: user5
        state: present
      tags: 
        - l3
        - l4

只执行l2标签的
[student@server ansible]$ ansible-playbook  test2.yml  -t  l2
  • ansible-playbook --skip-tags l1 test2.yml —跳过l1,其他执行,除了never外
  • ansible-playbook --tags always test2.yml --只执行always标签
  • ansible-playbook --tags tagged test2.yml --执行带标签任务,除了never标签外
  • ansible-playbook --tags untagged test2.yml --执行不带标签的任务,但是always仍执行
  • ansible-playbook --tags never test2.yml --执行never标签任务,但是always仍执行

文本可添加参数

写法:
Tags:
always

4、template模块

补充:template模块
1、template模块的使用方法和copy模块基本一致,但是copy模块从本地ansible节点复制文件到受控节点时,源文件的内容是什么就是什么,不能发生改变;而使用template模块复制文件时,源文件的内容可以随着受控主机的不同而发生变化。

2、使用template模块在server端写入文件变量时,该文件的扩展名必须为“.j2”。

例题1:创建模板文件html.j2,该文件的内容为
The 【受控主机的hostname】 address is 【IP地址】(需要随着受控主机的不同,文件的内容而发生变化)
每一台主机都会有自己的事实变量

1、编辑文件html.j2
[student@server ansible]$ cat html.j2 
the {{ansible_fqdn}} address is {{ansible_ens160.ipv4.address}}

2、撰写playbook,将模板文件复制到受控主机的/tmp/目录下,并重命名为html

[student@server ansible]$ vim a.yml
---
- name: test
  hosts: node1,node2
  tasks:
    - name: cp html.j2
      template:
        src: /etc/ansible/html.j2
        dest: /tmp/html

3、执行该playbook
Ansible-playbook  a.yml


4、分别去node1和node2两台受控主机中去验证,变量验证成功
Node1: 
[root@node1 ~]# cat /tmp/html 
the node1.example.com address is 172.16.30.10
[root@node1 ~]# 

Node2:
[root@node2 ~]# cat /tmp/html 
the node2.example.com address is 172.16.30.20
[root@node2 ~]# 

6、Copy模块

例题五:
Copy模块:
创建一个名为/home/student/ansible/b.yml的playbook
该playbook在所有的清单主机中运行
该playbook的内容为:
如果将受控主机的/tmp/chenyu文件的内容替换成如下:
在net主机组中的主机上,这行文本显示:chenyu
在hr主机组中的主机上,这行文本显示:cy123

[student@server ansible]$cat hosts
[net]
node1

[hr]        //主机组
node2

1、撰写剧本
[student@server ansible]$ vim b.yml
---
- name: test
  hosts: all
  tasks:
    - name: cp file
      copy:
        content: |      //判断当主机显示是那列hosts,则执行命令
          {% if "net" in group_names %}   //group…内置变量,if 则用来找清单中的主机组
          Chenyu                     //判断成功后则显示文本内容
          {% elif "hr" in group_names %}   
          cy123
          {% endif %}      //结束
        dest: /tmp/chenyu   //对受控主机的次目录进行执行

2、执行该剧本
Ansible-playbook  b.yml

3、验证:
Node1:
[root@node1 ~]# cat /tmp/chenyu 
chenyu
[root@node1 ~]# 

Node2:
[root@node2 ~]# cat /tmp/chenyu 
cy123
[root@node2 ~]# 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值