云计算百科
云计算领域专业知识百科平台

Linux入门DAY24

Linux入门DAY24

Ansible

实施任务控制

实验环境

[phoenix@controller ~ 10:55:24]$ cat ansible.cfg
[defaults]
remote_user = phoenix
inventory = ./inventory

[privilege_escalation]
become = True
become_user = root
become_method = sudo
become_ask_pass = False

[phoenix@controller ~ 10:55:06]$ cat inventory
controller

node1
node2
node3
node4

编写循环任务

简单循环

#准备测试文件
[phoenix@controller ~ 10:32:35]$ vim deploy_web1.yml

#playbook

– name: Enable intranet services
hosts: node1
tasks:
– name: latest version of httpd and firewalld installed
yum:
name:
– httpd
– firewalld
state: latest

– name: test html page is installed

copy:
content: "Welcome tp {{ansible_hostname}} WebSite!\\n"
dest: /var/www/html/index.html

– name: firewalld enabled and running
service:
name: "{{ item }}"
enabled: true
state: started
loop:
– httpd
– firewalld

– name: firewalld permits access to httpd service
firewalld:
service: http
permanent: true
state: enabled
immediate: yes

– name: httpd enabled and running
service:
name: httpd
enabled: true
state: started

– name: Test intranet web server
hosts: localhost
become: no
tasks:
– name: connect to intranet web server
uri:
url: http://node1
return_content: yes
status_code: 200

...

[phoenix@controller ~ 10:39:22]$ ansible-playbook deploy_web1.yml

PLAY [Enable intranet services] ***************************************************************************

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

TASK [latest version of httpd and firewalld installed] ****************************************************
ok: [node1]

TASK [test html page is installed] ************************************************************************
changed: [node1]

TASK [firewalld enabled and running] **********************************************************************
ok: [node1] => (item=httpd)
ok: [node1] => (item=firewalld)

TASK [firewalld permits access to httpd service] **********************************************************
ok: [node1]

TASK [httpd enabled and running] **************************************************************************
ok: [node1]

PLAY [Test intranet web server] ***************************************************************************

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

TASK [connect to intranet web server] *********************************************************************
ok: [localhost]

PLAY RECAP ************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node1 : ok=6 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

#测试
[phoenix@controller ~ 10:39:29]$ curl node1
Welcome tp node1 WebSite!
[phoenix@controller ~ 10:39:39]$ curl node2
Hello World From node2
[phoenix@controller ~ 10:39:44]$ curl node3
Hello World From node3
[phoenix@controller ~ 10:39:46]$ curl node4
Hello World From node4

循环散列

#loop用户
[phoenix@controller ~ 10:51:39]$ vim deploy_web2.yml

1
2 – name: add several users
3 hosts: node1
4 gather_facts: no
5 vars:
6 users:
7 – name: jane
8 groups: wheel
9 – name: joe
10 groups: root
11 tasks:
12 – name: add users
13 user:
14 name: "{{ item.name }}"
15 state: present
16 groups: "{{ item.groups }}"
17 loop: "{{ users }}"
18 ...

[phoenix@controller ~ 10:52:21]$ ansible-playbook deploy_web2.yml

PLAY [add several users] **********************************************************************************

TASK [add users] ******************************************************************************************
changed: [node1] => (item={u'name': u'jane', u'groups': u'wheel'})
changed: [node1] => (item={u'name': u'joe', u'groups': u'root'})

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

循环关键字

with items

– name: test loop
hosts: node1
gather_facts: no
tasks:
– name: add users
user:
name: "{{ item }}"
state: present
groups: "wheel"
with_items:
– jane
– joe

ping loop

[phoenix@controller ~ 11:31:25]$ vim testnode2.yml
1
2 – name: test loop
3 hosts: node1
4 gather_facts: no
5 tasks:
6 – shell: ping -c1 -w 2 node2
7 register: result
8 until: result.rc == 0
9 retries: 20
10 delay: 1
11 ...

[phoenix@controller ~ 11:31:14]$ ansible-playbook testnode2.yml

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

TASK [shell] **********************************************************************************************
changed: [node1]

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

[phoenix@controller ~ 11:31:18]$ ansible-playbook testnode2.yml –ask-vault-pass
Vault password:

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

TASK [shell] **********************************************************************************************
changed: [node1]

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

