Linux —— ansible自动化运维(五)

目录

处理任务失败

忽略任务失败

任务失败后强制执行处理程序

指定任务失败条件

指定报告何时报告"Changed"结果

ansible块和错误处理

练习

总结

在受管节点上创建文件或目录

修改文件并将其复制到主机

常用文件模块

file模块处理文件,如果不存在新建

修改文件属性 

永久更改 

在受管主机上删除文件

检测受管主机上文件状态 

检测文件的MD5校验和

使用jinja2模板部署自定义文件 

控制结构

循环

条件语句

变量过滤器

管理大项目

利用主机模式选择主机

管理动态清单

配置并行

管理滚动更新

包含和导入文件

管理大项目综合实验


处理任务失败

通常情况下playbook遇到错误会终止执行,但是有特定时候我们需要在它失败后还要继续执行

忽略任务失败

关键字:ignore_errors

ignore_errors: no
ignore_errors: yes

cat test.yml
---
- name: Test
  hosts: web
  tasks:
    - name: Install Package
      yum:
        name: k8s
        state: latest
      ignore_errors: yes
...

Linux —— ansible自动化运维(五)_第1张图片

Linux —— ansible自动化运维(五)_第2张图片

任务失败后强制执行处理程序

关键字:force_handlers: yes

  • ansible playbook中,handler其实也类似于task,不过该task默认不执行,只有在触发的时候才执行
  • handler通过notify来监视单个或者多个task,一旦task执行结果发生变化,则触发handler,执行相应操作
  • handler会在所有的play都执行完毕之后才会执行,这样可以避免当handler监视的多个task执行结果都发生了变化之后而导致handler的重复执行(handler只需要在最后执行一次即可)

在notify中定义内容一定要和tasks中定义的 - name 内容一样,这样才能达到触发的效果,否则会不生效 

默认情况下,在一个play中,只要有task执行失败,则play终止,即使是与handler关联的task在失败的task之前运行成功了,handler也不会被执行。若向handler仍然能执行,需设置force_handlers: yes 

cat test01.yml
---
- hosts: web
  #  force_handlers: yes
  tasks:                   
    - name: always notify          # 一个成功的任务
      command: /bin/true
      notify: restart apache

    - name: fail task              # 一个失败的任务
      yum:
        name: k8s
        state: latest

  handlers:                        # 触发器,处理程序只有在changed的情况下执行
    - name: restart apache
      service:
        name: httpd
        state: restarted
...

Linux —— ansible自动化运维(五)_第3张图片

Linux —— ansible自动化运维(五)_第4张图片

指定任务失败条件

关键字:failed_when

tasks:
  - name: run script
    shell: /user/local/bin/user.sh
    register: command_result
    failed_when: "'failure' in command_result.stdout"

failed模块可以实现此效果

tasks:
  - name: run script
    shell: /user/local/bin/user.sh
    register: command_result
    ignore_errors: yes

  - name: Report failure
    fail:
      msg: "Authentication failure"     # fail模块可以提供明确消息
    when: "'failure' in command_result.stdout"

指定报告何时报告"Changed"结果

- name: get time
  shell: date
  changed_when: false

ansible块和错误处理

三种关键字:

block:定义要运行的主要任务

rescue:定义在block子句中定义的任务失败时运行的任务

always:定义时中独立运行的任务

练习

故意制造错误

- name: Task Failure
  hosts: web
  vars:
    web_pkg: http
    db_pkg: mariadb-server
    db_service: mariadb
  tasks:
    - name: Install {{ web_pkg }} packages
      yum:
        name: "{{ web_pkg }}"
        state: present
                 
    - name: Install {{ db_pkg }} packages
      yum:
        name: "{{ db_pkg }}"
        state: present

Linux —— ansible自动化运维(五)_第5张图片

在这里我们发现,第一个任务失败,第二个任务就不会运行

添加忽略关键字

13         ignore_errors: yes

Linux —— ansible自动化运维(五)_第6张图片

使用block、rescue、always将任务分开

rescue:定义任务失败的时候的定义,相当于if...else中的else语句

always:定义始终独立运行的任务

