ansible 流程控制
Posted 徐中祥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ansible 流程控制相关的知识,希望对你有一定的参考价值。
一、Ansible定义变量
1.设置变量的方法
1.在主机清单中配置变量
2.在命令行定义变量
3.在playbook中定义变量
4.使用内置变量
5.通过vars_file定义变量
6.通过host_vars和group_vars定义变量
2.变量优先级测试
1)在playbook中定义变量
[root@m01 project]# vim test.yml
- hosts: web_group
vars:
file: playbook_vars
tasks:
- name: Touch File
file:
path: /tmp/{{ file }}
state: touch
2)在vars_file中定义变量
#1.定义变量文件
[root@m01 project]# vim vars.yml
file: vars_file
#2.剧本调用
[root@m01 project]# vim test.yml
- hosts: web_group
vars:
file: playbook_vars
vars_files: /project/vars.yml
tasks:
- name: Touch File
file:
path: /tmp/{{ file }}
state: touch
3)主机清单定义变量
[root@m01 project]# vim /etc/ansible/hosts
[web_group:vars]
file=inventory_vars
4)host_vars 定义变量
[root@m01 project]# vim host_vars/web01
file: host_vars
5)group_vars定义变量
[root@m01 project]# vim group_vars/web_group
file: group_vars
6)命令行定义变量
[root@m01 project]# ansible-playbook test.yml -e "file=command"
7)测试优先级结果
命令行优先级 > vars_file优先级 > playbook_vars优先级 > host_vars优先级 > group_vars优先级 > 主机清单中主机组的优先级 > 主机清单中整合组的优先级
3.层级定义变量
#编辑变量文件
[root@m01 ~]# vim vars_file.yml
lamp:
framework:
web_package: httpd
db_package: mariadb-server
php_package: php
lnmp:
framework:
web_package: nginx
db_package: mysql
php_package: php
lnmt:
framework:
web_package: nginx
db_package: mysql
java_package: tomcat
#编辑playbook文件
[root@m01 ~]# vim test.yml
- hosts: web_group
vars_files: ./vars_file.yml
tasks:
- name: Install LAMP httpd
yum:
name: "{{ lamp.framework.web_package }}"
- name: Install LAMP mariadb-server
yum:
name: "{{ lamp.framework.db_package }}"
- name: Install LAMP php
yum:
name: "{{ lamp.framework.php_package }}"
#官方推荐写法
[root@m01 ~]# vim test.yml
- hosts: web_group
vars_files: ./vars_file.yml
tasks:
- name: Install LAMP httpd
yum:
name: "{{ lamp['framework']['web_package'] }}"
- name: Install LAMP mariadb-server
yum:
name: "{{ lamp['framework']['db_package'] }}"
- name: Install LAMP php
yum:
name: "{{ lamp['framework']['php_package'] }}"
#执行playbook
[root@m01 ~]# ansible-playbook test.yml
二、变量注册
当absible的模块在运行之后,其实都会返回一些result结果,就像是执行脚本,我们有的时候需要脚本给我们一些return返回值,我们才知道,上一步是否可以执行成功,但是...默认情况下,ansible的result并不会显示出来,所以,我们可以把这些返回值'存储'到变量中,这样我们就能通过'调用'对应的变量名,从而获取到这些result,这种将模块的返回值,写入到变量中的方法被称为变量注册
1.使用ad-hoc模式会得到返回结果
[root@m01 project]# ansible web01 -m shell -a 'ls -l /tmp'
web01 | CHANGED | rc=0 >>
total 0
drwx------. 2 root root 41 Dec 23 15:07 ansible_command_payload_Q9bnkr
-rw-r--r--. 1 root root 0 Dec 23 14:54 command
-rw-r--r--. 1 root root 0 Dec 23 14:57 host_vars
-rw-r--r--. 1 root root 0 Dec 23 14:56 playbook_vars
-rw-r--r--. 1 root root 0 Dec 23 14:55 vars_file
2.使用playbook执行同样的命令得不到结果
[root@m01 project]# cat test.yml
- hosts: web_group
tasks:
- name: Touch File
shell: "ls -l /tmp"
[root@m01 project]# ansible-playbook test.yml
PLAY [web_group] *****************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************
ok: [web01]
ok: [web02]
TASK [Touch File] ****************************************************************************************************
changed: [web01]
changed: [web02]
PLAY RECAP ***********************************************************************************************************
web01 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web02 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
3.使用注册变量的方式
1)注册一个变量
[root@m01 project]# vim test.yml
- hosts: web_group
tasks:
- name: Touch File
shell: "ls -l /tmp"
register: get_dir_list
2)调用并输出变量
[root@m01 project]# vim test.yml
- hosts: web_group
tasks:
- name: Touch File
shell: "ls -l /tmp"
register: get_dir_list
- name: Get Register
debug:
msg: "{{ get_dir_list }}"
3)只输出想要的部分
[root@m01 project]# vim test.yml
- hosts: web_group
tasks:
- name: Touch File
shell: "ls -l /tmp"
register: get_dir_list
- name: Get Register
debug:
msg: "{{ get_dir_list['stdout_lines'] }}"
4.变量注册一般使用场景
[root@m01 project]# cat php.yml
- hosts: web_group
tasks:
- name: Tar php Package
unarchive:
src: /project/package/php.tar.gz
dest: /tmp/
- name: Check php Install Status
shell: "rpm -qa | grep php | wc -l"
register: get_php_instll_status
- name: Install php Server
shell: "yum localinstall -y /tmp/*.rpm"
when: get_php_instll_status.stdout_lines == 0
- name: Config php Server
copy:
src: /project/conf/php.ini
dest: /etc/
- name: Config php Server
copy:
src: /project/conf/www.conf
dest: /etc/php-fpm.d/
- name: Start php Server
systemd:
name: php-fpm
state: started
三、facts缓存
Ansible facts是在被管理主机上通过Ansible自动采集发现的变量。facts包含每台特定的主机信息。比如:被控端的主机名、IP地址、系统版本、CPU数量、内存状态、磁盘状态等等。
1.使用场景
1.通过facts缓存检查CPU,来生成对应的nginx配置文件
2.通过facts缓存检查主机名,生成不同的redis配置文件
3.通过facts缓存检索物理机的内存大小来生成不通的mysql配置文件
综上所述的Ansible facts类似于saltstack中的grains对于做自动化的小伙伴是非常有用滴。
2.关闭facts缓存
[root@m01 ~]# vim facts.yml
- hosts: web_group
gather_facts: no #关闭信息采集
tasks:
#如果不使用内置变量,可以关闭会提高剧本的执行速度,如果使用内置变量,那么不能关闭facts缓存
3.一般使用
#1.配置redis配置文件
[root@m01 ~]# vim /etc/redis.conf
bind {{ ansible_eth1.ipv4.address }}
#2.编写剧本
- hosts: web_group
tasks:
- name: Install Redis Server
yum:
name: redis
state: present
- name: Config Redis Server
template:
src: /etc/redis.conf
dest: /etc/
#3.查看受控端配置
[root@web01 ~]# vim /etc/redis.conf
bind 172.16.1.7
[root@web02 ~]# vim /etc/redis.conf
bind 172.16.1.8
Ansible 流程控制
四、playbook 条件语句
不管是shell还是各大编程语言中,流程控制,条件判断这些都是必不可少的,在我们使用Ansible的过程中,条件判断的使用频率极其高。
例如:
1.我们使用不同的系统的时候,可以通过判断系统来对软件包进行安装。
2.在nfs和rsync安装过程中,客户端服务器不需要推送配置文件,之前我们都是写多个play,会影响效率。
3.我们在源码安装nginx的时候,执行第二遍就无法执行了,此时我们就可以进行判断是否安装过。
1.判断系统
[root@m01 project]# vim xitong.yml
- hosts: web_group
tasks:
- name: Install Centos httpd
shell: "yum install -y httpd"
when: ansible_distribution == "CentOS"
- name: Install Ubuntu httpd
shell: "apt-get apache2"
when: ansible_distribution == "Ubuntu"
2.判断主机
[root@m01 project]# cat base.yml
- name: Create www Group
group:
name: www
gid: 666
state: present
when: ansible_fqdn != "db01"
- name: Create www User
user:
name: www
uid: 666
group: www
shell: /sbin/nologin
create_home: false
state: present
when: ansible_fqdn != "db01"
3.判断服务是否安装
[root@m01 project]# cat php.yml
- hosts: web_group
tasks:
- name: Tar php Package
unarchive:
src: /project/package/php.tar.gz
dest: /tmp/
#使用shell模块,检查php是否安装,将结果赋值给注册的变量
- name: Check php Install Status
shell: "rpm -qa | grep php | wc -l"
register: get_php_instll_status
#调用注册的变量,当变量中stdout_lines为0的时候,才会安装php
- name: Install php Server
shell: "yum localinstall -y /tmp/*.rpm"
when: get_php_instll_status.stdout_lines == 0
4.判断系统版本启动服务
1)写法一:使用列表的形式
[root@m01 project]# vim startserver.yml
- hosts: web_group
tasks:
- name: Start CentOS 6 Server
shell: "/etc/init.d/httpd start"
when:
- ansible_distribution == "CentOS"
- ansible_distribution_major_version == "6"
- name: Start CentOS 7 Server
shell: "systemctl start httpd"
when:
- ansible_distribution == "CentOS"
- ansible_distribution_major_version == "7"
2)写法二:多条件and连接
[root@m01 project]# vim startserver.yml
- hosts: web_group
tasks:
- name: Start CentOS 6 Server
shell: "/etc/init.d/httpd start"
when: (ansible_distribution == "CentOS") and
(ansible_distribution_major_version == "6")
- name: Start CentOS 7 Server
shell: "systemctl start httpd"
when: (ansible_distribution == "CentOS") and (ansible_distribution_major_version == "7")
5.判断服务是否启动
- hosts: web_group
tasks:
- name: Check Httpd Server
command: systemctl is-active httpd
ignore_errors: yes
register: check_httpd
- name: debug outprint
debug: var=check_httpd
- name: Httpd Restart
service:
name: httpd
state: restarted
when: check_httpd.rc == 0
五、playbook 循环语句
在之前的学习过程中,我们经常会有传送文件,创建目录之类的操作,创建2个目录就要写两个file模块来创建,如果要创建100个目录,我们需要写100个file模块???妈耶~~~~ 当然不是,只要有循环即可,减少重复性代码。
1.定义循环安装服务
[root@m01 project]# vim yum.yml
- hosts: web_group
gather_facts: no
tasks:
- name: Install Redis Server
yum:
name: "{{ package }}"
state: present
vars:
package:
- redis
- httpd
2.定义循环启动服务
#错误写法
[root@m01 project]# vim start.yml
- hosts: web_group
tasks:
- name: Start Server
systemd:
name: "{{ package }}"
state: started
vars:
package:
- redis
- httpd
#正确写法
[root@m01 project]# vim start.yml
- hosts: web_group
tasks:
- name: Start Server
systemd:
name: "{{ item }}"
state: started
with_items:
- redis
- httpd
3.字典定义变量
[root@m01 project]# cat user.yml
- hosts: lb01
tasks:
- name: Create Some Group
group:
name: "{{ item.name }}"
gid: "{{ item.gid }}"
state: present
with_items:
- { name: "lhd", gid: "777" }
- { name: "test", gid: "888" }
- { name: "egon", gid: "999" }
- name: Create Some User
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
group: "{{ item.group }}"
shell: "{{ item.shell }}"
create_home: "{{ item.create_home }}"
with_items:
- { name: "lhd", uid: "777", group: "lhd", shell: "/sbin/nologin", create_home: "false" }
- { name: "test", uid: "888", group: "test", shell: "/bin/bash", create_home: "false" }
- { name: "egon", uid: "999", group: "egon", shell: "/bin/bash", create_home: "true" }
六、playbook handlers 触发器
1.什么是handlers?
handler用来执行某些条件下的任务,比如当配置文件发生变化的时候,通过notify触发handler去重启服务。
在saltstack中也有类似的触发器,写法相对Ansible简单,只需要watch,配置文件即可。
2.配置触发器
[root@m01 project]# cat nginx.yml
- hosts: nginx
tasks:
- name: Config Nginx Server
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
notify: restart_nginx
- name: Start Nginx Server
systemd:
name: nginx
state: started
handlers:
- name: restart_nginx
systemd:
name: nginx
state: restarted
3.触发器使用注意事项
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
4.简单优化后的php文件
[root@m01 project]# cat php.yml
- hosts: web_group
tasks:
- name: Tar php Package
unarchive:
src: /project/package/php.tar.gz
dest: /tmp/
- name: Check php Install Status
shell: "rpm -qa | grep php | wc -l"
register: get_php_instll_status
- name: Install php Server
shell: "yum localinstall -y /tmp/*.rpm"
when: get_php_instll_status.stdout_lines == 0
- name: Config php Server
copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
with_items:
- { src: "/project/conf/php.ini", dest: "/etc" }
- { src: "/project/conf/www.conf", dest: "/etc/php-fpm.d/" }
notify: restart_php
- name: Start php Server
systemd:
name: php-fpm
state: started
handlers:
- name: restart_php
systemd:
name: php-fpm
state: restarted
七、playbook 任务标签
1.标签的作用
默认情况下,Ansible在执行一个playbook时,会执行playbook中定义的所有任务,Ansible的标签(tag)功能可以给单独任务甚至整个playbook打上标签,然后利用这些标签来指定要运行playbook中的个别任务,或不执行指定的任务。
2.打标签的方式
1.对一个task打一个标签
2.对一个task打多个标签
3.对多个task打一个标签
3.对一个task打一个标签
- hosts: nginx
- name: Config Nginx Server
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
notify: restart_nginx
tags: reconf_nginx
4.对多个task打一个标签
- hosts: nginx
- name: Config Nginx Server
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
notify: restart_nginx
tags: reconf_nginx
- name: Config Nginx wordpress
copy:
src: /project/conf/linux.wp.com.conf
dest: /etc/nginx/conf.d/
notify: reload_nginx
when: (ansible_fqdn == "web01") or (ansible_fqdn == "web02")
tags: reconf_nginx
5.对一个task打多个标签
- hosts: nginx
- name: Config Nginx Server
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
notify: restart_nginx
tags:
- reconf_nginx
- reconfig_nginx
6.标签使用方式
1)查看标签
[root@m01 project]# ansible-playbook wp.yml --list-tags
playbook: wp.yml
play #1 (nginx): nginx TAGS: []
TASK TAGS: [reconf_nginx, reconfig_nginx]
2)执行指定标签的内容
[root@m01 project]# ansible-playbook wp.yml -t reconfig_nginx
3)执行多个标签代表的内容
[root@m01 project]# ansible-playbook wp.yml -t reconf_nginx,reconfig_nginx
4)不执行指定标签的内容
[root@m01 project]# ansible-playbook wp.yml --skip-tags reconfig_nginx
八、playbook 复用
在之前写playbook的过程中,我们发现,写多个playbook没有办法,一键执行,这样我们还要单个playbook挨个去执行,很鸡肋。所以在playbook中有一个功能,叫做include用来动态调用task任务列表。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rDNwm4tz-1623254345938)(img/image-20201224101614708.png)]
1.playbook复用的配置
1)编辑两个剧本
[root@m01 project]# cat play1.yml
- name: Install Nginx Server
yum:
name: nginx
state: present
[root@m01 project]# cat play2.yml
- name: Config Nginx Server
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/
2)编写复用剧本的文件
[root@m01 project]# vim main.yml
- hosts: web_group
tasks:
- include_tasks: /project/play1.yml
- include_tasks: /project/play2.yml
2.直接复用palybook文件
[root@m01 project]# cat main.yml
- import_playbook: ./base.yml
- import_playbook: ./nginx.yml
- import_playbook: ./php.yml
- import_playbook: ./wordpress.yml
- import_playbook: ./mariadb.yml
以上是关于ansible 流程控制的主要内容,如果未能解决你的问题,请参考以下文章