如何創建Ansible模板以節省配置時間

管理多個伺服器和環境的配置是使用 Ansible 的一大好處。但是,當配置文件在不同伺服器間有所不同時會發生什麼情況呢?與其為每個伺服器或環境創建獨立的配置,不如研究一下 Ansible 模板。

在這個教程中,您將學習到什麼是 Ansible 模板,它們是如何工作的,以及如何使用Ansible 模板模組來節省大量時間。

先決條件

本文將是一個逐步教程。如果您想跟著操作,請確保您有一個Ansible 控制器主機。本教程將使用 Ansible v2.9.18

什麼是 Ansible 模板?

有時您需要將文本文件傳輸到遠程主機。這些文本文件通常是某種配置文件。例如,如果您正在使用單個伺服器,可能需要創建一個名為app.conf的配置文件,供某個服務使用。

該配置文件可能包含特定於該服務器的信息,如主機名、IP地址等。由於您正在使用單個服務器,您可以在Ansible控制器上創建該文件,然後在playbook中使用copy模塊將其複製到服務器上。

但是,如果您有多個網絡服務器,每個服務器都需要相同的配置文件,但又具有自己的特定值怎麼辦?您不能只將配置文件複製到所有機器上;它只適用於具有特定主機名、IP地址等的單個服務器。您需要一個Ansible模板。

Ansible模板允許您定義帶有變量而不是靜態值的文本文件,然後在playbook運行時替換這些變量。

Ansible模板長什麼樣子?

Ansible模板是使用Jinja2模板語言構建的文本文件,具有j2文件擴展名。Jinja2模板看起來與您想要放在遠程主機上的文本文件完全相同。唯一的不同之處在於,該文件包含變量而不是靜態值。

例如,也許您需要在所有的Web伺服器上取得名為app.conf的配置文件,該文件包含對每個相應伺服器的IP地址、Ansible主機和Ansible用戶的引用。單個伺服器的app.conf文件可能如下所示。

my_ip    = "192.168.0.1"
my_host  = "ANSBILECONTROL"
my_user  = "ansible_user"

您不能將此文件複製到每個Web伺服器上,因為每個項目都會根據遠程主機的IP、Ansible控制器的主機名和Ansible用戶而唯一。

與其靜態地設置這些值,Ansible模板允許您定義在運行時解釋並在遠程主機上替換的變數。

下面是app.conf.j2模板文件的示例。您現在可以看到,每個靜態值都已被替換為在兩側用雙大括號標記的變數。在這個例子中,這些變數來自Ansible事實

模板文件始終具有J2文件擴展名,通常與它們在目標主機上創建的文件具有相同的名稱。

my_ip    = "{{ansible_default_ipv4["address"]}}"
my_host  = "{{ansible_host}}"
my_user  = "{{ansible_user}}"

如何在遠程主機上創建模板文件?

創建模板後,您需要將該模板文件傳輸到遠程主機並“轉換”為其應該呈現的實際文本文件。為此,您需要在播放書中引用模板文件。

大多數Ansible管理員使用copy模組將文件傳輸到遠程主機,但正如上面所提到的,這對於模板來說是不可行的。

下面是一個簡單的示例參考,從一個playbook將app.conf文件複製到所有playbook的目標主機的/opt目錄中。

- name: copy file from local host to remote host
  copy:                               # Declaring Copy Module 
    src: "app.conf"                   # Source Location 
    dest: "/opt/app.conf"             # Destination Location on remote host

現在假設您已經將app.conf配置文件“模板化”,在前一節中涵蓋了Ansible控制器上的app.conf.j2模板文件。現在,您需要確保app.conf仍然到達/opt目錄,但變量被實際值替換。

要告訴playbook在/opt目錄中創建app.conf文件,只需將copy參考替換為如下所示的template。這樣做後,Ansible會調用template模組來傳輸模板並將變量替換為靜態值。

- name: template file to remote host
  template:                 # Ansible template module
    src: "app.conf.j2"      # This is template src i.e source location 
    dest: "/opt/app.conf"   # Destination of Remote host

一旦playbook中的上述任務執行完畢,Ansible就會將app.conf.j2複製到遠程主機的/opt目錄中,將其中的所有變量替換為靜態值並將文件重命名為app.conf

當您提供帶有目錄路徑的模板src時,Ansible 將在 /<ansible_installation_directory>/files/ 目錄中尋找模板。如果您只提供文件名,則 Ansible 將會在 /<ansible_installation_directory>/templates/ 目錄中尋找該模板。

渲染配置文件:模板示例

現在讓我們進入示範,看看如何設置 Ansible 模板並使用 Ansible 模板模塊動態生成配置文件。在這個示例中,您將在名為/etc的目錄中的一台名為SRV1的服務器上創建一個名為app.conf的文件。

本節中的步驟適用於任何類型的文本文件。本教程將以配置文件作為單個示例。

1. 使用您通常用於管理 Ansible 的用戶 SSH 登錄到 Ansible 控制器主機。

