ansible之when条件语法、处理任务失败、jinja2模板和项目管理

简介: ansible之when条件语法、处理任务失败、jinja2模板和项目管理

一、item---loop

1.给定数据如下:

使用loop来输出 My name is zhangsan/lisi My age is 18/20

 users:

    - name: zhangsan

      age: 18

    - name: lisi

       age: 20

[root@good ~]# vim playbook2.yml 
---
- name:
  hosts: rhce
  tasks:
    - name:
      shell: "{{ item }}"
      loop:
        - name: zhangsan
          age: 18
        - name: lisi
          age: 20
...
[root@good ~]# ansible-playbook playbook2.yml -C
PLAY [rhce] ********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [rhce]
TASK [shell] *******************************************************************
skipping: [rhce] => (item={'name': 'zhangsan', 'age': 18}) 
skipping: [rhce] => (item={'name': 'lisi', 'age': 20}) 
PLAY RECAP *********************************************************************
rhce                       : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

2.给定数据Services,要求使用loop来重启服务:

提示:将services定义为变量


可以使用lookup('dict', services)来进行转换或者使用{{ services | dict2items }}

services:

httpd:

name: httpd

state: restarted

firewalld:

name: firewalld

state: restarted

# 编辑文件
[root@good ~]# vim playbook2.yml 
---
- name:
  hosts: rhce
  tasks:
    - name:
      service:
        name: "{{ item.name }}"
        state: "{{ item.state }}"
      loop:
        - name: httpd
          state: restarted
        - name: firewalld
          state: restarted
...
# 执行命令
[root@good ~]# ansible-playbook playbook2.yml -C
PLAY [rhce] ********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [rhce]
TASK [service] *****************************************************************
changed: [rhce] => (item={'name': 'httpd', 'state': 'restarted'})
changed: [rhce] => (item={'name': 'firewalld', 'state': 'restarted'})
PLAY RECAP *********************************************************************
rhce                       : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

二、when条件任务语法

1.使用when,当条件成立时才执行任务:测试给定一个0/1,

#给1
- name: Simple Boolean task Demo
  hosts: rhce
  vars:
    run_my_task: 1
  tasks:
    - name: httpd package is installed
      yum:
        name: httpd
      when: run_my_task
#给0
- name: Simple Boolean task Demo
  hosts: rhce
  vars:
    run_my_task: 0
  tasks:
    - name: httpd package is installed
      yum:
        name: httpd
      when: run_my_task

2.给定一个未定义的变量

- name: Simple Boolean task Demo
  hosts: rhce
  tasks:
    - name: httpd package is installed
      yum:
        name: httpd
      when: run_my_task

3.给定一个变量当变量>10时才执行

- name: Simple Boolean task Demo
  hosts: rhce
  vars:
    run_my_task: 11
  tasks:
    - name: httpd package is installed
      yum:
        name: httpd
      when: run_my_task > 10

4.使用and 和 or来连接两个条件: True and False , True or False

# and 运算必须两个都为真
---
- name:
  hosts: rhce
  vars:
    true: 0
    false: 1
  tasks:
    - name:
      yum:
        name: httpd
      when: true == 1 and false == 1
...
不执行
# or 一个为真就可以
---
- name:
  hosts: rhce
  vars:
    true: 0
    false: 1
  tasks:
    - name:
      yum:
        name: httpd
      when: true == 1 or false == 1
...
执行

5.loop和when联合使用 1 中,当name == firewalld时不执行任务

# 编写playbook
---
- name:
  hosts: rhce
  tasks:
    - name:
      service:
        name: "{{ item.name }}"
        state: started
      loop:
        - name: firewalld
        - name: httpd
      when: item.name == "firewalld"
...
# 执行playbook
[root@good ~]# ansible-playbook playbook4.yml -C
PLAY [rhce] ********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [rhce]
TASK [service] *****************************************************************
changed: [rhce] => (item={'name': 'firewalld'})
skipping: [rhce] => (item={'name': 'httpd'}) 
PLAY RECAP *********************************************************************
rhce                       : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

三、notify和handler的使用

1.定义一个任务:使用shell模块执行 echo "123", 使用notify通知handler 任务 debug info

# 编写playbook
---
- name:
  hosts: rhce
  tasks:
    - name:
      debug:
        msg: echo'123'
      notify:
        - debug info
  handlers:
    - name: debug info
      shell: echo'123'
...
#执行
[root@good ~]# ansible-playbook playbook5.yml -C
PLAY [rhce] ********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [rhce]
TASK [debug] *******************************************************************
ok: [rhce] => {
    "msg": "echo'123'"
}
PLAY RECAP *********************************************************************
rhce                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

2.定义handler: 包含一个任务:debug info: 执行 输出: I handled the notify

