ansible点滴

介绍ansible的Playbook的一些写法

背景

最近业务需要滚动更新,用ansible,然后就发现了一些ansible的用法,这里记录一下。

循环

一个典型循环

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
---
- hosts: all
  remote_user: root
  gather_facts: no
  vars:
    - timeout: 300
    - default_size: 2

  tasks:
    - name: "{{ inventory_hostname }}"
      shell: for i in $(seq 1 3);do echo $i
      register: loopout

    - name: test1  "{{ inventory_hostname }}"
      shell: echo "test"
      loop: "{{ loopout.stdout_lines }}"

循环三次

问题: 如果想循环多个task怎么做

首先loop挪层数没法挪, 会报错

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
ERROR! 'loop' is not a valid attribute for a Play

The error appears to be in '/etc/ansible/playbook.yml': line 2, column 3, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

---
- hosts: all
  ^ here

如果用role呢,demo如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
liuliancao@liuliancao:/etc/ansible$ cat roles/test/tasks/main.yml
- name: server test
  shell: echo "11" >> /tmp/liuliancao
  #delegate_to: "{{ item }}"
liuliancao@liuliancao:/etc/ansible$ cat playbook.yml
---
- hosts: all
  remote_user: root
  gather_facts: no
  vars:
    - timeout: 300
    - default_size: 2

  tasks:
    - name: "{{ inventory_hostname }}"
      shell: for i in $(seq 1 3);do echo $i;done
      register: loopout
  roles:
    - role: test
      loop: "{{ loopout.stdout_lines }}"
      #- name: test1  "{{ inventory_hostname }}"
      #include_role:
      #name: "test"
      #loop: "{{ loopout.stdout_lines }}"

发现只执行了一次 其实这里最好的办法是include和include_role 用法参考如下demo

include_role写法
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
liuliancao@liuliancao:/etc/ansible$ cat playbook.yml
---
- hosts: all
  remote_user: root
  gather_facts: no
  vars:
    - timeout: 300
    - default_size: 2

  tasks:
    - name: "{{ inventory_hostname }}"
      shell: for i in $(seq 1 3);do echo $i;done
      register: loopout
    - name: test1  "{{ inventory_hostname }}"
      include_role:
        name: test
      loop: "{{ loopout.stdout_lines }}"
include写法
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
liuliancao@liuliancao:/etc/ansible$ cat playbook.yml
---
- hosts: all
  remote_user: root
  gather_facts: no
  vars:
    - timeout: 300
    - default_size: 2

  tasks:
    - name: "{{ inventory_hostname }}"
      shell: for i in $(seq 1 3);do echo $i;done
      register: loopout
    - name: test1  "{{ inventory_hostname }}"
      include: test.yml
      loop: "{{ loopout.stdout_lines }}"


liuliancao@liuliancao:/etc/ansible$ cat test.yml
- name: server test
  shell: echo "11" >> /tmp/liuliancao

这里需要注意include这里其实也可以传变量,类似这样, 注意变量的问题,无论是-e命令行变量还是playbook变量,include和include_role,include等都是可以直接使用的

1
2
- name: test
  include: test.yml name=hello gender=boy

资产如何自刷新

这里需要介绍ansible本身其实有很多meta函数,建议大家找功能优先从官文搜索框搜索 https://docs.ansible.com/ansible/latest/collections/ansible/builtin/meta_module.html end_host 结束host这次的task end_play 结束整个playbook refresh_inventory 修改了/etc/ansible/hosts然后需要类似reload的操作, 这里基本逻辑是

1
2
3
4
5
6
- name: echo to hosts
  shell: echo "192.168.0.1" > /etc/ansible/hosts
- name: refresh
  meta: refresh_inventory
- name: do something with 192.168.0.1 "{{ inventory_hostname }}"
  shell: whoami

这里需要注意,loop和when后面是不能再执行refresh_inventory的,那怎么做呢

分配

如何把一个task分派给特定主机 通过delegate_to, 但是注意include和include家族都不支持delegate_to,写了语法不会报错,但不会委派,但是include里面的内容可以被委派, 具体不再演示

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
liuliancao@liuliancao:/etc/ansible$ cat playbook.yml
---
- hosts: all
  remote_user: root
  gather_facts: no
  vars:
    - timeout: 300
    - default_size: 2

  tasks:
    - name: test delegate
      shell: hostname -f
      delegate_to: "192.168.0.83"

这时候看输出, 有一个这样的箭头

1
changed: [localhost -> 192.168.0.83]