ansible入门

目录

一、Ansible基础概述

1.1 什么是Ansible

Ansible是一个IT自动化的配置管理工具,自动化主要体现在Ansible集成了丰富模块、丰富的功能组件,可以通过一个命令完成一系列的操作。进而减少我们重复性的工作和维护成本,以提高工作效率!

1.2 Ansible 可以完成哪些功能

  • 批量执行远程命令,可以对N多台主机同时进行命令的执行;
  • 批量配置软件服务,可以进行自动化的方式配置和管理服务;
  • 实现软件开发功能,Jumpserver底层使用ansible来实现的自动化管理;
  • 编排高级的IT任务,Ansible的Playbook是一门编程语言,可以用来描绘一套IT架构;

1.3 Ansible特点

  • 容易学习,无代理模式,不像saltstack既要学习客户端与服务端,还要学习客户端与服务端中间通信协议;
  • 操作灵活,体现在Ansible有较多的模块,提供了丰富的功能、playbook则提供类似于编程语言的复杂功能;
  • 简单复用,体现在Ansible一个命令可以完成很多事情;
  • 安全可靠,因为Ansible使用了SSH协议进行通信,既稳定也安全;
  • 移植性高,可以将写好的playbook拷贝任意机器进行执行;

1.4 Ansible的架构中的控制节点、被控制节点、inventory、ad-hoc、playbook、连接协议这些是什么?

20200925223530

二、Ansible安装配置

2.1 ansible安装

$ wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
$ yum install ansible -y
$ ansible --version
ansible 2.9.10
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Nov 20 2015, 02:00:19) [GCC 4.8.5 20150623 (Red Hat 4.8.5-4)]

$ ansible <host-pattern> [option]
--version: # ansible版本信息
-v:显示详细信息
-i:主机清单文件路径,默认是/etc/ansibel/hosts
-m:使用的模块的名称,默认使用command模块
-a:使用的模块参数,模块的具体工作
-k:提示输入ssh密码,而不使用基于ssh的秘钥认证
-C:模拟执行测试,但不会真的执行
-T:指定命令的超时时间

ansible配置文件优先级顺序:

  • 最先查找$ANSIBLE_CONFIG变量;
  • 其次查找当前目录下ansible.cfg
  • 然后查找用户家目录下的.ansible.cfg
  • 最后查找/etc/ansible/ansible.cfg(默认)

三、Ansible inventory

Inventory文件中填写需要被管理主机与主机组信息(逻辑上定义)。默认Inventory文件在/etc/ansible/hosts。当然也可以自定义,然后使用-i指定Inventory文件位置:示例:

3.1 场景一:基于密码连接

$ cat /etc/ansible/hosts

# 方法一
[webservers]
192.168.100.225 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass='123456'
192.168.100.226 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass='123456'

# 方法二
[webservers]
web[1:2].lzj.com ansible_ssh_pass='123456'

# 方法三
[webservers]
web[1:2].lzj.com
[webservers:vars]
ansible_ssh_pass='123456'

3.2 场景二:基于秘钥连接

$ ssh-keygen
$ ssh-copy-id 192.168.100.225
$ ssh-copy-id 192.168.100.226
$ mkdir project1/ && cd project1/
$ vim hosts
[web]
192.168.100.225
192.168.100.226
$ ansible web -m ping -i hosts

3.3 场景三:主机组使用方式

[lbservers]
192.168.100.221
192.168.100.222

[webservers]
192.168.100.223
192.168.100.224

[servers:children]    # 定义servers组包含两个子组(lbservers、webservers)
lbservers
webservers

3.4 列出每个主机组下面的主机情况

$ ansible all -i hosts --list-hosts
  hosts (2):
    192.168.100.225
    192.168.100.226
$ ansible web -i hosts --list-hosts
  hosts (2):
    192.168.100.225
    192.168.100.226

四、Ansible ad-hoc

4.1 什么是ad-hoc

ad-hoc就是临时命令,执行完成后就结束,并不会保存!

4.2 ad-hocm模式的使用场景