编写条件任务

when 语句

[phoenix@controller ~ 14:06:25]$ cat test.yml

– name: test
hosts: node1
gather_facts: no
vars:
username: devops
supergroup: wheel
tasks:
– name: gather user information
shell: id {{ username }}
register: result
– name: Task run if user is in supergroups
user:
name: "{{ username }}"
groups: "{{ supergroup }}"
append: yes
when: supergroup not in result.stdout
...

#运行
[phoenix@controller ~ 13:44:26]$ ansible-playbook test.yml

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

TASK [gather user information] ****************************************************************************
changed: [node1]

TASK [Task run if user is in supergroups] *****************************************************************
changed: [node1]

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

变量判断

[phoenix@controller ~ 14:06:29]$ cat test1.yml

– name: test
hosts: node1 node3
gather_facts: no
tasks:
– name: install httpd
yum:
name: httpd
state: present
when: inventory_hostname in groups.webs
– name: install mariadb
yum:
name: mariadb
state: present
when: inventory_hostname in groups.dbs
...

#运行
[phoenix@controller ~ 14:02:34]$ ansible-playbook test1.yml

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

TASK [install httpd] **************************************************************************************
skipping: [node3]
ok: [node1]

TASK [install mariadb] ************************************************************************************
skipping: [node1]
changed: [node3]

PLAY RECAP ************************************************************************************************
node1 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
node3 : ok=1 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

loop 和 when 联合

1
2 – name: Combining Loops and Conditional Play
3 hosts: node1
4 tasks:
5 – name: install mariadb-server if enough space on root
6 yum:
7 name: mariadb-server
8 state: latest
9 loop: "{{ ansible_mounts }}"
10 when:
11 – item.mount == "/"
12 – item.size_available > 300000000
13 ...
~

#运行
[phoenix@controller ~ 14:25:14]$ ansible-playbook test3.yml

PLAY [Combining Loops and Conditional Play] ***************************************************************

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

TASK [install mariadb-server if enough space on root] *****************************************************
skipping: [node1] => (item={u'block_used': 35554, u'uuid': u'd43a42ec-932d-441b-b612-bc418aff8ea0', u'size_total': 1063256064, u'block_total': 259584, u'mount': u'/boot', u'block_available': 224030, u'size_available': 917626880, u'fstype': u'xfs', u'inode_total': 524288, u'options': u'rw,relatime,attr2,inode64,noquota', u'device': u'/dev/sda1', u'inode_used': 326, u'block_size': 4096, u'inode_available': 523962})
changed: [node1] => (item={u'block_used': 491363, u'uuid': u'5573248a-295f-49ea-a0f0-10d7e246a26a', u'size_total': 50432839680, u'block_total': 12312705, u'mount': u'/', u'block_available': 11821342, u'size_available': 48420216832, u'fstype': u'xfs', u'inode_total': 24637440, u'options': u'rw,relatime,attr2,inode64,noquota', u'device': u'/dev/mapper/centos-root', u'inode_used': 33463, u'block_size': 4096, u'inode_available': 24603977})

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

Ansible Handlers

Handlers(处理器) 是 Ansible 中一种特殊的任务,它 不会立即执行,而是 被其他任务 notify(通知)后,在 Playbook 的末尾统一执行

Handlers 主要用于 管理服务的重启、配置重载等操作,确保它们只在 真正发生变更时执行,避免不必要的重启

[phoenix@controller ~ 14:33:50]$ vim testhandlers.yml

– name: deploy web server
hosts: node1
tasks:
– name: install packages
yum:
name: httpd
state: present
notify:
enable and restart apache

– name: install httpd-manual
yum:
name: httpd-manual
state: present
notify:
enable and restart apache

– debug:
msg: last task in tasks

handlers:
– name: enable and restart apache
service:
name: httpd
state: restarted
enabled: yes
...

#运行
[phoenix@controller ~ 14:41:04]$ ansible-playbook testhandlers.yml

PLAY [deploy web server] **********************************************************************************

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

TASK [install packages] ***********************************************************************************
ok: [node1]

TASK [install httpd-manual] *******************************************************************************
changed: [node1]

TASK [debug] **********************************************************************************************
ok: [node1] => {
"msg": "last task in tasks"
}

RUNNING HANDLER [enable and restart apache] ***************************************************************
changed: [node1]

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

