个人博客,记录知识防止遗忘
ansible中playbook控制语句
ansible中playbook控制语句

ansible中playbook控制语句

内容大纲

1    条件判断

1.1    when

  • 只有当条件符合时才执行对应任务
  • 如下例 , 只有当cpu 大于等于3个, 且内存大于等于400时, 才会执行同等级的debug,输出信息
  • 注意: when 中用于判断的变量无需使用双花括号来引用 (因为when语句默认包含一层双花括号)
---
- hosts: group_a
  remote_user: root
  tasks:
    - name: a
      debug:
        msg: "{{ ansible_processor_vcpus }} , {{ ansible_memtotal_mb }}"
      when:
        - ansible_processor_vcpus >= 3
        - ansible_memtotal_mb >= 400 

image.png

1.2    changed_when

  • 当条件满足时,会将本任务的执行状态设置为 changed
  • 可以用来触发 handlers
---
- name: test
  hosts: group_a
  gather_facts: false
  vars: 
    flag: 1
  tasks:
    - name: aaa
      debug: 
        msg: "aaaaaaaaaaaaaa"
      changed_when: flag==1       # 当flag值为1的时候,本任务的状态将变为changed,从而触发handlers,重启nginx
      notify: restart_nginx

  handlers:
    - name: restart_nginx
      service:
        name: nginx
        state: restarted

可以看到, 默认是ok状态的debug输出信息变成了changed状态信息, nginx也因为handlers重启了
image.png

1.3    failed_when

  • 当条件满足时,会将本任务的执行状态设置为 failed
  • 可以用来触发 handlers
---
- name: test
  hosts: group_a
  tasks:
    - name: echo error
      shell: "echo 'start error aaaaaaaaaa'"
      register: status
      failed_when: " 'error' in status.stdout"  # echo输出的内容中有error,所以触发失败
    - name: debug
      debug:
        msg: "{{ status.stdout }}"

image.png
去除 failed_when 后,顺利执行
image.png


2    循环语句

循环关键字都是 item

2.1    with_items

分为循环数组 和 循环字典(kv键值对) 两种

2.1.1    循环数组

若有多个数组,会将各数组展开, 然后逐个循环其中元素

---
- hosts: host_1
  remote_user: root
  gather_facts: no            # 不获取facts,加快执行速度
  tasks:
    - name: a
      debug:
        msg: "{{ item }}"
      when:
        - item | int  >= 2    # 先通过管道符,尝试转化为整型,再参与判断
        - item | int  <= 3
      with_items:             # with_items 中若有多个数组,会将各数组展开,逐个循环其中元素
        - [1,2,3,4]
        - [aaa,bbb]
        - "2"

image.png

2.1.2    循环字典

例; 使用循环创建用户和组

---
- hosts: group_a
  remote_user: root
  gather_facts: no
  tasks:

    - name: add group
      group: 
        name: "{{ item.groups }}"
        state: present
      with_items:
        - { name: 'testuser1',groups: 'testgroup1'}
        - { name: 'testuser2',groups: 'testgroup2'} 

    - name: add users
      user:
        name: "{{ item.name }}"
        group: "{{ item.groups }}"
        state: present
      with_items:
        - { name: 'testuser1',groups: 'testgroup1'}
        - { name: 'testuser2',groups: 'testgroup2'}

    - name: check user
      shell: "id testuser1;id testuser2"
      register: "user_status"

    - name: debug user
      debug: 
        msg: "{{ user_status.stdout_lines }}"

image.png

2.2    with_list

不会将数组展开, 而是作为一个整体参与循环

---
- hosts: host_1
  remote_user: root
  gather_facts: no            # 不获取facts,加快执行速度
  tasks:
    - name: a
      debug:
        msg: "{{ item }}"
      when:
        - item | int  >= 2    # 先通过管道符,尝试转化为整型,再参与判断
        - item | int  <= 3
      with_list:             # with_items 中若有多个数组,会将各数组展开,逐个循环其中元素
        - [1,2,3,4]
        - [aaa,bbb]
        - "2"

image.png

2.3    with_together

数组会对位重组

---
- hosts: host_1
  remote_user: root
  gather_facts: no
  tasks:
    - name: a
      debug:
        msg: "{{ item }}"
      with_together:
        - [1,2,3,4]
        - [a,b,c,d]
        - ['1','2','3','4']

image.png


3    触发器 handlers

在task 任务之后再加一个同级的 handlers ,其中定义要执行的任务
随后在需要监听的地方通过 notify 调用 handlers下具体任务

---
- hosts: group_a
  remote_user: root
  tasks:
    - name: add group
      group:
        name: nginx
        state: present

    - name: add user
      user:
        name: nginx
        group: nginx

    - name: install nginx
      yum: 
        name: nginx
        state: latest

    - name: config
      template:
        src: ./template/nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        owner: nginx
        group: nginx
        mode: '0644'
      notify: nginx restart

    - name: start nginx
      service:
        name: nginx
        state: started

  handlers:
    - name : nginx restart
      service:
        name: nginx
        state: restarted

