【运维知识进阶篇】Ansible流程控制详解

简介: 【运维知识进阶篇】Ansible流程控制详解

大家好,今天给大家讲解Ansible的流程控制,Ansible作为可以批量管理客户机的工具,自然是功能齐全,其条件语句、判断语句类似于shell脚本,所以我们要熟练掌握,在实际运用中灵活使用。

playbook条件语句

例如:我们在使用不同的系统的时候,可以通过判断系统来对软件包进行安装;在nfs和rsync安装过程中,客户端服务器不需要推送配置文件,用条件语句可以减少剧本的编写;在安装源码时,可以判断是否执行成功。执行成功就启动等等。

1、根据不同操作系统安装apache

1. [root@Ansible test]# vim test.yml 
2. - hosts: web01
3.   tasks:
4.  - name: install centos httpd
5.       yum:
6.         name: httpd
7.         state: present
8. when: ansible_facts['os_family'] == "CentOS"    #官方写法
9.       #when: ansible_distribution == "CentOS"    非官方写法
10. 
11.  - name: install ubuntu httpd
12.       yum:
13.         name: apache2
14.         state: present
15. when: ansible_facts['os_family'] == "Ubuntu"
16. 
17. #还可以使用括号对条件进行分组
18. tasks:
19.  - name: "shut down CentOS 6 and Debian 7 systems"
20.     command: /sbin/shutdown -t now
21. when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "6") or (ansible_facts['distribution'] == "Debian" and ansible_facts['distribution_major_version'] == "7")    #如果当前管理机为CentOS6或者是Debin7就关机
22. 
23. #也可以以列表形式指定多个条件
24. tasks:
25.  - name: "shut down CentOS 6 systems"
26.     command: /sbin/shutdown -t now
27. when:
28.  - ansible_facts['distribution'] == "CentOS"
29.  - ansible_facts['distribution_major_version'] == "6"
30. 
31. #也可以进行条件运算
32. tasks:
33.  - shell: echo "only on Red Hat 6, derivatives, and later"
34. when: ansible_facts['os_family'] == "RedHat" and ansible_facts['lsb']['major_release']|int >= 6    #当系统为RedHat并且版本大于等于6时进行输出
35. 
36. #过滤匹配返回值包含successful
37. tasks:
38.  - name: Check Nginx Configure
39.     command: /usr/sbin/nginx -t
40.     register: result
41.  - name: Restart web02
42.     command: /usr/sbin/reboot
43. when:  result.stderr_lines is match ".*successful.*"    精准匹配,通常配合正则使用
44.     或者    
45. when:  result.stderr_lines is search "successful"       模糊匹配

2、rsync服务端推送配置文件

1. [root@Ansible test]# cat /ansible/rsyncd/rsyncd.yml
2. - hosts: all
3.   tasks:
4.  - name: Install Rsyncd Server
5.       yum: 
6.         name: rsync
7.         state: present
8.  - name: Create www Group
9. group:
10.         name: www
11.         gid: 666
12.  - name: Create www User
13.       user:
14.         name: www
15.         uid: 666
16. group: www
17.         shell: /sbin/nologin
18.         create_home: false
19.  - name: Scp Rsync Config
20. copy: 
21.         src: /ansible/rsyncd/rsyncd.conf
22.         dest: /etc/rsyncd.conf
23.         owner: root
24. group: root
25. mode: 0644
26. when: ansible_hostname == "Backup"
27.  - name: create passwd file
28. copy:
29. content: 'rsync_backup:123'
30.         dest: /etc/rsync.passwd
31.         owner: root
32. group: root
33. mode: 0600
34. when: ansible_hostname == "Backup"
35.  - name: Create backup Directory
36. file:
37.         path: /backup
38.         state: directory
39. mode: 0755
40.         owner: www
41. group: www
42.         recurse: yes
43. when: ansible_hostname == "Backup"
44.  - name: Start Rsyncd Server
45.       systemd:
46.         name: rsyncd 
47.         state: started
48. when: ansible_hostname == "Backup"

3、rsync客户端推送脚本

