zoukankan      html  css  js  c++  java
  • 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
    
    *************** 当你发现自己的才华撑不起野心时,就请安静下来学习吧!***************
  • 相关阅读:
    build.gradle中引入jar
    SparkSQL 运行异常:org/codehaus/janino/InternalCompilerException 执行SparkSQL时出现异常:
    MapReduce wordcount 输入路径为目录 java.lang.UnsatisfiedLinkError: org.apache.hadoop.io.nativeio.NativeIO$POSIX.stat(Ljava/lang/String;)Lorg/apache/hadoop/io/nativeio/NativeIO$POSIX$Stat;
    spark远程调试代码报错 StandaloneAppClient$ClientEndpoint: Failed to connect to master 192.168.126.128:7077
    springboot集成spark
    springboot集成spark并使用sparksql
    SparkSession、SparkContext、SQLContext和HiveContext之间的区别。
    启动thriftserver.sh
    Hive学习系列:maven+springboot+CDH环境下,连接Hive进行操作
    【网络流】——P2756 飞行员配对方案问题
  • 原文地址:https://www.cnblogs.com/lvzhenjiang/p/14199445.html
Copyright © 2011-2022 走看看