# 编写playbook
---
- name:
  hosts: rhce
  tasks:
    - name:
      debug:
        msg: I handled the notify
      notify:
        - debug info
  handlers:
    - name: debug info
      shell: echo'123'
...
#执行
[root@good ~]# ansible-playbook playbook5.yml -C
PLAY [rhce] ********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [rhce]
TASK [debug] *******************************************************************
ok: [rhce] => {
    "msg": "I handled the notify"
}
PLAY RECAP *********************************************************************
rhce                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

3.tags使用:定义三个任务:分别打上标签:tag1, tag2, tag2

tags标签: 通过此标签来指定playbook文件执行哪条命令
- hosts: rhce
  remote_user: root
  tasks:
  - name: copy
    copy: content="apple" dest=/tmp/mama.txt
    tags: copy1  # 标签名是copy1,在下面执行文件时会用到
  - name: copy
    copy: content="banana" dest=/tmp/mama.txt
    tags: copy2  # 标签名是copy2,在下面执行文件时会用到
  - name: copy
    copy: content="egg" dest=/tmp/mama.txt
    tags: copy3  # 标签名是copy3,在下面执行文件时会用到

4.执行playbook, 且指定只执行tag2

#ansible-playbook -t copy2 pbook.yml  #执行文件中第二条copy2命令

四、处理任务失败

1.ignore_errors的使用: 定义任务使用command模块执行 test1111

默认情况下任务失败时play会终止。可以通过ingnore乎略失败,其他任务可以继续执行。
---
- name:
  hosts: rhce
  tasks:
    - name:
      command: 
      ignore_errors: yes
    - name:
      service:
        name: httpd
        state: started