- name: Task Failure
  hosts: web
  vars:
    web_pkg: http
    db_pkg: mariadb-server
    db_service: mariadb
  tasks:
    - name: set up web
      block:
        - name: Install {{ web_pkg }} packages
          yum:
            name: "{{ web_pkg }}"
            state: present
      rescue:
        - name: Install {{ db_pkg }} packages
          yum:
            name: "{{ db_pkg }}"
            state: present
      always:
        - name: start {{ db_service }} service
          service:
            name: "{{ db_service }}"
            state: started

Linux —— ansible自动化运维(五)_第7张图片

执行结果有报错,但是mariadb正常启动

再修改,将http的包改为正确

    web_pkg: httpd

Linux —— ansible自动化运维(五)_第8张图片

发现rescue部分被忽略,但是always总会执行

控制'changed'条件

- name: Task Failure
  hosts: web
  vars:
    web_pkg: httpd
    db_pkg: mariadb-server
    db_service: mariadb
  tasks:
    - name: check time
      command: date
      register: command_result
      #changed_when: false

    - name: print time
      debug:
        var: command_result.stdout

    - name: set up service
      block:
        - name: Install {{ web_pkg }} packages
          yum:
            name: "{{ web_pkg }}"
            state: present
            #  failed_when: web_pkg == 'httpd'

      rescue:
        - name: Install {{ db_pkg }} packages
          yum:
            name: "{{ db_pkg }}"
            state: present

      always:
        - name: start {{ db_service }} service
          service:
            name: "{{ db_service }}"
            state: started

Linux —— ansible自动化运维(五)_第9张图片

运行发现check time任务始终是changed

但是因为任务没有更改受管主机,所以不应该每次都是changed

修改文件

12       changed_when: false

Linux —— ansible自动化运维(五)_第10张图片

再次运行,变为OK

使用failed_when关键字

            failed_when: web_pkg == 'httpd'

有报错,但是其实已经安装了httpd包,failed_when关键字只是改变了任务的执行状态,没有改变任务本身。但是失败的状态可以让rescue语句块执行

总结

  1. 循环迭代的方法
  2. 条件用于仅在符合特定条件时执行任务或play
  3. 处理程序用法
  4. 只有任务报告受管主机做了更改,才会通知处理程序
  5. 处理任务失败,即使成功的任务也可以标记为失败
  6. 块用于将任务分组为单元,通过任务是否成功来确定执行其他任务与否

在受管节点上创建文件或目录

修改文件并将其复制到主机

常用文件模块

文件模块 功能
blockinfile 将文本块添加到现有文件
copy 将文件复制到受管主机
fetch 从受管主机拷贝文件到控制节点
file 设置文件属性
lineinfile 确保特定行位于某个文件
stat 检索文件状态信息
synchronize rsync命令的一个打包程序

file模块处理文件,如果不存在新建

- name: Test
  hosts: web
  tasks:
    - name: Touch a file
      file:
        path: /root/file
        owner: westos
        group: westos
        mode: 0640
        state: touch

Linux —— ansible自动化运维(五)_第11张图片

修改文件属性 

    - name: set selinux
      file:
        path: /root/file
        setype: samba_share_t

Linux —— ansible自动化运维(五)_第12张图片

永久更改 

    - name: set selinux
      sefcontext:
        target: /root/file
        setype: samba_share_t
        state: present

Linux —— ansible自动化运维(五)_第13张图片

在受管主机上删除文件

- name: delete file
  file:
    dest: /root/file
    state: absent      # absent即删除

检测受管主机上文件状态 

检测文件的MD5校验和

    - name: verify the status
      stat:
        path: /root/file
        checksum_algorithm: md5
      register: result

    - debug:
        msg: "The checksum is {{ result.stat.checksum }}"

使用jinja2模板部署自定义文件 

构建出模板可以更方便的管理文件