image.png


4    标签tags

4.1    运行指定tags任务

--tags=
---
- hosts: group_a
  remote_user: root
  tasks:

    - name: echo aaaa
      debug: 
        msg: "aaaa"

    - name: check worker_processes
      shell: "ps -ef |grep nginx"
      register: "wk_pcs"
      tag: c_w_p

    - name: debug worker_processes
      debug: 
        msg: "{{ wk_pcs.stdout_lines }}"
      tag: c_w_p

可以看到,仅仅执行了指定标签的任务
image.png

4.2    排除指定tags

--skip-tags

image.png

4.3    为一个任务添加多个tags

tags:
  - aaaa
  - bbbb

tags: ['aaaa','bbbb']

tags: aaaaa,bbbb

4.4    为一个play指定一组标签

添加之后,此play下的所有tasks都将继承这些tags

- name: nginx_web_install_config
  hosts: group_a
  remote_user: root
  tags: 
    - web
  tasks:
    ...
    ...

4.5    ansible内置的标签

除了用户自定义tag,ansible也内置了几个tag,这些tag都包含特殊含义:

  • always:一旦某个task被打上了always的tag,则无论是playbook的完整执行,还是指定tag执行,不管你指定的tag是啥,该任务总是会被执行。除非明确指定"--skip-tags=always"选项,才不会执行该task。

  • never:该标签与always正好相反,总是不会执行,除非明确指定"--tags=never"选项。

  • tagged:在调用时使用

    # 所有打了tag的任务都会被执行,包含never tag的除外,没有标签的不会被执行
    ansible-playbook --tags tagged install_web.yaml 
    # 所有打了tag的任务都不会被执行,包括always tag也不会被执行
    ansible-playbook --skip-tags tagged install_web.yaml
  • untagged:在调用时使用

    # 所有未打tag的任务都会被执行,打了always tag的也会被执行
    ansibl-playbook --tags untagged install_web.yaml
    # 所有未打tag的任务都不会被执行
    ansibl-playbook --skip-tags untagged install_web.yaml
  • all:表示所有任务都会被执行,在默认情况下,不指定任何标签,则使用的就是该标签


5   include和import 导入

5.1    使用方法

共有2种常见的导入方法
include 和 import
2者使用方法都相似, 在tasks中直接导入即可

  tasks:
    - include_tasks: test1.yml
  tasks:
    - import_tasks: test1.yml

5.2    主要区别

include和import的主要区别有2点

  • 导入时变量作用域不同
  • 导入时的文件名称是否可以加变量

文件 test1.yml

---
- set_fact: aaaa=="bbbb" 
- name: test1
  debug:
    msg: "{{ aaaa }}"

5.2.1    include_tasks

  • ansible会在完全执行完test.yml里的task后,再加载test1.yml里的变量,

    即若本地变量和待导入的文件中有变量冲突时, 不会发生变量值的替换

  • 举例:
    test.yml中aaaa的值为"aaaa1234",test1.yml中aaaa的值为"bbbb",两者互不影响;
    由于when判断通过,从而执行test1.yml中的task
---
- name: test
  hosts: group_a
  gather_facts: false
  vars: 
    aaaa: "aaaa1234"
    file_name: "test1"
  tasks:
    - include_tasks: "{{ file_name }}.yml"     
    # include 导入方法可以将文件名用变量表示, import会直接报错
      when:
        aaaa=="aaaa1234"

image.png

5.2.2    import_tasks

  • ansible会在playbook解析阶段就将所有文件的变量都全部解析,此时可能会出现变量重新赋值等问题

举例:
test.yml中aaaa的值开始时定义为"aaaa1234",test1.yml中aaaa的值为"bbbb"
合并之后,后导入的test1中变量会替换test中变量,将test.yml中aaaa的值更新为"bbbb"
导致test.yml中when判断不符,从而跳过执行test1.yml中的task

---
- name: test
  hosts: group_a
  gather_facts: false
  vars: 
    aaaa: "aaaa1234"
  tasks:
    - import_tasks: test1.yml      # import方法此处只能指明文件名,用变量会报错
      when:
        aaaa=="aaaa1234"

image.png


6    错误忽略 ignore_errors

在playbook执行的过程中,难免会遇到一些错误,但是playbook遇到错误后,不会执行之后的任务,不便于调试。
所以此时可以使用ignore_errors来暂时忽略错误,使得playbook继续执行

---
- name: test
  hosts: group_a
  gather_facts: false
  vars: 
    aaaa: "aaaa1234"
  tasks:
    - name: copy                        # 创建一个copy模块,并指定一个不存在的src源文件
      copy:
        src: ./aaaa/aaaa/aaa.sh
        dest: /root/aaa.sh
      ignore_errors: True               # 配置此项后,会暂时跳过忽略错误

    - name: echo
      debug:
        msg: "已经跳过上一步copy错误"

image.png

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注