比如在多台机器上查看某个进程是否启动,或拷贝指定文件到本地,等等!

4.3 ad-hoc模式的命令使用

20200926003906

4.4 使用ad-doc指定一次远程命令,注意观察返回结果的颜色

  • 绿色:表示被管理主机没有被修改;
  • 黄色:表示被管理端主机发现变更;
  • 红色:表示出现了故障,注意查看提示;

4.5 ad-hoc常用的模块

command			# 指定shell命令(不支持管道等特殊字符)
shell			# 执行shell命令
scripts			# 执行shell脚本
yum_repository	# 配置yum仓库
yum				# 安装软件
copy			# 变更配置文件
file			# 建立目录或文件
service			# 启动、停止服务
mount			# 挂载设备
cron			# 定时任务
firewalld		# 防火墙
get_url			# 下载软件

4.6 使用过程中需要先了解anisble-doc帮助手册

$ ansible-doc -l		# 查看所有模块说明
$ ansible-doc copy		# 表示指定模块方法
$ ansible-doc -s copy	# 表示指定模块参数

五、ansibel 模块

5.1 yum模块

# 示例一: 安装当前最新的Apache软件,如果存在则更新
$ ansible web -m yum -a "name=httpd state=latest" -i hosts

# 示例二: 安装当前最新的Apache软件,通过epel安装
$ ansible web -m yum -a "name=httpd state=present enablerepo=epel" -i hosts

# 示例三: 通过公网URL安装rpm软件
$ ansible web -m yum -a "name=https://mirrors4.tuna.tsinghua.edu.cn/zabbix/zabbix/4.0/rhel/7/x86_64/zabbix-agent-4.0.0-2.el7.x86_64.rpm state=present" -i hosts

# 示例四:更新所有的软件包,但排除和kernel相关的
$ ansible web -m yum -a "name="*" state=present exclude="kernel*" -i hosts

# 示例五: 删除Apache软件
$  ansible web -m yum -a "name=httpd state=absent" -i hosts

5.2 copy模块

# 示例一: 将本地的httpd.conf文件Listen 端口修改为9999,然后推送到远程主机
$ sed -i 's/Listen 80/Listen 9999/g' httpd.conf
$ ansible web -m copy -a "src=httpd.conf dest=/etc/httpd/conf/httpd.conf owner=root group=root mode-644" -i hosts

# 示例二: 将本地的httpd.conf文件Listen端口修改为9988,然后推送到远端,检查远端是否存在上次备份的文件
$ sed -i 's/Listen 9999/Listen 9988/g' httpd.conf
$ ansible web -m copy -a "src=httpd.conf dest=/etc/httpd/conf/httpd.conf owner=root group=root mode=644 backup=yes" -i hosts

# 示例三: 往远程的主机文件写入内容
$ ansible web -m copy -a "content=123456........ dest=/var/www/html/index.html" -i hosts

5.3 file模块

# 示例一: 创建文件,并设置属主、属组、权限
$ ansible web -m file -a "path=/var/www/html/t1.html state=touch owner=apache group=apache mode=644" -i hosts

# 示例二: 创建目录,并设置属主、属组、权限
$ ansible web -m file -a "path=/var/www/html/dd state=directory owner=apache group=apache mode=755" -i hosts
# 示例三:递归授权目录的方式
$ ansible web -m file -a "path=/var/www/html state=directory owner=apache group=apache recurse=yes" -i hosts

5.4 get_url模块

# 示例一: 下载互联网的软件到本地
$ ansible web -m get_url -a "url=http://192.168.99.181:12138/document/Ansible.docx dest=/root/" -i hosts

# 示例二: 下载互联网文件并进行mds校验
$ md5sum Ansible.docx      # 获取文件md5值
7b1a6fe7af7252005987e16ce64e1e1a  Ansible.docx
$ ansible web -m get_url -a "url=http://192.168.99.181:12138/document/Ansible.docx dest=/root/ checksum=md5:7b1a6fe7af7252005987e16ce64e1e1a" -i hosts