meta 模块

[phoenix@controller ~ 19:42:36]$ vi testmeta.yml

1
2 – name: deploy db server
3 hosts: node1
4 tasks:
5 – name: install mariadb
6 yum:
7 name:
8 – mariadb-server
9 – MySQL-python
10 state: present
11 notify:
12 – enable_and_start_db
13
14 – meta: flush_handlers
15
16 – name: add mariadb user
17 mysql_user:
18 name: phoenix01
19 password: 1
20
21 handlers:
22 – name: enable_and_start_db
23 service:
24 name: mariadb
25 state: started
26 ...
[phoenix@controller ~ 19:42:27]$ ansible-playbook testmeta.yml

PLAY [deploy db server] ***********************************************************************************

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

TASK [install mariadb] ************************************************************************************
changed: [node1]

RUNNING HANDLER [enable_and_start_db] *********************************************************************
ok: [node1]

TASK [add mariadb user] ***********************************************************************************
[WARNING]: The value ******** (type int) in a string field was converted to u'********' (type string). If
this does not look like what you expect, quote the entire value to ensure it does not change.
[WARNING]: Module did not set no_log for update_password
changed: [node1]

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

errors

fail模块

[phoenix@controller ~ 14:49:00]$ vim failedtest.yml
[phoenix@controller ~ 15:00:48]$ ansible-playbook faildtest.yml
ERROR! the playbook: faildtest.yml could not be found
[phoenix@controller ~ 15:00:59]$ ansible-playbook failedtest.yml

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

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

TASK [shell] **********************************************************************************************
changed: [node1]

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

[phoenix@controller ~ 15:01:09]$ vim failedtest.yml
[phoenix@controller ~ 15:03:01]$ ansible-playbook failedtest.yml

PLAY [test fail module] ***********************************************************************************

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

TASK [shell] **********************************************************************************************
fatal: [node1]: FAILED! => {"changed": true, "cmd": "/root/adduser", "delta": "0:00:00.003069", "end": "2025-08-14 15:03:06.261860", "msg": "non-zero return code", "rc": 127, "start": "2025-08-14 15:03:06.258791", "stderr": "/bin/sh: /root/adduser: 没有那个文件或目录", "stderr_lines": ["/bin/sh: /root/adduser: 没有那个文件或目录"], "stdout": "", "stdout_lines": []}

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

force_handlers

当hanlers处理任务失败后,可以选择–force强制执行

[phoenix@controller ~ 19:48:44]$ vim force.yml

– name: test
hosts: node1
force_handlers: yes
tasks:
– name: a task which always notifies its handler
command: /bin/true
notify: restart the sshd

– name: fails because the package doesn't exist
yum:
name: notexistpkg
state: latest

handlers:
– name: restart the sshd
service:
name: sshd
state: restarted

[phoenix@controller ~ 19:54:14]$ ansible-playbook force.yml

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

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

TASK [a task which always notifies its handler] ***********************************************************
changed: [node1]