1. [root@Ansible rsyncd]# cat rsyncd_kehu.yml
2. - hosts: all
3.   tasks:
4.  - name: SCP Backup Shell
5. copy:
6.         src: backup.sh
7.         dest: /root/backup.sh
8. when: ansible_hostname is match "web*"
9. [root@Ansible rsyncd]# ansible-playbook rsyncd_kehu.yml
10. 
11. PLAY [all] *********************************************************************
12. 
13. TASK [Gathering Facts] *********************************************************
14. ok: [nfs]
15. ok: [mysql]
16. ok: [lb01]
17. ok: [rsync]
18. ok: [lb00]
19. ok: [web02]
20. ok: [web01]
21. ok: [lb02]
22. 
23. TASK [SCP Backup Shell] ********************************************************
24. skipping: [rsync]
25. skipping: [nfs]
26. skipping: [lb01]
27. skipping: [lb02]
28. skipping: [mysql]
29. skipping: [lb00]
30. skipping: [web01]
31. skipping: [web02]
32. 
33. PLAY RECAP *********************************************************************
34. lb00                       : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
35. lb01                       : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
36. lb02                       : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
37. mysql                      : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
38. nfs                        : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
39. rsync                      : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
40. web01                      : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
41. web02                      : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
42. 
43. [root@Ansible rsyncd]#

4、变量注册后进行判断

1. [root@Ansible ~]# vim /ansible/test/test.yml 
2. - hosts: web_group
3.   tasks:
4.  - name: check httpd server
5.       command: systemctl is-active httpd
6.       ignore_errors: yes        #忽视报错继续执行
7.       register: check_httpd
8.     -name: print check_httpd    #调试完后可以取消debug
9.       debug:
10.         msg: "{{ check_httpd }}"
11.  - name: httpd restart
12.       service:
13.         name: httpd
14.         state: restated
15. when: check_httpd.rc == 0
16. 
17. [root@Ansible test]# ansible-playbook test.yml 
18. 
19. PLAY [web_group] ***************************************************************
20. 
21. TASK [Gathering Facts] *********************************************************
22. ok: [web02]
23. ok: [web01]
24. 
25. TASK [check httpd server] ******************************************************
26. fatal: [web01]: FAILED! => {"changed": true, "cmd": ["systemctl", "is-active", "httpd"], "delta": "0:00:00.072816", "end": "2023-04-19 21:10:07.733494", "msg": "non-zero return code", "rc": 3, "start": "2023-04-19 21:10:07.660678", "stderr": "", "stderr_lines": [], "stdout": "unknown", "stdout_lines": ["unknown"]}
27. ...ignoring
28. fatal: [web02]: FAILED! => {"changed": true, "cmd": ["systemctl", "is-active", "httpd"], "delta": "0:00:00.073889", "end": "2023-04-19 21:10:07.735992", "msg": "non-zero return code", "rc": 3, "start": "2023-04-19 21:10:07.662103", "stderr": "", "stderr_lines": [], "stdout": "unknown", "stdout_lines": ["unknown"]}
29. ...ignoring
30. 
31. TASK [print check_httpd] *******************************************************
32. ok: [web01] => {
33. "msg": {
34. "changed": true, 
35. "cmd": [
36. "systemctl", 
37. "is-active", 
38. "httpd"
39.         ], 
40. "delta": "0:00:00.072816", 
41. "end": "2023-04-19 21:10:07.733494", 
42. "failed": true, 
43. "msg": "non-zero return code", 
44. "rc": 3, 
45. "start": "2023-04-19 21:10:07.660678", 
46. "stderr": "", 
47. "stderr_lines": [], 
48. "stdout": "unknown", 
49. "stdout_lines": [
50. "unknown"
51.         ]
52.     }
53. }
54. ok: [web02] => {
55. "msg": {
56. "changed": true, 
57. "cmd": [
58. "systemctl", 
59. "is-active", 
60. "httpd"
61.         ], 
62. "delta": "0:00:00.073889", 
63. "end": "2023-04-19 21:10:07.735992", 
64. "failed": true, 
65. "msg": "non-zero return code", 
66. "rc": 3, 
67. "start": "2023-04-19 21:10:07.662103", 
68. "stderr": "", 
69. "stderr_lines": [], 
70. "stdout": "unknown", 
71. "stdout_lines": [
72. "unknown"
73.         ]
74.     }
75. }
76. 
77. TASK [httpd restart] ***********************************************************
78. skipping: [web01]
79. skipping: [web02]
80. 
81. PLAY RECAP *********************************************************************
82. web01                      : ok=3    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=1
83. web02                      : ok=3    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=1