5.5 service模块

# 示例一: 启动httpd服务
$ ansible web -m service -a "name=httpd state=started" -i hosts

# 示例二: 重载httpd服务
$ ansible web -m service -a "name=httpd state=reloaded" -i hosts

# 示例三: 重启httpd服务
$ ansible web -m service -a "name=httpd state=restarted" -i hosts

# 示例四: 停止httpd服务
$ ansible web -m service -a "name=httpd state=stopped" -i hosts

# 示例五: 启动httpd服务,并加入开机自启
$ ansible web -m service -a "name=httpd state=started enabled=yes" -i hosts

5.6 group模块

# 示例一: 创建news基本组,指定gid为9999
$ ansible web -m group -a "name=news gid=9999 state=present"
 -i hosts
 
# 示例二: 创建http系统组,指定gid为8888
$ ansible web -m group -a "name=http gid=8888  state=present
 system=yes" -i hosts
 
# 示例三: 删除test基本组
$ ansible web -m group -a "name=test state=absent" -i hosts

5.7 user模块

# 示例一: 创建job用户,uid是1040,主要组是adm
$ ansible web -m user -a "name=job uid=1040 group=adm" -i hosts

# 示例二: 创建joh用户,登录shell是/sbin/nologin,追加bin、sys两个组
$ ansible web -m user -a "name=joh groups=bin,sys shell=/sbin/nologin" -i hosts

# 示例三: 创建jsm用户,为其添加123作为登录密码,并创建家目录
$ ansible localhost -m debug -a "msg={{ '123' | password_hash('sha512','salt') }}"
# 获取123加密后的字符串
$6$salt$jkHSO0tOjmLW0S1NFlw5veSIDRAVsiQQMTrkOKy4xdCCLPNIsHhZkIRlzfzIvKyXeGdOfCBoW1wJZPLyQ9Qx/1

$ ansible web -m user -a 'name=jsm password=$6$salt$jkHSO0tOjmLW0S1NFlw5veSIDRAVsiQQMTrkOKy4xdCCLPNIsHhZkIRlzfzIvKyXeGdOfCBoW1wJZPLyQ9Qx/1 create_home=yes' -i hosts

# 示例四: 移除job用户
$ ansible web -m user -a "name=job state=absent remove=yes" -i hosts
# remove=yes删除普通用户家目录

# 示例五: 创建http用户,并为该用户创建2048字节的私钥,存放在~/http/.ssh/id_rsa
$ ansible web -m user -a "name=http generate_ssh_key=yes ssh_key_bits=2048 ssh_key_file=.ssh/id_rsa" -i hosts

5.8 cron模块

# 示例一: 添加定时任务,每分钟执行一次ls
$ ansible web -m cron -a "name=job1 job='ls > /dev/null'" -i hosts

# 示例二: 添加定时任务,每天的凌晨2点和凌晨5点执行一次ls
$ ansible web -m cron -a "name=job2 job='ls > /dev/null' minute=0 hour=2,5" -i hosts

# 示例三: 关闭定时任务,使定时任务失败
$ ansible web -m cron -a "name=job2 job='ls > /dev/null' minute=0 hour=2,5 disabled=yes" -i hosts

5.9 mount

# 环境准备:
$ ansible localhost -m yum -a "name=nfs-utils state=present" 
$ ansible localhost -m file -a "path=/ops state=directory"
$ ansible localhost -m copy -a 'content="/ops 192.168.100.1/24(rw,sync)" dest=/etc/exports'
$ ansible localhost -m service -a "name=nfs state=restarted"

# 示例一: 挂载nfs存储到本地的/opt目录,并实现开机自动挂载
$ ansible web -m mount -a "src=192.168.99.181:/ops path=/opt fstype=nfs opts=defaults state=mounted" -i hosts

# 示例二: 临时卸载nfs的挂载,但不会清理/etc/fstab
$ ansible web -m mount -a "src=192.168.99.181:/ops path=/opt fstype=nfs opts=defaults state=unmounted" -i hosts

