【分享】網(wǎng)絡(luò)自動化的項目實踐:場景、工具和方案
原創(chuàng)【51CTO.com原創(chuàng)稿件】網(wǎng)絡(luò)自動化是針對一組網(wǎng)絡(luò)設(shè)備批量執(zhí)行一連串的網(wǎng)絡(luò)操作。它可以歸納為三個組件:命令 + 操作 + 目標(biāo)設(shè)備,適用于兩個場景。
場景1:針對既有網(wǎng)絡(luò)的操作和/或增量配置,提高重復(fù)性任務(wù)的效率。它又包括兩個方面(以思科設(shè)備為例):
- 日常的enable mode操作,例如采集一組設(shè)備的設(shè)備信息,接口狀態(tài)和描述檢查,設(shè)備版本查驗,配置文件一致性驗證等。
- 為現(xiàn)有網(wǎng)絡(luò)上平穩(wěn)運行的多個設(shè)備提供具備共性的增量配置。例如新增或刪除一個授權(quán)登錄的帳號,統(tǒng)一修改AAA認(rèn)證服務(wù)器/日志/Netflow/NTP服務(wù)器地址,更新SNMP Community string,統(tǒng)一關(guān)閉某個端口等。
場景2:針對新建大規(guī)模數(shù)據(jù)中心,提供快速部署。主要是基于一個基線配置模板,調(diào)用特定于設(shè)備的Location/Type/Role/Loopback等信息的變量文件,來動態(tài)創(chuàng)建完整的配置文件。
一、流行的網(wǎng)絡(luò)自動化工具和手段
根據(jù)我個人的工作經(jīng)驗和負(fù)責(zé)的項目,總結(jié)了如下幾個解決方案,并列舉了一些細(xì)節(jié):
1. Cisco Prime Infrastructure,封閉系統(tǒng),一個運行在虛擬服務(wù)器上的OVA文件。
- 內(nèi)置專有OS,提供專有的Shell界面,不是工業(yè)標(biāo)準(zhǔn)的Linux shell。
- 無法獲知它的Inventory文件(CVS格式)/配置文件/模板/變量在系統(tǒng)中的保存位置。
- 無法獲知它的系統(tǒng)采用什么腳本編寫,也無法修改實現(xiàn)個性化。
- 系統(tǒng)不支持任何版本控制機制,無法將本地的配置文件Push到GitHub。
- 內(nèi)置封閉的Web daemon提供用戶GUI接口,采用Oracle DB但是用戶沒有DB root帳號和Prime 用戶帳號,即無法編輯修改數(shù)據(jù)庫文件。
- Cicso PI是一個集網(wǎng)絡(luò)監(jiān)測、日志服務(wù)、Netflow采集分析、配置備份和網(wǎng)絡(luò)自動化為一體的綜合系統(tǒng),但是每一個單項拿出來都不如專門提供特定功能的系統(tǒng)強大,例如配置備份有RANCID,Syslog有Splunk, Netflow有Scrutinizer, 網(wǎng)絡(luò)監(jiān)測有Observium/Nagios/Check_MK。
2. RANCID, 在我所在公司的部署中,是通過與Observium集成來實現(xiàn)的:
- 通過RANCID自帶的腳本(generate-rancid.custom.php)讀取Observium inventory文件(和Linux server的/etc/hosts也有關(guān)聯(lián))動態(tài)生成router.db,但是設(shè)備型號的描述粒度不夠細(xì)。
- 版本控制采用CVS或SVN,與Git相比略顯老舊。
- 通過clogin –c “show clock” “show version” ‘ls *aus*’命令來針對hostname中有‘aus’字符的所有網(wǎng)絡(luò)設(shè)備按順序執(zhí)行一組enable模式操作。
- 通過clogin –x commands.txt ‘ls *sv4*’命令來針對hostname中有‘sv4’字符的所有設(shè)備按順序執(zhí)行一組配置命令。
- 腳本執(zhí)行過程中和用戶沒有交互,只能采用rancid自己的帳號登錄設(shè)備進行操作,審計功能弱。
- 不如Python腳本調(diào)用command-set和device-group兩個Argument方便靈活。
- 沒有異常處理機制(例如針對100臺設(shè)備進行批量操作,萬一第30臺設(shè)備因故障登錄失敗,腳本將停止)。
3. Ansible,發(fā)展之初更多地面向服務(wù)器進行自動化部署
(1) 實現(xiàn)復(fù)雜,引入很多新概念,包括如下:
- Role/Playbook
- Jinja2 template
- Yaml grammar
- Host Inventory
- Engine/Modules/Plugins
(2) 一次Ansible操作的流程,可以顯示出完整的Ansible架構(gòu),如下圖:
(3) 看似一條簡單的命令“Ansible-playbook templates.yaml”實際上需要四個input (tasks, hosts, jinja-template, vars),每個input都是特定于設(shè)備的,即每臺設(shè)備都有專門針對自己的四個參數(shù),如果設(shè)備的數(shù)量不夠大,很可能維護變量/模板/Inventory等文件的精力要抵消自動化提高的效率。說通俗一點就是,我采用Ansible節(jié)省了30分鐘時間,但是我事先需要花2個小時準(zhǔn)備相關(guān)的、需要被Ansible在執(zhí)行過程中調(diào)用的基礎(chǔ)數(shù)據(jù)。
(4) 理論上更適合新建大規(guī)模數(shù)據(jù)中心的應(yīng)用場景,網(wǎng)絡(luò)拓?fù)鋵ΨQ且層次化,有規(guī)律可循。按照固定的Pattern來搭建,容易制定一個具有普適性的基線模板,只需為數(shù)不多的變量就可以生成不同site、type和role的設(shè)備配置文件。
(5) 由于我現(xiàn)在任職的公司主要是總部和分支機構(gòu)之間的Corporation網(wǎng)絡(luò),每個Remote site的組網(wǎng)原理類似Campus network,以其中一個分公司的LAN-Switch為例,共有57個個性化元素需要提取出來作為變量,工作量很大。其中的VLAN ID變量雖然只有6個,但是在288個接口上隨機分布,Jinca2模板必須為每個Interface預(yù)留VLAN ID變量的輸入;更復(fù)雜的是Interface description, 作為LAN-Switch我們需要對連接
WLC/VMW/NetApp/WAP/Zoom/Camera/Monitor系統(tǒng)的Port進行特別描述,但是46個接口描述變量在交換機的288個接口上也是隨機的,和其他分公司的LAN-Switch之間沒有共性,導(dǎo)致Ansible的變量文件幾近不可維護,花在維護變量和模版上的精力,遠遠大于自動化提高的效率。
4. 還有幾個技術(shù)方案我沒有深入研究,在NANOG會議資料中看到行業(yè)專家進行過權(quán)威陳述,摘要如下:
- Python with NAPALM (Python module): 思科目前只支持IOS-XR,不適合企業(yè)網(wǎng)絡(luò)。
- NETCONF/YANG: 12年前的IETF標(biāo)準(zhǔn)(RFC4741),截至目前只有JUNOS支持比較好。
- XML via CLI: Schema:尚未標(biāo)準(zhǔn)化。
- RESTful API: 工業(yè)標(biāo)準(zhǔn)還在制定中。
- OpenFlow: 目前最新版本1.6,只有一個技術(shù)規(guī)范不足以支撐SDN生態(tài)(IETF有8000+ RFC)。
二、網(wǎng)絡(luò)和網(wǎng)絡(luò)之間的差異
上面論述了目前業(yè)界比較流行的幾種解決方案。首先我們要有這樣的共識:到目前為止網(wǎng)絡(luò)自動化尚沒有完美的解決方案。不同的業(yè)務(wù)模式和公司規(guī)模導(dǎo)致它的組網(wǎng)模式和組網(wǎng)技術(shù)差異很大。
另外,同樣是網(wǎng)絡(luò),ISP網(wǎng)絡(luò)(以中國電信的ChinaNet為例)主要是覆蓋全國甚至全球的Backbone(由所有POP和傳送網(wǎng)組成),以及提供接入線路可延伸到千家萬戶的城域網(wǎng)組成;云計算提供商(以AWS為例)則主要是在世界各地建立自營的大型互聯(lián)網(wǎng)數(shù)據(jù)中心,利用租用ISP的波分或裸光纖實現(xiàn)所有IDC互聯(lián);企業(yè)網(wǎng)絡(luò)則主要是由規(guī)模相對較小的Production backbone/IDC和用于公司總部、分部之間互聯(lián)的Corporation網(wǎng)絡(luò)構(gòu)成。
現(xiàn)階段可行的方案
這三類網(wǎng)絡(luò)擁有者對網(wǎng)絡(luò)自動化的需求是不一樣的。沒有任何一種網(wǎng)絡(luò)自動化方案可以適應(yīng)、解決所有網(wǎng)絡(luò)架構(gòu)。我這里提出的可行方案,是基于我公司的網(wǎng)絡(luò)具體現(xiàn)實而推薦的。
我公司的網(wǎng)絡(luò)屬于企業(yè)網(wǎng)絡(luò),有如下幾個特點:
- 網(wǎng)絡(luò)結(jié)構(gòu)穩(wěn)定,變化不頻繁,平均每年新增一個分支機構(gòu)。
- 每次網(wǎng)絡(luò)的調(diào)整內(nèi)容不復(fù)雜,Monitor由Solarwinds改為Observium后需要修改SNMP Community string, Netflow服務(wù)器由NFSEN改為Scrutinizer后需要修改Collector服務(wù)器地址。
- 面向公眾的大型數(shù)據(jù)中心已經(jīng)遷移到AWS,公司只維護一個用于企業(yè)內(nèi)部服務(wù)(人事、法律、財務(wù)數(shù)據(jù),和源代碼、郵件、AD/LDAP/RSA等)的小型Internal DC,網(wǎng)絡(luò)規(guī)模24個Rack, 不到40臺交換機。
- 網(wǎng)絡(luò)由多個廠家設(shè)備組成,包括Cisco, Juniper, F5, CheckPoint等。
基于上面的分析,我們平時的網(wǎng)絡(luò)運營維護最大的特點是依次登錄多臺設(shè)備進行重復(fù)性的操作,或者是在現(xiàn)有網(wǎng)絡(luò)平穩(wěn)運行的基礎(chǔ)上對部分功能進行增量配置。我們認(rèn)為采用Python結(jié)合Netmiko模塊是切實可行的,滿足現(xiàn)階段我們的需求。
三、Python和Netmiko介紹
這個方案是我公司的Best current practice。
Python是業(yè)界很流行的腳本語言,可讀性強,模塊和函數(shù)豐富,在網(wǎng)絡(luò)自動化方面有很多活躍社區(qū)作出貢獻。
Netmiko是一個開源Python模塊,由Kirk Byers(https://pynet.twb-tech.com/) 維護,所有源代碼和腳本、JSON文件、技術(shù)文檔和應(yīng)用范例都在GitHub上供借鑒和下載(https://github.com/ktbyers/netmiko) 。
Netmiko簡化了針對網(wǎng)絡(luò)設(shè)備的SSH管理功能,例如:
1. 支持不同廠家設(shè)備和同廠家不同平臺設(shè)備,成功建立SSH連接。
- 基于Cisco和Juniper CLI的差異性,自動隱性輸入enable, conft。
- 針對Cisco WLC,自動屏蔽login字符錄入。
2. 針對多廠家環(huán)境可順利執(zhí)行Enable模式的所有操作并將設(shè)備的交互信息反饋到執(zhí)行腳本的機器。
3. 針對多廠家環(huán)境可順利執(zhí)行Configure模式的所有操作并將設(shè)備的交互信息反饋到執(zhí)行腳本的機器。
基于上述特點,和我公司的具體需求,我們重點實現(xiàn)了場景1的網(wǎng)絡(luò)自動化,可以將自動化的實現(xiàn)高度提煉為如下的結(jié)構(gòu):
- Python script + command-set + device-group
編制兩個Python腳本,名字為enable.py和configure.py,分別代表執(zhí)行enable或configure模式下的腳本文件。每個腳本都可以調(diào)用兩個參數(shù),一個是命令集(command-set)要執(zhí)行的一組操作指令,另一個是設(shè)備組(device-group)即腳本要執(zhí)行的對象。我們還優(yōu)化了腳本,提供交互式的運行環(huán)境,用戶只需要鍵入腳本名稱,Python和Linux shell交互,自動詢問用戶需要執(zhí)行哪組命令,用戶進行選擇后腳本自動詢問需要執(zhí)行的目標(biāo)設(shè)備,用戶再次進行選擇后Python按腳本順序執(zhí)行,并將結(jié)果輸出到Linux服務(wù)器。
為了配合兩個不同腳本的執(zhí)行,我們還制定了一些文件名稱約定,命令集本質(zhì)上是txt文件,為了區(qū)分是enable還是configure模式,采用后綴名.enab和.conf來分別代表;Device-group必須采用Python字典數(shù)據(jù)結(jié)構(gòu),是JSON格式,可直接采用.json來代表。文件命名約定主要利于在Linux shell下與用戶交互時提供正確的輸出供用戶選擇。
腳本的執(zhí)行環(huán)境是一臺Linux 服務(wù)器,安裝PIP和Netmiko, 腳本中調(diào)用json, netmiko, sys, signal, os等模塊/函數(shù),實現(xiàn)需要的功能。此外import getpass實現(xiàn)通過用戶的AD帳號進行認(rèn)證來登錄目標(biāo)設(shè)備,并在Python輸出中隱藏用戶密碼。腳本中利用for loop來實現(xiàn)對命令集的逐行執(zhí)行和設(shè)備集的逐個登錄。
以下是enable.py的源代碼:
- #!/usr/bin/env python
- from __future__ import absolute_import, division, print_function
- from getpass import getpass
- import json
- import netmiko
- #from netmiko import ConnectHandler
- #from netmiko.cisco import CiscoIosBase (device type: "cisco_ios", "cisco_xe")
- #from netmiko.cisco import CiscoIosBase (device type: "cisco_xe")
- import sys
- import signal
- import os
- signal.signal(signal.SIGPIPE, signal.SIG_DFL) # IOError: Broken pipe
- signal.signal(signal.SIGINT, signal.SIG_DFL) # KeyboardInterrupt: Ctrl-C
- def get_input(prompt=''):
- try:
- line = raw_input(prompt)
- except NameError:
- line = input(prompt)
- return line
- def get_credentials():
- """Prompt for and return a username and password."""
- username = get_input('Username(Please input your adm credentials): ')
- password = getpass()
- return username, password
- netmiko_exceptions = (netmiko.ssh_exception.NetMikoTimeoutException,
- netmiko.ssh_exception.NetMikoAuthenticationException)
- username, password = get_credentials()
- os.system('find *.enab')
- os.system('echo')
- os.system('echo "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"')
- commandfile = raw_input("Please select what command you want to run: \n")
- os.system('find *.json')
- os.system('echo')
- os.system('echo "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"')
- devicegroup = raw_input("Please select what device-group you want to apply to: \n")
- with open(commandfile) as cmd_file:
- commands = cmd_file.readlines()
- with open(devicegroup) as dev_file:
- devices = json.load(dev_file)
- for device in devices:
- device['username'] = username
- device['password'] = password
- try:
- print('~' * 80)
- print('Connecting to device:', device['ip'])
- connection = netmiko.ConnectHandler(**device)
- for command in commands:
- print(connection.send_command(command))
- """To keep 2 lines space between 2 devices"""
- print()
- print()
- connection.disconnect()
- except netmiko_exceptions as e:
- print('Failed to ', device['ip'], e)
Python腳本一旦制定就不用頻繁更新,唯一需要維護的是command-set和device-group信息,因為每次的任務(wù)是不同的,包括需要批量執(zhí)行的操作指令不同,每次需要對哪些設(shè)備進行操作也是特定于任務(wù)的。這就要求腳本的具體執(zhí)行者需要對自己的操作編寫單獨的命令集和設(shè)備組文件。
例如我們要通過enable.py調(diào)用一組命令對lab中的所有設(shè)備依次執(zhí)行,device-group的文件如下(Python字典文件,Json格式):
- [
- {
- "ip": "lab-wan-isr4431-1",
- "device_type": "cisco_xe"
- },
- {
- "ip": "lab-wan-isr4431-2",
- "device_type": "cisco_xe"
- },
- {
- "ip": "lab-wan-c3650-1",
- "device_type": "cisco_xe"
- },
- {
- "ip": "lab-wan-c3650-2",
- "device_type": "cisco_xe"
- },
- {
- "ip": "lab-lan-c3850ss-1",
- "device_type": "cisco_xe"
- }
- ]
假定要對上面的每臺設(shè)備依次執(zhí)行show clock命令,.enab的內(nèi)容如下(txt格式):
- show clock
執(zhí)行結(jié)果將在執(zhí)行此腳本的Linux服務(wù)器上,以STD1 方式輸出如下:
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Connecting to device: lab-wan-isr4431-1
- 03:42:24.324 UTC Sat Apr 28 2018
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Connecting to device: lab-wan-isr4431-2
- 03:42:29.472 UTC Sat Apr 28 2018
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Connecting to device: lab-wan-c3650-1
- *03:40:15.780 UTC Sat Apr 28 2018
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Connecting to device: lab-wan-c3650-2
- *03:42:05.544 UTC Sat Apr 28 2018
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Connecting to device: lab-lan-c3850ss-1
- *03:42:45.277 UTC Sat Apr 28 2018
這里的例子中,command-set只有一條show clock命令,實際上可以由多條CLI命令進行任意組合,非常靈活。我在項目中已經(jīng)預(yù)先定義了一些命令集和設(shè)備組,連同Python腳本一并Push到GitHub Repository。同時在自己的Laptop上安裝了Pycharm IDE工具和GNS3網(wǎng)絡(luò)設(shè)備仿真環(huán)境,以及GitHub Desktop客戶端。利用這些工具,用戶可以在本地編輯腳本和配套文件,在虛擬網(wǎng)絡(luò)環(huán)境中驗證,并實現(xiàn)所有文檔的版本管理。
對于設(shè)備組的編寫我們最初希望能通過API或腳本的方式從現(xiàn)有網(wǎng)管系統(tǒng)自動Retrieve, 經(jīng)過研究個人覺得暫時還不可行。我公司現(xiàn)有RANCID/PI/Observium/IPAM等幾套系統(tǒng),首先是device-group的數(shù)據(jù)格式不一致,RANCID是TXT,PI是CVS, Observium是JSON,IPAM是專有格式。除了數(shù)據(jù)格式不同外,對Netmiko而言,最關(guān)鍵的信息是Device-type,這也是Netmiko支持跨平臺多廠家的最大優(yōu)勢所在,都是通過對設(shè)備類型的明確指定來指導(dǎo)SSH登錄設(shè)備后的操作細(xì)節(jié)。
前述的幾個系統(tǒng)要么沒有指定設(shè)備類型(例如PI默認(rèn)就只是Cisco, IPAM對設(shè)備類型根本不關(guān)注,Observium系統(tǒng)不對設(shè)備進行控制無需SSH登錄因此也沒有設(shè)備類型信息),要么設(shè)備類型信息粒度粗(RANCID對思科設(shè)備只有Cisco一類,但實際上思科設(shè)備可細(xì)分為IOS-XE, NX-OS, IOS-XR和IOS)。基于此,我們目前放棄了自動創(chuàng)建Device-group字典文件的想法。退一步講,即使我們通過腳本來自動創(chuàng)建一個json格式的device-group,我們?nèi)匀恍枰止ぶ付男┰O(shè)備歸屬到哪個組里面,人工參與程度并未降低,提高的效率有限。
四、其他需要考慮的問題
綜上所述,就是我們公司現(xiàn)在已經(jīng)實現(xiàn)的網(wǎng)絡(luò)自動化。由于網(wǎng)絡(luò)新增站點不頻繁,一年新增一處,對這種新增網(wǎng)絡(luò)的部署,也暫時決定不采用Ansible/Jinca2/Task/Variable來實現(xiàn),主要是不值得,我們有更簡單快捷的方式:拿一個現(xiàn)有站點的配置文件作為模板,對個性化的元素例如主機名、環(huán)回地址、SNMP location, BGP peer, OSPF area, Interface IP等進行修改,灌入設(shè)備,運抵現(xiàn)場,上電開通即可,不需要簡單問題復(fù)雜化。
另外要認(rèn)識到,網(wǎng)絡(luò)自動化第一宗旨是提高效率,對全網(wǎng)只有有限數(shù)量的VPN網(wǎng)關(guān),只設(shè)置在數(shù)據(jù)中心的LB,每個Site安全策略不具備共性的FW,沒有必要實行網(wǎng)絡(luò)自動化。
最后一點,我本人對網(wǎng)絡(luò)自動化還有些顧慮,就是潛在的風(fēng)險。畢竟一個腳本是對一組設(shè)備執(zhí)行一系列操作,萬一命令集配置有誤,有可能導(dǎo)致全網(wǎng)癱瘓。目前還沒有很完善的回退機制,一旦發(fā)生將是災(zāi)難性的結(jié)果。這也是為什么我在筆記本上安裝GNS3的原因,每次需要進行驗證,確保無誤后才能執(zhí)行。配套的管理流程也需要跟上,在Change工單上需要提交命令集和設(shè)備組的詳細(xì)信息,以備萬一需要回退,確定知道在哪些設(shè)備上回退哪些操作。
以上是結(jié)合我本人的工作實踐和項目研究總結(jié)的心得,網(wǎng)絡(luò)自動化是網(wǎng)絡(luò)行業(yè)的趨勢,網(wǎng)絡(luò)工程師無論喜歡與否,在大趨勢面前也只能順勢而為,否則就有被淘汰的危險。技術(shù)方案還在不斷進步,未來會有新的發(fā)展,即使是現(xiàn)有的手段,不同的公司也會有不同的推薦和實現(xiàn),希望我的文章能起到拋磚引玉的作用,我也非常希望和同行業(yè)的專家交流,對文章中內(nèi)容有不同觀點歡迎提出指正,相互學(xué)習(xí),共同提高。
胡捷,在國內(nèi)曾經(jīng)任職中國網(wǎng)通(CNC)、Verizon、Juniper 和中國電信。參與過中國電信 CN2 項目技術(shù)方案編寫和城域網(wǎng)優(yōu)化改造項目,以及中國電信 IPv6 研究和現(xiàn)網(wǎng)試驗。2014 年 6 月至今在舊金山一家互聯(lián)網(wǎng)公司從事網(wǎng)絡(luò)工程師職業(yè)。
【51CTO原創(chuàng)稿件,合作站點轉(zhuǎn)載請注明原文作者和出處為51CTO.com】