playbook循环语句

写循环语句可以减少剧本的编写,提高工作效率

1、启动多个服务

1. [root@Ansible test]# cat test.yml
2. - hosts: web_group
3.   tasks:
4.  - name: start service
5.       systemd:
6.         name: "{{ item }}"
7.         state: started
8. with_items:                    #或者是用loop
9.  - httpd
10.  - php-fpm
11.  - mariadb

2、循环定义变量(以列表形式)

1. [root@Ansible test]# cat test.yml
2. - hosts: web_group
3.   tasks:
4.  - name: ensure a list of packages instaled
5.       yum: 
6.         name: "{{ packages }}"
7.       vars:
8.         packages:
9.  - httpd
10.  - httpd-tools
11. 
12. [root@Ansible test]# cat test.yml
13. - hosts: web_group
14.   tasks:
15.  - name: ensure a list of packages instaled
16.       yum: name = "{{ item }}" state=present
17. with_items:
18.  - httpd
19.  - httpd-tools

3、字典循环

1. #创建用户
2. [root@Ansible test]# cat test.yml 
3. - hosts: web_group
4.   tasks:
5.  - name: Add Users    #记得提前创建组
6.       user:
7.         name: "{{ item.name }}"
8.         groups: "{{ item.groups }}"
9.         state: present
10. with_items:
11.  - { name: 'www',groups: 'www'}
12.  - { name: 'koten',groups: 'koten'}
13. 
14. #拷贝文件
15. [root@Ansible test]# cat test.yml 
16. - hosts: web_group
17.   tasks:
18.  - name: copy conf and code
19. copy:
20.         src: "{{ item.src }}"
21.         dest: "{{ item.dest }}"
22. mode: "{{ item.mode }}"
23. with_items:
24.  - { src: "./httpd.conf", dest: "/etc/httpd/conf/", mode: "0644" }
25.  - { src: "./upload_file.php", dest: "/var/www/html/", mode: "0600" }

playbookhandlers

handler是用来执行某些条件下的任务,比如配置文件发生变化时,通过notify触发handler去重启服务。(在saltstack中也有类似的触发器,写法相对Ansible简单,只需要watch,配置文件即可)

handlers案例

1. [root@Ansible test]# cat test.yml
2. - hosts: web_group
3.   vars:
4.  - http_port: 8080                #定义http端口变量
5.   tasks:    
6.  - name: Install Http Server      #安装http服务
7.       yum:
8.         name: httpd
9.         state: present
10. 
11.  - name: config httpd server      #配置http服务
12.       template:                      #将管理机变量内容导入至客户机的这个文件
13.         src: ./httpd.conf
14.         dest: /etc/httpd/conf
15.       notify:                        #检测到配置文件发生变化后,执行handler中的变量
16.  - Restart Httpd Server       #名字要与handlers中-name保持一致
17.  - Restart PHP Server
18. 
19.  - name: start httpd server       
20.       service:
21.         name: httpd
22.         state: started    
23.         enabled: yes
24. 
25.   handlers:                          #handler中内置的变量
26.  - name: Restart Httpd Server
27.       systemd:
28.         name: httpd
29.         state: restarted 
30. 
31.  - name: Restart PHP Server
32.       systemd:
33.         name: php-fpm
34.         state: restarted

注意:

1、无论多少个task通知了相同的handlers,handlers仅会在所有tasks结束后运行一次。

2、Handlers只有在其所在的任务被执行时,才会被运行;如果一个任务中定义了notify调用Handlers,但是由于条件判断等原因,该任务未被执行,那么Handlers同样不会被执行。

3、Handlers只会在每一个play的末尾运行一次;如果想在一个playbook中间运行Handlers,则需要使用meta模块来实现。例如: -meta: flush_handlers。

