運維自動化-Ansible ( 四 )

模板templates

功能:根據模塊文件動態生成對應的配置文件ios

 Jinja2語言,使用字面量,有下面形式
字符串:使用單引號或雙引號
數字:整數,浮點數
列表:[item1, item2, ...]
元組:(item1, item2, ...)
字典:{key1:value1, key2:value2, ...}
布爾型:true/false
 算術運算:+, -, *, /, //, %, **
 比較操做:==, !=, >, >=, <, <=
 邏輯運算:and, or, not
 流表達式:For If When
 templates文件必須存放於templates目錄下,且命名爲 .j2 結尾
 yaml/yml 文件需和templates目錄平級,目錄結構以下:
./
├── temnginx.yml
└── templates
     └── nginx.conf.j2

Playbook中template 的 算術運算

.j2文件nginx

server {
   worker_connectios {{ ansible_processor_vcpus *2 }};
}

yml文件git

- hosts: dns
  remote_user: root

  tasks:
    - template: src=/app/1.conf.j2 dest=/app/2.conf

生成的配置文件web

server {
   worker_connectios 4;   > ansible_processor_vcpus=2,因此2*2=4
}

Playbook中template 的 for 循環

語法:shell

{% for i in nginx_vhosts %}
    語句塊
{% endfor %}

{% if vhost.root is defined %}
root {{ vhost.root }};
{% endif %}

以實例來說:apache

- hosts: web
  remote_user: root
  vars:
    prot_list:
      - 8080
      - 8081
      - 8082

  tasks:
    - name: create vhost
      template: src=/app/1.conf.j2 dest=/app/2.conf    > for 循環是寫在.j2文件中的。

通常來說是配合template模板來使用,文件的後綴名爲.j2

先創建一個標準模板文件,這個文件須要跟dest使用的格式一致,只不過是將會變化的內容使用for循環的格式來寫

{% for prot in prot_list %}
server {
        listen prot;
}

{% endfor %}

是否是與shell編程的for循環很像?

image

#ansible-playbook for1.yml
結果:
#cat /app/2.conf 

server {
    listen 8080;
}

server {
    listen 8081;
}

server {
    listen 8082;
}

再來一個多行多主機的模板:編程

- hosts: web
  remote_user: root
  vars:
    vhosts:
      - web:
        prot: 8080
        server: web1.hunk.tech
        root: /app/webroot1
      - web:
        prot: 8081
        server: web2.hunk.tech
        root: /app/webroot2
      - web:
        prot: 8082
        server: web2.hunk.tech
        root: /app/webroot2
  tasks:
    - name: create vhost
      template: src=/app/1.conf.j2 dest=/app/2.conf

j2文件:

{% for vhost in vhost_list %}
server {
        listen {{ vhost.prot }};
        servername {{ vhost.server }};
        root {{ vhost.root }};
}

{% endfor %}

執行:
#ansible-playbook for1.yml
結果:

#cat /app/2.conf 
server {
    listen 8080;
    servername web1.hunk.tech;
    root /app/webroot1;
}

server {
    listen 8081;
    servername web2.hunk.tech;
    root /app/webroot2;
}

server {
    listen 8082;
    servername web2.hunk.tech;
    root /app/webroot2;
}

Playbook中template 的 if 判斷

語法:vim

{% if i is defined %}
        語句塊
{% endif %}

playbook文件:app

- hosts: web
  remote_user: root
  vars:
    vhost_list:
      - web1:                 
        prot: 8080
        name: web1.hunk.tech  > 注意,web1是定義了name的值
      - web2:                 > 注意,web2是沒有定義了name的值
        prot: 8081

  tasks:
    - template: src=/app/1.conf.j2 dest=/app/2.conf

j2文件:ide

{% for vhost in vhost_list %}
server {
        listen {{ vhost.prot }};
{% if vhost.name is defined %}      > 若是vhost.name有應以,剛填入下面的內容
        servername {{ vhost.name }};
{% endif %}
}

