• 自动化运维工具-Ansible之5-流程控制


    自动化运维工具-Ansible之5-流程控制

    playbook条件语句

    不管是shell还是各大编程语言中,流程控制,条件判断这些都是必不可少的,在我们使用Ansible的过程中,条件判断的使用频率极其高。

    例如:

    1. 使用不同系统的时候,可以通过判断系统型号,来区分需要安装的软件包。
    2. nfsrsync安装过程中,客户端服务器不需要推送配置文件,写多个play,影响效率。
    3. 在源码安装nginx的时候,执行第二遍就无法执行了,此时我们就可以使用判断验证是否安装过。

    单条件

    官方示例:

    tasks:
      - name: "shut down Debian flavored systems"
        command: /sbin/shutdown -t now
        when: ansible_facts['os_family'] == "Debian"
        # 请注意,所有变量都可以直接用于条件语句中,而无需使用双大括号
    
    1. 使用when判断系统
    - hosts: web_group
      tasks:
        - name: Install CentOS Httpd
          yum:
            name: httpd
            state: present
          when: ansible_distribution == "CentOS"
    
        - name: Install Ubuntu Httpd
          yum:
            name: apache2
            state: present
          when: ansible_distribution == "Ubuntu"
    
    1. 使用when判断系统版本
    - hosts: web_group
      tasks:
        - name: Start CentOS6 Httpd
          shell: "/etc/init.d/httpd start"
          when: ansible_distribution_major_version == '6'
    
        - name: Start CentOS7 Httpd
          shell: "systemctl start httpd"
          when: ansible_distribution_major_version == '7'
    
    1. 使用注册变量对返回值进行判断
    - hosts: web_group
      tasks:
        - name: Test php Rpm Install
          shell: "rpm -qa | grep php"
          register: check_php
    
        - name: Install php
          shell: "cd /usr/local/src && rpm -Uvh *rpm"
          when: check_php.rc != 0
    

    多条件

    1. 使用list列表形式(只能表示并且and和)
    tasks:
      - name: "shut down CentOS 6 systems"
        command: /sbin/shutdown -t now
        when:
          - ansible_facts['distribution'] == "CentOS"
          - ansible_facts['distribution_major_version'] == "6"
    

    1. 使用小括号分组
    tasks:
      - name: "shut down CentOS 6 and Debian 7 systems"
        command: /sbin/shutdown -t now
        when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "6") or
              (ansible_facts['distribution'] == "Debian" and ansible_facts['distribution_major_version'] == "7")
    

    1. 使用is match支持通配符
    tasks:
      - name: Add Crontab
        cron:
          name: "backup"
          minute: "00"
          hour: "01"
          job: "/bin/sh /root/backup.sh &>/dev/null"
        when: ansible_fqdn is match 'web*'
    

    多条件运算

    tasks:
      - shell: echo "only on Red Hat 6, derivatives, and later"
        when: ansible_facts['os_family'] == "RedHat" and ansible_facts['lsb']['major_release']|int >= 6
    

    示例

    rsync服务端推送配置文件

    [root@m01 ~]# cat > /root/rsyncd/rsyncd.yml <<EOF
    - hosts: rsync_server
      tasks:
        - name: Install Rsyncd Server
          yum:
            name: rsync
            state: present
    
        - name: Create www Group
          group:
            name: www
            gid: 666
    
        - name: Create www User
          user:
            name: www
            group: www
            uid: 666
            create_home: false
            shell: /sbin/nologin
    
        - name: Scp Rsync Config
          copy:
            src: ./rsyncd.j2
            dest: /etc/rsyncd.conf
            owner: root
            group: root
            mode: 0644
          when: ansible_hostname == "backup"
    
        - name: Create Passwd File
          copy:
            content: 'rsync_backup:123'
            dest: /etc/rsync.passwd
            owner: root
            group: root
            mode: 0600
          when: ansible_hostname == "backup"
    
        - name: Create backup Directory
          file:
            path: /backup
            state: directory
            mode: 0755
            owner: www
            group: www
            recurse: yes
          when: ansible_hostname == "backup"
    
        - name: Start Rsyncd Server
          systemd:
            name: rsyncd
            state: started
          when: ansible_hostname == "backup"
    EOF
    

    rsync客户端推送脚本

    [root@m01 ~]# cat > /root/rsyncd/rsync.yml <<EOF
    - hosts: all
      tasks:
        - name: SCP Backup Shell
          copy:
            src: ./backup.sh
            dest: /root/backup.sh
          when: ansible_hostname is match "web*"
    EOF
    

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

    如果httpd服务已经启动,就重启

    [root@m01 ~]# cat > /root/rsyncd/if.yml <<EOF
    - 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
    EOF
    

    playbook循环语句

    with_items列表循环

    - hosts: web_group
      tasks:
        - name: start service
          systemd:
            name: "{{ item }}"
            state: started
          with_items:
            - httpd
            - php-fpm
            - mariadb
    
    - hosts: web_group
      tasks:
        - name: ensure a list of packages installed
          yum: name= "{{ item }}" state=present
          with_items:
            - httpd
            - httpd-tools
    

    自定义变量列表循环

    - name: ensure a list of packages installed
      yum:
        name: "{{ packages }}"
      vars:
        packages:
        - httpd
        - httpd-tools
    

    字典循环

    - hosts: web_group
      tasks:
        - name: Create Groups
          group:
            name: "{{ item.name }}"
            gid: "{{ item.gid }}"
          with_items:
            - { name: www, gid: 666 }
            - { name: lhd, gid: 777 }
            - { name: dsb, gid: 888 }
    
    - hosts: web_group
      tasks:
        - name: Create Users
          user:
            name: "{{ item.name }}"
            uid: "{{ item.uid }}"
            group: "{{ item.name }}"
            shell: "{{ item.shell }}"
            create_home: "{{ item.create_home }}"
          with_items:
            - { name: www, uid: 666, shell: "/sbin/nologin", create_home: no }
            - { name: lhd, uid: 777, shell: "/bin/bash", create_home: no }
            - { name: dsb, uid: 888, shell: "/bin/bash", create_home: yes }
    
    - hosts: web_group
      tasks:
        - name: Copy Conf And Passwd
          copy:
            src: "{{ item.src }}"
            dest: "{{ item.dest }}"
            mode: "{{ item.mode }}"
          with_items:
            - { src: "./rsyncd.conf", dest: "/etc/rsyncd.conf", mode: "0644" }
            - { src: "./rsync.passwd", dest: "/etc/rsync.passwd", mode: "0600" }
    

    playbook触发器 handlers

    handler用来执行某些条件下的任务,比如当配置文件发生变化的时候,通过notify触发handler去重启服务。

    在saltstack中也有类似的触发器,写法相对Ansible简单,只需要watch,配置文件即可。


    示例

    - hosts: web_group
      vars:
        - http_port: 8080
      tasks:
        - name: Install Http Server
          yum:
            name: httpd
            state: present
    
        - name: config httpd server
          template:
            src: ./httpd.j2
            dest: /etc/httpd/conf/httpd.conf
          notify: 
            - Restart Httpd Server
    
      handlers:
        - name: Restart Httpd Server
          systemd:
            name: httpd
            state: restarted 
    

    注意:

    1. 无论多少个task通知了相同的HandlersHandlers仅会在所有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在执行一个playbook时,会执行playbook中定义的所有任务,Ansible的标签(tag)功能可以给单独任务甚至整个playbook打上标签,然后利用这些标签来指定要运行playbook中的个别任务,或不执行指定的任务。


    打标签的方式

    1. 对task下面的一个name打一个标签
    2. 对task下面的一个name打多个标签
    3. 对task下面的多个name打一个标签

    标签的使用

    -t:执行指定的tag标签任务
    --skip-tags:执行--skip-tags之外的标签任务


    使用-t指定tag

    - hosts: web_group
      vars:
        - http_port: 8080
      tasks:
        - name: Install Http Server
          yum:
            name: httpd
            state: present
          tags: 
            - install_httpd
            - httpd_server
    
        - name: configure httpd server
          template:
            src: ./httpd.j2
            dest: /etc/httpd/conf/httpd.conf
          notify: Restart Httpd Server
          tags: 
            - config_httpd
            - httpd_server
    
        - name: start httpd server
          service:
            name: httpd
            state: started
            enabled: yes
          tags: service_httpd
    
      handlers:
        - name: Restart Httpd Server
          systemd:
            name: httpd
            state: restarted
    
    #查看所有的标签(也可以查看该剧本有多少 hosts )
    [root@m01 ~]# ansible-playbook tag.yml --list-tags
    
    #执行指定的tag标签任务
    [root@m01 ~]# ansible-playbook tag.yml -t httpd_server
    
    #执行多个指定的tag标签任务
    [root@m01 ~]# ansible-playbook tag.yml -t install_httpd,confiure_httpd
    
    #跳过指定的tag标签任务
    [root@m01 ~]# ansible-playbook tag.yml --skip-tags httpd_server
    

    playbook文件复用

    在之前写playbook的过程中,多个playbook没有办法一键执行,可以使用playbook的功能include,来动态调用task任务列表。

    image-20200929141747837


    准备被调用的剧本

    [root@m01 ~]# mkdir tesk
    [root@m01 ~]# cat > /root/tesk/task_install.yml <<EOF
    - name: Install Http Server
      yum:
        name: httpd
        state: present
    EOF
    
    [root@m01 ~]# cat > /root/tesk/task_configure.yml <<EOF
    - name: configure httpd server
      template:
        src: ./httpd.j2
        dest: /etc/httpd/conf/httpd.conf
      notify: Restart Httpd Server
    EOF
    
    [root@m01 ~]# cat > /root/tesk/task_start.yml <<EOF
    - name: start httpd server
      service:
        name: httpd
        state: started
        enabled: yes
    EOF
    
    1. 只调用task:include_tasks
    [root@m01 ~]# cat > /root/tesk/task.yml <<EOF
    - hosts: web_group
      vars:
        - http_port: 8080
    
      tasks:
        - include_tasks: task_install.yml
        - include_tasks: task_configure.yml
        - include_tasks: task_start.yml
    
      handlers:
        - name: Restart Httpd Server
          systemd:
            name: httpd
            state: restarted
    EOF
    
    1. 调用整个task文件旧版:include
    [root@m01 ~]# cat > /root/tesk/task.yml <<EOF
    - include: httpd.yml
    - include: nfs.yml
    - include: rsync.yml
    EOF
    

    调用整个task文件新版:import_playbook

    [root@m01 ~]# cat > /root/tesk/task.yml <<EOF
    - import_playbook: httpd.yml
    - import_playbook: nfs.yml
    - import_playbook: rsync.yml
    EOF
    

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


    playbook忽略错误

    默认playbook会检测task执行的返回状态,如果遇到错误则会立即终止playbook的后续task执行,然而有些时候playbook即使执行错误了也要让其继续执行。

    忽略错误:ignore_errors:yes

    - hosts: web_group
      tasks:
        - name: Ignore False
          command: /bin/false
          ignore_errors: yes
    	  
        - name: touch new file
          file:
            path: /tmp/oldboy.txt
            state: touch
    

    playbook错误处理

    如上所述,当task执行失败时,playbook将不再继续执行,包括如果在task中设置了handler也不会被执行。

    • 当task执行失败时,可以使用force_handlers: yes,强制调用handler
    • 当task执行成功时,可以使用changed_when: false,将change状态改为ok,显示为绿色

    强制调用handler

    - hosts: web_group
      vars:
        - http_port: 8080
      force_handlers: yes
      tasks:
        - name: config httpd server
          template:
            src: ./httpd.j2
            dest: /etc/httpd/conf/httpd.conf
          notify: 
            - Restart Httpd Server
    
        - name: start httpd server
          service:
            name:httpd
            state: started
            enabled: yes
    
      handlers:
        - name: Restart Httpd Server
          systemd:
            name: httpd
            state: restarted 
    

    抑制changed

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

    - hosts: web_group
      force_handlers: yes
      tasks:
        - name: shell
          shell: netstat -lntup|grep httpd
          register: check_httpd
          changed_when: false
    
        - name: debug
          debug: msg={{ check_httpd.stdout_lines }}
    

    多条件抑制changed_when

    - hosts: web_group
      vars:
        - http_port: 8080
      tasks:
        - name: configure httpd server
          template:
            src: ./httpd.j2
            dest: /etc/httpd/conf/httpd.conf
          notify: Restart Httpd Server
    
        - name: Check HTTPD
          shell: /usr/sbin/httpd -t
          register: httpd_check
          changed_when: 
            - httpd_check.stderr_lines[1] == "Syntax OK"
            - false
    
        - name: debug
          debug: msg={{ httpd_check.stderr_lines[1] }}
    
        - name: start httpd server
          service:
            name: httpd
            state: started
            enabled: yes
    
      handlers:
        - name: Restart Httpd Server
          systemd:
            name: httpd
            state: restarted 
    

    https://www.cnblogs.com/f-ck-need-u/p/7576137.html#ansible

  • 相关阅读:
    第三方驱动备份与还原
    Greenplum 解决 gpstop -u 指令报错
    yum安装(卸载)本地rpm包的方法(卸载本地安装的greenplum 5.19.rpm)
    Java JUC(java.util.concurrent工具包)
    netty 详解(八)基于 Netty 模拟实现 RPC
    netty 详解(七)netty 自定义协议解决 TCP 粘包和拆包
    netty 详解(六)netty 自定义编码解码器
    netty 详解(五)netty 使用 protobuf 序列化
    netty 详解(四)netty 开发 WebSocket 长连接程序
    netty 详解(三)netty 心跳检测机制案例
  • 原文地址:https://www.cnblogs.com/backups/p/ansible_5.html
Copyright © 2020-2023  润新知