4、如果一个play在运行到调用Handlers的语句之前失败了,那么这个Handlers将不会被执行。我们可以使用meta模块的–force-handlers选项来强制执行Handlers,即使Handlers所在的play中途运行失败也能执行。

5、不能使用handlers替代tasks

 

playbook任务标签

默认情况下,Ansible在执行一个剧本时,会执行剧本里的所有任务,Ansible的tag功能,可以实现给剧本中的一个或多个任务(整个剧本也可以)打上标签,利用标签来指定这些要运行剧本中的个别任务,或不执行个别任务。

1、打标签方式

对一个task打一个标签;对一个task打多个标签;对多个task打一个标签

2、标签的使用

-t                      执行指定搞定tag标签任务

-skip-tags        执行-skip-tags之外的标签任务

1. [root@Ansible test]# cat test.yml 
2. - hosts: web_group
3.   vars:
4.  - http_port: 8080
5.   tasks:
6.  - name: Install Http Server
7.       yum:
8.         name: httpd
9.         state: present
10.       tags: 
11.  - install_httpd
12.  - httpd_server
13. 
14.  - name: configure httpd server
15.       template:
16.         src: ./httpd.conf
17.         dest: /etc/httpd/conf/httpd.conf
18.       notify: Restart Httpd Server
19.       tags: 
20.  - config_httpd
21.  - httpd_server
22. 
23.  - name: start httpd server
24.       service:
25.         name: httpd
26.         state: started
27.         enabled: yes
28.       tags: service_httpd
29. 
30.   handlers:
31.  - name: Restart Httpd Server
32.       systemd:
33.         name: httpd
34.         state: restarted 
35. 
36. [root@Ansible test]# ansible-playbook test.yml --list-tags    #显示当前剧本的所有标签
37. 
38. playbook: test.yml
39. 
40.   play #1 (web_group): web_group  TAGS: []
41.       TASK TAGS: [config_httpd, httpd_server, install_httpd, service_httpd]
42. 
43. [root@Ansible test]# ansible-playbook test.yml -t httpd_server    #执行httpd_server标签的命令
44. [root@Ansible test]# ansible-playbook test.yml -t install_httpd,confiure_httpd    #执行install_httpd,confiure_httpd的命令
45. [root@Ansible test]# ansible-playbook test.yml --skip-tags httpd_server    #执行除了带httpd_server的命令

playbook文件复用

先前我们写的剧本都是一个一个去执行,我们能否通过写剧本的方法让剧本一键执行,ansible中准备了include的命令,用来动态调用task任务列表

1、只调用task:include_tasks,小剧本中只留tasks,变量需要写在单独的剧本中

1. [root@Ansible test]# cat task.yml
2. - hosts: web_group
3. vars:
4. - http_port: 8080
5. 
6. tasks:
7. - include_tasks: task_install.yml            #下面可以加when判断
8.     - include_tasks: task_configure.yml
9.     - include_tasks: task_start.yml
10. 
11. handlers:
12.     - name: Restart Httpd Server
13. systemd:
14. name: httpd
15. state: restarted
16. 
17. [root@Ansible test]# cat task_install.yml 
18. - name: Install Http Server
19. yum:
20. name: httpd
21. state: present
22. 
23. [root@Ansible test]# cat task_configure.yml 
24. - name: configure httpd server
25. template:
26. src: ./httpd.conf
27. dest: /etc/httpd/conf/httpd.conf
28. notify: Restart Httpd Server
29. 
30. [root@Ansible test]# cat task_start.yml 
31. - name: start httpd server
32. service:
33. name: httpd
34. state: started
35. enabled: yes

2、调用整个task文件:include(新版本:import_playbook)

1. - include: httpd.yml
2. - include: nfs.yml
3. - include: rsync.yml
4. 
5. - import_playbook: httpd.yml
6. - import_playbook: nfs.yml
7. - import_playbook: rsync.yml

3、在saltstack中,叫做top file入口文件

 

playbook忽略错误

剧本在执行中会检测任务执行的返回状态,遇到错误就会终止剧本,但是有些时候,即使执行错误,我们也需要它继续执行。

