zoukankan      html  css  js  c++  java
  • 自动化运维工具-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

  • 相关阅读:
    使用STM32驱动双通道12位DAC(TLV5618)
    CentOS 7挂载离线yum源
    有关于Git的使用的一点心得和说明
    STM32单片机学习心得——MDK使用技巧
    小米手机连接ADB
    我看操作系统的发展
    centos7下cups + samba共打印服务
    CentOS 7.0默认使用的是firewall作为防火墙,这里改为iptables防火墙步骤
    centos7 更新yum源
    CentOS7 安装Odoo9.0
  • 原文地址:https://www.cnblogs.com/backups/p/ansible_5.html
Copyright © 2011-2022 走看看