# 示例三: 永久卸载ns的挂载,清理/etc/fstab
$ ansible web -m mount -a "src=192.168.99.181:/ops path=/opt fstype=nfs opts=defaults state=absent" -i hosts

5.10 firewalld

# 示例一: 永久放行https的流量,只有重启才生效
$ ansible web -m firewalld -a "zone=public service=https permanent=yes state=enabled" -i hosts

# 示例二: 永久放行8081端口的流量,只有重启才生效
$ ansible web -m firewalld -a "zone=public port=8081/tcp permanent=yes state=enabled" -i hosts

# 示例三: 放行8080-8090的所有的tcp端口流量,临时和永久都生效
$ ansible web -m firewalld -a "zone=public port=8080-8090/tcp immediate=yes permanent=yes state=enabled" -i hosts

六、Ansible playbook

6.1 什么是playbook

  • playbook:定义了一个文本文件,以.yml为后缀结尾;
  • play:定义的是主机的角色;
  • task:定义的是具体执行的任务;

总结:playbook是由一个多个多个play组成,一个play可以包含多个task任务。可以理解为:使用不同的模块来共同完成一件事情!

20200926140848

6.2 Ansible playbook与ad-hoc的关系

  • playbook是对ad-hoc的一种编排方式;
  • playbook可以持久运行,而ad-hoc只能临时运行;
  • playbook适合复杂的任务,而ad-hoc适合做快速简单的任务;
  • playbook能控制任务执行的先后顺序;

6.3 Ansible playbook书写格式

playbook是由yaml语法书写,结构清晰、可读性强。所以必须掌握yaml基础语法!

语法 概述
缩进 YAML使用固定的缩进风格表示层级结构,每个缩进由两个空格组成,不能使用ta键
冒号 以冒号结尾的除外,其他所有冒号后面所有必须有空格
短横线 表示列表项,使用一个短横杠加一个空格。多个项使用同样的缩进级别作为统一列表

七、变量

7.1 变量概述

变量提供了便捷的方式来管理ansible项目中的动态值,比如:nginx-1.12,可能后期会反复的使用这个版本的值,那么如果将此值设置为变量,后续使用和修改都将变得非常方便。这样可以简化项目的创建和维护。

那么在ansible中定义变量分为以下三种方式:

  • 通过命令行进行变量定义;
  • 在play文件中进行定义变量;
  • 通过Inventory在主机组或单个主机中设置变量;

如果定义的变量出现重复,且造成冲突,怎么办?谁说了算?

7.2 变量定义

1、在playbook的文件开头通过vars关键字进行变量定义

- hosts: web
  vars:
    - web_packages: httpd
    - ftp_packages: vsftpd

  tasks:
    - name: Install Rpm Packages "{{ web_packages }}" "{{ ftp_packages }}"
      yum:
        name:
          - "{{ web_packages }}"
          - "{{ ftp_packages }}"
        state: present

2、可以在playbook中使用vars_files指定文件作为变量文件,好处就是其他的playbook也可以调用

# 1)准备一个变量的文件,建议使用yml格式
$ cat vars.yml
web_packages: httpd
ftp_packages: vsftpd

# 2)准备playbook进行调用
$ cat test.yml
- hosts: web
  vars_files:
    - vars.yml
  tasks:
    - name: Install Rpm Packages "{{ web_packages }}" "{{ ftp_packages }}"
      yum:
        name:
          - "{{ web_packages }}"
          - "{{ ftp_packages }}"
        state: present

3、在Inventory主机清单中定义变量,但是注意:主机变量优先级高于主机组变量

# 1)在Inventory主机清单中对主机组进行定义变量
$ cat hosts
[web]
192.168.100.225
192.168.100.226

[web:vars]
filename=group_vars

# 2)playbook中直接调用变量
$ cat test.yml
- hosts: web
  tasks:
    - name: Create File
      file:
        name: /tmp/{{ filename}}
        state: touch

4、官方建议是在ansible项目目录中创建两个额外的变量目录,分别是host_varsgroup_vars

  • 测试group_vars定义变量方式
