乐趣区

关于ansible:ansible使用笔记三Jinja2模板及playbook简介

ansible playbook 编写

一、Jinja2 模板简介
Jinja2 是什么
Jinja2 是基于 Python 的模板引擎, 蕴含变量和表达式两局部, 两者在模板求值时会被替换为值, 模板中还有标签, 管制模板的逻辑

为什么要学习 Jinja2 模板
因为 playbook 的模板应用 Python 的 Jinja2 模块来解决

Jinja2 模版的根本语法

  • 模板的表达式都是蕴含在他要分隔符 ”{{}}” 内的
  • 管制的语句都是蕴含在分隔符 ”{% %}” 内的
  • 模板反对正文, 都是蕴含在分隔符 '{# #}’ 内, 反对块正文
  • 调用变量
    {{varname}}
  • 计算
    {{2+2}}
  • 判断
    {{1 in {{1,2,3}}
  • Jinja2 模版管制语句
{% if name == '诗仙' %}
  李白
{% elif name == '诗圣' %}
  杜甫
{% elif name == '诗魔' %}
  白居易
{% else %}
  李贺
{% endif %}

Jinja2 过滤器
变量能够通过过滤器批改, 过滤器与变量用管道符号 (|) 宰割, 也能够用圆括号传递可选参数, 多个过滤器能够链式调用, 前一个过滤器的输入会被作业后一个过滤器的输出

例如:
加密一个字符串:{{‘astr’|password_hash(‘sha512’)}}

二、playbook 简介

playbook 是什么
playbook 是 ansible 用于配置, 部署和治理托管主机剧本, 通过 playbook 的详细描述, 执行其中一系列 tasks, 能够让远端主机达到预期的状态

也能够说 playbook 字面意思即剧本, 事实中由演员按剧本表演, 在 ansible 中由计算机进行装置, 部署利用, 提供对外服务, 以及组织计算机解决各种各样的事件

为什么要应用 palybook

  • 执行一些简略的工作, 应用 ad-hoc 命令能够不便的解决问题, 但有时一个设施过于简单时, 执行 ad-hoc 命令是不适合的, 最好应用 playbook
  • playbook 能够重复应用编写的代码, 能够放到不同机器下面, 像函数一样, 最大化的利用代码, 在应用 ansible 的过程中, 解决的大部分操作都是在编写 playbook

playbook 语法根底(1)

  • playbook 由 YAML 语文编写, 遵循 YAML 规范
  • 在同一行中,# 之后的内容示意正文
  • 同一个列表中元素应该放弃雷同缩进
  • playbook 由一个或多个 play 组成
  • play 中 host,variables,roles,tasks 等对角示意办法都是键值两头以 ”: “ 分隔示意
  • YAML 还有一个小的怪癖, 它的文件开始行都是以 —, 这是 YAML 格局的一部分, 表明一个文件的开始

playbook 形成

  • hosts: 定义交要执行 playbook 的近程主机级
  • vars: 定义 playbook 运行时须要应用的变量
  • tasks: 定义将要近程主机上执行的工作列表
  • handlers: 定义 task 执行实现当前须要调用的工作

playbook 执行后果
应用 ansible-playbook 运行 playbook 文件, 输入内容为 JSON 格局, 由不同色彩组成便于辨认

  • 绿色代表执行胜利
  • 黄色 代表零碎状态产生扭转
  • 红色代表执行失败

ansible 具备幂等性,幂等性可能保障咱们反复的执行一项操作时,失去的后果是雷同的,咱们再来回顾一下幂等性的概念

“ 幂等性 ” 是什么意思呢?举个例子,你想把一个文件拷贝到指标主机的某个目录上,然而你不确定此目录中是否曾经存在此文件,当你应用 ansible 实现这项工作时,就非常简单了,因为如果指标主机的对应目录中曾经存在此文件,那么 ansible 则不会进行任何操作,如果指标主机的对应目录中并不存在此文件,ansible 就会将文件拷贝到对应目录中,说白了,ansible 是 ” 以后果为导向的 ”,咱们指定了一个 ” 指标状态 ”,ansible 会主动判断,” 以后状态 ” 是否与 ” 指标状态 ” 统一,如果统一,则不进行任何操作,如果不统一,那么就将 ” 以后状态 ” 变成 ” 指标状态 ”,这就是 ” 幂等性 ”,” 幂等性 ” 能够保障咱们反复的执行同一项操作时,失去的后果是一样的。

有了幂等性的概念下面显示色彩代表的不同后果就比拟好了解了

  • 绿色 代表执行胜利 后果曾经和指定 ” 指标状态 ” 统一不须要批改
  • 黄色 执行胜利, 零碎状态产生扭转, 批改过 ” 指标状态 ”
  • 红色代表执行失败

三、playbook 编写

应用 ping 模块编写 第一个 playbook

[root@ansible default]# cat ping.yml 
---                   #第一行, 示意开始
- hosts: all          #近程主机, 多个能够用逗号孙隔开
  remote_user: root   #近程执行的用户名
  tasks:
  - name: ping test   #工作名称, 你也能够了解为备注信息, 会在执行中显示, 不便浏览
    ping:             #模块名 ping

[root@ansible default]# ansible-playbook ping.yml -f 5    #-f 并发过程数量, 默认是 5

PLAY [all] ******************************************************************************************

TASK [Gathering Facts] ******************************************************************************
ok: [cache]
ok: [web1]
ok: [web2]
ok: [db2]
ok: [db1]

TASK [ping test] ************************************************************************************
ok: [cache]
ok: [web1]
ok: [web2]
ok: [db1]
ok: [db2]

PLAY RECAP ******************************************************************************************
cache                      : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
db1                        : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
db2                        : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
web1                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
web2                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

playbook 语法根底(2)

  • tasks
    命令的汇合
    每一个 play 蕴含一个 task 列表(工作列表)
    一个 task 在其所对应的所有主机上(通过 hosts pattern 匹配的所有主机) 执行结束之后, 下一个 task 才执行
  • hosts
    主机的汇合
    定义要执行的主机

案例 1:
实现 给 web 主机增加用户 james
设置默认明码 123456, 并把 james 用户增加到 users 组

[root@ansible default]# cat user.yml 
---
- hosts: web
  remote_user: root
  tasks:
    - name: Add the user 'james'
      user:
        name: james
        groups: users 
    - name: set passwd
      shell: echo 123456|passwd --stdin james

[root@ansible default]# ansible-playbook user.yml 

PLAY [web] ******************************************************************************************

TASK [Gathering Facts] ******************************************************************************
ok: [web1]
ok: [web2]

TASK [Add the user 'james'] *************************************************************************
changed: [web1]
changed: [web2]

TASK [set passwd] ***********************************************************************************
changed: [web2]
changed: [web1]

PLAY RECAP ******************************************************************************************
web1                       : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
web2                       : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0

案例 2:
要求:
1. 所以 web 主机装置 Apache
2. 批改配置文件的监听端口为 8080
3. 设置默认页面 hello world
4. 启动服务
5. 设置开机自启

1)先在本面筹备默认拜访

[root@ansible default]# cat /root/index.htm
hello world

2)编号 playbook