{% endfor %

執行:
#ansible-playbook if.yml

結果:
#cat /app/2.conf 
server {
    listen 8080;
    servername web1.hunk.tech;
}

server {
    listen 8081;
}

roles

用於層次性、結構化地組織playbook。 roles可以根據層次型結構自動裝載變量文件、tasks以及handlers等。

要使用roles只須要在playbook中使用import_tasks指令便可。(include也能夠用,官方明確聲明此命令將會淘汰)

簡單來說,roles就是經過分別將變量、文件、任務、模板及處理器放置於單獨的目錄中,並能夠便捷地

include它們的一種機制。角色通常用於基於主機構建服務的場景中,但也能夠是用於構建守護進程等場景中

 複雜場景:建議使用roles,代碼複用度高

建立role的步驟

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

建議的目錄結構

├── roles                   > 必須是這個名字
│   ├── git                 > 具體項目名稱
│   │   ├── default         > 設定默認變量時使用此目錄中的main.yml文件
│   │   │   └── main.yml            > 至少應該包含一個名爲main.yml的文件
│   │   ├── files           > 存放有copy或script模塊等調用的文件
│   │   ├── handlers        > 定義觸發器
│   │   │   └── main.yml            > 至少應該包含一個名爲main.yml的文件
│   │   ├── meta            > 定義當前角色的特殊設定及其依賴關係
│   │   │   └── main.yml            > 至少應該包含一個名爲main.yml的文件
│   │   ├── tasks           > 定義任務
│   │   │   └── main.yml            > 至少應該包含一個名爲main.yml的文件
│   │   ├── templates       > template模塊查找所須要模板文件目錄
│   │   │   └── main.yml            > 至少應該包含一個名爲main.yml的文件
│   │   └── vars            > 定義變量;;其餘的文件須要在此文件中經過include進行包含
│   │       └── main.yml            > 至少應該包含一個名爲main.yml的文件

仍是拿一個實例來講:

若是要在一臺初始化的主機上面安裝httpd服務,有如下過程:(這裏不考慮編譯安裝狀況,假設yum腳本里不會建立組和用戶)

1.建立用於httpd服務的組
2.建立用於httpd服務的用戶
3.安裝httpd軟件包
4.啓動httpd服務

把這些過程體如今ansible上面就是對應的具體的tasks,所以,將須要在roles/tasks/下面建立分別用於這些過程的獨立yml文件

1.建立用於httpd服務的
#vim groupadd.yml
- name: groupadd apache
  group: name=apache 

2.建立用於httpd服務的用戶
#vim useradd.yml
- name: useradd apache
  user: name=apache group=apache shell=/sbin/nologin system=yes

3.安裝httpd軟件包
#vim install_httpd.yml
- name: yum install httpd
  yum: name=httpd

4.啓動httpd服務
#vim start_httpd.yml
- name: start httpd
  service: name=httpd state=started

每一個具體的小任務有了,那麼就得有一個主的配置文件,默認劇本就會讀取它,從而肯定其餘任務的關係。

注意,文件名必須是main.yml

注意,順序不能顛倒,步驟是從上而下順序執行,就像編排電影劇本同樣。有沒有當導演的感受?
#vim main.yml
- import_tasks: groupadd.yml
- import_tasks: useradd.yml
- import_tasks: install_httpd.yml
- import_tasks: start_httpd.yml

最後,建立一個執行的playbook文件,這個文件與roles目錄是同級目錄。

#vim httpd_roles.yml
---
- hosts: web
  remote_user: root

  roles:
    - httpd              > 注意,這個- 後面跟就是roles目錄下的子目錄名稱

固然,也能夠寫成
  roles:
    - role: httpd        > 注意,這個- role: 是不能夠改變名稱的,後面跟就是roles目錄下的子目錄名稱

image

至此,此時的目錄結構爲:

├── httpd_roles.yml                 > 執行的playbook文件
└── roles                           > roles角色目錄
    ├── httpd                       > 項目文件夾
    │   ├── default
    │   ├── files
    │   ├── handlers
    │   ├── meta
    │   ├── tasks                   > 任務文件夾
    │   │   ├── groupadd.yml
    │   │   ├── install_httpd.yml
    │   │   ├── main.yml
    │   │   ├── start_httpd.yml
    │   │   └── useradd.yml
    │   ├── templates
    │   └── vars
#ansible web -m shell -a 'ss -nlt|grep 80'
6-web-1.hunk.tech | SUCCESS | rc=0 >>
LISTEN     0      128         :::80
7-web-2.hunk.tech | SUCCESS | rc=0 >>
LISTEN     0      128         :::80
7-web-0.hunk.tech | SUCCESS | rc=0 >>
LISTEN     0      128         :::80

調用其餘任務

爲了更好的複用代碼,能夠將一些公共的代碼集中在一個目錄裏,按須要在之後的roles進行調用

├── pubtasks
│   └── create_nginx_user_and_group.yml
#cat create_nginx_user.yml
- name: create nginx group
  group: name=nginx

- name: create nginx user
  user: name=nginx shell=/usr/sbin/nologin comment="nginx service" group=nginx createhome=no

調用的時候,在tasks中引入便可

- hosts: dns
  remote_user: root

  tasks:
    - name: test
      import_tasks: /app/yml/pubtasks/create_nginx_user_and_group.yml

同理,在別的文件中引入import_role也是能夠的。

roles中的tags

前面的章節針對tasks有tags,而roles中也能夠運用此方法

- hosts: web
  remote_user: root

  roles:
    - { role: httpd, tags: [ 'web', 'apache22' ] }  > 其實,這是字典的一種寫法,前面章節有講到,只不過是寫在一行裏了。

因此,下面的寫法是同等的
  roles:
    - role: httpd
      tags: 
        - web
        - apache22

基於條件判斷的roles的tags

- { role: nginx, tags: [ 'nginx', 'web' ], when: ansible_distribution_major_version == "6" }

當roles中有了tags後,執行時候加上-t tags名稱便可

# ansible-playbook  httpd_roles.yml -t web
# ansible-playbook  httpd_roles.yml -t apache22

也能夠同時調用多個tags
# ansible-playbook  httpd_roles.yml -t "web,db"

第 (五) 篇屬於應用級別的。後續再更新了。

相關文章
相關標籤/搜索