• Ansible--04 ansible 流程控制


    ansible 流程控制

    playbook 条件语句

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


    例如:

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

    根据不同的操作系统安装apache

    官方示例:

    tasks:
      - name: "shut down Debian flavored systems"
        command: /sbin/shutdown -t now
        when: ansible_facts['os_family'] == "Debian"
        # note that all variables can be used directly in conditionals without double curly braces
    

    示例: 根据不同的 系统安装不同的服务

    - hosts: web_group
      tasks:
        - name: Install CentOS Htt 
            state: present
        #官方
          when: ansible_facts['os_family'] == "CentOS"
        #非官方
          when: ansible_distribution == "CentOS"
    
        - name: Install Ubuntu Httpd
          yum:
            name: apache2
            state: present
          when: ansible_facts['os_family'] == "Ubuntu"
    

    可以使用括号对条件进行分组

    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")
    

    可以指定多条件为列表

    tasks:
      - name: "shut down CentOS 6 systems"
        command: /sbin/shutdown -t now
        when:
          - ansible_facts['distribution'] == "CentOS"
          - ansible_facts['distribution_major_version'] == "6"
    

    条件运算

    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 rsyncd/rsyncd.yml
    - 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 
            name: rsyncd
            state: started
          when: ansible_hostname == "backup"
    

    rsync客户端推送脚本

    [root@m01 ~]# vim rsync.yml
    - hosts: rsync_server
      tasks:
        - name: SCP Backup Shell
          copy:
            src: ./backup.sh
            dest: /root/backup.sh
          when: ansible_hostname is match "web*"
    
    #执行结果
    PLAY [rsync_server] **************************************************************************************************************************************************************************************************************************
    
    TASK [Gathering Facts] ***********************************************************************************************************************************************************************************************************************
    ok: [web02]
    ok: [backup]
    ok: [web01]
    
    TASK [SCP Backup Shell] **********************************************************************************************************************************************************************************************************************
    skipping: [backup]
    changed: [web01]
    changed: [web02]
    
    PLAY RECAP ***********************************************************************************************************************************************************************************************************************************
    backup                     : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
    web01                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    web02                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

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

    - 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
    

    使用when判断主机名

    - hosts: rsync_server
      tasks:
    
        - name: Install rsyncd Server
          yum:
            name: rsync
            state: present
    
        - name: Config rsyncd Conf
          copy:
            src: ./rsyncd.j2
            dest: /etc/rsyncd.conf
            owner: root
            group: root
            mode: 0644
          when: ansible_fqdn == 'backup'
    
        - name: Create dir
          file:
            path: /backup
            state: directory
            owner: www
            group: www
            mode: 0755
            recurse: yes
          when: ansible_fqdn == 'backup'
    
    
        - name: Create passwd file
          copy:
            content: "rsync_backup:123"
            dest: /etc/rsync.passwd
            owner: root
            group: root
            mode: 0600
          when: ansible_fqdn == 'backup'
    
    #单条件判断
        - name: Start rsyncd
          systemd:
            name: rsyncd
            state: started
            enabled: yes
          when: ansible_fqdn == 'backup'
    
    #多条件判断,使用小括号分组
        - name: copy shell
          template:
            src: ./backup.sh
            dest: /root
          when: (ansible_fqdn == 'web01') or (ansible_fqdn == 'web02')
    
    #多条件判断,使用list列表形式
        - name: copy shell
          template:
            src: ./backup.sh
            dest: /root
          when:
            - ansible_fqdn == 'web01'
            - ansible_fqdn == 'web02'
            
    #多条件判断,使用is match 支持通配符
        - name: Add Crontab
          cron:
            name: "backup"
            minute: "00"
            hour: "01"
            job: "/bin/sh /root/backup.sh &>/dev/null"
          when: ansible_fqdn is match 'web*'
    

    2.使用when判断系统

    - hosts: webs
      tasks:
        - name: Install CentOS Apache
          yum:
            name: httpd
            state: present
          when: ansible_distribution == 'CentOS'
    
        - name: Install Ubuntu Apache
          apt:
            name: apache2
            state: present
          when: ansible_distribution == 'Ubuntu'
    

    3.使用when判断系统版本

    - hosts: webs
      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'
    

    4.使用注册变量对返回值进行判断

        - name: pan duan rpm bao
          shell: "rpm -qa|grep php"
          register: check_php
    
        - name: Install php
          shell: "cd /usr/local/src && rpm -Uvh *rpm"
          when: check_php.rc != 0
    

    playbook 循环语句

    创建目录之类的操作,2个目录就要写两个file 模块来创建,如果有循环,可以减少重复性代码。

    1.启动多个服务

    - hosts: web_group
      tasks:
        - name: start service
          systemd:
            name: "{{ item }}"
            state: started
          with_items:
            - httpd
            - php-fpm
            - mariadb
    

    2.定义变量循环

    - name: ensure a list of packages installed
      yum:
        name: "{{ packages }}"
      vars:
        packages:
        - httpd
        - httpd-tools
    
    - hosts: web_group
      tasks:
        - name: ensure a list of packages installed
          yum: name= "{{ item }}" state=present
          with_items:
            - httpd
            - httpd-tools
    

    3.字典循环

    拷贝文件

    - hosts: web_group
      tasks:
        - name: copy conf and code
          copy:
            src: "{{ item.src }}"
            dest: "{{ item.dest }}"
            mode: "{{ item.mode }}"
          with_items:
            - { src: "./httpd.conf", dest: "/etc/httpd/conf/", mode: "0644" }
            - { src: "./upload_file.php", dest: "/var/www/html/", mode: "0600" }
    
        - name: tar php and nginx and wordpress
          unarchive:
            src: "{{ item.src }}"
            dest: "{{ item.dest }}"
            owner: "{{ item.user }}"
            group: "{{ item.user }}"
            copy: yes
          with_items:
            - { src: "./php.tgz", dest: "/usr/local/src", user: "root" }
            - { src: "./nginx-1.16.0.tar.gz", dest: "/root", user: "root" }
            - { src: "./wordpress.tgz", dest: "/code", user: "www" }
    
    

    ansible handlers(触发器)

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

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

    实践案例:

        - name: scp nginx shell conf
          copy:
            src: "{{ item.src }}"
            dest: "{{ item.dest }}"
          with_items:
            - { src: "./nginx.service", dest: "/usr/lib/systemd/system" }
            - { src: "./nginx.conf", dest: "/usr/local/nginx/conf/" }
            - { src: "./www.drz.com.conf", dest: "/usr/local/nginx/conf/conf.d" }
          #添加触发器
          notify: reload nginx
    
      handlers:
        - name: reload nginx
          systemd:
            name: nginx
            state: reloaded
    
    

    注意:

    1.无论多少个task通知了相同的handlers,handlers仅会在所有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打一个标签
    2. 对一个task打多个标签
    3. 对多个task打一个标签

    打完标签如何使用

    -t : 指定的tag标签任务

    --skip-tags : 执行--skip-tags之外的标签任务

    使用 - t 指定 tag

    [root@m01 m01]# cat tag.yml 
    - 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 
    
    [root@m01 m01]# ansible-playbook tag.yml --list-tags
    [root@m01 m01]# ansible-playbook tag.yml -t httpd_server
    [root@m01 m01]# ansible-playbook tag.yml -t install_httpd,confiure_httpd
    [root@m01 m01]# ansible-playbook tag.yml --skip-tags httpd_server
    

    playbo ok复用include

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

    只调用task include_tasks

    调用整个task 文件: include (新版本: import_playbook)

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

    示例:

    [root@m01 web]# vim install_nginx.yml 
    
    - name: Install nginx
      yum:
        name: nginx
        state: present
    
    [root@m01 web]# vim conf_nginx.yml 
    - name: conf nginx
      copy:
        src: ./www.drz.com.conf
        dest: /etc/nginx/conf.d
      notify: reload nginx
    
    
    [root@m01 web]# vim main.yml 
    - hosts:
      tasks:
        - include_tasks: ./install_nginx.yml
        - include_tasks: ./conf_nginx.yml
      handlers:
        - name: reload nginx
          systemd:
            name: nginx
            state: reloaded
    
    

    2.直接复用写好的yml文件

    • 旧版:include
    • 新版:import_playbook
    - import_playbook: ./lnmp.yml
    - import_playbook: ../mariadb/mysql.yml
    

    playbook 忽略错误

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

    加入参数: ignore_errors:yes 忽略错误

    [root@m01 ~]# cat ignore.yml
    ---
    - hosts: web_group
      tasks:
        - name: Ignore False
          command: /bin/false
          ignore_errors: yes
          
        - name: touch new file
          file:
            path: /tmp/zls.txt
            state: touch
    

    playbook 错误处理

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

    但是我们可以采取强制措施..


    强制调用handler

    [root@m01 ~]# cat handler.yml 
    - hosts: web_group
      vars:
        - http_port: 8080
      force_handlers: yes
      tasks:
    
        - name: config httpd server
          template:
            src: ./httpd.j2
            dest: /etc/httpd/conf
          notify: 
            - Restart Httpd Server
            - Restart PHP Server
    
        - name: Install Http Server
          yum:
            name: htttpd
            state: present
    
        - name: start httpd server
          service:
            name:httpd
            state: started
            enabled: yes
    
      handlers:
        - name: Restart Httpd Server
          systemd:
            name: httpd
            state: restarted 
    
        - name: Restart PHP Server
          systemd:
            name: php-fpm
            state: restarted
    

    抑制changed

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

    [root@m01 ~]# cat handler.yml 
    - hosts: web_group
      vars:
        - http_port: 8080
      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 }}
    
    [root@m01 project2]# cat changed_when.yml 
    - hosts: webservers
      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.stdout.find('OK')
            - false
    
        - name: start httpd server
          service:
            name: httpd
            state: started
            enabled: yes
    
      handlers:
        - name: Restart Httpd Server
          systemd:
            name: httpd
            state: restarted 
    
  • 相关阅读:
    matlab 修改窗口logo 使用Javaframe
    matlab guide 开发心得
    判断两个集合的包含关系
    xaml 中 引用嵌套类的对象
    xaml中显示 “大括号左边” 文本
    步进电机脉冲与毫米
    最短路径:Dijkstra算法 C#
    JPA自定义sql的三种方式
    double相乘少一分的问题,BigDecimal参数传小数也会出问题
    String类小知识
  • 原文地址:https://www.cnblogs.com/gongjingyun123--/p/11600316.html
Copyright © 2020-2023  润新知