[root@ansible default]# cat http.yml 
---
- hosts: web
  remote_user: root
  tasks:                                         
     - name: install one specific version of Apache   //tasks01. 装置 
       yum:
         name: httpd
         state: installed
     - lineinfile:                               //tasks02. 批改监听端口
           path: /etc/httpd/conf/httpd.conf
           regexp: '^Listen'
           line: 'Listen 8080'
     - copy:                                  //tasks03 替换主页 index.html
         src: /root/index.html
         dest: /var/www/html/index.html
     - service:                             //tasks04. 开启服务 
         name: httpd
         enabled: yes
         state: restarted
[root@ansible default]# ansible-playbook http.yml 

PLAY [web] ***********************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************
ok: [web1]
ok: [web2]

TASK [install one specific version of Apache] ************************************************************************************

changed: [web2]
changed: [web1]

TASK [lineinfile] ****************************************************************************************************************
changed: [web1]
changed: [web2]

TASK [copy] **********************************************************************************************************************
changed: [web2]
changed: [web1]

TASK [service] *******************************************************************************************************************
changed: [web2]
changed: [web1]

PLAY RECAP ***********************************************************************************************************************
web1                       : ok=5    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
web2                       : ok=5    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible default]# curl web1:8080    // 测试
holle world

四、playbook 进阶

4.1 变量

案例 3:**
要求: 增加用户 应用变量 username 代替
给 web 主机增加用户 james2, 设置默认明码 123456

[root@ansible default]# cat user2.yml 
---
- hosts: web
  remote_user: root
  vars:
    username: james2
  tasks:
    -
      name: Add the user  "{{username}}"
      user: 
        name: "{{username}}"
    -
      shell: echo 123456|passwd --stdin "{{username}}"