$ cat hosts
[web]
192.168.100.225
192.168.100.226

# 1)在当前的项目目录中创建两个变量的目录
$ mkdir {group,host}_vars

# 2)在group_vars目录中创建一个文件,文件名与Inventory清单中的主机组名称要保持一致
$ cat group_vars/web
web_packages: wget
ftp_packages: tree

# 3)编写playbook,只需在playbook中使用变量即可
$ cat test.yml
- hosts: web
  tasks:
    - name: Install Rpm Packages "{{ web_packages }}" "{{ ftp_packages }}"
      yum:
        name:
          - "{{ web_packages }}"
          - "{{ ftp_packages }}"
        state: present

测试test组能否使用web组定义的变量,无法使用!但是系统提供了特殊的all组,也就是说group_vars目录下创建一个all文件,定义变量对所有的主机都生效!

  • 测试host_vars定义变量方式
# 1)在host_vars目录创建一个文件,文件名与Inventory清单中的主机名称要保持一致,如果是IP地址,则创建相同的IP
$ cat hosts
[web]
192.168.100.225
192.168.100.226

# 2)在host_vars目录中创建文件,给192.168.100.225主机定义变量
$ cat host_vars/192.168.100.225
web_packages: zlib-static
ftp_packages: zmap

# 3)转别一个playbook文件调用host主机变量
$ cat test.yml
- hosts: 192.168.100.225
  tasks:
    - name: Install Rpm Packages "{{ web_packages }}" "{{ ftp_packages }}"
      yum:
        name:
          - "{{ web_packages }}"
          - "{{ ftp_packages }}"
        state: present

5、通过命令行-extra-vars-e外置穿餐设定变量

# 1)准备playbook文件
$ cat test.yml
- hosts: "{{ host }}"
  tasks:
    - name: Install Rpm Packages "{{ web_packages }}" "{{ ftp_packages }}"
      yum:
        name:
          - "{{ web_packages }}"
          - "{{ ftp_packages }}"
        state: present

# 2)执行playbook时进行变量的传递
$ ansible-playbook -i hosts test.yml -e "host=web"

6、变量的优先级顺序:

命令行变量——>paly中的vars_files——>paly中的vars——>host_vars——>group_vars/all

7.3 变量注册

register关键字可以将某个task任务结果存储至变量中,最后使用debug输出变量内容,可以用于后续排查故障!

- hosts: all
  tasks:
    - name: system status
      shell: netstat -lntp
      register: System_Status

    - name: System Status
      debug: msg="{{ System_Status.stdout_lines }}"

7.4 facts变量

Ansible facts是在被管理主机上通过ansible自动采集发现的变量。facts包含每台特定的主机信息。比如:被控端主机的主机名、IP地址、系统版本、CPU数量、内存状态、磁盘状态等等。

默认情况的facts变量名都已经预先定义好了,只需要采集被控端的信息,然后传递至facts变量即可!

 $ ansible web -m setup -i hosts > facts.txt
 # 获取所有的facts变量

facts变量使用场景:

  • 通过facts变量检查被控端主机硬件CPU信息,从而生成不同的Nginx配置文件;

  • 通过facts变量检查被控端主机名称信息,从而生成不同的zabbix配置文件;

  • 通过facts变量检查被控端主机内存状态信息,从而生成不同的memcached配置文件;

    ………………

1、facts基本用法:比如获取被控端的主机名和IP地址,然后通过debug输出

- hosts: all
  tasks:
    - name: OutPut variables ansible facts
      debug:
        msg: this default IPv4 address "{{ ansible_fqdn }}" is "{{ ansible_default_ipv4.address }}"

2、facts开启后会影响Ansible主机的性能,如果没有采集被控端主机需求可选择关闭

- hosts: web
  gather_facts: no    # 关闭信息采集

八、Ansible Task 任务控制

8.1 piaybook条件语句

判断在Ansible任务中的使用频率非常高,比如yum模块可以检测软件包是否已经被安装,而在这个过程中我们不用做太多的人工干预。但是也有部分任务需要进行判断。

