網路自動化已成為現代網路管理的根本,而 Jinja2 和 YAML 正是實作自動化的利器。Jinja2 作為範本引擎,負責定義組態的框架,YAML 則提供結構化的資料,兩者結合,讓網路工程師得以擺脫繁瑣的手動組態。本文將深入淺出地介紹如何運用 Jinja2 和 YAML,搭配 Python 及 Netmiko,實作 Cisco 路由器的自動化組態,包含主機名設定、介面組態以及批次佈署。透過實際案例,讀者將理解如何建構 Jinja2 範本、撰寫 YAML 資料檔案,並使用 Python 指令碼將兩者整合,最終透過 Netmiko 將組態推播至網路裝置。此方法不僅提升組態效率,更能有效降低人為錯誤,確保網路穩定執行。
網路自動化組態管理:Jinja2 與 YAML 的實務應用
在現代網路工程領域中,自動化組態管理已成為提升效率和降低錯誤率的關鍵技術。其中,Jinja2 範本引擎與 YAML 語言的結合使用,為網路裝置的組態管理提供了強大的工具。本文將探討 Jinja2 和 YAML 的基本概念,以及如何利用這兩種技術實作網路裝置的自動化組態。
Jinja2 範本引擎簡介
Jinja2 是一種流行的 Python 範本引擎,其語法與 Python 相似,具有高效、靈活的特點。在網路自動化領域,Jinja2 被廣泛用於生成網路裝置的組態範本。透過使用 Jinja2,網路工程師可以將組態範本與具體的組態資料分離,從而實作對多台網路裝置的統一管理和組態。
Jinja2 範本範例
以下是一個簡單的 Jinja2 範本範例,用於組態網路裝置的主機名和介面 IP 地址:
hostname {{ name }}
!
interface GigabitEthernet 0/1
ip address {{ ip_address }} {{ subnet_mask }}
no shutdown
!
interface GigabitEthernet 0/2
ip address {{ ip_address }} {{ subnet_mask }}
no shutdown
!
在這個範本中,{{ name }}、{{ ip_address }} 和 {{ subnet_mask }} 是變數,它們的值將在渲染範本時被具體的組態資料取代。
內容解密:
hostname {{ name }}:設定網路裝置的主機名,{{ name }}將被 YAML 檔案中的對應值取代。interface GigabitEthernet 0/1和interface GigabitEthernet 0/2:組態兩個不同的介面,分別設定 IP 地址和子網路遮罩,並啟用介面。- 使用 Jinja2 的優勢在於,可以根據不同的 YAML 組態檔案,生成適用於不同網路裝置的組態範本。
YAML 語言簡介
YAML(YAML Ain’t Markup Language)是一種人類友好的資料序列化語言,被廣泛應用於各種程式語言和工具中,包括 Ansible 這種流行的網路自動化工具。YAML 的語法簡單、易於閱讀,且支援多種資料型別,如字串、布林值、整數、浮點數、列表和字典。
YAML 語法要點
- 縮排:YAML 使用縮排表示層級關係,與 Python 類別似。
- 註解:使用
#符號進行註解。 - 大小寫敏感:YAML 語言區分大小寫。
- 檔案副檔名:YAML 檔案通常以
.yaml或.yml為副檔名。
YAML 範例
以下是一個簡單的 YAML 檔案範例,用於定義 Jinja2 範本中的變數值:
name: Router1
ip_address: 192.168.1.1
subnet_mask: 255.255.255.0
這個 YAML 檔案定義了 name、ip_address 和 subnet_mask 三個變數,分別對應於 Jinja2 範本中的 {{ name }}、{{ ip_address }} 和 {{ subnet_mask }}。
內容解密:
name: Router1:定義了主機名變數name的值為Router1。ip_address: 192.168.1.1和subnet_mask: 255.255.255.0:定義了 IP 地址和子網路遮罩的值。- 這些值將被用於替換 Jinja2 範本中的對應變數,從而生成最終的網路裝置組態。
結合 Jinja2 與 YAML 實作自動化組態
要實作網路裝置的自動化組態,需要結合 Jinja2 範本和 YAML 組態檔案。以下是一個 Python 指令碼範例,展示瞭如何使用 Jinja2 和 YAML 模組渲染組態範本:
from jinja2 import Environment, FileSystemLoader
from yaml import safe_load
# 建立 Jinja2 環境並載入範本檔案
env = Environment(loader=FileSystemLoader("."))
template = env.get_template("commands.txt")
# 載入 YAML 組態檔案
with open("info.yml", "r") as file:
data = safe_load(file)
# 渲染範本並輸出結果
rendered_config = template.render(data)
print(rendered_config)
內容解密:
env = Environment(loader=FileSystemLoader(".")):建立一個 Jinja2 環境,並指定從當前目錄載入範本檔案。template = env.get_template("commands.txt"):載入名為commands.txt的 Jinja2 範本檔案。data = safe_load(file):使用safe_load方法載入 YAML 組態檔案中的資料。rendered_config = template.render(data):將 YAML 資料渲染到 Jinja2 範本中,生成最終的組態文字。
Jinja 範本與 YAML 檔案結合的網路裝置組態自動化
在網路自動化的過程中,Jinja 範本引擎與 YAML 檔案的結合使用可以大幅簡化網路裝置的組態管理工作。本章節將探討如何利用 Jinja 範本和 YAML 資料檔案來自動化組態 Cisco 路由器等網路裝置。
基本原理
Jinja 是一個功能強大的範本引擎,能夠讓使用者定義範本並將變數或表示式嵌入其中。YAML 檔案則用於儲存結構化的資料。透過 Jinja 的渲染功能,可以將 YAML 中的資料填充到範本中,生成最終的組態命令或檔案。
範例 5.6:使用 Jinja 範本與 YAML 檔案渲染組態
首先,我們建立一個名為 commands.txt 的 Jinja 範本檔案,其中包含了一個變數 language,被雙大括號包圍:
We try to learn {{ language }}
接著,建立一個名為 info.yml 的 YAML 檔案,用於儲存 language 的值:
language: Python
在 Python 指令碼中,我們使用 Jinja2 和 PyYAML 函式庫來讀取範本和 YAML 資料,並渲染出最終的組態:
from jinja2 import Environment, FileSystemLoader
from yaml import safe_load
# 設定 Jinja 環境並載入範本
env = Environment(loader=FileSystemLoader("."))
template = env.get_template("commands.txt")
# 載入 YAML 資料
with open("info.yml") as r:
data = safe_load(r)
# 渲染範本
print(template.render(data))
程式碼解析:
- 載入 Jinja 範本:使用
FileSystemLoader載入當前目錄下的commands.txt範本檔案。 - 讀取 YAML 資料:使用
safe_load函式讀取info.yml檔案中的資料。 - 渲染範本:呼叫
render方法,將 YAML 中的資料填充到 Jinja 範本中,生成最終輸出。
輸出結果為:We try to learn Python
範例 5.7:使用 Jinja 組態 Cisco 路由器
在這個範例中,我們將使用 Jinja 範本來組態 Cisco 路由器的主機名、介面描述、IP 位址和子網路遮罩。
commands.txt(Jinja 範本):
hostname {{ name }}
interface GigabitEthernet0/1
description {{ description }}
ip address {{ ip_address }} {{ subnet_mask }}
no shutdown
info.yml(YAML 資料):
name: Router-1
description: Test_Interface
ip_address: 192.168.10.10
subnet_mask: 255.255.255.0
Python 指令碼:
from jinja2 import Environment, FileSystemLoader
from yaml import safe_load
from netmiko import Netmiko
import re
# 路由器連線資訊
ip = {"host": "10.10.10.1", "username": "admin", "password": "cisco", "device_type": "cisco_ios", "global_delay_factor": 0.1}
# 載入 Jinja 範本和 YAML 資料
env = Environment(loader=FileSystemLoader("."))
template = env.get_template("commands.txt")
with open("info.yml") as r:
data = safe_load(r)
# 渲染範本並轉換為命令列表
command = template.render(data)
command = re.split("\n", command)
# 連線到路由器並執行組態命令
print(f"\n
---
Try to Login: {ip['host']}
---
\n")
net_connect = Netmiko(**ip)
output = net_connect.send_config_set(command)
print(output)
程式碼解析:
- Jinja 範本渲染:將
info.yml中的資料填充到commands.txt範本中,生成路由器的組態命令。 - 命令分割:使用正規表示式將渲染後的命令字串分割成列表,以便逐行執行。
- Netmiko 連線:使用 Netmiko 函式庫連線到 Cisco 路由器,並執行組態命令。
使用迴圈進行批次組態
當需要對多個介面進行相同的組態時,可以在 Jinja 範本中使用迴圈來簡化操作。
範例 Jinja 範本:
{% for interface in interfaces %}
interface {{ interface.name }}
description {{ interface.description }}
ip address {{ interface.ip_address }} {{ interface.subnet_mask }}
{% endfor %}
範例 YAML 資料:
interfaces:
- name: GigabitEthernet0/1
description: Test_Interface_1
ip_address: 192.168.10.10
subnet_mask: 255.255.255.0
- name: GigabitEthernet0/2
description: Test_Interface_2
ip_address: 192.168.20.10
subnet_mask: 255.255.255.0
程式碼解析:
- 迴圈語法:在 Jinja 範本中使用
{% for %}和{% endfor %}定義迴圈,遍歷 YAML 中的interfaces清單。 - 變數參照:在迴圈內部,使用
{{ interface.name }}、{{ interface.description }}等語法參照每個介面的屬性。
透過這種方式,可以輕鬆地對多個介面進行相同的組態,大大提高了網路自動化的效率和靈活性。
使用 Jinja 範本組態多個介面與裝置
在網路自動化的領域中,Jinja 範本的使用大大簡化了組態管理的複雜性。透過結合 Python、YAML 以及 Jinja,我們可以輕鬆地對多個網路裝置進行組態。
範例 5.8:使用 Jinja 組態多個介面
在這個範例中,我們展示瞭如何使用 Jinja 範本來組態路由器的主機名稱以及多個介面的設定,包括介面描述、IP 位址以及啟用介面。
commands.txt:
hostname {{hostname}}
{% for int in interfaces %}
interface {{ int["name"] }}
description {{ int["description"] }}
ip address {{ int["ip_address"] }} {{ int["subnet_mask"] }}
no shutdown
{% endfor %}
info.yml:
hostname: Router-1
interfaces:
- name: GigabitEthernet0/1
description: Service_Interface
ip_address: 172.16.10.10
subnet_mask: 255.255.255.0
- name: GigabitEthernet0/2
description: MGMT_Interface
ip_address: 10.0.0.10
subnet_mask: 255.255.255.0
- name: GigabitEthernet0/3
description: Dowlink_Interface
ip_address: 1.1.1.1
subnet_mask: 255.255.255.0
程式碼執行結果:
當我們執行 Python 程式碼後,Jinja 範本會根據 info.yml 中的資料生成組態命令,並套用到 Router-1 上。
R1(config)#hostname Router-1
Router-1(config)#
Router-1(config)#interface GigabitEthernet0/1
Router-1(config-if)# description Service_Interface
Router-1(config-if)# ip address 172.16.10.10 255.255.255.0
Router-1(config-if)# no shutdown
...
內容解密:
commands.txtJinja範本:使用{{hostname}}將主機名稱動態插入組態中,並透過for迴圈遍歷interfaces清單,為每個介面生成相應的組態命令。info.yml資料檔:定義了主機名稱和介面清單,每個介面包含名稱、描述、IP 位址和子網路遮罩等資訊。- Python程式碼的作用:讀取
info.yml中的資料,使用 Jinja 範本渲染出組態命令,並透過 Netmiko 將這些命令套用到目標裝置上。
範例 5.9:使用 Jinja 組態多個裝置
在這個範例中,我們展示瞭如何使用相同的 Jinja 範本和 Python 指令碼對多個裝置進行不同的組態。
commands.txt:
hostname {{hostname}}
interface {{int_name}}
description {{description}}
ip address {{ip_address}} {{subnet_mask}}
no shutdown
info.yml:
- hostname: R1
int_name: GigabitEthernet0/3
description: Test-1
ip_address: 10.1.1.1
subnet_mask: 255.255.255.0
- hostname: R2
int_name: GigabitEthernet0/3
description: Test-2
ip_address: 10.1.1.2
subnet_mask: 255.255.255.0
- hostname: R3
int_name: GigabitEthernet0/3
description: Test-3
ip_address: 10.1.1.3
subnet_mask: 255.255.255.0
Python 指令碼:
from jinja2 import Environment, FileSystemLoader
from yaml import safe_load
from netmiko import Netmiko
# 裝置 IP 清單
ip_list = ["10.10.10.1", "10.10.10.2", "10.10.10.3"]
# 設定 Jinja 環境並載入範本
env = Environment(loader=FileSystemLoader("."))
template = env.get_template("commands.txt")
# 載入 YAML 資料
with open("info.yml") as f:
data = safe_load(f)
# 對每個裝置進行組態
for x, ip in zip(data, ip_list):
device = {
"host": ip,
"username": "admin",
"password": "cisco",
"device_type": "cisco_ios"
}
command = template.render(x)
command = command.split("\n")
net_connect = Netmiko(**device)
output = net_connect.send_config_set(command)
print(output)
內容解密:
- 同時組態多個裝置:透過迴圈遍歷裝置 IP 清單和對應的組態資料,使用 Jinja 範本為每個裝置生成組態命令。
- 動態渲染範本:根據
info.yml中的資料動態替換 Jinja 範本中的變數,生成最終的組態命令。 - 使用 Netmiko 連線裝置:將生成的組態命令套用到每個裝置上,實作自動化組態。