[root@ansible default]# ansible-playbook user2.yml 

PLAY [web] ************************

......

用户设明码
作完以上的试验你必定曾经发现为什么不必 user 模块间接设置明码, 而且用 shell 模块独自设置, 这是因为 user 模块是把 Password 字符串间接写入 shadow, 并没有扭转, 而 Linux 的 shadow 明码是通过加密的, 所以明文明码不能间接应用

解决方案
- 应用变量过滤器 password_hash
{{‘urpassword’|password_hash(‘sha512’)}}

最初的 playbook 如下

[root@ansible default]# cat user3.yml 
---
- hosts: web
  remote_user: root
  vars:
    username: james2
  tasks:
    - name: Add the user "{{username}}"
      user: 
        name: "{{username}}"
        group: root
        password: "{{'123qqq...A'|password_hash('sha512')}}"

变量参数
-e 传递变量或文件参数
-e @文件
文件的格局必须是 YAML 或 JSON 格局

[root@ansible default]# ansible-playbook user3.yml -e username=james4

PLAY [web] *******************************************************************************************

TASK [Gathering Facts] *******************************************************************************
ok: [web2]
ok: [web1]

TASK [Add the user "james4"] *************************************************************************
changed: [web2]
changed: [web1]

PLAY RECAP *******************************************************************************************
web1                       : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0 
web2                       : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0 

[root@ansible default]# ssh web1 id james4
uid=1007(james4) gid=0(root) 组 =0(root)

[root@ansible default]# cat username.yml 
---
username:
  james5

[root@ansible default]# ansible-playbook user3.yml -e @username.yml

PLAY [web] ******************************************************************************************

TASK [Gathering Facts] ******************************************************************************
ok: [web1]
ok: [web2]

TASK [Add the user "james5"] ************************************************************************
changed: [web2]
changed: [web1]

PLAY RECAP ******************************************************************************************
web1                       : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
web2                       : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible default]# cat username.yml 
---
username:
  james5
[root@ansible default]# ssh web1 id james5
uid=1008(james5) gid=0(root) 组 =0(root)

4.2 error 解决 ansible-playbook 对谬误的解决

因为 playbook 是程序执行, 当遇到谬误就会进行往下执行, 默认状况判断上一个工作 $?, 如果值不为 0 就进行执行
但某些状况咱们须要疏忽谬误继续执行

案例 4:
要求:
创立缓存目录, 而后重启 apache
1. 因为 /tmp/web 之前曾经存在 shell 模块 mkdir 报错 playbook 进行继续执行, 但其实这个谬误是不影响上面的工作执行

[root@ansible default]# cat Restart.yml 
---
- hosts: web
  remote_user: root
  tasks:
  - shell: mkdir /tmp/web
  - name: ReStart service httpd
    service:
      name: httpd
      state: restarted

[root@ansible default]# ansible-playbook Restart.yml 

PLAY [web] ******************************************************************************************

TASK [Gathering Facts] ******************************************************************************
ok: [web2]
ok: [web1]

TASK  ****************************************************************************************
[WARNING]: Consider using the file module with state=directory rather than running 'mkdir'.  If you
need to use command because file is insufficient you can add 'warn: false' to this command task or
set 'command_warnings=False' in ansible.cfg to get rid of this message.
fatal: [web2]: FAILED! => {"changed": true, "cmd": "mkdir /tmp/web", "delta": "0:00:00.008765", "end": "2020-11-19 16:55:04.967697", "msg": "non-zero return code", "rc": 1, "start": "2020-11-19 16:55:04.958932", "stderr": "mkdir: 无奈创立目录 \"/tmp/web\": 文件已存在", "stderr_lines": ["mkdir: 无奈创立目录 \"/tmp/web\": 文件已存在"], "stdout": "","stdout_lines": []}
fatal: [web1]: FAILED! => {"changed": true, "cmd": "mkdir /tmp/web", "delta": "0:00:00.007319", "end": "2020-11-19 16:55:05.751981", "msg": "non-zero return code", "rc": 1, "start": "2020-11-19 16:55:05.744662", "stderr": "mkdir: 无奈创立目录 \"/tmp/web\": 文件已存在", "stderr_lines": ["mkdir: 无奈创立目录 \"/tmp/web\": 文件已存在"], "stdout": "","stdout_lines": []}

