1. 程式人生 > 實用技巧 >第二十八章 ansible流程控制

第二十八章 ansible流程控制

一、playbook條件語句

不管是shell還是各大程式語言中,流程控制,條件判斷這些都是必不可少的,在我們使用Ansible的過程中,條件判斷的使用頻率極其高。
例如:
1.我們使用不同的系統的時候,可以通過判斷系統來對軟體包進行安裝。
2.在nfs和rsync安裝過程中,客戶端伺服器不需要推送配置檔案,之前我們都是寫多個play,會影響效率。
3.我們在原始碼安裝nginx的時候,執行第二遍就無法執行了,此時我們就可以進行判斷是否安裝過。

1.判斷主機

[root@m01 ~]# cat lnmp5.yml 
- hosts: nfs_group
  tasks:
    - name: Install nfs Server
      yum:
        name: nfs-utils
        state: present

    - name: Install rpcbind Server
      yum:
        name: rpcbind
        state: present

    - name: Config nfs Server
      copy:
        content: /data/wp-content 172.16.1.0/24(rw,sync,all_squash,anonuid=666,anongid=666)
        dest: /etc/exports      
      when: ansible_fqdn == "nfs"

    - name: Mkdir data
      file:
        path: /data
        state: directory
        owner: www
        group: www
      when: ansible_fqdn == "nfs"

    - name: Start nfs Server
      systemd:
        name: nfs
        state: started
      when: ansible_fqdn == "nfs"

    - name: Copy wp-content to NFS
      copy:
        src: /root/package/wp-content
        dest: /data
        owner: www
        group: www
      when: ansible_fqdn == "nfs"
    
    - name: Start rpcbind Server
      systemd:
        name: rpcbind
        state: started
      when: ansible_fqdn != "nfs"

    - name: Mount nfs
      mount:
        src: 172.16.1.31:/data/wp-content
        path: /code/wordpress/wp-content/
        fstype: nfs
        opts: defaults
        state: mounted
      when: ansible_fqdn != "nfs"

2.多條件判斷

[root@m01 ~]# cat lnmp5.yml 
- hosts: all
  tasks:
    - name: Install nfs Server
      yum:
        name: nfs-utils
        state: present
      when: (ansible_fqdn == "nfs") or (ansible_fqdn is match "web*")

    - name: Install rpcbind Server
      yum:
        name: rpcbind
        state: present
      when: (ansible_fqdn == "nfs") or (ansible_fqdn is match "web*")

    - name: Config nfs Server
      copy:
        content: /data/wp-content 172.16.1.0/24(rw,sync,all_squash,anonuid=666,anongid=666)
        dest: /etc/exports      
      when: ansible_fqdn == "nfs"

    - name: Mkdir data
      file:
        path: /data
        state: directory
        owner: www
        group: www
      when: ansible_fqdn == "nfs"

    - name: Start nfs Server
      systemd:
        name: nfs
        state: started
      when: ansible_fqdn == "nfs"

    - name: Copy wp-content to NFS
      copy:
        src: /root/package/wp-content
        dest: /data
        owner: www
        group: www
      when: ansible_fqdn == "nfs"
    
    - name: Start rpcbind Server
      systemd:
        name: rpcbind
        state: started
      when: (ansible_fqdn == "nfs") or (ansible_fqdn is match "web*")

    - name: Mount nfs
      mount:
        src: 172.16.1.31:/data/wp-content
        path: /code/wordpress/wp-content/
        fstype: nfs
        opts: defaults
        state: mounted
      when: ansible_fqdn is match "web*"

3.判斷服務是否安裝

