网络设备自动化运维工具——Nornir3.0.0入门笔记
Nornir概述:
官方網(wǎng)站:https://nornir.readthedocs.io/en/latest/
Nornir是Netmiko的高級(jí)封裝,天生實(shí)現(xiàn)支持多線程并發(fā),并且可與python一起使用。大多數(shù)自動(dòng)化框架通過使用一些繁瑣的偽語(yǔ)言(通常幾乎是圖靈完整的)來(lái)隱藏編寫它們的語(yǔ)言,但缺乏調(diào)試和故障排除工具(明顯看出指的是Ansible)。與其他系統(tǒng)集成通常也相當(dāng)困難,因?yàn)樗鼈兺ǔS袕?fù)雜的api(如果有的話)。這些偽語(yǔ)言的其他一些常見問題是,它們通常在處理數(shù)據(jù)方面相當(dāng)糟糕,而且重用性有限。
Nornir旨在通過提供一個(gè)純python框架來(lái)解決這些問題。不妨把Nornir想象成自動(dòng)化的Flask。Nornir將負(fù)責(zé)處理包含主機(jī)信息的目錄,它將負(fù)責(zé)將任務(wù)分派到你的設(shè)備,并提供一個(gè)通用框架來(lái)編寫“插件”。
注意:目前Nornir要求安裝Python 3.6.2或更高版本。
在NetDevOps中,相比于Ansible,目前更推薦使用Nornir,原因除了上述提到的,還有兩點(diǎn):
1.Norinir的速度相比于Ansible速度快上不止一星半點(diǎn),可以根據(jù)下圖看到:處理1萬(wàn)臺(tái)設(shè)備,Ansible需要2300秒左右,而Nornir只需要17秒。
2. Nornir作為Netmiko的高級(jí)封裝,自然支持Netmiko所支持的設(shè)備。而Ansible目前支持的國(guó)產(chǎn)設(shè)備相對(duì)較少,例如華為設(shè)備僅支持CE系列,因此,在國(guó)內(nèi)的環(huán)境中,Ansible有較大局限性。
Nornir三大文件:
分別為default.yaml、groups.yaml、hosts.yaml:
1.default.yaml:
platform: cisco_ios
username: prin
password: Cisc0123
設(shè)置整個(gè)系統(tǒng)級(jí)別的默認(rèn)值,如果在hosts.yaml和groups.yaml都沒有定義相關(guān)信息,則使用default.yaml的信息。
2.groups.yaml:
cisco_ios:platform: cisco_ios # 等于netmiko的device_type
配置整個(gè)設(shè)備組的相關(guān)信息,如果hosts.yaml中沒有定義相關(guān)信息,則使用其加入的group中的信息。
3.hosts.yaml:
csr1: #設(shè)備名稱groups:- cisco_ios #自己定義的組名稱hostname: 192.168.0.66connection_options: # 不同的connection_type相關(guān)的參數(shù)(與netmiko參數(shù)相同),例如:cisco_asa的secretnetmiko:extras:secret: # secret密碼部分需要提前準(zhǔn)備data:site: sichuantype: routerrouter_id: 1.1.1.1ospf_process_id: 1interface_list:- interface_name: Loopback0ipaddr: 1.1.1.1netmask: 255.255.255.255- interface_name: GigabitEthernet2ipaddr: 10.1.1.1netmask: 255.255.255.0- interface_name: GigabitEthernet3ipaddr: 172.16.0.1netmask: 255.255.255.0ospf_network_list:- network: 10.1.1.0wildmask: 0.0.0.255area: 0- network: 1.1.1.1wildmask: 0.0.0.0area: 0domain: cisco.comuser_info:- username: adminprivilege: 15password: Cisc0123- username: otheradminprivilege: 1password: Cisc0123dns_servers: 114.114.114.114 8.8.8.8logging_console: notificationslogging_hosts:- 192.168.0.166- 192.168.0.188
hosts.yaml定義與每個(gè)具體設(shè)備相關(guān)的數(shù)據(jù)信息。而具體hosts.yaml文件如何編寫,可以使用python代碼打印查看:
from nornir import InitNornir
from nornir.core.inventory import Host
from pprint import pprintnr = InitNornir(config_file="config.yaml")pprint(Host.schema(), indent=4)
打印結(jié)果如下:
可以通過打印的信息看到,nornir其實(shí)是規(guī)定了hosts.yaml文件中的一些頂級(jí)參數(shù)的具體格式(可以對(duì)比一下上文的hosts.yaml文件),主要是關(guān)于連接設(shè)備的一些基礎(chǔ)信息,例如hostname、password、platform等。但是data參數(shù)的具體信息,我們則可以自己進(jìn)行定義發(fā)揮。
Nornir查詢相關(guān)代碼:
1.查看hosts.yaml文件下所有主機(jī)名稱:
pprint(nr.inventory.hosts)
2.查看hosts.yaml文件下的具有主機(jī)名稱:
pprint(nr.inventory.hosts['csr1'])
3.查看groups.yaml文件下所有組的名稱
pprint(nr.inventory.groups)
4.查看groups.yaml文件下具體組的名稱
pprint(nr.inventory.groups['cisco_ios'])
5.獲取hosts.yaml中data下的相關(guān)信息
csr1 = nr.inventory.hosts['csr1']
# 獲取data下的所有key
print(csr1.keys())
# 提取具體key下的值
print(csr1['interface_list'])
6.過濾出hosts.yaml文件中具體的主機(jī)
# 站點(diǎn)為sichuan, 并且類型為router的所有主機(jī)
print(nr.filter(site="sichuan", type="router").inventory.hosts)
實(shí)驗(yàn)測(cè)試:
實(shí)驗(yàn)?zāi)康?#xff1a;
完成CSR1和CSR2的基礎(chǔ)配置。
前提準(zhǔn)備:
- 兩臺(tái)CSR1000v設(shè)備,地址為192.168.0.88和192.168.0.99。
- 在兩臺(tái)設(shè)備上提前配置好SSH。
最終文件結(jié)構(gòu)如下:
步驟一: 安裝python相關(guān)模塊,requirements.txt文件如下:
hvac==0.10.6
nornir==3.0.0
nornir-jinja2==0.1.1
nornir-netmiko==0.1.1
nornir-utils==0.1.1
cffi>=1.12
cryptography
在requirements.txt文件夾下,使用命令:pip3 install -r requirements.txt -i http://pypi.douban.com/simple/ 完成安裝。
步驟二: 定義三大文件
defaults.yaml:
platform: cisco_ios
username: prin
password: Cisc0123
groups.yaml:
cisco_ios:platform: cisco_ios
hosts.yaml:
csr1:groups:- cisco_ios # 所屬于的grouphostname: 192.168.0.66connection_options: # 不同的connection_type相關(guān)的參數(shù)(與netmiko參數(shù)相同),例如:cisco_asa的secretnetmiko:extras:secret: # secret密碼部分需要提前準(zhǔn)備(enable密碼,如果沒有的話可以忽略)data: # data數(shù)據(jù)按照需要配置的數(shù)據(jù)之星發(fā)揮即可site: sichuantype: routerrouter_id: 1.1.1.1ospf_process_id: 1interface_list:- interface_name: Loopback0ipaddr: 1.1.1.1netmask: 255.255.255.255- interface_name: GigabitEthernet2ipaddr: 10.1.1.1netmask: 255.255.255.0- interface_name: GigabitEthernet3ipaddr: 172.16.0.1netmask: 255.255.255.0ospf_network_list:- network: 10.1.1.0wildmask: 0.0.0.255area: 0- network: 1.1.1.1wildmask: 0.0.0.0area: 0domain: qytang.comuser_info:- username: qytadminprivilege: 15password: Cisc0123- username: otheradminprivilege: 1password: Cisc0123dns_servers: 114.114.114.114 8.8.8.8logging_console: notificationslogging_hosts:- 192.168.0.166- 192.168.0.188csr2: #定義設(shè)備2groups:- cisco_ioshostname: 192.168.0.77connection_options: # 不同的connection_type相關(guān)的參數(shù)(與netmiko參數(shù)相同),例如:cisco_asa的secretnetmiko:extras:secret: # secret密碼部分需要提前準(zhǔn)備data:site: sichuantype: routerrouter_id: 2.2.2.2ospf_process_id: 1interface_list:- interface_name: Loopback0ipaddr: 2.2.2.2netmask: 255.255.255.255- interface_name: GigabitEthernet2ipaddr: 10.1.1.2netmask: 255.255.255.0- interface_name: GigabitEthernet3ipaddr: 172.16.0.2netmask: 255.255.255.0ospf_network_list:- network: 10.1.1.0wildmask: 0.0.0.255area: 0- network: 2.2.2.2wildmask: 0.0.0.0area: 0domain: qytang.comuser_info:- username: qytadminprivilege: 15password: Cisc0123- username: otheradminprivilege: 1password: Cisc0123dns_servers: 114.114.114.114 8.8.8.8logging_console: notificationslogging_hosts:- 192.168.0.166- 192.168.0.188
需要注意的是,這里在hosts.yaml文件中并沒與去配置頂級(jí)參數(shù),username(SSH賬號(hào))、password(SSH密碼)和secret(enable密碼)的原因是后續(xù)可以通過python代碼直接在vault(一種保管敏感信息的工具)中提取相關(guān)的信息,并且加入在hosts.yaml文件。
使用python提取vault中的密鑰的好處是為了不讓敏感信息出現(xiàn)在hosts.yaml文件中,增加安全性,這里不展開說(shuō)明。
步驟四: 定義config.yaml文件:
---
inventory:plugin: SimpleInventoryoptions:host_file: "inventory/hosts.yaml"group_file: "inventory/groups.yaml"defaults_file: "inventory/defaults.yaml"runner:plugin: threadedoptions:num_workers: 100
...
定義三大組件的位置和線程數(shù)。
步驟五: 根據(jù)CSR1000v的CLI命令,準(zhǔn)備好需要使用的jinja2的template,方便后續(xù)nornir配置時(shí)調(diào)用。jinja2相關(guān)知識(shí)請(qǐng)參考:https://blog.csdn.net/tushanpeipei/article/details/116895189?spm=1001.2014.3001.5501
1.cisco_dns_servers.template:
ip name-server {{ host.dns_servers }}
提前hosts.yaml文件中的鍵dns_servers對(duì)應(yīng)的值,填入模板中,后續(xù)同理。
2.cisco_ios_interface.template:
{% for i in host.interface_list %}interface {{ i.interface_name }}ip address {{ i.ipaddr }} {{ i.netmask }}no shutdown
{% endfor %}
3.cisco_ios_ospf.template:
router ospf {{ host.ospf_process_id }}router-id {{ host.router_id }}{% for n in host.ospf_network_list %}network {{ n.network }} {{ n.wildmask }} area {{ n.area }}{% endfor %}
4.cisco_ios_user.template:
ip domain name {{ host.domain }}
{% for i in host.user_info %}username {{ i.username }} privilege {{ i.privilege }} password {{ i.password }}
{% endfor %}
5.cisco_logging_config.template:
logging console {{ host.logging_console }}
{% for i in host.logging_hosts %}logging host {{ i }}
{% endfor %}
步驟六: 組織nornir的各項(xiàng)task,完成自動(dòng)化配置
nornir_config.py:
from nornir import InitNornir
from nornir_netmiko.tasks import netmiko_send_command, netmiko_send_config
from nornir_jinja2.plugins.tasks import template_file
from nornir_utils.plugins.functions import print_result
from vault_test.vault_1_init import client
from nornir.core.task import Task, Result# Nornir加載配置文件
nr = InitNornir(config_file="config.yaml")# 通過過濾提取,希望應(yīng)用Task(任務(wù))的主機(jī),本次實(shí)驗(yàn)中也就是CSR1和CSR2
routers = nr.filter(type="router",
)# 模板目錄
templates_path = './templates/'# 從vault讀取信息,并更新nornir inventory(如果沒有vault,則忽略此部分,僅需手工將username、password、secret信息填入hosts.yaml中即可)
for host in routers.inventory.hosts.keys():# 從vault讀取用戶名和密碼vault_data = client.secrets.kv.v2.read_secret_version(mount_point='qytang',path=f'{nr.inventory.hosts[host].platform}/cred')cred_data = vault_data['data']['data']nr.inventory.hosts[host].username = cred_data.get('username')nr.inventory.hosts[host].password = cred_data.get('password')nr.inventory.hosts[host].connection_options['netmiko'].extras['secret'] = cred_data.get('secret')# 一個(gè)大任務(wù)中包含多個(gè)小任務(wù)
def config_routers(task:Task) -> Result:# -------------------------------配置接口------------------------------# 讀取模板,并通過參數(shù)render為具體配置ios_interface_template = task.run(name='第一步.1:讀取IOS接口配置模板', # 任務(wù)名稱task=template_file, # 任務(wù)的目的是獲取配置的模板,固定值template='cisco_ios_interface.template',path=templates_path)# 傳入具體配置, 對(duì)設(shè)備進(jìn)行配置, 注意需要".split('\n')"把配置轉(zhuǎn)換為列表task.run(task=netmiko_send_config, # 任務(wù)的目的是通過netmiko完成配置,固定值name='第一步.2:配置路由器接口',config_commands=ios_interface_template.result.split('\n'), # 將模板信息轉(zhuǎn)換為列表,然后通過netmiko進(jìn)行配置cmd_verify=True)# -------------------------------配置OSPF------------------------------# 讀取模板,并且通過參數(shù)render為具體配置ios_ospf_template = task.run(name='第二步.1:讀取路由器OSPF模板',task=template_file,template='cisco_ios_ospf.template',path=templates_path)# 傳入具體配置, 對(duì)設(shè)備進(jìn)行配置, 注意需要".split('\n')"把配置轉(zhuǎn)換為列表task.run(task=netmiko_send_config,name='第二步.2:配置路由器OSPF',config_commands=ios_ospf_template.result.split('\n'),cmd_verify=True)# ---------------------------------配置Logging----------------------------# 讀取模板,并通過參數(shù)render為具體配置ios_logging_template = task.run(name='第三步.1:讀取logging服務(wù)器配置模板',task=template_file,template='cisco_logging_config.template',path=templates_path)# 傳入具體配置, 對(duì)設(shè)備進(jìn)行配置, 注意需要".split('\n')"把配置轉(zhuǎn)換為列表task.run(task=netmiko_send_config,name='第三步.2:配置logging服務(wù)器',config_commands=ios_logging_template.result.split('\n'),cmd_verify=True)# ---------------------------------配置管理員信息----------------------------# 讀取模板,并通過參數(shù)render為具體配置ios_user_template = task.run(name='第四步.1:讀取設(shè)備管理員配置模板',task=template_file,template='cisco_ios_user.template',path=templates_path)# 傳入具體配置, 對(duì)設(shè)備進(jìn)行配置, 注意需要".split('\n')"把配置轉(zhuǎn)換為列表task.run(task=netmiko_send_config,name='第四步.2:配置管理員信息',config_commands=ios_user_template.result.split('\n'),cmd_verify=True)# ---------------------------------配置管理員信息----------------------------# 讀取模板,并通過參數(shù)render為具體配置ios_dns_template = task.run(name='第五步.1:讀取DNS服務(wù)器模板',task=template_file,template='cisco_dns_servers.template',path=templates_path)# 傳入具體配置, 對(duì)設(shè)備進(jìn)行配置, 注意需要".split('\n')"把配置轉(zhuǎn)換為列表task.run(task=netmiko_send_config,name='第五步.2:配置DNS服務(wù)器',config_commands=ios_dns_template.result.split('\n'),cmd_verify=True)# 大任務(wù)的執(zhí)行完成后的返回結(jié)果return Result(host=task.host,result=f"{task.host}運(yùn)行完成")# 執(zhí)行大任務(wù),任務(wù)名稱為配置CSR路由器
run_result = routers.run(task=config_routers,name='配置CSR路由器')
# 打印返回結(jié)果。
print_result(run_result)
測(cè)試結(jié)果:
參考資料來(lái)源:弈心、現(xiàn)任明教教主相關(guān)學(xué)習(xí)資料
總結(jié)
以上是生活随笔為你收集整理的网络设备自动化运维工具——Nornir3.0.0入门笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FFT字符串匹配(解决通配符问题)
- 下一篇: 2021CCPC华为云挑战赛:HDU 7