案例一:根据不同操作系统,安装相同的软件包
- hosts: web
  tasks:
    - name: Centos Install Httpd
      yum:
        name: httpd
        state: present
      when: ( ansible_distribution == "CentOS" )
案例二:为所有web主机名的添加nginx仓库,其余的都跳过添加
- hosts: all
  tasks:
    - name: Create YUM Repo
      yum_repository:
        name: ansible_nginx
        description: ansible_test
        baseurl: http://nginx.org/packages/centos/$releasever/$basearch/
        enabled: yes
        gpgcheck: no
      when: ( ansible_fqdn is match("web*") )
      
# 当然when也可以使用and与or方式
# when: ( ansible_fqdn is match("web*") ) or
#		 ( ansible_fqdn is match("lb*") )
案例三:根据命令执行的结果进行判断

通过register将命令执行结果保存至变量,然后通过when语句进行判断

- hosts: all
  tasks:
    - name: Check Httpd Server
      command: systemctl is-active httpd
      ignore_errors: yes        # 忽略错误
      register: check_httpd

    - name: Httpd Restart        # 如果check_httpd执行命令结果等于0,则重启httpd,否则跳过
      service:
        name: httpd
        state: restarted
      when: check_httpd.rc == 0

8.2 playbook循环语句

有时候我们写playbook的时候会发现了很多task都要重复引用某个模块,比如一次启动10个服务,或者一个拷贝10个文件。如果安装传统的写法最少要写10次,这样会显得playbook很臃肿。如果使用循环的方式来编写playbokk,这样可以减少重复使用某个模块!

案例一: 使用循环启动多个服务
- hosts: all
  tasks:
    - name: Service Start
      service: 
        name: "{{ item }}"
        state: started
      with_items:
        - httpd
        - sshd
案例二: 使用字典批量创建用户
- hosts: all
  tasks:
    - name: Add Users
      user: 
        name: "{{ item.name }}"
        group: "{{item.group }}"
        state: present
      with_items:
        - { name: 'test01',group: 'bin' }
        - { name: 'test02',group: 'root' }
案例三: 使用变量字典循环的方式拷贝文件
- hosts: all
  tasks:
    - name: Copy File
      copy:
        src: "{{ item.src }}"
        dest: "{{ item.dest }}"
        mode: "{{ item.mode }}"
      with_items:
        - { src: 'rsync.conf' , dest: '/tmp/rsync.conf' , mode: 644 }
        - { src: 'rsync.pass' , dest: '/tmp/rsync.pass' , mode: 600 }

高级写法(变量套变量):

- hosts: all
  vars:
    - Path: /tmp
  tasks:
    - name: Copy File
      copy:
        src: "{{ item.src }}"
        dest: "{{ item.dest }}"
        mode: "{{ item.mode }}"
      with_items:
        - { src: 'rsync.conf' , dest: '{{ Path }}/rsync.conf' , mode: 644 }
        - { src: 'rsync.pass' , dest: '{{ Path }}/rsync.pass' , mode: 600 }

8.3 playbook handlers

handlers是一个触发器,也是一个tasks,只不过是一个特殊的tasks,它是需要被tasks触发才会执行。只要配置文件发生变更,则会触发handlers执行重启服务操作,如果配置文件不发生任何变化,则不会重启!
notify监控——>通知——>handlers触发

案例:playbook安装nginx
- hosts: web
  tasks:
  - name: Instll Nginx
    yum: 
      name: nginx
      state: present

  - name: Copy Nignx.conf
    template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify: Restart Nignx Service

  handlers:
    - name: Restart Nignx Service
      service:
        name: nginx
        state: restarted

handlers注意事项:

  • 无论多少个task通知相同的handlers,handlers仅会在所有task结束后执行一次;
  • 只有task发生变化后才会通知handlers,没有改变则不会触发handlers;
  • 不能使用handlers代替task,因为handlers是一个特殊的task;

8.4 playbook tag