需要加入参数:ignore_errors: yes 忽略错误

1. [root@Ansible test]# 
2. - hosts: web_group
3.   tasks:
4.  - name: Ignore False
5.       command: /bin/false
6.       ignore_errors: yes
7. 
8.  - name: touch new file
9. file:
10.         path: /tmp/oldboy.txt
11.         state: touch

playbook错误处理

当剧本执行失败时,如果在task中设置了handler也不会被执行。但是我们可以通过参数强制调用handler

1、强制调用handler

1. [root@Ansible test]# cat test.yml
2. - hosts: web_group
3.   vars:
4.  - http_port: 8080
5.   force_handlers: yes                    #错误后强制也会调用handler
6.   tasks:
7.  - name: Install Http Server
8.       yum:
9.         name: htttpd
10.         state: present
11. 
12.  - name: config httpd server
13.       template:
14.         src: ./httpd.conf
15.         dest: /etc/httpd/conf
16.       notify:                            #检测当配置文件变化时,执行变量里的内容
17.  - Restart Httpd Server
18.  - Restart PHP Server
19. 
20.  - name: start httpd server
21.       service:
22.         name: httpd
23.         state: started
24.         enabled: yes
25. 
26.   handlers:
27.  - name: Restart Httpd Server
28.       systemd:
29.         name: httpd
30.         state: restarted 
31. 
32.  - name: Restart PHP Server
33.       systemd:
34.         name: php-fpm
35.         state: restarted

2、抑制changed

被管理主机没有发生变化,可以使用参数将change状态改为ok

1. [root@Ansible test]# cat handler.yml
2. - hosts: web_group
3.   vars:
4.  - http_port: 8080
5.   force_handlers: yes
6.   tasks:
7.  - name: shell
8.       shell: netstat -lntup|grep httpd
9.       register: check_httpd
10.       changed_when: false                        #将客户机状态设置为false,这样当管理机执行剧本时候,就不会因为这条命令执行handler中的内容,不必再去重启服务
11. 
12.  - name: debug
13.       debug: msg={{ check_httpd.stdout.lines }}
14. 
15. [root@Ansible test]# cat test.yml
16. - hosts: webservers
17.   vars:
18.  - http_port: 8080
19.   tasks:
20.  - name: configure httpd server
21.       template:
22.         src: ./httpd.conf
23.         dest: /etc/httpd/conf/httpd.conf
24.       notify: Restart Httpd Server    
25. 
26.  - name: Check HTTPD
27.       shell: /usr/sbin/httpd -t
28.       register: httpd_check
29.       changed_when: 
30.  - httpd_check.stdout.find('OK')
31.  - false
32. 
33.  - name: start httpd server
34.       service:
35.         name: httpd
36.         state: started
37.         enabled: yes
38. 
39.   handlers:
40.  - name: Restart Httpd Server
41.       systemd:
42.         name: httpd
43.         state: restarted

我是koten,10年运维经验,持续分享运维干货,感谢大家的阅读和关注!