2. 在您的家目錄中創建一個文件夾來存放本教程的演示文件,並將工作目錄更改為該文件夾。

mkdir ~/ansible_template_demo
cd ~/ansible_template_demo

3. 在看起來像下面的目錄中創建一個名為app.conf.j2的模板文件。

my_ip = {{ansible_default_ipv4["address"]}}
my_host  = {{ansible_host}}
my_user  = {{ansible_user}}

您還可以在模板中使用特定於 Ansible 模板模塊本身的各種變量

4. 在同一目錄中創建一個名為my_playbook.yml的簡單 playbook。此 playbook 將在/etc目錄中創建app.conf文件。


name: Ansible template example 
hosts: myserver 
remote_user: ubuntu   # Using Remote host as ubuntu 
tasks: 
 - name: Create the app.conf configuration file
   template:
     src: "~/ansible_template_demo/app.conf.j2"
     dest: "/etc/app.conf"
   become: true 

5. 調用 Ansible playbook,將其針對SRV1遠程主機。

ansible-playbook my_playbook.yml --inventory SRV1
You should then see Ansible execute the playbook.

6. 現在確認 /etc/app.conf 配置文件是否存在並具有預期的值。

confirm the /etc/app.conf configuration file

使用模板模塊更新文件權限

現在您已經看到了使用模板模塊的基礎知識,現在讓我們更進一步。對於這個演示,您將創建與之前顯示的相同的 app.conf 文件。但是這一次,您將設置該文件的所有者和權限。

要更改模板模塊創建的文件的權限,您必須在 playbook 內使用三個參數:

  • owner – 文件所有者
  • group – 文件應該屬於的組
  • mode – 權限。此字符串可以使用符號表示,也可以使用八進制數字表示

在符號模式中,u 代表 “用戶”,g 代表 “組” ,o 代表 “其他”。

假設您仍然擁有之前部分建立的~/ansible_template_demo文件夾,打開my_playbook.yml playbook並將內容替換為下面的內容。在這個示例中,Ansible將使用連接變量將所有者和組設置為Ansible用戶。然後將文件權限設置為0644,代表:

  • 所有者具有讀/寫權限
  • 組中的用戶和其他所有人具有讀取權限
---
- name: Ansible file permission example
  remote_user: ubuntu
  tasks:
    - name: Create the app.conf configuration file and assign permissions
      template:
          src: "~/ansible_template_demo/app.conf.j2"
          dest: "/etc/app.conf"
	  owner: "{{ ansible_user }}"
          group: "{{ ansible_user }}"
          mode:  0644 ## OR  mode: u=rw, g=w,o=r       
      become: true

您可以在Ansible模板模塊文檔中找到所有可用的模板模塊參數。

現在,按照下面的示例再次執行playbook。

ansible-playbook my_playbook.yml --inventory SRV1

現在,您可以看到app.conf具有預期的文件權限。

app.conf

使用循環模板多個文件

有時候單個文件是不夠的,您需要在遠程主機上添加多個文件。在這種情況下,您可以使用循環與模板模塊。使用loop參數定義循環允許您添加存儲在目錄中的多個文本文件。

假設您仍然擁有之前部分建立的~/ansible_template_demo文件夾,您應該已經有app.conf.j2在其中。

1. 在~/ansible_template_demo文件夾中創建第二個模板文件,名為app2.conf.j2,如下所示。

 template_host = "{{ template_host }}"
 template_uid = "{{ template_uid }}"
 template_path = "{{ template_path }}"
 template_fullpath = "{{ template_fullpath }}"
 template_run_date = "{{ template_run_date }}"

2. 打開 my_playbook.yml 書籍並用以下 YAML 替換所有內容。此 playbook 使用 {{item}} 變量來表示循環中處理的每個模板文件。然後,loop 參數定義循環要處理的每個模板文件。

---
- name: Ansible file permission example 
  remote_user: ubuntu 
  tasks: 
   - name: Create the app.conf configuration file and assign permissions 
     template:   
        src: "~/ansible_template_demo/{{item}}.j2"    # 遍歷 2 個模板
        dest: "/etc/{{item}}"
        owner: "{{ ansible_user }}"   
        group: "{{ ansible_user }}"   
        mode:  0644 ## OR  mode: u=rw, g=w,o=r
     become: true     
     loop: # 告訴模板模塊找到這些模板並處理
      - app1.conf 
      - app2.conf 

3. 現在再次運行 playbook。 ansible-playbook my_playbook.yml --inventory SRV1

ansible-playbook my_playbook.yml --inventory SRV1
Notice now that Ansible sees each template file and processes them accordingly.

結論

Ansible 模板和模板模塊可以為您節省大量時間,並在所有遠程主機上創建動態文本文件。複製模塊提供類似的功能,但如果需要創建動態文本文件,模板模塊就是您的好幫手。

Source:
https://adamtheautomator.com/ansible-template/