PLAY RECAP ******************************************************************************************
web1                       : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
web2                       : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

错误处理办法:
增加谬误选项:ignore_errors
True 示意疏忽谬误继续执行
False 示意遇到谬误就进行执行(默认)

[root@ansible default]# cat Restart.yml 
---
- hosts: web
  remote_user: root
  tasks:
  - shell: mkdir /tmp/web
    ignore_errors: True
  - name: ReStart service httpd
    service:
      name: httpd
      state: restarted

[root@ansible default]# ansible-playbook Restart.yml 

PLAY [web] ******************************************************************************************

TASK [Gathering Facts] ******************************************************************************
ok: [web1]
ok: [web2]

TASK  ****************************************************************************************
[WARNING]: Consider using the file module with state=directory rather than running 'mkdir'.  If you
need to use command because file is insufficient you can add 'warn: false' to this command task or
set 'command_warnings=False' in ansible.cfg to get rid of this message.
fatal: [web2]: FAILED! => {"changed": true, "cmd": "mkdir /tmp/web", "delta": "0:00:00.007426", "end": "2020-11-19 17:01:57.077906", "msg": "non-zero return code", "rc": 1, "start": "2020-11-19 17:01:57.070480", "stderr": "mkdir: 无奈创立目录 \"/tmp/web\": 文件已存在", "stderr_lines": ["mkdir: 无奈创立目录 \"/tmp/web\": 文件已存在"], "stdout": "","stdout_lines": []}
...ignoring
fatal: [web1]: FAILED! => {"changed": true, "cmd": "mkdir /tmp/web", "delta": "0:00:00.014932", "end": "2020-11-19 17:01:57.853702", "msg": "non-zero return code", "rc": 1, "start": "2020-11-19 17:01:57.838770", "stderr": "mkdir: 无奈创立目录 \"/tmp/web\": 文件已存在", "stderr_lines": ["mkdir: 无奈创立目录 \"/tmp/web\": 文件已存在"], "stdout": "","stdout_lines": []}
...ignoring

TASK [ReStart service httpd] ************************************************************************
changed: [web2]
changed: [web1]

PLAY RECAP ******************************************************************************************
web1                       : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1   
web2                       : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1   

4.3 tags 标签

tags: 给指定的工作定义一个调用标识 有时把多个模块写在一个 playbook 中. 但只想用到其中一个或其中几个模块

- 应用办法在模块里增加 tags 标签
-playbook 调用形式
-t TAGS, –tags=TAGS
案例 5:
要求: 调用工作 task03 创立文件

[root@ansible default]# cat tags2.yml 
---
- hosts: web
  remote_user: root
  tasks:
    - name: task01
      file:
        path: /tmp/web/task01
        state: touch
      tags: t1
    - name: task02
      file:
        path: /tmp/web/task02
        state: touch
      tags: t2
    - name: task03
      file:
        path: /tmp/web/task03
        state: touch
      tags: t3

[root@ansible default]# ansible-playbook tags2.yml -t t3

PLAY [web] ******************************************************************************************

TASK [Gathering Facts] ******************************************************************************
ok: [web2]
ok: [web1]

TASK [task03] ***************************************************************************************
changed: [web2]
changed: [web1]

PLAY RECAP ******************************************************************************************
web1                       : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
web2                       : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible default]# ssh web1 ls /tmp/web/
task03

4.4 handlers

当关注的资源发生变化时采取的操作
notify 这个 action 可用于每个 play 的最初触发, 这样就能够防止有屡次扭转产生时每次都执行指定的操作, 取而代之仅在所有的变动产生实现后一次性执行指定操作

在 notify 中列出的操作称为 handler, 即 notify 调用 handler 中定义的操作

咱们还是拿下面的 httpd 服务举例
案例 6:
要求:
批改 httpd 默认 index.html 而后重启 httpd 服务

[root@ansible default]# cat RestartHttp.yml 
---
- hosts: web
  remote_user: root
  tasks:
  - copy:
      src: /root/index.html
      dest: /var/www/html/index.html
    ignore_errors: True
  - name: ReStart service httpd
    service:
      name: httpd
      state: restarted

[root@ansible default]# ansible-playbook RestartHttp.yml 

PLAY [web] *******************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************************************************
ok: [web1]
ok: [web2]

TASK [copy] ******************************************************************************************************************************************************************************************************
changed: [web2]
changed: [web1]