目录
相关文章
|
11天前
|
运维 安全 应用服务中间件
自动化运维的利剑:Ansible实战应用
【9月更文挑战第24天】在现代IT基础设施的快速迭代与扩展中,自动化运维成为提升效率、保障稳定性的关键。本文将深入探讨Ansible这一流行的自动化工具,通过实际案例分析其如何简化日常运维任务,优化工作流程,并提高系统的可靠性和安全性。我们将从Ansible的基础概念入手,逐步深入到高级应用技巧,旨在为读者提供一套完整的Ansible应用解决方案。
|
17天前
|
运维 Ubuntu 应用服务中间件
自动化运维之路:Ansible实战指南
【9月更文挑战第18天】在追求效率和稳定性的今天,自动化运维已成为IT领域的热门话题。本文将引导你通过实际案例学习如何使用Ansible进行自动化配置管理、任务执行和流程编排,从而提升你的工作效率并减少人为错误。我们将从基础概念出发,逐步深入到高级应用,让你能够轻松掌握这一强大的自动化工具。
|
2天前
|
运维 应用服务中间件 持续交付
自动化运维的利器:Ansible实战应用
【9月更文挑战第33天】本文将带你深入理解Ansible,一个强大的自动化运维工具。我们将从基础概念开始,逐步探索其配置管理、任务调度等功能,并通过实际案例演示其在自动化部署和批量操作中的应用。文章旨在通过浅显易懂的语言和实例,为读者揭开Ansible的神秘面纱,展示其在简化运维工作中的强大能力。
94 64
|
1天前
|
运维 负载均衡 应用服务中间件
自动化运维:使用Ansible进行服务器配置管理
【9月更文挑战第34天】在现代IT运维工作中,自动化已成为提升效率、减少错误的关键。本文将介绍如何使用Ansible这一强大的自动化工具来简化和加速服务器的配置管理工作。我们将通过实际案例展示如何利用Ansible的Playbooks来自动化常见任务,并讨论其对提高运维团队工作效率的影响。
|
6天前
|
运维 持续交付 开发工具
自动化运维工具:Ansible入门教程
【8月更文挑战第60天】在现代IT运维管理中,自动化工具的使用已成为提高生产效率、减少人为错误和确保环境一致性的重要手段。本文将介绍Ansible——一款流行的开源自动化运维工具,通过其简单易学的语法和强大的功能,帮助读者快速入门并实现自动化部署和管理。我们将从Ansible的基本概念讲起,逐步深入到实际的代码示例,展示如何利用Ansible简化日常的运维任务。无论你是新手还是有经验的系统管理员,这篇文章都将为你提供实用的知识和技巧,让你轻松驾驭Ansible,开启自动化运维之旅。
|
6天前
|
存储 运维 Ubuntu
自动化运维:使用Ansible管理服务器
【8月更文挑战第61天】本文将介绍如何使用Ansible工具进行服务器的自动化管理。我们将从基础概念开始,逐步深入到实际的应用案例,最后通过代码示例展示如何实现自动化部署和配置管理。无论你是初学者还是有经验的运维工程师,这篇文章都会为你提供有价值的参考。
|
7天前
|
运维 应用服务中间件 持续交付
自动化运维的利器:Ansible入门与实践
【9月更文挑战第28天】在追求高效、稳定的IT运维时代,自动化工具Ansible凭借其简洁性、易用性和强大的功能脱颖而出。本文旨在通过实际案例引导读者理解Ansible的核心概念和操作流程,并分享如何通过Ansible简化日常运维任务,提升工作效率。从基础安装到高级应用,我们将一步步揭开Ansible的神秘面纱,让初学者也能轻松掌握自动化运维的要诀。
|
15天前
|
运维 Ubuntu 应用服务中间件
自动化运维:使用Ansible进行服务器配置管理
【9月更文挑战第20天】在当今快速发展的信息技术时代,自动化运维已成为提升工作效率、减少人为错误的关键技术手段。本文将引导读者了解如何使用Ansible这一强大的自动化工具来简化和加速服务器的配置管理工作。通过实际代码示例,我们将一起探索Ansible的核心概念、基本操作以及如何构建可重复使用的Playbooks,旨在为读者提供一种清晰、高效的服务器管理方法。无论你是运维新手还是希望提高现有工作流程的效率,这篇文章都将为你提供宝贵的指导和启发。
|
8天前
|
运维 Linux 网络安全
自动化运维的利器:Ansible、Puppet和Chef详解
自动化运维的利器:Ansible、Puppet和Chef详解
30 5
|
8天前
|
运维 Ubuntu 应用服务中间件
自动化运维:使用Ansible进行配置管理和任务自动化
【9月更文挑战第27天】在现代IT基础设施中,自动化运维是提高效率、减少人为错误和确保系统一致性的关键。本文将介绍如何使用Ansible,一个流行的开源IT自动化工具,来简化日常的运维任务。我们将探索Ansible的核心概念,包括它的架构、如何安装和使用它,以及一些实际的使用案例。无论你是新手还是有经验的运维专家,这篇文章都会提供有价值的见解和技巧,以帮助你更好地利用Ansible实现自动化。

热门文章

最新文章

下一篇
无影云桌面