1. 程式人生 > >運維自動化-Ansible ( 四 )

運維自動化-Ansible ( 四 )

變量 not 處理器 book 來講 是不是 運維 cti apache2

模板templates

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

? 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文件

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

yml文件

- hosts: dns
  remote_user: root

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

生成的配置文件

server {
   worker_connectios 4;   > ansible_processor_vcpus=2,所以2*2=4
}

Playbook中template 的 for 循環

語法:

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

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

以實例來講:

- 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循環很像?

技術分享圖片

#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 判斷

語法:

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

playbook文件:

- 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文件:

{% 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目錄下的子目錄名稱

技術分享圖片

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

├── 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"

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

運維自動化-Ansible ( 四 )