TASK [fails because the package doesn't exist] ************************************************************
fatal: [node1]: FAILED! => {"changed": false, "msg": "No package matching 'notexistpkg' found available, installed or updated", "rc": 126, "results": ["No package matching 'notexistpkg' found available, installed or updated"]}

RUNNING HANDLER [restart the sshd] ************************************************************************
changed: [node1]

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

failed_when

[phoenix@controller ~ 19:54:29]$ vim failedwhen.yml

– name: test failed_when
hosts: node1
tasks:
– shell: /root/adduser
register: command_result
failed_when: "'failed' in command_result.stdout"

#运行
[phoenix@controller ~ 19:57:09]$ ansible-playbook failedwhen.yml

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

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

TASK [shell] *********************************************************************************************
changed: [node1]

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

changed when

[phoenix@controller ~ 19:57:23]$ vim changewhen.yml

– name: changed_when
hosts: node1
tasks:
– name: upgrade-database
shell: /usr/local/bin/upgrade-database
register: result
changed_when: "'Success' in result.stdout"
notify:
– restart_database
handlers:
– name: restart_database
service:
name: mariadb
state: restarted

[phoenix@controller ~ 19:59:49]$ ansible-playbook changewhen.yml

PLAY [changed_when] **************************************************************************************

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

TASK [upgrade-database] **********************************************************************************
fatal: [node1]: FAILED! => {"changed": false, "cmd": "/usr/local/bin/upgrade-database", "delta": "0:00:00.002910", "end": "2025-08-14 20:00:04.136268", "msg": "non-zero return code", "rc": 127, "start": "2025-08-14 20:00:04.133358", "stderr": "/bin/sh: /usr/local/bin/upgrade-database: 没有那个文件或目录", "stderr_lines": ["/bin/sh: /usr/local/bin/upgrade-database: 没有那个文件或目录"], "stdout": "", "stdout_lines": []}

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

Ansible block

多个任务作为block子条目,block作为多个任务整体

示例
  • 在research卷组中创建逻辑卷:

    • 逻辑卷名称为data

    • 逻辑卷大小为4000MiB

    • 使用ext4文件系统格式化逻辑卷

    • 将逻辑卷挂载到/data目录

    • 如果无法创建请求的逻辑卷大小,应显示错误信息:Could not create logical volume of that size 并且应改为使用大小800MiB。

  • 如果卷组research不存在,应显示错误信息:Volume does not exist

[phoenix@controller ~ 19:48:39]$ cat createlv.yml

– name: create and user lv
hosts: all
tasks:
– block:
– name: create a lv of 4000m
lvol:
vg: research
lv: data
size: 4000
rescue:
– debug:
msg: Could not create logical volume of that size
– name: Create a logical volume of 800m
lvol:
vg: research
lv: data
size: 800
always:
– name: Create a ext4
filesystem:
fstype: ext4
dev: /dev/research/data
– name: create directory /data
file:
path: /data
state: directory
– name: Mount /dev/research/data
mount:
path: /data
src: /dev/research/data
fstype: ext4
state: mounted
when: ansible_lvm.vgs.research is defined

– name: Volume group does not exist
debug:
msg: Volume group does not exist
when: ansible_lvm.vgs.research is not defined

运行

[phoenix@controller ~ 16:02:34]$ ansible-playbook createlv.yml

PLAY [create and user lv] *********************************************************************************

TASK [Gathering Facts] ************************************************************************************
ok: [node1]
ok: [node3]
ok: [node2]
ok: [node4]
ok: [controller]

TASK [create a lv of 4000m] *******************************************************************************
skipping: [controller]
skipping: [node3]
skipping: [node4]
[WARNING]: The value 4000 (type int) in a string field was converted to u'4000' (type string). If this
does not look like what you expect, quote the entire value to ensure it does not change.
fatal: [node2]: FAILED! => {"changed": false, "err": " Volume group \\"research\\" has insufficient free space (255 extents): 1000 required.\\n", "msg": "Creating logical volume 'data' failed", "rc": 5}
changed: [node1]

TASK [debug] **********************************************************************************************
ok: [node2] => {
"msg": "Could not create logical volume of that size"
}

TASK [Create a logical volume of 800m] ********************************************************************
[WARNING]: The value 800 (type int) in a string field was converted to u'800' (type string). If this does
not look like what you expect, quote the entire value to ensure it does not change.
changed: [node2]

TASK [Create a ext4] **************************************************************************************
skipping: [controller]
skipping: [node4]
skipping: [node3]
changed: [node2]
changed: [node1]

TASK [create directory /data] *****************************************************************************
skipping: [controller]
skipping: [node3]
skipping: [node4]
changed: [node1]
changed: [node2]

TASK [Mount /dev/research/data] ***************************************************************************
skipping: [controller]
skipping: [node3]
skipping: [node4]
changed: [node1]
changed: [node2]

TASK [Volume group does not exist] ************************************************************************
ok: [controller] => {
"msg": "Volume group does not exist"
}
skipping: [node1]
skipping: [node2]
ok: [node3] => {
"msg": "Volume group does not exist"
}
ok: [node4] => {
"msg": "Volume group does not exist"
}

PLAY RECAP ************************************************************************************************
controller : ok=2 changed=0 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
node1 : ok=5 changed=4 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
node2 : ok=6 changed=4 unreachable=0 failed=0 skipped=1 rescued=1 ignored=0
node3 : ok=2 changed=0 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
node4 : ok=2 changed=0 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0

赞(0)
未经允许不得转载:网硕互联帮助中心 » Linux入门DAY24
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!