TASK [ReStart service httpd] *************************************************************************************************************************************************************************************
changed: [web2]
changed: [web1]

PLAY RECAP *******************************************************************************************************************************************************************************************************
web1                       : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
web2                       : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

第二次执行雷同操作

[root@ansible default]# ansible-playbook RestartHttp.yml 

第二次和第一次执行的区别是没有在拷贝文件, 因为第一次曾经拷贝过了, 但服务还是重启过两次, 看上去如同没问题, 但细想第二次文件没有改变过, 和咱们批改配置文件后重启服务的理论需要是有区别的, 或者说第二次服务重次是齐全没有必要的

这时就要用的 notify 调用 handler 中定义的操作
简略说就是当文件产生过改变后, 才重启服务

批改配置后

[root@ansible default]# cat RestartHttp.yml
---
- hosts: web
  remote_user: root
  tasks:
  - copy:
      src: /root/index.html
      dest: /var/www/html/index.html
    ignore_errors: True
    notify:
    - restart "ReStart service httpd"
    
  handlers:
  - name: ReStart service httpd
    service:
      name: httpd
      state: restarted

[root@ansible default]# ansible-playbook RestartHttp.yml 

PLAY [web] ******************************************************************************************

TASK [Gathering Facts] ******************************************************************************
ok: [web2]
ok: [web1]

TASK [copy] *****************************************************************************************
ok: [web1]
ok: [web2]

PLAY RECAP ******************************************************************************************
web1                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
web2                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

从执行后果来看 并没有重启 httpd 服务

4.5 when 条件判断

有些时候须要在满足特定条件后再触发某一项操作, 或在特定的条件下终止某个行为, 这时候须要进行条件判断,when 正是解决这个问题的最佳抉择, 行程中的零碎变量 facts 作为 when 的条件, 能够通过 setup 模块查看

案例 7:
咱们用 debug 模块做个测试 debug 模块咱们前面会讲到
通过两个 when 判断条件如果成立, 则输入 ”System release is centos7″

[root@ansible default]# cat when.yml 
---
- hosts: cache
  remote_user: root
  tasks:
  - debug:
      msg: "System release is centos7"
    when:
    - ansible_distribution == "CentOS"
    - ansible_distribution_major_version == "7"

[root@ansible default]# ansible-playbook when.yml 

PLAY [cache] ****************************************************************************************

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

TASK [debug] ****************************************************************************************
ok: [cache] => {"msg": "System release is centos7"}

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

4.6 register 返回值

有时候咱们还须要更简单的例子, 如判断前一个命令的执行后果去解决前面的操作, 这时候就须要 register 模块来保留前一个命令的返回状态, 在前面进行调用

案例 8:
要求: 把零碎负载太高的 Apache 服务进行
当零碎负载超过 0.7 时,则关掉 httpd

[root@web2 ~]# awk 'BEGIN{while(1){}}'    // 先用 awk 对 web2 进步零碎负载, 为测试创立条件

[root@ansible default]# ssh web2 uptime   // 曾经满足测试条件
 11:10:11 up 24 days, 17:47,  2 users,  load average: 0.88, 0.30, 0.14

root@all (5)[f:5]$ sys
[root@ansible default]# ansible-console web   // 通过 ansible-console 查看 httpd 状态
Welcome to the ansible console.
Type help or ? to list commands.

root@web (2)[f:5]$ systemctl status httpd
web1 | CHANGED | rc=0 >>
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since 四 2020-11-19 17:58:04 CST; 17h ago
......

web2 | CHANGED | rc=0 >>
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since 四 2020-11-19 17:58:03 CST; 17h ago
....

root@web (2)[f:5]$ exit

[root@ansible default]# cat when.yml 
---
- hosts: web
  remote_user: root
  tasks:
  - shell: uptime|awk '{printf("%.2f\n",$(NF-2))}'
    register: result                                      // 返回 shell 执行后果到变量 result
  - name: stop  service
    service:
      name: httpd
      state: stopped
    when: result.stdout|float > 0.7                // 对 result 后果进行判断

[root@ansible default]# ansible-playbook when.yml 

PLAY [web] ******************************************************************************************

TASK [Gathering Facts] ******************************************************************************
ok: [web1]
ok: [web2]

TASK  ****************************************************************************************
changed: [web1]
changed: [web2]

TASK [stop  service] ********************************************************************************
skipping: [web1]
changed: [web2]

