第3章
API和意圖驅動網絡
在第2章中,我們研究了使用Pexpect和Paramiko的網絡裝置進行互動的方式。這兩個工具都使用持久會話模拟使用者輸入指令,就好像他們自己坐在終端前面一樣。在某種程度上這起了很大的作用。是以,這使得在裝置上執行發出的指令和捕獲輸出變得足夠簡單。然而,當輸出超過數行字元時,使用計算機程式來解釋輸出就變得困難了。Pexpect和Paramiko的傳回輸出是一系列旨在被人類閱讀的字元。輸出的結構由行和空白組成,這些行和空白對人類是友好的但很難被計算機程式了解。
為了使我們的計算機程式能夠自動執行我們想要執行的許多任務,我們需要解釋傳回的結果并根據傳回的結果進行後續操作。當我們無法準确且可預測地解釋傳回的結果時,我們無法自信地執行下一個指令。
幸運的是,這個問題已經被網際網路社群解決了。想象一下計算機和人類在他們同時閱讀一個網頁時的差別。人類看到的是浏覽器解釋的文字、圖檔和空白;計算機可以看到原始HTML代碼、Unicode字元和二進制檔案。當網站需要成為另一台計算機的Web服務時會發生什麼?相同的Web資源需要适應人類客戶和其他計算機程式。這個問題聽起來不像我們之前介紹過的嗎?答案就是應用程式接口(API)。值得注意的是,根據維基百科,API是一個概念,而不是特定的技術或架構。
在計算機程式設計中,應用程式程式設計接口(API)是一組用于建構應用程式軟體的子例程定義、協定和工具。一般而言,它是一組定義明确的用于不同軟體元件間通信的方法。一個好的API可以通過提供所有建構塊來更容易地開發計算機程式,然後由程式員将它們組合在一起。
在我們的用例中,一組明确定義的通信方法将在我們的Python程式和目标裝置之間。網絡裝置的API為計算機程式提供單獨的接口。确切的API實作是特定于供應商的。一個供應商可能更喜歡基于JSON的XML,一些可能提供HTTPS作為底層傳輸協定,而另一些供應商可能提供Python庫作為包裝器。盡管存在差異,但API的概念仍然相同:它是針對其他計算機程式優化的獨立通信方法。
在本章中,我們将會看到下面幾個主題:
- 将基礎設施視作代碼、意圖驅動網絡和資料模組化。
- Cisco NX-API和以應用程式為中心的基礎設施。
- Juniper NETCONF和PyEZ。
- Arista eAPI和PyEAPI。
3.1 基礎設施作為代碼
在一個完美的世界中,設計和管理網絡的網絡工程師和架構師應該專注于他們希望網絡實作的目标,而不是裝置級别的互動。在我作為本地ISP實習生的第一份工作中,我的第一個任務是在客戶的網站上安裝路由器以打開他們的部分幀中繼鍊路(還記得嗎?)。我該怎麼辦?我問。接着我接到了一個标準的操作程式,用于打開幀中繼鍊路。我去了客戶現場,盲目地輸入了指令,看着綠燈閃爍,然後高高興興地收拾好行李,拍了拍自己的背部,做得很好。和第一次任務一樣令人興奮的是,我并不完全了解我在做什麼。我隻是按照說明而不考慮我輸入的指令的含義。如果燈是紅色而不是綠色,我将如何排除故障呢?我想我會打電話給辦公室求救。
當然,網絡工程不是要在裝置中輸入指令,而是建立一種方法,允許服務以盡可能少的摩擦從一個點傳遞到另一個點。我們必須使用的指令和我們必須解釋的輸出僅僅意味着結束。換句話說,我們應該關注我們對網絡的意圖。我們希望網絡實作的目标遠比用來使裝置完成我們希望它做的事情的指令文法更重要。如果我們進一步提取将我們的意圖描述為代碼行的想法,我們可以将整個基礎設施描述為特定狀态。在使用必要的軟體或架構來強制執行該狀态的情況下,以代碼來描述基礎結構。
3.1.1 意圖驅動網絡
自本書第1版出版以來,在主要網絡供應商選用基于意圖的網絡這一術語來描述下一代裝置之後,該術語的使用量有所增加。在我看來,意圖驅動網絡是定義一種狀态的方法并且網絡應該擁有軟體代碼來強制執行該狀态。例如,如果我的目标是阻止外界通路80端口,那就是我應該如何将其聲明為網絡的意圖。底層軟體将負責了解在邊界路由器上配置和應用必要的通路清單的文法,以實作該目标。當然,意圖驅動網絡是一個沒有明确答案的想法。但是這個想法很簡單明了,我認為應該把重點放在網絡的意圖上,并從裝置級的互動中抽象出來。
在使用API時,我認為它使我們更接近意圖驅動網絡的狀态。簡而言之,因為我們對在目标裝置上執行的特定指令的層進行抽象,我們專注于我們的意圖而不是特定的指令。例如,回到我們的block port 80通路清單示例,我們可能在Cisco上使用通路清單和通路組,在Juniper上使用過濾器清單。但是,在使用API時,我們的程式可以開始詢問執行程式的意圖,同時屏蔽它們正在與之交談的實體裝置類型。我們甚至可以使用更進階别的聲明性架構,例如Ansible,我們将在第4章中介紹。但就目前而言,讓我們專注于網絡API。
3.1.2 螢幕抓取與API結構化輸出
假設有一個常見的場景,我們需要登入到網絡裝置,并確定裝置上的所有接口都處于up/up狀态(狀态和協定都顯示為up)。對于進入Cisco NX-OS裝置的人工網絡工程師來說,在終端上發出show IP interface brief指令就足夠簡單了,從輸出的接口上就可以很容易地判斷出哪個接口是打開的:
行分隔符、空白和列标題的第一行很容易用人眼區分開來。實際上,它們是用來幫助我們将每個接口的IP位址從第一行排到第二行和第三行。如果我們把自己放在計算機的位置上,所有這些空格和換行隻會讓我們遠離真正重要的輸出,即:哪些接口處于up/up狀态?為了說明這一點,我們可以檢視相同操作的Paramiko輸出:
如果我們要解析這些資料,下面我将以僞代碼的方式來表示我所做的事情(我将編寫的代碼的簡化表示):
- 通過換行符分隔每一行。
- 我可能需要也可能不需要包含執行指令show ip interface brief的第一行。現在,我覺得我不需要它。
- 取出第二行的所有内容直到VRF,并将其儲存在變量中,因為我們想知道輸出顯示哪個VRF。
- 對于其餘的行,因為不知道有多少接口,我們将使用正規表達式語句來搜尋該行是否以可能的接口(例如lo環回接口和Eth以太網接口)開始。
- 我們需要通過空白将這一行分成三個部分,每個部分由接口名稱、IP位址和接口狀态組成。
-
然後使用正斜杠(/)進一步将接口狀态拆分為協定狀态、連結狀态和管理狀态。
這隻是為人們可以直接了解的事情而做的大量工作! 你可能能夠優化代碼和行數,但一般來說這就是當我們需要篩選非結構化的東西時需要做的事情。這個方法有許多缺點,但以下是我能看到的一些更大的問題:
- 可擴充性:在解析指令的細節上我們花了很多時間。很難想象如何才能啟動我們通常運作的上百個指令。
- 可預測性:實際上無法保證輸出在不同的軟體版本之間保持不變。 如果輸出稍有改變,就可能讓我們來之不易的資訊收集之戰變得毫無用處。
- 供應商和軟體鎖定:也許最大的問題是,一旦我們費力解析了這個特定供應商和軟體版本(比如Cisco NX-OS)的輸出,我們需要為下一個挑選的供應商重複這個過程。我不了解你,但如果我要評估一個新的供應商,如果我必須重寫所有螢幕代碼,供應商則處于嚴重的入職劣勢。
讓我們将它與同一個show IP interface brief指令的NX-API調用的輸出進行比較。我們在本章的後面部分将讨論從裝置擷取此輸出的細節,重要的是将以下輸出與以前的螢幕抓取輸出進行比較:
NX-API可以傳回XML或JSON格式的輸出,這是我們需要的JSON輸出。馬上,你可以看到結構化輸出,可以直接映射到Python字典資料結構。無須解析—你隻需選擇鍵并檢索與鍵關聯的值。你還可以從輸出中看到輸出中有各種中繼資料,例如指令的成功或失敗。如果指令失敗,會有一條消息告訴發送人失敗的原因。你不再需要跟蹤發出的指令,因為它在input字段中已經傳回給你了。輸出中還有其他有用的中繼資料,例如NX-API版本。
這種類型的轉換使供應商和營運商的生活更加輕松。在供應商方面,他們可以輕松傳輸配置和狀态資訊。如果需要暴露額外的東西,他們可以用相同的資料結構來添加額外的内容域。在營運商方面,他們可以輕松地擷取資訊并圍繞它建構基礎設施。使用者們普遍認為自動化是非常需要的,也是一件好事。問題通常以自動化的格式和結構為中心。正如你将在後面章節看到的那樣,API下有許多競争技術。僅在傳輸方面,我們有REST API、NETCONF和RESTCONF等。最終,整體市場可能會決定未來的最終資料格式。與此同時,我們每個人都可以形成自己的意見,并推動行業向前發展。
3.1.3 基礎設施的資料模組化作為代碼
根據維基百科(
https://en.wikipedia.org/wiki/Data_model),資料模型的定義如下:
資料模型是一種抽象模型,用于組織資料元素并标準化它們的互相關系及它們與現實世界實體的屬性的關系。例如,一個資料模型可以指定表示汽車的資料元素由多個其他元素組成,這些其他元素代表汽車的顔色和大小并定義其所有者。
資料模組化過程如下圖所示:
應用于網絡時,無論是資料中心,校園還是全球廣域網,我們可以将此概念應用于我們描述的網絡抽象模型。如果仔細檢視實體資料中心,我們可以将第2層以太網交換機視為包含每個端口的MAC位址映射表的裝置。我們的交換機資料模型描述了如何将MAC位址儲存在表中,其中包括密鑰、附加特性(考慮VLAN和專用VLAN)等。同樣,不局限于裝置,我們可以将整個資料中心映射到模型中。我們可以從每個通路層、分發層和核心層中的裝置數量、它們如何連接配接以及它們在生産環境中的行為方式開始。例如,如果我們有一個fat-tree網絡,每個主幹路由器應該有多少連結,它們應該包含多少路由,以及每個字首應該有多少個下一跳?這些特征被映射為我們應該經常檢查的理想狀态所引用的一種格式。
其中一種相對較新的網絡資料模組化語言Yet Another Next Generation(YANG)正在引起關注(盡管一般認為一些IETF工作組确實有幽默感)。它于2010年首次在RFC 6020中釋出,并且随後在供應商和營運商中獲得了關注。在撰寫本文時,從供應商到平台,對YANG的支援差異很大。是以生産中的适應率相對較低。但是,這是一項值得關注的技術。
3.2 Cisco API和Cisco ACI
Cisco系統公司,網絡領域的重量級公司,沒有錯過網絡自動化的趨勢。它在推動網絡自動化方面取得了成功,它進行了各種内部開發、産品增強、合作夥伴關系建立以及許多外部收購。但是,産品線包括路由器、交換機、防火牆、伺服器(統一計算)、無線、協作軟體和硬體以及分析軟體,僅舉幾例,很難知道從哪裡開始。
由于本書側重于Python和網絡,我們将把這一部分作為主要網絡産品。特别是,我們将涵蓋以下内容:
- 使用NX-API進行Nexus産品自動化。
- Cisco NETCONF和YANG的示例。
- Cisco以應用程式為中心的資料中心基礎設施。
- 面向企業的Cisco以應用程式為中心的基礎設施。
對于此處的NX-API和NETCONF示例,我們可以在實驗室裝置上始終使用Cisco DevNet,也可以在本地運作Cisco VIRL。由于ACI是一個單獨的産品并獲得了對于以下ACI示例的實體交換機的許可,我建議使用DevNet實驗了解這些工具。如果你是幸運的工程師之一,有一個你可以使用的私人ACI實驗室,請随意使用它作為相關的示例。
我們将使用與第2章中所做的類似的實驗拓撲,但運作nx-osv的裝置除外:
我們來看看NX-API。
3.2.1 Cisco NX-API
Nexus是Cisco資料中心交換機的主要産品線。NX-API(
http://www.cisco.com/c/en/us/td/docs/switches/datacenter/nexus9000/sw/6-x/programmability/guide/b_Cisco_Nexus_9000_Series_NXOS_Programmability_Guide/b_Cisco_Nexus_9000_SeriesNX-OS_Programmability_Guide_chapter_011.html)允許工程師與在裝置外部的交換機通過各種傳輸(包括SSH,HTTP和HTTPS)進行互動。
3.2.1.1 實驗軟體安裝和裝置準備
以下是我們将安裝的Ubuntu軟體包。你可能已經有了一些pip和git這樣的包:
提示:如果你使用的是Python 2,請改用以下軟體包:sudo apt-get install -y python-dev libxml2-dev libxslt1-devlibffi-dev libssl-dev zlib1g-dev python-pip git python requests。
ncclient(
https://github.com/ncclient/ncclient)庫是一個Python庫,用于NETCONF用戶端。我們将從GitHub倉庫安裝它,以便我們可以安裝最新版本:
Nexus裝置上的NX-API預設關閉,是以我們需要将其打開。我們要麼使用已建立的使用者(如果你使用的是VIRL自動配置),要麼建立一個NETCONF程式的新使用者:
對于我們的實驗,我們将打開HTTP和沙箱配置,因為它們在生産中應該是關閉的:
現在準備檢視我們的第一個NX-API示例。
3.2.1.2 NX-API示例
NX-API沙箱是一種很好的使用各種指令、資料格式,甚至直接從網頁上複制Python腳本的方式。在最後一步中,我們出于學習的目的打開了它。它應該在生産中關閉。讓我們啟動一個網絡浏覽器并根據我們已經熟悉的CLI指令檢視各種消息格式、請求和響應:
在以下示例中,我為show version指令選擇了JSON-RPC和CLI指令類型:
如果你不确定消息格式的可支援性,或者如果你對需要在你的代碼中檢索的值的響應資料字段鍵有疑問,沙箱會派上用場。
在我們的第一個例子中,我們隻是連接配接到Nexus裝置并列印出來首次建立連接配接時交換的功能:
主機、端口、使用者名和密碼的連接配接參數是非常明顯的。裝置參數指定用戶端連接配接的裝置類型。使用ncclient庫時,我們将在Juniper NETCONF部分中看到不同的響應。hostkey_verify繞過SSH的known_host要求;如果沒有,那麼主機需要列在~/.ssh/known_hosts檔案中。look_for_keys選項禁用公鑰–私鑰驗證,但使用使用者名和密碼認證。
警告:如果你遇到
https://github.com/paramiko/paramiko/issues/748使用Python 3和Paramiko的問題,請随意使用Python 2。希望在你閱讀本節時,問題已經解決。
輸出将顯示此版本NX-OS支援的XML和NETCONF功能:
在SSH上使用ncclient和NETCONF非常棒,因為它讓我們更接近本機實作和文法。我們稍後将使用相同的庫。對于NX-API,處理HTTPS和JSON-RPC可能更容易。在早期的NX-API Developer Sandbox截圖中,在Request框中,有一個标記為Python的框。如果單擊它,你将能夠獲得基于請求庫的自動轉換的Python腳本。
警告:以下腳本使用名為requests的外部Python庫。它是一個非常流行的、自稱為面向人類的HTTP庫,被亞馬遜、谷歌、NSA等公司使用。你可以找到有關它的更多資訊,請通路官方網站(
http://docs.python-requests.org/en/master/)。
對于show version示例,将自動為你生成以下Python腳本。我粘貼在輸出中而沒有做任何修改:
在cisco_nxapi_2.py腳本中,你将看到我隻修改了前面檔案的URL、使用者名和密碼。輸出被解析為僅包括軟體版本。這裡是輸出:
使用此方法的最佳部分是相同的整體文法結構用于配置指令以及show指令。cisco_nxapi_3.py檔案說明了這一點。對于多行配置,你可以使用ID字段指定操作順序。在cisco_nxapi_4.py中,列出了以下有效内容以更改接口配置模式下接口Ethernet 2/12的描述:
我們可以通過檢視Nexus裝置的運作配置情況來驗證上一個配置腳本的結果:
在下一節中,我們将檢視Cisco NETCONF和YANG的一些示例模型。
3.2.2 Cisco和YANG模型
在本章的前面,我們讨論了使用資料模組化語言YANG表示網絡的可能性。我們再來看一些例子。
首先,我們應該知道,YANG模型隻定義通過NETCONF協定發送的資料類型,而沒有規定資料應該是什麼。其次,值得指出的是,NETCONF是作為獨立協定存在的,正如我們在NX-API部分看到的那樣。相對較新的YANG在供應商和産品線之間的可移植性參差不齊。例如,如果我們運作以前用于運作IOS-XE的Cisco 1000v的功能交換腳本,我們将看到:
将其與我們看到的NX-OS的輸出進行比較。顯然,IOS-XE比NX-OS更支援YANG模型的特性。當支援全行業的網絡資料模組化時,它顯然可以跨裝置使用,這有利于網絡自動化。但是,在我看來,由于供應商和産品的支援不均衡,它還不夠成熟,不能完全用于生産網絡。對于本書,我包含了一個名為cisco_yang_1.py的腳本。它展示了如何使用名為urn:ietf:params:xml:ns:yang:ietf-interfaces的YANG過濾器解析NETCONF XML的輸出,作為檢視現有标記覆寫的起點。
警告:你可以在YANG GitHub項目頁面上檢視最新的供應商支援
(
https://github.com/YangModels/yang/tree/master/vendor3.2.3 Cisco ACI
Cisco應用程式中心基礎設施(ACI)旨在為所有網絡元件提供中心化的方法。在資料中心上下文中,它意味着集中控制器知道并管理機架交換機的主幹、葉片和頂部,以及所有的網絡服務功能。這可以通過GUI、CLI或API實作。一些人可能認為ACI是Cisco對更廣泛的基于控制器的軟體定義網絡的回答。
ACI和APIC-EM之間的差異是ACI中比較令人困惑的一點。簡而言之,ACI側重于資料中心操作,而APIC-EM側重于企業子產品。兩者都提供了對網絡元件的集中視圖和控制,但是它們都有自己的焦點和工具集的共享。例如,很少有大型資料中心面向客戶的無線基礎設施部署,但是無線網絡是當今企業的關鍵部分。另一個例子是不同的網絡安全方法。雖然安全在任何網絡中都很重要,但是在資料中心環境中,為了可伸縮性,許多安全政策被推送到伺服器上的邊緣節點。在企業安全中,政策在網絡裝置和伺服器之間共享。
與NETCONF RPC不同,ACI API遵循REST模型,使用HTTP動詞(GET、POST、DELETE)指定需要的操作。
警告:我們可以看看cisco_apic_em_1.py檔案,它是Cisco示例代碼上的一個修改版本lab2-1-get-network-device-list.py (
https://github.com/CiscoDevNet/apicem-1.3-LL-sample-codes/blob/master/basic-labs/lab2-1-get-network-device-list.py)。
以下部分列出了不帶注釋和空格的縮略版本。
第一個名為getTicket()的函數在控制器上使用HTTPS POST,其路徑為/api/v1/ticket,頭部嵌入使用者名和密碼。此函數将傳回解析後的響應作為憑證,它僅在有限的時間内有效:
然後,第二個函數調用另一個路徑/api/v1/network-devices,将新獲得的票據嵌入到頭部中,然後解析結果:
這是一個非常常見的API互動工作流。用戶端将在第一個請求中使用伺服器進行身份驗證,并接收一個基于時間的令牌。此令牌将在後續請求中使用,并作為身份驗證的證明。
輸出同時顯示了原始JSON響應輸出和解析表。對DevNet實驗控制器執行時的部分輸出如下所示:
如你所見,我們隻查詢單個控制器裝置,但是我們能夠獲得控制器所知道的所有網絡裝置的進階視圖。在我們的輸出中,Catalyst 2960-C交換機、3500 Access Points、4400 ISR路由器和5500 Wireless Controller都可以進一步研究。當然,缺點是ACI控制器目前隻支援Cisco裝置。
3.3 Juniper網絡的Python API
Juniper網絡一直是服務提供商的寵兒。如果我們回頭看一下垂直的服務提供商,就會發現自動化網絡裝置是其首要需求。在運級别資料中心出現之前,服務提供商擁有最多的網絡裝置。一個典型的企業網絡可能在公司總部有一些備援的網際網路連接配接,使用服務提供商的私有MPLS網絡将一些輪輻式遠端站點連接配接回總部。對于服務提供商,它們需要建構、提供、管理和故障排除連接配接和底層網絡。它們通過出售帶寬和增值的托管服務來賺錢。對于服務提供商來說,投資于自動化以用最少的工程時間來保持網絡的運轉是有意義的。在它們的用例中,網絡自動化是它們競争優勢的關鍵。
在我看來,服務提供商的網絡需求與雲資料中心之間的差別在于,傳統上,服務提供商将更多的服務聚合到一個裝置中。一個很好的例子是多協定标簽交換(MPLS),幾乎所有主要的服務提供商都提供這種交換,但是很少在企業或資料中心網絡中使用。Juniper,作為一個非常成功的公司,已經發現了這一需求,并擅長于滿足自動化服務提供商的需求。讓我們看看Juniper的一些自動化API。
3.3.1 Juniper和NETCONF
網絡配置協定(NETCONF)是一種IETF标準,2006年首次釋出為RFC 4741,後來在RFC 6241中進行了修訂。Juniper網絡對這兩個RFC标準都做出了重大貢獻。事實上,Juniper是RFC 4741的唯一作者。Juniper裝置完全支援NETCONF是有道理的,它是大多數自動化工具和架構的底層。NETCONF的一些主要特征包括:
- 它使用可擴充标記語言(XML)進行資料編碼。
- 它使用遠端過程調用(RPC),是以在HTTP(s)作為傳輸的情況下,URL端點是相同的,而預期的操作是在請求體中指定的。
- 它從上到下是基于層的概念。這些層包括内容、操作、消息和傳輸:
Juniper網絡在它的技術庫裡提供了一個廣泛的NETCONF XML管理協定開發指南(
https://www.juniper.net/techpubs/en_US/junos13.2/information-products/pathway-pages/netconf-guide/netconf.html#overview)。讓我們看一下它的用法。
3.3.1.1 裝置準備
為了開始使用NETCONF,讓我們建立一個單獨的使用者,并打開所需的服務:
警告:對于Juniper裝置實驗,我使用的是一個較老的、不受支援的平台,名為Juniper Olive。僅供實驗使用。你可以用你最喜歡的搜尋引擎找到一些關于Juniper Olive的有趣的事實和曆史。
在Juniper裝置上,你總是可以以平面檔案或XML格式檢視配置。當你需要指定一行指令來進行配置更改時,平面檔案非常有用:
當你需要檢視配置的XML結構時,XML格式非常有用:
我們已經在Cisco部分安裝了必要的Linux庫和ncclient Python庫。如果你還沒有這樣做,請參閱該部分并安裝必要的包。
現在,我們準備看第一個Juniper NETCONF示例。
3.3.1.2 Juniper NETCONF示例
我們将使用一個非常簡單的示例來執行show version。我們将這個檔案命名為junos_netcon_1.py:
除了device_params之外,腳本中的所有字段都應該是非常容易了解的。從ncclient 0.4.1開始,添加了裝置處理程式來指定不同的供應商或平台。例如,名稱可以是juniper、CSR、Nexus或華為。我們還添加了hostkey_verify=False,因為我們使用的是Juniper裝置的自簽名證書。
傳回的輸出是用XML編碼的rpc-reply,并帶有一個output元素:
我們可以将XML輸出解析為隻包含輸出文本:
在junos_netconf_2.py中,我們将對裝置進行配置更改。我們将從一些新的導入開始,以建構新的XML元素和連接配接管理對象:
我們将鎖定配置并進行配置更改:
在建構配置部分中,我們使用host-name和domain-name的子元素建立了一個新的system元素。如果你想知道層次結構,可以從XML顯示中看到,system的節點結構是host-name和domain-name的父節點:
建構配置之後,腳本将增加配置并送出配置更改。以下是Juniper配置更改的正常最佳實踐步驟(鎖、配置、解鎖、送出):
總的來說,NETCONF步驟很好地映射到你在CLI步驟中應該做的事情。請檢視junos_netcon_3.py腳本,以獲得更多可重用代碼。下面的示例将一些逐漸完成的例子與一些Python函數結合起來:
這個檔案可以自己執行,也可以導入以供其他Python腳本使用。
Juniper還提供了一個Python庫,用于它們的裝置PyEZ。在下一節中,我們将檢視一些使用該庫的示例。
3.3.2 開發者的Juniper PyEZ
PyEZ是一個進階Python實作,可以更好地與現有Python代碼內建。通過使用Python API,你可以在不了解Junos CLI的情況下執行常見操作和配置任務。
提示:Juniper在
https://www.juniper.net/techpubs/en_US/junos-pyez1.0/information-products/pathway-pages/junos-pyez-developer-guide.html#configuration的技術庫中維護了一個全面的Junos PyEZ開發指南。如果你對使用PyEZ感興趣,我強烈建議你至少浏覽一下指南中的各個主題。
3.3.2.1 安裝和準備
在安裝Junos PyEZ時可以找到每個作業系統的安裝說明頁面(
https://www.juniper.net/techpubs/en_US/junos-pyez1.0/topics/task/installation/junos-pyez-server-installing.html)我們将展示Ubuntu 16.04的安裝說明。
以下是一些依賴包,由于運作之前的示例其中許多包應該已經在主機上了:
PyEZ包可以通過pip安裝。在這裡,我為python 3和Python 2安裝:
在Juniper裝置上,NETCONF需要配置為PyEZ的底層XML API:
對于使用者身份驗證,我們可以使用密碼身份驗證或SSH密鑰對。建立本地使用者很簡單:
對于ssh密鑰身份驗證,首先在主機上生成密鑰對:
預設情況下,公鑰名為id_rsa.pub。公匙在~/.ssh/之下,而私鑰将在同一個目錄下命名為id_rsa。将私鑰視為你永遠不會分享的密碼。公鑰可以自由分發。在我們的用例中,我們将公鑰移到/tmp目錄,并啟用Python 3 HTTP伺服器子產品建立一個可通路的URL:
提示:對于Python 2,使用python -m SimpleHTTPServer代替。
在Juniper裝置上,我們可以通過從python 3 Web伺服器下載下傳公鑰來建立使用者并關聯公鑰:
現在,如果我們嘗試使用管理站的私鑰ssh,使用者将自動驗證:
讓我們確定這兩種身份驗證方法都與PyEZ一起工作。讓我們試試使用者名和密碼組合:
我們還可以嘗試使用SSH密鑰身份驗證:
太棒了!現在我們準備看一些PyEZ的示例。
3.3.2.2 PyEZ示例
在前面的互動提示中,我們已經看到,當裝置連接配接時,對象自動檢索關于裝置的一些事實。在我們的第一個示例junos_pyez_1.py中,我們連接配接到裝置,對show interface em1執行RPC調用:
裝置類具有rpc屬性,該屬性包含所有操作指令。這非常棒,因為我們在CLI中所能做的事情相較于API沒有下滑。問題是我們需要找到xml rpc元素标記。在第一個示例中,我們如何知道show interface em1等于get_interface_information?我們有三種方法可以找到此資訊:
- 我們可以引用供開發人員參考的Junos XML API。
- 我們可以使用CLI并顯示等效的XML RPC,并将單詞之間的短橫線(-)替換為下劃線(_)。
-
我們還可以通過使用PyEZ庫以程式設計的方式實作這一點。
我通常使用第二個選項直接獲得輸出:
這裡有一個使用PyEZ程式設計的示例(第三個選項):
當然,我們還需要更改配置。在junos_pyez_2.py配置示例中,我們将從PyEZ導入一個額外的Config()方法:
我們将使用相同的塊連接配接到一個裝置:
new Config()方法将加載XML資料并進行配置更改:
PyEZ示例的設計非常簡單。希望它們能夠展示如何利用PyEZ滿足Junos自動化的需求。
3.4 Arista Python API
Arista網絡一直緻力于大規模的資料中心網絡。在公司簡介頁面(
https://www.arista.com/en/company/company-overview)這樣描述它:
“Arista網絡建立的目的是為大型資料中心存儲和計算環境提供軟體驅動的雲網絡解決方案。”
請注意,該聲明特别提到了大型資料中心,我們已經知道這些資料中心由伺服器、資料庫和網絡裝置組成。自動化一直是Arista的主要特性之一,這是有道理的。事實上,Linux背後支援它們的作業系統,允許許多附加的好處,比如Linux指令和内置的Python解釋器。
與其他供應商一樣,你可以通過eAPI直接與Arista裝置互動,也可以選擇利用它們的Python庫。我們将看到兩者的例子。在後面的章節中,我們還将讨論Arista與Ansible架構的內建。
3.4.1 Arista eAPI管理
Arista的eAPI是在幾年前在EOS 4.12中首次引入的。它通過HTTP或HTTPS傳輸顯示或配置指令清單,并以JSON響應。一個重要的差別是,它是遠端過程調用(RPC)和JSON-RPC,而不是通過HTTP或HTTPS服務的純RESTFul API。對于我們的意圖和目的,差別在于我們使用相同的HTTP方法(POST)向相同的URL端點送出請求。我們不使用HTTP動詞(GET、POST、PUT、DELETE)來表示我們的操作,而是在請求體中聲明我們想要的操作。對于eAPI,我們将為我們的意圖指定一個具有runCmds值的method鍵。
對于以下示例,我使用的是運作EOS 4.16的Arista實體交換機。
3.4.1.1 eAPI準備
在預設情況下,Arista裝置上的eAPI代理是被禁用的,是以在裝置上,需要在使用它之前啟用它:
正如所見,我們已關閉HTTP伺服器,而是使用HTTPS作為唯一的傳輸。從幾個EOS版本之前開始,管理接口預設置于名為management的VRF中。在我的拓撲中,我通過管理界面通路裝置,是以,我已經為eAPI管理指定了VRF。你可以通過“show management api http-commands”指令檢查API管理狀态:
啟用代理後,你可以通過轉到裝置的IP位址來通路eAPI的探索頁面。如果你更改了預設端口以進行通路,則隻需将其附加到最後。身份驗證與交換機上的身份驗證方法相關聯。我們将使用裝置上本地配置的使用者名和密碼。預設情況下,将使用自簽名證書:
你将進入一個資料總管頁面,你可以在其中鍵入CLI指令,并為你的請求正文擷取一個不錯的輸出。例如,如果我想看看如何為show version建立一個請求體,這是我将在資料總管中看到的輸出:
概述連結将帶你到示例使用和背景資訊,而指令文檔将作為show指令的參考點。每個指令引用都将包含傳回值的字段名稱、類型和簡要說明。來自Arista的線上參考腳本使用jsonrpclib(
https://github.com/joshmarshall/jsonrpclib/),這是我們将使用的。但是,截至編寫本書時,它依賴于Python 2.6+并且還沒有移植到Python 3,是以,在這些示例中我們将使用Python 2.7。
提示:當你閱讀本書時,可能會有更新的狀态。請閱讀GitHub拉取請求(
https://github.com/joshmarshall/jsonrpclib/issues/38)和GitHub README檔案(
)擷取最新狀态。
使用easy_install或pip直接安裝:
3.4.1.2 eAPI示例
然後我們可以編寫一個名為eapi_1.py的簡單程式來檢視響應文本:
請注意,由于這是Python 2,在腳本中,我使用了from__future__import print_function使未來的遷移變得更容易。與ssl相關的行适用于2.7.9之後的Python版本。欲獲得更多資訊,請參閱
https://www.python.org/dev/peps/pep-0476/。
這是我從之前的runCms()方法收到的響應:
如你所見,結果是包含一個字典項的清單。如果我們需要擷取序列号,我們可以簡單地引用項目編号和密鑰:
輸出将僅包含序列号:
為了熟悉指令參考,我建議你點選eAPI頁面上的Command Documentation連結,并将你的輸出與文檔中show version的輸出進行比較。
如前所述,與REST不同,JSON-RPC用戶端使用相同的URL端點來調用伺服器資源。你可以從前面的示例中看到runCmds()方法包含指令清單。要執行配置指令,可以遵循相同的架構,并通過指令清單配置裝置。
以下是名為eapi_2.py的配置指令示例。在示例中,我們編寫了一個函數,它将switch對象和指令清單作為屬性:
以下是指令執行的輸出:
現在,快速檢查交換機以驗證指令的執行:
總的來說,eAPI非常簡單易用。大多數程式設計語言都有類似jsonrpclib的庫,它們抽象出JSON-RPC内部。通過一些指令,你可以開始将Arista EOS自動化內建到你的網絡中。
3.4.2 Arista Pyeapi庫
Python用戶端Pyeapi(
http://pyeapi.readthedocs.io/en/master/index.html)庫是eAPI的原生Python庫包裝器。它提供了一組綁定來配置Arista EOS節點。當我們已經擁有eAPI時,為什麼我們需要Pyeapi呢?如果你在Python環境中,Pyeapi與eAPI之間的挑選主要是通過主觀判斷。
但是,如果你處于非Python環境中,那麼eAPI可能就是你的選擇。從我們的示例中,你可以看到eAPI的唯一要求是支援JSON-RPC的用戶端。是以,它與大多數程式設計語言相容。當我第一次使用時,Perl是腳本和網絡自動化的主要語言。仍有許多企業依賴Perl腳本作為主要的自動化工具。如果公司已投入大量資源并且代碼庫使用的語言不是Python,使用JSON-RPC的eAPI将是一個不錯的選擇。
但是,對于我們這些喜歡使用Python編寫代碼的人來說,原生Python庫在編寫代碼時意味着更自然的感覺。它當然使擴充Python程式更容易支援EOS節點。它還使得更容易跟上Python的最新變化。例如,我們可以使用Python 3和Pyeapi!
警告:在編寫本書時,官方宣稱Python 3(3.4+)的支援正在進行中,如文檔(
http://pyeapi.readthedocs.io/en/master/requirements.html)中所述。請檢視文檔以擷取更多詳細資訊。
3.4.2.1 Pyeapi安裝
使用pip安裝很簡單:
警告:請注意,pip還将安裝netaddr庫,因為它是Pyeapi規定的要求(
)的一部分。
預設情況下,Pyeapi用戶端将在你的主目錄中查找名為eapi.conf的隐藏(前面有句點)INI樣式檔案。你可以通過指定eapi.conf檔案路徑來覆寫此行為,但通常最好将連接配接憑據分開并将其從腳本本身鎖定。你可以通過檢視Arista Pyeapi文檔(
http://pyeapi.readthedocs.io/en/master/configfile.html#configfile),找到那些包含在檔案中的字段。這是我在實驗中使用的檔案:
第一行[connection:Arista1]包含我們将在Pyeapi連接配接中使用的名稱;其餘的字段應該是不言自明的。你可以為使用此檔案使用者将檔案鎖定為隻讀:
3.4.2.2 Pyeapi示例
現在,我們準備好了解一下使用情況。讓我們首先通過在互動式Python shell中建立一個對象來連接配接到EOS節點:
我們可以對節點執行show指令并接收輸出:
配置字段可以是單個指令,也可以是使用config()方法的指令清單:
請注意,指令縮寫(show run與show running-config)和一些擴充将不起作用:
但是,你始終可以捕獲結果并獲得所需的值:
到目前為止,我們一直在使用eAPI執行顯示和配置指令。Pyeapi提供各種API,讓生活更輕松。在以下示例中,我們将連接配接到節點,調用VLAN API,并開始操作裝置的VLAN參數。讓我們來看看:
讓我們驗證是否在裝置上建立了VLAN 10:
正如你所看到的,EOS對象上的Python原生API實際上是Pyeapi優于eAPI的地方。它将較低級别的屬性抽象到裝置對象中,使代碼更清晰,更易于閱讀。
警告:有關不斷增加的Pyeapi API的完整清單,請檢視官方文檔(
http://pyeapi.readthedocs.io/en/master/api_modules/_list_of_modules.html為了完善本章,假設我們重複前面的步驟足夠多次,以便編寫另一個Python類來為我們節省一些工作。
pyeapi_1.py腳本如下所示:
從腳本中可以看出,我們會自動連接配接到節點并在連接配接時設定hostname和running_config。我們還為使用VLAN API建立VLAN的類建立了一種方法。讓我們在互動式shell中試用腳本:
3.5 廠商中立的庫
像Netmiko(
https://github.com/ktbyers/netmiko)、NAPALM(
https://github.com/napalm-automation/napalm)這樣的與供應商無關的庫已經做出了一些傑出的努力。由于這些庫并非來自裝置供應商,是以有時它們在支援最新平台或特性方面會慢一些。但是,由于庫是與供應商無關的,如果你不喜歡将工具鎖定在供應商,那麼這些庫是一個不錯的選擇。使用這些庫的另一個好處是它們通常是開源的,是以你可以向上貢獻新特性和缺陷修複。
另一方面,由于這些庫是社群支援的,如果你需要依賴其他人來修複缺陷或實作新特性,那麼它們不一定是理想的選擇。如果你有一個相對較小的團隊,仍然需要為你的工具遵守某些服務水準保證,那麼你最好使用供應商支援的庫。
3.6 小結
在本章中,我們研究了來自Cisco、Juniper和Arista的各種通信和管理網絡裝置的方法。我們研究了與NETCONF和REST等的直接通信,以及使用供應商提供的庫(如PyEZ和Pyeapi)。這些是不同的抽象層,旨在提供一種無須人工幹預就可以以程式設計方式管理網絡裝置的方法。
在第4章中,我們将研究一個更高層次的與供應商無關的抽象架構Ansible。Ansible是一個用Python編寫的開源、通用的自動化工具。它可以用于自動化伺服器、網絡裝置、負載平衡器等。當然,出于我們的目的,我們将重點介紹如何将這個自動化架構用于網絡裝置。