[root@m01 ~]# cat lnmp3.yml 
- hosts: web_group
  tasks:
    - name: Tar php.tar.gz
      unarchive:
        src: /root/package/php.tar.gz
        dest: /tmp/

    - name: Get PHP Install status
      shell: "rpm -qa | grep php"
      ignore_errors: yes
      register: get_php_install_status
    
    #列印註冊的變數資訊,沒有任何作用,只是為了獲取安裝狀態判斷引數 rc
    - name: print PHP Install status
      debug:
        msg: "{{ get_php_install_status }}"

    - name: Install PHP Server
      shell: yum localinstall -y /tmp/*.rpm
      when: get_php_install_status.rc != 0

    - name: Config php Server
      copy:
        src: /root/conf/php.ini
        dest: /etc/

    - name: Config php Server
      copy:
        src: /root/conf/www.conf
        dest: /etc/php-fpm.d/

    - name: Start php Server
      systemd:
        name: php-fpm
        state: started
        enabled: yes

4.判斷系統

[root@m01 ~]# vim web.yml
- hosts: nfs
  tasks:
    - name: Install httpd
      shell: "yum install -y httpd"
      when: ansible_distribution == "CentOS"

    - name: Install apache2
      shell: "apt-get apache2"
      when: ansible_distribution == "Ubuntu"

5.判斷系統版本

1)方式一:
[root@m01 ~]# cat version.yml 
- hosts: nfs
  tasks:
    - name: CentOS6 Start httpd
      shell: "service httpd start"
      when: (ansible_distribution == "CentOS") and (ansible_distribution_major_version == "6")

    - name: CentOS7 Start httpd
      shell: "systemctl start httpd"
      when: (ansible_distribution == "CentOS") and (ansible_distribution_major_version == "7")
2)方式二
#多條件判斷的第二種方式,列表的形式(只能表示並且\and\和)
[root@m01 ~]# cat version.yml 
- hosts: nfs
  tasks:
    - name: CentOS6 Start httpd
      shell: "service httpd start"
      when: 
        - ansible_distribution == "CentOS"
        - ansible_distribution_major_version == "6"

    - name: CentOS7 Start httpd
      shell: "systemctl start httpd"
      when: 
        - ansible_distribution == "CentOS"
        - ansible_distribution_major_version == "7"
3)一般使用場景
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

二、playbook迴圈語句

1.定義變數安裝多服務

[root@m01 ~]# vim install.yml 
- hosts: nfs
  tasks:
    - name: Install Server
      yum: 
        name: "{{ package }}"
        state: present
      vars:
        package:
          - httpd
          - nfs-utils
          - mariadb-server

2.定義變數啟動多服務

[root@m01 ~]# cat install.yml 
- hosts: nfs
  vars:
    package:
      - httpd
      - nfs-utils
      - mariadb-server
  tasks:
    - name: Install Server
      yum: 
        name: "{{ package }}"
        state: present
  
    - name: Start Server
      systemd:
        name: "{{ item }}"
        state: started
        enabled: yes
      with_items:
        - httpd
        - nfs-utils
        - mariadb

3.字典定義變數

1)建立多個使用者組
    - name: Create www Group
      group:
        name: "{{ item.name }}"
        gid: "{{ item.gid }}"
      with_items:
        - { name: www, gid: 666 }
        - { name: lhd, gid: 777 }
        - { name: dsb, gid: 888 }
2)建立多個使用者
    - name: Create www User
      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 }
4.使用字典定義變數的方式優化lnmp劇本
[root@m01 ~]# cat lnmp.yml 
- hosts: all
  tasks:
    - name: Stop selinux
      selinux:
        state: disabled

    - name: Stop Firewalld
      systemd:
        name: firewalld
        state: stopped
        enabled: no

    - name: Install unzip
      yum:
        name: unzip
        state: present

    - name: Create www Group
      group:
        name: www
        gid: 666

    - name: Create www User
      user:
        name: www
        uid: 666
        group: www
        shell: /sbin/nologin
        create_home: no

    - name: Copy nginx.repo
      copy:
        src: /root/conf/nginx.repo
        dest: /etc/yum.repos.d/
      when: (ansible_fqdn == "lb01") or (ansible_fqdn is match "web*")

    - name: Install Nginx Server
      yum:
        name: nginx
        state: present
      when: (ansible_fqdn == "lb01") or (ansible_fqdn is match "web*")

    - name: Config Nginx Server
      copy:
        src: /root/conf/nginx.conf
        dest: /etc/nginx/
      when: (ansible_fqdn == "lb01") or (ansible_fqdn is match "web*")

    - name: Config slb Server
      copy:
        src: /root/conf/proxy.conf
        dest: /etc/nginx/conf.d
      when: ansible_fqdn == "lb01"

    - name: Copy proxy_params
      copy:
        src: /root/conf/proxy_params
        dest: /etc/nginx/
      when: ansible_fqdn == "lb01"
    
    - name: Start slb Server
      systemd:
        name: nginx
        state: started
      when: ansible_fqdn == "lb01"

    - name: Config nginx Server
      copy:
        src: /root/conf/linux.wp.com.conf
        dest: /etc/nginx/conf.d/
      when: ansible_fqdn is match "web*"
      
    - name: Mkdir Code
      file:
        path: /code
        state: directory
      when: ansible_fqdn is match "web*"

    - name: Tar wordpress and php
      unarchive:
        src: "{{ item.src }}"
        dest: "{{ item.dest }}"
      with_items:
        - { src: /root/package/wordpress-5.0.3-zh_CN.tar.gz, dest: /code/ }
        - { src: /root/package/php.tar.gz, dest: /tmp/ }
      when: ansible_fqdn is match "web*"

    - name: Grant Code Dir
      file:
        path: /code
        owner: www
        group: www
        recurse: yes
      when: ansible_fqdn is match "web*"

    - name: Start Web Nginx Server
      systemd:
        name: nginx
        state: started
        enabled: yes
      when: (ansible_fqdn is match "web*") or (ansible_fqdn is match "lb01")

    - name: Get PHP Install status
      shell: "rpm -qa | grep php"
      ignore_errors: yes
      register: get_php_install_status

    - name: Install PHP Server
      shell: yum localinstall -y /tmp/*.rpm
      when: 
        - ansible_fqdn is match "web*"
        - get_php_install_status.rc != 0

    - name: Config php Server
      copy:
        src: "{{ item.src }}"
        dest: "{{ item.dest }}"
      with_items:
        - { src: /root/conf/php.ini, dest: /etc/ }
        - { src:/root/conf/www.conf, dest: /etc/php-fpm.d/ }
      when: ansible_fqdn is match "web*"

    - name: Start php and nginx Server
      systemd:
        name: "{{ item.name }}"
        state: started
        enabled: yes
      with_items:
        - { name: php-fpm }
        - { name: nginx }
      when: ansible_fqdn is match "web*"

    - name: Install Mariadb Server
      yum:
        name: "{{ db }}"
        state: present
      vars:
        db:
          - mariadb-server
          - MySQL-python
      when: ansible_fqdn == "db01"
    
    - name: Start Mariadb Server
      systemd:
        name: mariadb
        state: started
        enabled: yes
      when: ansible_fqdn == "db01"

    - name: Create wordpress Database
      mysql_db:
        name: wordpress
        state: present
      when: ansible_fqdn == "db01"

    - name: Create wordpress Database User
      mysql_user:
        name: "wp"
        host: "172.16.1.%"
        password: '123456'
        priv: "wordpress.*:ALL"
        state: present
      when: ansible_fqdn == "db01" 
        
    - name: Install nfs Server
      yum:
        name: "{{ nfs_server }}"
        state: present
      vars:
        nfs_server:
          - nfs-utils
          - rpcbind
      when: (ansible_fqdn == "nfs") or (ansible_fqdn is match "web*")

    - name: Config nfs Server
      copy:
        content: /data/wp-content 172.16.1.0/24(rw,sync,all_squash,anonuid=666,anongid=666)
        dest: /etc/exports      
      when: ansible_fqdn == "nfs"

    - name: Mkdir data
      file:
        path: /data
        state: directory
        owner: www
        group: www
      when: ansible_fqdn == "nfs"

    - name: Start nfs Server
      systemd:
        name: nfs
        state: started
      when: ansible_fqdn == "nfs" 

    - name: Copy wp-content to NFS
      copy:
        src: /root/package/wp-content
        dest: /data
        owner: www
        group: www
      when: ansible_fqdn == "nfs"
    
    - name: Start rpcbind Server
      systemd:
        name: rpcbind
        state: started
      when: (ansible_fqdn == "nfs") or (ansible_fqdn is match "web*")

    - name: Mount nfs
      mount:
        src: 172.16.1.31:/data/wp-content
        path: /code/wordpress/wp-content/
        fstype: nfs
        opts: defaults
        state: mounted
      when: ansible_fqdn is match "web*"

    - name: Install rsync Server
      yum:
        name: rsync
        state: present
      when: ansible_fqdn == "backup"

    - name: Config Rsync Server
      copy:
        src: /root/conf/rsyncd.conf
        dest: /etc/
      when: ansible_fqdn == "backup"

    - name: Config rsync.passwd
      copy:
        content: rsync_backup:123456
        dest: /etc/rsync.passwd
        mode: 0600
      when: ansible_fqdn == "backup"

    - name: Mkdir backup Dir
      file:
        path: /backup
        state: directory
        owner: www
        group: www
      when: ansible_fqdn == "backup"

    - name: Start rsync Server
      systemd:
        name: rsyncd
        state: started
      when: ansible_fqdn == "backup"

    - name: Install rsync and Inotify-tools Server
      yum:
        name: "{{ item }}"
        state: present
      with_items:
        - rsync
        - inotify-tools
      when: ansible_fqdn == "nfs"

    - name: Install sersync Server
      copy:
        src: /root/package/sersync
        dest: /usr/local/
        mode: 0755
      when: ansible_fqdn == "nfs"

    - name: Config rsync.pass
      copy:
        content: 123456
        dest: /etc/rsync.pass
        mode: 0600
      when: ansible_fqdn == "nfs"

    - name: Start sersync
      script: /root/start_rsync.sh
      when: ansible_fqdn == "nfs"

三、playbook handlers 觸發器

1.什麼是觸發器

handler用來執行某些條件下的任務,比如當配置檔案發生變化的時候,通過notify觸發handler去重啟服務。
在saltstack中也有類似的觸發器,寫法相對Ansible簡單,只需要watch,配置檔案即可

2.配置觸發器

[root@m01 ~]# cat handler.yml 
- hosts: web_group
  tasks:
    - name: Install Http Server
      yum:
        name: httpd
        state: present

    - name: config httpd server
      copy:
        src: ./httpd.conf
        dest: /etc/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

3.注意事項

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