ansible之playbook

ansible之playbook


1. 什麼是YAML

  • YAML(/ˈjæməl/,尾音相似camel駱駝)是一個可讀性高,用來表達數據序列的格式。YAML參考了其餘多種語言,包括:C語言、Python、Perl,並從XML、電子郵件的數據格式(RFC 2822)中得到靈感。Clark Evans在2001年首次發表了這種語言,另外Ingy döt Net與Oren Ben-Kiki也是這語言的共同設計者。目前已經有數種編程語言或腳本語言支持(或者說解析)這種語言。php

  • YAML是"YAML Ain't a Markup Language"(YAML不是一種標記語言)的遞歸縮寫。在開發的這種語言時,YAML 的意思實際上是:"Yet Another Markup Language"(還是一種標記語言),但爲了強調這種語言以數據作爲中心,而不是以標記語言爲重點,而用反向縮略語重命名。html

  • YAML的語法和其餘高級語言相似,而且能夠簡單表達清單、散列表,標量等數據形態。它使用空白符號縮進和大量依賴外觀的特點,特別適合用來表達或編輯數據結構、各類配置文件、傾印除錯內容、文件大綱(例如:許多電子郵件標題格式和YAML很是接近)。

2. Playbook的核心元素

  • Hosts:指明playbook應用的對象
  • Tasks:任務列表(核心)
  • Variables:一個值會被引用屢次,且引用的過程當中有可能會發生變化,可用變量來代替。可有效簡化配置過程。
  • Templates:包含了模板語法的文本文件;
  • Handlers:由特定條件知足時纔會觸發的任務;

3. playbook的基礎組件:

  • Hosts:運行指定任務的主機列表
  • remoute_user/sudo_user: 在遠程主機上執行任務的用戶
    • sudo_user必須爲可執行須要任務的用戶
  • tasks:任務列表
    • 模塊,模塊參數
    • 格式:
      1. action: module arguments
      2. module: arguments
        注意:shell和command模塊後面直接跟命令,而非key=value類的參數列表
      3. 某任務的狀態在運行後爲changed時,可經過「notify」通知給相應的handlers
      4. 任務能夠經過"tags「打標籤,然後可在ansible-playbook命令上使用-t指定進行調用
  • 運行playbook的方式
    1. 測試
      • ansible-playbook --check 只檢測可能會發生的改變,但不真正執行操做
      • ansible-playbook --list-hosts 列出運行任務的主機
      • ansible-playbook --list-tasks 列出要運行的任務列表
      • ansible-playbook --syntax-check 語法檢查
      • ansible-playbook --list-tags 列出全部可用的標籤
      • ansible-playbook -t TAGS , --tags=TAGS 只運行指定標籤的任務
      • ansible-playbook --skip-tigs=SKIP_TIGS 跳過指定標籤的任務
      • ansible-playbook --list-tasks 列出全部任務列表
    2. 運行
      • ansible-playbook YAML_FILE

一個簡單的示例: 遠程主機np1.lxk.com安裝memcached並設置開機自動啓動node

  1. 編輯文件memcached.yaml,添加如下內容:
- hosts: np1.lxk.com
  remote_user: root
  tasks:
        - name: 'install memcached package'
          yum: 'name=memcached state=installed'
        - name: 'start memcached server'
          service: 'name=memcached enabled=true state=started'
- hosts: np2.lxk.com
  remote_user: root
  tasks:
        - name: install memcached package
          yum: name=memcached state=installed
        - name: start memcached server
          service: name=memcached enabled=true state=started
  1. 測試語法:
[root@nfs ansible_workshop]# ansible-playbook --syntax-check memcached.yaml 

playbook: memcached.yaml
  1. 測試運行:

PLAY [np1.lxk.com] ****nginx

TASK [Gathering Facts] ****
ok: [np1.lxk.com]web

TASK [install memcached package] **
ok: [np1.lxk.com]shell