...
#执行跳过失败
[root@good ~]# ansible-playbook playbook6.yml -C
PLAY [rhce] ********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [rhce]
TASK [command] *****************************************************************
fatal: [rhce]: FAILED! => {"changed": false, "cmd": null, "delta": null, "end": null, "msg": "no command given", "rc": 256, "start": null, "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring
TASK [service] *****************************************************************
changed: [rhce]
PLAY RECAP *********************************************************************
rhce                       : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1

2.再定义一个任务:使用debug模块输出: This is test for ignore errors(确保这个任务可以正常执行)

---
- name:
  hosts: rhce
  tasks:
    - name:
      debug:
        msg: This is test for ignore errors
      ignore_errors: yes
    - name:
      service:
        name: httpd
        state: started
...
# 执行
[root@good ~]# ansible-playbook playbook6.yml -C
PLAY [rhce] ********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [rhce]
TASK [debug] *******************************************************************
ok: [rhce] => {
    "msg": "This is test for ignore errors"
}
TASK [service] *****************************************************************
changed: [rhce]
PLAY RECAP *********************************************************************
rhce                       : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

3.failed_when: 定义一个任务: 使用shell模块执行echo 123, 将此任务设置为执行失败

vim playbook.yml
---
- name:
  hosts: rhce
  tasks:
    - name:
      shell: echo '123' 
      register: return_value #将echo的标准输出定义到return_value变量中
      failed_when: "'123' in return_value.stdout"  # 当'123' 在return_value中则执行失败
...
[root@good ~]# ansible-playbook playbook.yml 
PLAY [rhce] ********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [rhce]
TASK [shell] *******************************************************************
fatal: [rhce]: FAILED! => {"changed": true, "cmd": "echo '123'", "delta": "0:00:00.003196", "end": "2022-08-08 22:13:54.989842", "failed_when_result": true, "msg": "", "rc": 0, "start": "2022-08-08 22:13:54.986646", "stderr": "", "stderr_lines": [], "stdout": "123", "stdout_lines": ["123"]}
PLAY RECAP *********************************************************************
rhce                       : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0 

4.changed_when: 定义一个任务: 使用shell模块执行echo 123 > /root/changed_test, 将此任务的changed状态改为0

---
- name:
  hosts: rhce
  tasks:
    - name:
      shell: echo '123' > /root/changed_test
      changed_when: false
...
#当设置changed_when 为false,则该任务执行后永远不会返回changed状态,只返回ok或者failed。
[root@good ~]# ansible-playbook playbook6.yml 
PLAY [rhce] ********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [rhce]
TASK [shell] *******************************************************************
ok: [rhce]
PLAY RECAP *********************************************************************
rhce                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

5.block, rescue, always: 在block定义两个任务,在rescue中定义两个任务,在always中定义两个任务,让rescue中的任务可以执行

  • block: 定义要运行的主要的任务。
  • rescue: 定义要在block子句中定义的任务失败时运行的任务。
  • always:定义始终都独立运行的任务,不论block和rescue子句中定义的任务是否成功还是失败。
# 编写playbook
---
- name:
  hosts: rhce
  tasks:
    - name:
      block:
        - name:
          yum:
            name: 123
      rescue:
        - name:
          service:
            name: httpd
            state: started
      always:
        - name:
          service:
            name: firewalld
            state: started
...
# 执行
[root@good ~]# ansible-playbook playbook6.yml -C
PLAY [rhce] ********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [rhce]
TASK [yum] *********************************************************************
fatal: [rhce]: FAILED! => {"changed": false, "failures": ["123 没有能够与之匹配的软件包: 123"], "msg": "Failed to install some of the specified packages", "rc": 1, "results": []}
TASK [service] *****************************************************************
changed: [rhce]
TASK [service] *****************************************************************
changed: [rhce]
PLAY RECAP *********************************************************************
rhce                       : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0

五、使用jinja2模板部署自定义文件

1. 构建一个jinja2模板:

    要求:在模板中输出1-10, 打印主机的全限定名称, 输出默认的IP地址

    如果权限定名称为node1.example.com 将其输出为: node1

在受控主机中会按照jinja2动态模板文件,生成相对应的主机信息。
[student@workstation ~]$ cat playbook.yml 
---
- name: 1
  hosts: all
  remote_user: root
  tasks:
    - name: deplay /etc/hosts
      template:
        src: templates/hosts.j2
        dest: /etc/myhosts
[student@workstation ~]$ cat templates/hosts.j2 
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for host in groups['all'] %}
{{ hostvars[host]['ansible_facts']['default_ipv4']['address'] }} {{ hostvars[host]['ansible_facts']['fqdn'] }} {{ hostvars[host]['ansible_facts']['hostname'] }}
{% endfor %}
{#hostvars[host]不能加引号host是命令Hostvars[cmd]['变量名'] #}
[student@workstation ~]$ ssh servera
Activate the web console with: systemctl enable --now cockpit.socket
Last login: Wed Dec 29 20:07:19 2021 from 172.25.250.9
[student@servera ~]$ cat /etc/myhosts 
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.250.10 servera.lab.example.com servera
172.25.250.11 serverb.lab.example.com serverb
172.25.250.12 serverc.lab.example.com serverc
172.25.250.13 serverd.lab.example.com serverd

六、并行处理forks seria

1.forks和serial的区别

forks(广度优先)

       依据 forks 参数,决定一次在多少个服务器上并行执行相应的 task,对于包含多个 task 的场景,这种方式会先将 1 个 task 在指定的所有服务器上都执行完成之后,才会执行后续的 task。所以对于一个包含多个 task 的 playbook 来说,此时所有服务器的状态都是不完整的,都是处于中间状态的。但是当这个包含多个 task 的 playbook 执行完成之后,所有执行成功的服务器的状态都是被更新完成的。这种方式适合对服务器的中间状态不敏感的场景,其优点是可以对指定的所有主机执行同步的配置操作;缺点是更新过程中所有服务器都是未完成配置的中间状态。比如下面的场景,有 4 台服务器需要配置(nodeA, nodeB, nodeC, nodeD),playbook 中定义了 2 个 task,forks 指定的参数是 5,而每个 task 执行的耗时为 5 秒。


serial(深度优先)

       而对于深度优先的执行方式,则是在指定数目的服务器上执行完 playbook 的所有 task 之后,才会继续在剩余的其他主机上执行这个 playbook 中定义的 task。这是通过在 playbook 中指定 serial 关键字实现的,所以其是在 forks 参数的基础上,进一步进行约定,从而实现指定数目的服务器执行完成 playbook 之后,才会在其他服务器上执行的操作。这种方式类似于滚动更新。比如,此时仍然为 4 台服务器,forks 仍然设置为 5,然后在 playbook 中增加 serial 关键字,并将其值设置为 2,playbook 中仍然有 2 个 task,且每个 task 执行耗费时间为5秒。

七、playbook的文件导入

1.导入playbook和task

 建立一个import_playbook.yaml 然后将其导入另一个playbook: main_playbook.yaml

# main_playbook.yaml
---
- name:
  import_playbook: import_playbook.yml
- name: main play
  hosts: rhce
  tasks:
    - name: main task
      debug:
        msg: "this is my main playbook"
...
# import_playbook.yaml
---
- name:
  hosts: rhce
  tasks:
    - name: import play book
      debug:
        msg: "this is to import playbook"
...

建立一个import_task.yaml里面只写任务:将其导入main_task_playbook.yaml中

# import_task.yaml
---
- name: import_tasks
  debug:
    msg: "this is to import tasks"
...
# main_task_playbook.yaml
---
- name:
  hosts: rhce
  tasks:
    - name:
      import_tasks: import_tasks.yml
    - name:
      debug:
        msg: "this is main tasks"
...
目录
相关文章
|
运维 Cloud Native Go
Ansible自动化:简化你的运维任务
Ansible自动化:简化你的运维任务
127 0
|
3月前
|
运维 Unix 应用服务中间件
自动化运维:使用Ansible简化日常任务
【8月更文挑战第4天】在现代IT架构中,自动化运维成为提升效率、减少人为错误的关键。本文将介绍如何使用Ansible这一强大的自动化工具来简化日常的运维任务,通过实际代码示例,展示配置管理、软件部署和系统更新等操作。我们将探索如何利用Ansible的简洁语法和强大功能来优化工作流程,从而为读者提供一套实用的自动化解决方案。
|
3月前
|
运维 监控 Devops
自动化运维的魔法:如何利用Ansible简化日常任务
【8月更文挑战第24天】在快速迭代的互联网时代,运维效率成为企业竞争力的关键。本文将介绍一种强大的自动化工具——Ansible,它如何通过简化配置管理和自动化部署来提升运维效率。你将了解到Ansible的基本概念、优势以及如何应用它来优化你的工作流程。让我们一起探索这个自动化的魔法世界,释放运维的潜能!
124 60
|
1月前
|
运维 应用服务中间件 数据库
自动化运维:使用Ansible简化日常任务
【10月更文挑战第2天】在快速迭代的软件开发周期中,运维工作往往变得重复而繁琐。本文将介绍如何使用Ansible这一强大的自动化工具来简化日常任务,从而提升效率并减少人为错误。从基础配置到复杂部署,我们将一步步展示如何通过编写简单的Playbook来实现自动化管理。
68 3
|
2月前
|
运维 Ubuntu 应用服务中间件
自动化运维:使用Ansible进行配置管理和任务自动化
【9月更文挑战第27天】在现代IT基础设施中,自动化运维是提高效率、减少人为错误和确保系统一致性的关键。本文将介绍如何使用Ansible,一个流行的开源IT自动化工具,来简化日常的运维任务。我们将探索Ansible的核心概念,包括它的架构、如何安装和使用它,以及一些实际的使用案例。无论你是新手还是有经验的运维专家,这篇文章都会提供有价值的见解和技巧,以帮助你更好地利用Ansible实现自动化。
|
2月前
|
运维 监控 安全
自动化运维:使用Ansible简化日常任务
【9月更文挑战第19天】在现代IT架构中,自动化运维是提升效率和减少人为错误的关键。本文将介绍如何使用Ansible这一强大的自动化工具来简化日常运维任务,包括安装软件、配置系统和应用部署等。通过实际的代码示例,我们将展示如何编写简单的Ansible playbook来实现这些任务,并讨论其在真实场景中的应用价值。
70 5
|
2月前
|
运维 应用服务中间件 nginx
自动化运维:使用Ansible简化日常任务
【9月更文挑战第2天】在快速迭代的软件开发周期中,高效可靠的运维成为项目成功的关键。本文将介绍如何使用Ansible这一强大的自动化工具来简化日常运维任务,从基础概念到实战应用,带你一步步构建自动化运维流程,解锁更高效的工作方式。
|
3月前
|
运维 Ubuntu 应用服务中间件
自动化运维:使用Ansible简化日常任务
【8月更文挑战第31天】告别繁琐,拥抱高效。本文带你领略Ansible的魅力,通过具体示例展示如何用它来自动化你的日常IT运维任务。准备好让你的服务器管理工作变得简单而有趣!
|
3月前
|
机器学习/深度学习 运维 Ubuntu
自动化运维:使用Ansible简化日常任务探索Python编程之美:从基础到进阶
【8月更文挑战第28天】在快速迭代的软件开发周期中,运维工作的效率至关重要。本文将介绍如何使用Ansible这一强大的自动化工具来简化日常的运维任务,通过代码示例展示如何配置和使用Ansible,以及它如何帮助提升工作效率和减少人为错误。文章将深入讨论Ansible的核心概念,包括Playbooks和Tasks,并探讨如何利用这些概念进行高效的系统管理。 【8月更文挑战第28天】在数字时代的浪潮中,编程已成为一门艺术和科学。本文将通过Python语言的镜头,带领读者踏上一段从零基础到熟练运用的旅程。我们将一起探索Python的简洁语法、强大库支持以及它在数据科学、网络开发等领域的应用。无论你
|
3月前
|
运维 JavaScript 安全
自动化运维:使用Ansible简化日常任务深入理解Node.js事件循环和异步编程
【8月更文挑战第27天】在快节奏的技术环境中,自动化不再是奢侈品,而是必需品。本文将引导你通过Ansible实现自动化运维,从基础到高级应用,解锁高效管理服务器群的秘诀,让你的IT操作更加流畅和高效。