{ % EXPR % }        # 表达式或者逻辑
{{ EXPR }}          # 最终向用户输出表达式或结果
{ # COMMENT # }     # 注释

构建jinja2模板

jinja2模板由多个元素组成:数据、变量、表达式,模板中使用的变量可以在playbook的vars中指定

模板中所有的值都使用变量方式,将来会被受管主机对应的值替代

Port 22 ==> Port {{ ssh_port }}

PermitRootLogin yes ==> {{ root_allowed }}

部署jinja2模板

tasks:
  - name: template
    template:
      src: /root/j2-template.j2
      dest: /root/dest-config-file.txt

控制结构

循环

#1
{ % for user in users %}
    {{ user }}       # user变量将遍历users
{ % endfor % }

#2
{ % for myhost in groups['myhosts'] %}   # 列出myhosts组中所有主机
    {{ myhosts }}           
{ % endfor % }

条件语句

{ % if finished % }    # 只有此条件为真,才会将result变量的值放入文件
{{ result }}
{ % endif % }

注意:jinja2的循环和条件只能在模板中使用,不能在playbook中使用 

变量过滤器

{{ output | to_json }}     #以 json 格式输出
{{ output | to_yaml }} 


{{ output | from_json }}    #对 json 格式字符串进行解析
{{ output | from_yaml }}

变量可以通过“过滤器”进行修改,过滤器可以理解为是jinja2里面的内置函数和字符串处理函数

过滤器名称 说明
safe 渲染时值不转义
capitialize 把值的首字母转换成大写,其他子母转换为小写
lower 把值转换成小写形式
upper 把值转换成大写形式
title 把值中每个单词的首字母都转换成大写
trim 把值的首尾空格去掉
striptags 渲染之前把值中所有的HTML标签都删掉
join 拼接多个值为字符串
replace 替换字符串的值
round 默认对数字进行四舍五入,也可以用参数进行控制
int 把值转换成整型

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

  • file 模块库包含创建、复制、编辑、修改等权限和其他属性
  • 使用 jinja2 模板动态构建文件来部署
  • jinja2 模板由两个元素构成:变量和表达式,在使用 jinja2 模板时,他们被替换为值
  • 通过 jinja2 过滤器,模板表达式可以从一种数据格式转换为另一种

管理大项目

利用主机模式选择主机

1.使用通配符匹配多个主机
-hosts:'*'  匹配所有 
 -hosts:'*.example.com'   匹配所有已example.com结尾的主机 
  -hosts:'172.25.254.*'    匹配所有此网段的主机
2.通过列表匹配主机或主机组
-hosts:www1.example.com,www2.example.com,172.25.254.250   匹配此三台主机
-hosts:webservers,westos   匹配此两个主机组
3.将通配符和列表等一起使用 
-hosts:webservers,&westos 即属于webserver组也属于westos组  
4.匹配westos组中所有主机,但是 servera.lab.example.com除外 
-hosts:westos,!servera.lab.example.com
5.匹配所有主机除了servera.lab.example.com 
-hosts all,!servera.lab.example.com

管理动态清单

编写动态清单程序,将 INI 格式的清单转换为 JSON 格式

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

配置并行

使用 forks 在 ansible 中配置并行,ansible 最大同时连接数由 ansible 配置文件中 forks 参数控制

å¨è¿éæå¥å¾çæè¿°

可以在命令行使用 -f 或者 --forks 参数来指定并行数

管理滚动更新

如果更新发生在负载均衡服务器,更新完成会重启,可能导致后端所有 web 服务器停止服务, 可以使用 serial 关键字来分批运行

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

serial 参数优点:
在更新时如果出现问题,那么在前 2 台发生问题是 playbook 就会 停止运行,后面的服务器不会执行,那么也就保证了服务的高可用

包含和导入文件

大型 playbook 管理起来比较复杂,可以用模块化的方式管理

两种方法:包含、导入

1. 导入 playbook

例 1:
 - name: configure webserver
    import_playbook: web.yml 
    
例 2:
 - name: Play 1
    hosts: localhost 
    tasks:
      - debug: 
          msg: Play1
   - name: Import Playbook
     import_playbook: play2.yml

2. 导入和包含任务的 playbook

一个只有任务的 playbook

å¨è¿éæå¥å¾çæè¿°

  • 导入任务

å¨è¿éæå¥å¾çæè¿°

使用导入时,when 等条件语句应用于导入的每个任务;循环不能作用于导入的任务

  • 包含任务

å¨è¿éæå¥å¾çæè¿°

为外部 play 和任务定义变量

提高复用性

å¨è¿éæå¥å¾çæè¿°

可以用于导入

å¨è¿éæå¥å¾çæè¿°

管理大项目综合实验

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

  • 运行

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

  • 测试

å¨è¿éæå¥å¾çæè¿°

å¨è¿éæå¥å¾çæè¿°

 

你可能感兴趣的:(ansible自动化运维)