TASK [start memcached server] *****
ok: [np1.lxk.com]編程

PLAY [np2.lxk.com] ****vim

TASK [Gathering Facts] ****
ok: [np2.lxk.com]centos

TASK [install memcached package] **
changed: [np2.lxk.com]tomcat

TASK [start memcached server] *****
changed: [np2.lxk.com]

PLAY RECAP ****
np1.lxk.com : ok=3 changed=0 unreachable=0 failed=0
np2.lxk.com : ok=3 changed=2 unreachable=0 failed=0

4. 運行memcached.yaml

```leaf
[root@nfs ansible_workshop]# ansible-playbook memcached.yaml 

PLAY [np1.lxk.com] ********************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [np1.lxk.com]

TASK [install memcached package] ******************************************************************************************
ok: [np1.lxk.com]

TASK [start memcached server] *********************************************************************************************
ok: [np1.lxk.com]

PLAY [np2.lxk.com] ********************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [np2.lxk.com]

TASK [install memcached package] ******************************************************************************************
changed: [np2.lxk.com]

TASK [start memcached server] *********************************************************************************************
changed: [np2.lxk.com]

PLAY RECAP ****************************************************************************************************************
np1.lxk.com                : ok=3    changed=0    unreachable=0    failed=0   
np2.lxk.com                : ok=3    changed=2    unreachable=0    failed=0
  1. 在目標主機上查看:
[root@np1 ~]# systemctl is-enabled memcached
enabled                     #已設置爲開機自動運行
[root@np1 ~]# systemctl status memcached            #已經啓動成功
● memcached.service - Memcached
   Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2018-06-10 12:20:56 CST; 5min ago
 Main PID: 18030 (memcached)
   CGroup: /system.slice/memcached.service
           └─18030 /usr/bin/memcached -u memcached -p 11211 -m 64 -c 1024

Jun 10 12:20:56 np1.lxk.com systemd[1]: Started Memcached.
Jun 10 12:20:56 np1.lxk.com systemd[1]: Starting Memcached...
  1. 補充:查看要執行任務的主機:
[root@nfs ansible_workshop]# ansible-playbook --check --list-hosts memcached.yaml 

playbook: memcached.yaml

  play #1 (np1.lxk.com): np1.lxk.com    TAGS: []
    pattern: [u'np1.lxk.com']
    hosts (1):
      np1.lxk.com

  play #2 (np2.lxk.com): np2.lxk.com    TAGS: []
    pattern: [u'np2.lxk.com']
    hosts (1):
      np2.lxk.com
  • handlers:
    • 任務,在特定條件下觸發
    • 接收到其它任務的通知時被觸發
      • notify: HANDLER TASK NAME

示例: 爲memcached提供監聽在11311端口的配置文件,並重啓服務

  1. 修改yuml文件 memcached_v1.yuml
- hosts: np1.lxk.com
  remote_user: root
  tasks:
        - name: 'install memcached package'
          yum: 'name=memcached state=installed'
        - name: 'install conf file'
          copy: 'src=/etc/sysconfig/memcached dest=/etc/sysconfig/memcached'
          notify: 'restart memcached service'
        - name: 'start memcached server'
          service: 'name=memcached enabled=true state=started'
  handlers:
        - name: 'restart memcached service'
          service: 'name=memcached state=restarted'
  1. 語法檢測:
[root@nfs ansible_workshop]# ansible-playbook --syntax-check memcached_v2.yaml

playbook: memcached_v2.yaml
  1. check yuml文件是否可運行
跟下面一步內容相同,只是語句不一樣,語句以下:
~]# ansible-playbook --check memcached_v2.yaml
  1. 運行:
[root@nfs ansible_workshop]# ansible-playbook memcached_v2.yaml 

PLAY [np1.lxk.com] ********************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [np1.lxk.com]

TASK [install memcached package] ******************************************************************************************
ok: [np1.lxk.com]

TASK [install conf file] **************************************************************************************************
changed: [np1.lxk.com]

TASK [start memcached server] *********************************************************************************************
ok: [np1.lxk.com]

RUNNING HANDLER [restart memcached service] *******************************************************************************
changed: [np1.lxk.com]

PLAY RECAP ****************************************************************************************************************
np1.lxk.com                : ok=5    changed=2    unreachable=0    failed=0
  1. 查看np1.lxk.com上memcached監聽的端口:
[root@np1 ~]# systemctl status memcached
● memcached.service - Memcached
   Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2018-06-10 13:28:42 CST; 5min ago
 Main PID: 19732 (memcached)
   CGroup: /system.slice/memcached.service
           └─19732 /usr/bin/memcached -u memcached -p 11311 -m 64 -c 1024

Jun 10 13:28:42 np1.lxk.com systemd[1]: Started Memcached.
Jun 10 13:28:42 np1.lxk.com systemd[1]: Starting Memcached...

#經過ss -tnlp也能夠查看,可是太長了。這裏也能夠看到memcached監聽的端口爲11311

注:若配置文件發生改變,再一次運行memcached_v2.yaml時,會觸發複製配置文件並重啓服務。配置文件不發生改變,不會觸發。

  • variables:
    1. facts:內建變量,可直接調用
      注意:可以使用setup模塊直接獲取目標主機的facters
    2. 用戶自定義變量
      • 經過ansible-playbook命令的選項調用函數
        -e VARS, --extra-vars=VARS
      • 在playbook中定義變量的方法
        vars:
        '- var1: value1'
        '- var2: value2'
    3. 變量引用:{{ variable }}

示例:經過自定義變量安裝tree

  1. 編輯yaml文件pkgs.yaml
- hosts: np1.lxk.com
  remote_user: root
  vars:
  - pkgname: 'tree'
  tasks:
  - name: install {{ pkgname }}
    yum: name={{ pkgname }} state=installed
  1. 安裝
[root@nfs ansible_workshop]# ansible-playbook pkgs.yaml 

PLAY [np1.lxk.com] ********************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [np1.lxk.com]

TASK [install tree] *******************************************************************************************************
ok: [np1.lxk.com]

PLAY RECAP ****************************************************************************************************************
np1.lxk.com                : ok=2    changed=0    unreachable=0    failed=0

示例2:使用pkgs.yaml文件,不修改文件內容,經過ansible-playbook中的-e選項給定變量的參數

[root@nfs ansible_workshop]# ansible-playbook --check -e pkgname='httpd' pkgs.yaml 

PLAY [np1.lxk.com] ********************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [np1.lxk.com]

TASK [install httpd] ******************************************************************************************************
ok: [np1.lxk.com]

PLAY RECAP ****************************************************************************************************************
np1.lxk.com                : ok=2    changed=0    unreachable=0    failed=0

能夠看到運行時的TASK對象變爲了httpd

  1. 經過roles傳遞變量
  2. Host Inventory
    • 用戶自定義變量
      1. 向不一樣的主機傳遞不一樣的變量
        IP/HOSTNAME varaiable=value var2=value2
      2. 向組中的主機傳遞相同的變量
        [groupname:vars]
        variable=value
    • invertory參數
      • 用於定義ansible遠程鏈接目標主機時使用的參數,而非傳遞給playbook的變量
        ansible_ssh_host
        ansible_ssh_port
        ansible_ssh_user
        ansible_ssh_pass
        ansbile_sudo_pass

示例:組中的主機傳遞參數:
/etc/ansible/hosts配置:

[root@nfs ansible_workshop]# tail -15 /etc/ansible/hosts
[db]
node1.lxk.com
node2.lxk.com
[db:vars]
pkgname='mariadb-server'

[web]
np1.lxk.com
np2.lxk.com

[web:vars]
pkgname='nginx'

[nfs]
nfs.lxk.com

yaml文件內容:

- hosts: db
  remote_user: root
  tasks:
  - name: install {{ pkgname }}
    yum: name={{ pkgname }} state=installed

- hosts: web
  remote_user: root
  tasks:
  - name: install {{ pkgname }}
    yum: name={{ pkgname }} state=installed

幹跑模式結果:

[root@nfs ansible_workshop]# ansible-playbook --check pkgs.yaml 

PLAY [db] *****************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [node2.lxk.com]
ok: [node1.lxk.com]

TASK [install mariadb-server] *********************************************************************************************
ok: [node2.lxk.com]
ok: [node1.lxk.com]

PLAY [web] ****************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [np2.lxk.com]
ok: [np1.lxk.com]

TASK [install nginx] ******************************************************************************************************
changed: [np2.lxk.com]
changed: [np1.lxk.com]

PLAY RECAP ****************************************************************************************************************
node1.lxk.com              : ok=2    changed=0    unreachable=0    failed=0   
node2.lxk.com              : ok=2    changed=0    unreachable=0    failed=0   
np1.lxk.com                : ok=2    changed=1    unreachable=0    failed=0   
np2.lxk.com                : ok=2    changed=1    unreachable=0    failed=0

經過以上示例能夠看出,在hosts文件中也能夠傳遞參數。

示例:經過invertory參數鏈接目標主機

  1. 修改要鏈接的主機監聽的端口爲22022
[root@node1 ~]# vim /etc/ssh/sshd_config 
增長如下內容:
port 22
port 22022
[root@node1 ~]# systemctl restart sshd
[root@node1 ~]# ss -tnl
State       Recv-Q Send-Q                Local Address:Port                               Peer Address:Port              
LISTEN      0      128                               *:22                                            *:*                  
LISTEN      0      100                       127.0.0.1:25                                            *:*                  
LISTEN      0      128                               *:22022                                         *:*                  
LISTEN      0      50                                *:3306                                          *:*                  
LISTEN      0      128                              :::22                                           :::*                  
LISTEN      0      100                             ::1:25                                           :::*                  
LISTEN      0      128                              :::22022                                        :::*
  1. 編輯/etc/ansible/hosts文件鏈接目標服務器
node1.lxk.com ansible_ssh_port=22022
node2.lxk.com ansible_ssh_root=root ansible_ssh_pass=magedu.com
  1. 編輯yaml文件內容以下:
[root@nfs ansible_workshop]# cat pkgs.yaml 
- hosts: all
  remote_user: root
  vars:
  - pkgname: 'tree'
  tasks:
  - name: install {{ pkgname }}
    yum: name={{ pkgname }} state=installed
  1. 向目標主機傳遞命令,鏈接成功。
[root@nfs ansible_workshop]# ansible all -m shell -a '[[ -f /etc/hosts ]]'
node1.lxk.com | SUCCESS | rc=0 >>

node2.lxk.com | SUCCESS | rc=0 >>
  • 模板:templates
    文本文件,嵌套有腳本(使用模板編程語言編寫)
    Jinja2:
字面量:
            字符串:使用單引號或雙引號;
            數字:整數,浮點數;
            列表:[item1, item2, ...]
            元組:(item1, item2, ...)
            字典:{key1:value1, key2:value2, ...}
            布爾型:true/false
運算符:                                
        算術運算:
            +, -, *, /, //, %, **

        比較操做:
            ==, !=, >, >=, <, <=

        邏輯運算:
            and, or, not

示例:

- hosts: websrvs
  remote_user: root
  tasks:
    - name: install nginx
    yum: name=nginx state=present
    - name: install conf file
    template: src=files/nginx.conf.j2 dest=/etc/nginx/nginx.conf
    notify: restart nginx
    tags: instconf
    - name: start nginx service
    service: name=nginx state=started
    handlers:
    - name: restart nginx
    service: name=nginx state=restarted

模板配置文件 :nginx.conf.j2

worker_processes {{ ansible_processor_vcpus - 1 }};
listen {{ http_port }};
server_name

示例1: 複製模板至目標主機:
主機列表:

node1.lxk.com
node2.lxk.com
np1.lxk.com
np2.lxk.com
nfs.lxk.com
  1. 編輯模板文件:
[root@nfs ansible_workshop]# cat test.j2 
hostname: {{ansible_fqdn }}         #調用系統變量中的主機名
vars: {{ pkgname }}                 #調用自定義變量,可在ansible-playbook中用-e選項給定
  1. 編輯yaml文件,複製test.j2文件至目標主機
[root@nfs ansible_workshop]# cat test.yaml 
- hosts: all
  remote_user: root
  tasks:
  - name: install file
    template: src=/root/ansible_workshop/test.j2 dest=/tmp/test.conf
  1. 執行復制,命令行中給定參數pkgname的值爲somepkg:
[root@nfs ansible_workshop]# ansible-playbook -e pkgname='somepkg' test.yaml 

PLAY [all] ****************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [node2.lxk.com]
ok: [np1.lxk.com]
ok: [np2.lxk.com]
ok: [node1.lxk.com]
ok: [nfs.lxk.com]

TASK [install file] *******************************************************************************************************
changed: [np2.lxk.com]
changed: [np1.lxk.com]
changed: [node2.lxk.com]
changed: [node1.lxk.com]
changed: [nfs.lxk.com]

PLAY RECAP ****************************************************************************************************************
nfs.lxk.com                : ok=2    changed=1    unreachable=0    failed=0   
node1.lxk.com              : ok=2    changed=1    unreachable=0    failed=0   
node2.lxk.com              : ok=2    changed=1    unreachable=0    failed=0   
np1.lxk.com                : ok=2    changed=1    unreachable=0    failed=0   
np2.lxk.com                : ok=2    changed=1    unreachable=0    failed=0

示例2: 在目標主機上安裝tomcat,配置文件中jvmRoute設置爲各自主機名,並提供manaager-gui和admin-gui的登陸用戶

  1. 修改tomcat默認配置文件,在engine處添加jvmRoute={{ ansible_hostname }}
<Engine name="Catalina" defaultHost="localhost" jvmRoute="{{ ansible_hostname }}" >
  1. 編輯tomcat-user.xml文件,添加如下內容:
<role rolename="manaager-gui"/>
<role rolename="admin-gui"/>
<user username="tomcat" password="tomcat" roles="manager-gui,admin-gui"/>
  1. 編輯yaml文件:server-user.xml是通用配置,不用作成j2文件,server.xml內有變量,須要用template模塊
- hosts: tomcat
   remote_user: root
   tasks:
   - name: install tomcat-admin-webapps
     yum: name=tomcat-admin-webapps state=installed
   - name: install tomcat-users.xml
     copy: src=/root/ansible_workshop/tomcat-users.xml dest=/etc/tomcat/tomcat-users.xml owner=root group=tomcat mode=0640
     notify: restart tomcat
   - name: install server.xml
     template: src=/root/ansible_workshop/server.xml.j2 dest=/etc/tomcat/server.xml owner=root group=tomcat
   - name: start tomcat
     service: name=tomcat state=started
   handlers:
   - name: restart tomcat
     service: name=tomcat state=restarted
  1. 執行操做:
[root@nfs ansible_workshop]# ansible-playbook tomcat.yaml 

PLAY [tomcat] *************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [np2.lxk.com]
ok: [np1.lxk.com]

TASK [install tomcat-admin-webapps] ***************************************************************************************
ok: [np2.lxk.com]
ok: [np1.lxk.com]

TASK [install tomcat-users.xml] *******************************************************************************************
changed: [np2.lxk.com]
changed: [np1.lxk.com]

TASK [install server.xml] *************************************************************************************************
changed: [np1.lxk.com]
changed: [np2.lxk.com]

TASK [start tomcat] *******************************************************************************************************
changed: [np2.lxk.com]
changed: [np1.lxk.com]

RUNNING HANDLER [restart tomcat] ******************************************************************************************
changed: [np2.lxk.com]
changed: [np1.lxk.com]

PLAY RECAP ****************************************************************************************************************
np1.lxk.com                : ok=6    changed=4    unreachable=0    failed=0   
np2.lxk.com                : ok=6    changed=4    unreachable=0    failed=0
  1. 查看目標主機上配置文件:
    np1:
[root@np1 ~]# grep np1 /etc/tomcat/server.xml
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="np1" >
[root@np1 ~]# cat /etc/tomcat/tomcat-users.xml | head -44 | tail -3
<role rolename="manaager-gui"/>
<role rolename="admin-gui"/>
<user username="tomcat" password="tomcat" roles="manager-gui,admin-gui"/>

tags用於讓用戶選擇運行playbook中的部分代碼。ansible具備冪等性,所以會自動跳過沒有變化的部分,即使如此,有些代碼爲測試其確實沒有發生變化的時間依然會很是地長。此時,若是確信其沒有變化,就能夠經過tags跳過此些代碼片段。

示例:

  1. 在以下yaml文件中定義兩個tags
- hosts: tomcat
   remote_user: root
   tasks:
   - name: install tomcat-admin-webapps
     yum: name=tomcat-admin-webapps state=installed
   - name: install tomcat-users.xml
     copy: src=/root/ansible_workshop/tomcat-users.xml dest=/etc/tomcat/tomcat-users.xml owner=root group=tomcat mode=0640
     tags: tcusers
     notify: restart tomcat
   - name: install server.xml
     template: src=/root/ansible_workshop/server.xml.j2 dest=/etc/tomcat/server.xml owner=root group=tomcat
     notify: restart tomcat
     tags: serverconf
   - name: start tomcat
     service: name=tomcat state=started
   handlers:
   - name: restart tomcat
     service: name=tomcat state=restarted
  1. 測試觀察
[root@nfs ansible_workshop]# ansible-playbook --check --tags=tcusers tomcat.yaml 

PLAY [tomcat] *************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [np1.lxk.com]
ok: [np2.lxk.com]

TASK [install tomcat-users.xml] *******************************************************************************************
ok: [np2.lxk.com]
ok: [np1.lxk.com]

PLAY RECAP ****************************************************************************************************************
np1.lxk.com                : ok=2    changed=0    unreachable=0    failed=0   
np2.lxk.com                : ok=2    changed=0    unreachable=0    failed=0

經測試,使用--tags指定tags以後,只運行了指定tags的任務。

條件測試:when語句:在task中使用,jinja2的語法格式
示例:當系統版本是7時,複製nginx.conf.c7.j2。系統版本是6時,複製nginx.conf.c6

tasks: 
- name: install conf file to centos7
  template: src=files/nginx.conf.c7.j2
  when: ansible_distribution_major_version == "7"
- name: install conf file to centos6
  template: src=files/nginx.conf.c6.j2
  when: ansible_distribution_major_version == "6"

循環:迭代,須要重複執行的任務;
對迭代項的引用,固定變量名爲」item「,然後,要在task中使用with_items給定要迭代的元素列表;

- name: install some packages
  yum: name={{ item }} state=present            #item:固定字符,不能更改
  with_items:       #使用如下值給item賦值
  - nginx
  - memcached
  - php-fpm

- name: add some groups
  group: name={{ item }} state=present
  with_items:
  - group11
  - group12
  - group13

- name: add some users
  user: name={{ item.name }} group={{ item.group }} state=present
        #name={{ item.name }}  指明變量名
        #group={{ item.group}}  指明變量組
  with_items:
  - { name: 'user11', group: 'group11' }
  - { name: 'user12', group: 'group12' }
  - { name: 'user13', group: 'group13' }

示例:在目標主機上一次性安裝三個包並啓動起來

  1. 配置文件
- hosts: np1.lxk.com
  remote_user: root
  tasks:
  - name: install {{ item }}
    yum: name={{ item }} state=installed
    with_items:
    - nginx
    - memcached
    - php-fpm
  - name: start {{ item }}
    service: name={{ item }} state=started
    with_items:
    - nginx
    - memcached
    - php-fpm
  1. 運行:
[root@nfs ansible_workshop]# ansible-playbook nmp.yaml 

PLAY [np1.lxk.com] ********************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [np1.lxk.com]

TASK [install {{ item }}] *************************************************************************************************
ok: [np1.lxk.com] => (item=[u'nginx', u'memcached', u'php-fpm'])

TASK [start {{ item }}] ***************************************************************************************************
changed: [np1.lxk.com] => (item=nginx)
ok: [np1.lxk.com] => (item=memcached)
ok: [np1.lxk.com] => (item=php-fpm)

PLAY RECAP ****************************************************************************************************************
np1.lxk.com                : ok=3    changed=1    unreachable=0    failed=0

roles

ansilbe自1.2版本引入的新特性,用於層次性、結構化地組織playbook。roles可以根據層次型結構自動裝載變量文件、tasks以及handlers等。要使用roles只須要在playbook中使用include指令便可。簡單來說,roles就是經過分別將變量、文件、任務、模板及處理器放置於單獨的目錄中,並能夠便捷地include它們的一種機制。角色通常用於基於主機構建服務的場景中,但也能夠是用於構建守護進程等場景中。
一個roles的案例以下所示:

site.yml
        webservers.yml
        dbservers.yml
        roles/
           common/
             files/
             templates/
             tasks/
             handlers/
             vars/
             meta/
           webservers/
             files/
             templates/
             tasks/
             handlers/
             vars/
             meta/

而在playbook中,能夠這樣使用roles:

- hosts: webservers
      roles:
         - common
         - webservers

也能夠向roles傳遞參數,例如:

- hosts: webservers
      roles:
        - common
        - { role: foo_app_instance, dir: '/opt/a',  port: 5000 }
        - { role: foo_app_instance, dir: '/opt/b',  port: 5001 }

甚至也能夠條件式地使用roles,例如:

- hosts: webservers
      roles:
        - { role: some_role, when: "ansible_os_family == 'RedHat'" }

建立role的步驟

(1) 建立以roles命名的目錄;
(2) 在roles目錄中分別建立以各角色名稱命名的目錄,如webservers等;
(3) 在每一個角色命名的目錄中分別建立files、handlers、meta、tasks、templates和vars目錄;用不到的目錄能夠建立爲空目錄,也能夠不建立;
(4) 在playbook文件中,調用各角色;

role內各目錄中可用的文件

tasks目錄:至少應該包含一個名爲main.yml的文件,其定義了此角色的任務列表;此文件可使用include包含其它的位於此目錄中的task文件;
files目錄:存放由copy或script等模塊調用的文件;
templates目錄:template模塊會自動在此目錄中尋找Jinja2模板文件;
handlers目錄:此目錄中應當包含一個main.yml文件,用於定義此角色用到的各handler;在handler中使用include包含的其它的handler文件也應該位於此目錄中;
vars目錄:應當包含一個main.yml文件,用於定義此角色用到的變量;
meta目錄:應當包含一個main.yml文件,用於定義此角色的特殊設定及其依賴關係;ansible 1.3及其之後的版本才支持;
default目錄:爲當前角色設定默認變量時使用此目錄;應當包含一個main.yml文件;

示例1:安裝nginx併爲其提供配置文件和主頁

  1. 建立所需目錄:

/etc/ansible/role

[root@nfs roles]# mkdir -pv ./nginx/{files,templates,tasks,handlers,vars,meta,default}
  1. 提供所需配置文件:
    在/etc/ansible/roles/nginx目錄下提供如下配置文件
[root@nfs nginx]# cat tasks/main.yml        #提供任務列表
- name: install epel-release package
  yum: name=epel-release state=installed
- name: install nginx package
  yum: name=nginx state=installed
- name: create doc root
  file: path={{ docroot }} state=directory
- name: install home page
  copy: src=index.html dest={{ docroot }}/
- name: install conf file
  template: src=server.conf.j2 dest=/etc/nginx/conf.d/server.conf
  notify: reload nginx
- name: start nginx service
  service: name=nginx enabled=true state=started

[root@nfs nginx]# cat vars/main.yml         #提供變量
docroot: /data/nginx/

[root@nfs nginx]# cat templates/server.conf.j2      #提供配置文件模板
server { 
    listen 80;
    server_name {{ ansible_fqdn }} {{ ansible_hostname }} ;

    location / {
        root {{ docroot }};
        index index.html index.jsp;
    }
}

[root@nfs nginx]# cat files/index.html      #提供主頁
<h1> Welcome to Nginx</h1>

[root@nfs nginx]# cat handlers/main.yml         #提供條件式觸發文件
- name: reload nginx
  service: name=nginx state=reloaded

在其它位置提供nginx.yaml文件:

[root@nfs ansible_workshop]# cat nginx.yaml 
- hosts: np1.lxk.com
  remote_user: root
  roles:
  - nginx
  1. 運行:
[root@nfs ansible_workshop]# ansible-playbook nginx.yaml 

PLAY [np1.lxk.com] ********************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************
ok: [np1.lxk.com]

TASK [nginx : install epel-release package] *******************************************************************************
changed: [np1.lxk.com]

TASK [nginx : install nginx package] **************************************************************************************
ok: [np1.lxk.com]

TASK [nginx : create doc root] ********************************************************************************************
changed: [np1.lxk.com]

TASK [nginx : install home page] ******************************************************************************************
changed: [np1.lxk.com]

TASK [nginx : install conf file] ******************************************************************************************
changed: [np1.lxk.com]

TASK [nginx : start nginx service] ****************************************************************************************
changed: [np1.lxk.com]

RUNNING HANDLER [nginx : reload nginx] ************************************************************************************
changed: [np1.lxk.com]

PLAY RECAP ****************************************************************************************************************
np1.lxk.com                : ok=8    changed=6    unreachable=0    failed=0

示例2:

同示例1,修改如下內容:

  1. templates下增長proxy.conf.j2文件,內容以下:
[root@nfs nginx]# cat templates/proxy.conf.j2 
server {
    listen 80;
    server_name {{ ansible_fqdn }} {{ ansible_hostname }};
    location / {
        proxy_pass {{ backendurl }};
    }
}
  1. vars下main.yml修改成以下:
[root@nfs nginx]# cat vars/main.yml 
servertype: web
backendurl: 'http://127.0.0.1:8080'
docroot: /data/nginx/
  1. tasks下main.yml修改成以下:
[root@nfs nginx]# cat tasks/main.yml 
- name: install epel-release package
  yum: name=epel-release state=installed
- name: install nginx package
  yum: name=nginx state=installed
- name: create doc root
  file: path={{ docroot }} state=directory
  when: servertype == 'web'
- name: install home page
  copy: src=index.html dest={{ docroot }}/
  when: servertype == 'web'
- name: install web conf file
  template: src=server.conf.j2 dest=/etc/nginx/conf.d/server.conf
  when: servertype == 'web'
  notify: reload nginx
- name: install proxy conf file
  template: src=proxy.conf.j2 dest=/etc/nginx/conf.d/server.conf
  when: servertype == 'proxy'
  notify: reload nginx
- name: start nginx service
  service: name=nginx enabled=true state=started

4.nginx.yaml修改成以下:

[root@nfs nginx]# cat /root/ansible_workshop/nginx.yaml 
- hosts: tomcat
  remote_user: root
  roles:
  - { role: nginx, servertype: proxy }

- hosts: web
  remote_user: root
  roles:
  - nginx
相關文章
相關標籤/搜索