默认情况下,Ansible在执行一个playbook时,会执行playbook中的定义的所有任务。Ansible的标签(Tags)功能可以给单独任务甚至整个playbook打上tag标签,然后利用tag标签指定要运行的个别任务,或跳过个别的任务!

案例:
- hosts: web
  tasks:
  - name: Instll Nginx
    yum: 
      name: nginx
      state: present
    tags: install nginx            # 添加tag标签

  - name: Copy Nignx.conf
    template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify: Restart Nignx Service

  - name: Start Nginx 
    service:
      name: nginx
      state: started
    tags: start nginx          # 添加tag标签

  handlers:
    - name: Restart Nignx Service
      service:
        name: nginx
        state: restarted

$ ansible-playbook -i hosts test.yml  -t 'install nginx'
# 仅仅执行playbook中的某个tag标签

$ $ ansible-playbook -i hosts test.yml  --skip-tags 'install nginx'
# 跳过playbook中的特定的tag标签

$ ansible-playbook -i hosts test.yml  -t 'install nginx' -t 'start nginx'
# 指定多个tag标签

$ ansible-playbook -i hosts test.yml  --skip-tags 'install nginx' --skip-tags 'start nginx'
# 跳过多个tag标签

8.5 playbook include

有时发现大量的playbook内容要重复编写,与tasks之间贡呢需相互调用才能完成各自贡呢。playbook庞大到维护困难,这是就需要使用include!

案例:
$ cat restart_httpd.yml 
- name: Restart Httpd Service
  service:
    name: httpd
    state: restarted

A Project的yaml文件:

- hosts: web
  tasks:
    - name: A Project command
      command: echo "A"
    - name: Restart Httpd
      include: restart_httpd.yml

A Project的yaml文件:

- hosts: web
  tasks:
    - name: B Project command
      command: echo "B"
    - name: Restart Httpd
      include: restart_httpd.yml

高级用法:

一次执行的多个playbook文件!

$ cat tasks_total.yml 
- import_playbook: test.yml
- import_playbook: test01.yml

$ ansible-playbook -i hosts  tasks_total.yml

8.6 ignore_errors忽略错误

- hosts: web
  tasks:
    - name: Command
      command: /bin/false
      ignore_errors: yes
  
    - name: Create File
      file:
        path: /tmp/file
        state: touch

8.7 playbook错误处理

通常情况下,当task失败后,play将会终止,任何在前面已经被tasks notify的handlers都不会被执行。如果在play中设置force_handlers,被通知的handlers就会被强制执行。

案例一:task执行失败强制调用handlers
- hosts: web
  force_handlers: yes     # 强制调用handlers

  tasks:
    - name: Touch File
      file:
        path: /tmp/test
        state: touch
      notify: Restart Httpd Service
    
    - name: Install Packages
      yum: 
        name: sb
        state: present

  handlers:
    - name: Restart Httpd Service
      service:
        name: httpd
        state: restarted
案例二: 关闭change的状态(确定不会对被控端主机进行任何的修改和变更)
- hosts: web
  tasks:
    - name: Install Httpd Server
      yum: 
        name: httpd
        state: present
    - name: Service Httpd Started
      service:
        name: httpd
        state: started
    - name: Check Httpd Server
      shell: ps aux | grep httpd
      register: check_httpd
      changed_when: false
    - name: OutPut Variables
      debug:
        msg: "{{ check_httpd.stdout_lines }}"
案例三: 使用changed_when检查tasksrre任务返回结果
- hosts: web
  tasks:
    - name: Configure Nginx Server
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: Restart Nginx Server

    - name: Check Httpd
      shell: /usr/sbin/nginx -t
      register: nginx_check
      changed_when:
        - (nginx_check.stdout.find('successful'))
        - false

    - name: Start Httpd Server
      service:
        name: nginx
        state: started
        enabled: yes
    
    - handlers: Restart Httpd Server
      service:
        name: nginx
        state: restarted
posted @ 2020-12-27 22:59  吕振江  阅读(559)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end