PLAY RECAP ******************************************************************************************
web1                       : ok=2    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
web2                       : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible default]# ssh web2 systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: inactive (dead) since 五 2020-11-20 11:24:23 CST; 41s ago    //httpd 服务已敞开
......

4.7 with_items 循环

with_items 是 playbook 规范循环, 能够用于迭代一个列表或字典, 通过 {{item}} 获取每次迭代的值
案例 9:
要求: 一次性创立多个用户 nb、aa、plj、lx

[root@ansible default]# cat adduser.yml 
---
- hosts: cache
  remote_user: root
  tasks:
  - name: add users
    with_items: ["nb","aa","plj","lx"]
    user: group=wheel password={{'123456'|password_hash('sha512')}} name={{item}}
[root@ansible default]# ansible-playbook adduser.yml 

PLAY [cache] ****************************************************************************************

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

TASK [add users] ************************************************************************************
changed: [cache] => (item=nb)
changed: [cache] => (item=aa)
changed: [cache] => (item=plj)
changed: [cache] => (item=lx)

PLAY RECAP ******************************************************************************************
cache                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

4.8 include

在编写 playbook 的时候随随着我的项目越来越大,playbook 越来越简单, 批改也很麻烦, 这时能够把一些 paly、task 或 handler 放到其余文件中, 通过 include 指令蕴含进来是一个不错的抉择
蕴含项包含

  • vars: 变量层
  • tasks: 工作层
  • handlers: 触发条件
  • files: 文件
  • template: 模板
  • default: 默认, 优先级最低

案例 10:
把工作层独立进去

[root@ansible default]# cat include1.yml 
---
- hosts: cache
 remote_user: root
 tasks:
 - include: in3.yml    
   when: 2 > 1

[root@ansible default]# cat in3.yml 
- debug:
   msg: "task1 in in3.yml"
- debug:
   msg: "task2 in in3.yml"

[root@ansible default]# ansible-playbook include1.yml

4.9 debug 调试

如果对于 Python 语法不相熟的,playbook 书写起来容易出错, 且排错艰难, 这里介绍几种简略的排错调试形式

检测语法

  • ansible-playbook –syntax-check playbook.ymal

显示受到影响的主机

  • –list-hosts
    显示工作的 task
  • –list-tasks
    显示将要运行的 tag
  • –list-tags

测试运行
模仿运行后果, 但如果在工作列表中, 工作 2 须要工作 1 执行的后果, 那么工作 2 可能会报错, 因为工作 1 没有理论执行

  • ansible-playbook -C playbook.yaml

还能够在运行时输入更为具体的信息, 帮忙排错 比方: 变量的值

案例 11:
以之前 when.yml 为例, 查看 result 变量中的内容

[root@ansible default]# cat  when.yml 
---
- hosts: web
  remote_user: root
  tasks:
  - shell: uptime|awk '{printf("%.2f\n",$(NF-2))}'
    register: result
  - name: stop  service
    service:
      name: httpd
      state: stopped
    when: result.stdout|float > 0.7
  - name: Show debug info
    debug:
      var: result

[root@ansible default]# ansible-playbook when.yml 

PLAY [web] ******************************************************************************************

TASK [Gathering Facts] ******************************************************************************
ok: [web1]
ok: [web2]

TASK  ****************************************************************************************
changed: [web1]
changed: [web2]

TASK [stop  service] ********************************************************************************
skipping: [web1]
ok: [web2]

TASK [Show debug info] ******************************************************************************
ok: [web1] => {
    "result": {
        "changed": true, 
        "cmd": "uptime|awk'{printf(\"%.2f\\n\",$(NF-2))}'","delta":"0:00:00.010118","end":"2020-11-20 15:12:05.959884","failed": false,"rc": 0,"start":"2020-11-20 15:12:05.949766","stderr":"", 
        "stderr_lines": [], 
        "stdout": "0.04", 
        "stdout_lines": ["0.04"]
    }
}
ok: [web2] => {
    "result": {
        "changed": true, 
        "cmd": "uptime|awk'{printf(\"%.2f\\n\",$(NF-2))}'","delta":"0:00:00.010133","end":"2020-11-20 15:12:05.484865","failed": false,"rc": 0,"start":"2020-11-20 15:12:05.474732","stderr":"", 
        "stderr_lines": [], 
        "stdout": "2.04", 
        "stdout_lines": ["2.04"]
    }
}

PLAY RECAP ******************************************************************************************
web1                       : ok=3    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
web2                       : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=
退出移动版