絡(luò)拓?fù)渑渲梦募稍O(shè)備配置)
簡(jiǎn)介壓縮包內(nèi)的docx文檔是一份企業(yè)網(wǎng)絡(luò)設(shè)計(jì)與仿真實(shí)現(xiàn)中的網(wǎng)絡(luò)拓?fù)渑渲梦募嫦蛴?jì)算機(jī)網(wǎng)絡(luò)課程學(xué)習(xí)者、實(shí)驗(yàn)實(shí)訓(xùn)人員及網(wǎng)絡(luò)運(yùn)維新手解決交換機(jī)分層配置無(wú)從下手的問(wèn)題。包內(nèi)共1個(gè)docx文件約1.43MB內(nèi)容完整覆蓋接入層與核心層交換機(jī)的核心配置。文檔以技術(shù)部接入交換機(jī)為例從設(shè)置主機(jī)名、配置enable secret和VTY口令、設(shè)置exec-timeout與關(guān)閉DNS解析入手逐步展開(kāi)VTP客戶端模式、管理VLAN地址、訪問(wèn)端口VLAN劃分、Trunk主干道封裝以及MAC地址與端口綁定的防ARP欺騙策略同時(shí)包含兩臺(tái)核心交換機(jī)的VLAN信息與命名配置。讀者可以參照分步說(shuō)明在仿真拓?fù)渲袕?fù)現(xiàn)并排查配置理解每條命令的作用。已有2500人瀏覽學(xué)習(xí)適合需要完成課程設(shè)計(jì)、畢業(yè)設(shè)計(jì)或企業(yè)網(wǎng)絡(luò)配置實(shí)踐的讀者下載參考。1. 配套的網(wǎng)絡(luò)拓?fù)渑渲梦募?docx交付物不是附件拿到一個(gè)叫「配套的網(wǎng)絡(luò)拓?fù)渑渲梦募?docx」的文件很多人的第一反應(yīng)是打開(kāi)看一眼拓?fù)浣Y(jié)構(gòu)示意圖。但真正干過(guò)交付的人都知道圖片只是入口價(jià)值在它背后那套能和設(shè)備配置對(duì)上的信息接口、VLAN、IP、路由、安全策略。下面來(lái)把這個(gè) docx 當(dāng)作網(wǎng)絡(luò)項(xiàng)目的單一事實(shí)來(lái)源讓文檔里的表格能被腳本讀取、轉(zhuǎn)成設(shè)備配置、再和 running-config 比對(duì)。適合正在做園區(qū)網(wǎng)絡(luò)交付、機(jī)房割接、日常巡檢的人不需要很強(qiáng)的開(kāi)發(fā)經(jīng)驗(yàn)但你手邊得有一個(gè)能跑 Python 的終端環(huán)境。2. 拓?fù)鋱D到配置的一致性網(wǎng)絡(luò)拓?fù)渑渲梦募?docx 里該放哪些信息2.1 一份可用的網(wǎng)絡(luò)拓?fù)渑渲梦募?docx 該包含哪些表在動(dòng)手寫腳本之前先定義「配套」到底配套到什么程度。一份能支撐配置生成和比對(duì)的 docx至少要有下面這幾張表缺任何一張都會(huì)在生成配置或排障時(shí)露出破綻。表名關(guān)鍵字段缺了它會(huì)發(fā)生什么設(shè)備清單設(shè)備名、型號(hào)、角色、管理地址腳本不知道有哪些設(shè)備生成和巡檢都無(wú)從談起接口連接表本端設(shè)備/接口、對(duì)端設(shè)備/接口、鏈路類型拓?fù)鋱D上有線配置里沒(méi)有端口對(duì)排障全靠猜VLAN 規(guī)劃表VLAN ID、名稱、三層網(wǎng)關(guān)、DHCP 網(wǎng)段交換機(jī) VLAN 建不全終端拿不到正確網(wǎng)段IP 編址表接口名、IP 地址、掩碼、描述接口地址只能手填最容易寫錯(cuò)路由參數(shù)協(xié)議、區(qū)域/進(jìn)程號(hào)、宣告網(wǎng)段、認(rèn)證方式OSPF 區(qū)域或靜態(tài)路由優(yōu)先級(jí)不一致業(yè)務(wù)路徑不符合設(shè)計(jì)公共服務(wù)NTP、SNMP、syslog 地址與安全參數(shù)設(shè)備時(shí)間不一致日志無(wú)法集中告警少了一半這些表不需要一次做全但必須從第一天就有空表殼。否則等工程收尾再補(bǔ)數(shù)據(jù)沒(méi)人愿意填文檔很快就會(huì)和設(shè)備脫節(jié)。2.2 為什么「能對(duì)上」比「畫得全」更重要「大型園區(qū)網(wǎng)絡(luò)拓?fù)浼芭渲脤?shí)例」這類資料大家應(yīng)該都看過(guò)拓?fù)浣Y(jié)構(gòu)示意圖長(zhǎng)得差不多核心、匯聚、接入三層下面掛著服務(wù)器區(qū)和辦公區(qū)。圖里不會(huì)告訴你的恰恰是要敲進(jìn)設(shè)備的命令。舉個(gè)例子核心和匯聚之間畫了兩條線到底是鏈路聚合還是兩條獨(dú)立三層鏈路加浮動(dòng)路由這兩條線在配置上的差異是一整套參數(shù)聚合組、負(fù)載均衡算法、最少鏈路數(shù)、雙主檢測(cè)畫圖時(shí)一個(gè)箭頭就帶過(guò)了。所以我的習(xí)慣是圖只負(fù)責(zé)讓人理解結(jié)構(gòu)表里的「另一端」才決定配置正確性。每個(gè)接口都必須寫出本端和對(duì)端兩個(gè)地址哪怕兩端就在同一個(gè)機(jī)柜里。文檔里寫「上聯(lián)核心」這種話在腳本眼里等于沒(méi)有。接口編號(hào)、VLAN 號(hào)、IP 網(wǎng)段只要有一位對(duì)不上這份 docx 的價(jià)值就歸零。2.3 用 python-docx 把表讀成結(jié)構(gòu)化數(shù)據(jù)先安裝依賴然后寫一個(gè)最小腳本把這個(gè) docx 里全部表格讀成 JSONpip install python-docxfrom docx import Document import json doc Document(配套的網(wǎng)絡(luò)拓?fù)渑渲梦募?docx) tables {} for idx, table in enumerate(doc.tables): header [c.text.strip() for c in table.rows[0].cells] rows [] for row in table.rows[1:]: values [c.text.strip() for c in row.cells] if not any(values): continue rows.append(dict(zip(header, values))) tables[ftable_{idx}] {header: header, rows: rows} print(json.dumps(tables, ensure_asciiFalse, indent2))這個(gè)腳本做的事很簡(jiǎn)單用Document.tables直接取到 Word 文檔里所有表格把第一行當(dāng)作表頭剩下的行轉(zhuǎn)成字段字典。zip(header, values)把表頭和單元格一一配對(duì)if not any(values)跳過(guò)完全空的行ensure_asciiFalse保證中文不亂碼。跑完會(huì)看到table_0、table_1這樣的鍵下一步再根據(jù)表頭內(nèi)容做路由區(qū)分設(shè)備清單、接口連接表和 VLAN 規(guī)劃表。提示表頭如果有合并單元格row.cells會(huì)把合并單元格的值重復(fù)很多遍列名會(huì)錯(cuò)位。遇到這種情況先手工把源表格的合并單元格拆開(kāi)再重跑腳本比在代碼里猜列名省時(shí)間。3. 用腳本把網(wǎng)絡(luò)拓?fù)渑渲梦募锏那鍐纬槌鰜?lái)生成設(shè)備配置初稿3.1 為什么選 docx 而不是 YAML 或 Excel做配置自動(dòng)化的人第一反應(yīng)總是把配置源改成 YAML 或 Excel。YAML 干凈、可版本化Excel 行列分明??蓪?shí)際交付場(chǎng)景里業(yè)主和驗(yàn)收方要的不是 YAML而是一份能直接打開(kāi)、能打印簽字的 Word 文檔。你讓業(yè)務(wù)同事去改 YAML他大概率會(huì)把縮進(jìn)改壞讓他改 docx 表格他只會(huì)多填一列內(nèi)容。所以常見(jiàn)做法是交付時(shí)保留 docx 作為人工維護(hù)的入口腳本讀完 docx 生成中間層 YAML再進(jìn) Jinja2 模板渲染設(shè)備配置。配置源業(yè)務(wù)同事可維護(hù)性腳本讀取成本版本管理docx 表格高天生就是給人看的低python-docx 一個(gè)庫(kù)解決二進(jìn)制需要先轉(zhuǎn)文本再入庫(kù)Excel中公式和合并單元格容易亂低pandas 或 openpyxl二進(jìn)制同樣要先轉(zhuǎn)格式Y(jié)AML低縮進(jìn)錯(cuò)了沒(méi)法看極低文本天然適合 gitdocx 讀起來(lái)麻煩一點(diǎn)換來(lái)的是「文檔有人維護(hù)」。自動(dòng)化項(xiàng)目死在數(shù)據(jù)沒(méi)人更新上的概率遠(yuǎn)大于死在庫(kù)選型上。3.2 從 docx 配置文件里的設(shè)備清單渲染交換機(jī)配置假設(shè) docx 里有一張表表頭是「設(shè)備名、管理地址、VLAN 列表」。下面這段腳本按表頭關(guān)鍵字定位這張表再渲染成配置from docx import Document from jinja2 import Environment, FileSystemLoader import re doc Document(配套的網(wǎng)絡(luò)拓?fù)渑渲梦募?docx) devices [] for table in doc.tables: header [c.text.strip() for c in table.rows[0].cells] if 設(shè)備名 not in header or 管理地址 not in header: continue for row in table.rows[1:]: cells [c.text.strip() for c in row.cells] if not any(cells): continue row dict(zip(header, cells)) vlans [v.strip() for v in re.split(r[,、\s], row.get(VLAN 列表, )) if v.strip()] devices.append({ name: row[設(shè)備名], mgmt_ip: row[管理地址], vlans: vlans, }) break env Environment(loaderFileSystemLoader(templates)) template env.get_template(switch.j2) for dev in devices: config template.render(devicedev) with open(fout/{dev[name]}.conf, w, encodingutf-8) as f: f.write(config)對(duì)應(yīng)模板templates/switch.j2hostname {{ device.name }} ! interface vlan 1 ip address {{ device.mgmt_ip }} 255.255.255.0 ! {% for vid in device.vlans %} vlan {{ vid }} ! {% endfor %}邏輯說(shuō)明腳本把人工維護(hù)的 docx 變成一組.conf文件只負(fù)責(zé)「生成初稿」不負(fù)責(zé)直接下發(fā)。re.split(r[,、\s], ...)兼容 VLAN 列表里的英文逗號(hào)、中文逗號(hào)和頓號(hào)比單獨(dú)split(,)更抗造。break確保只處理第一張命中的表避免設(shè)備和接口表混在一起。模板里每個(gè)vlan后面加!分隔符是為了讓生成文本接近真實(shí)設(shè)備格式后面做 diff 時(shí)少一點(diǎn)干擾。換設(shè)備品牌時(shí)不需要改腳本只換模板就行。華為的接口叫interface GigabitEthernet0/0/1思科的寫法是interface Gi0/1把switch.j2換成對(duì)應(yīng)品牌的模板腳本內(nèi)部還是同一個(gè)字典輸入。3.3 與 running-config 做 diff找出漂移點(diǎn)生成配置只完成一半另一半是拿它跟設(shè)備當(dāng)前配置比對(duì)。把每臺(tái)設(shè)備的 running-config 導(dǎo)出來(lái)存成本地文件然后做差異預(yù)覽# 導(dǎo)出設(shè)備配置落成本地文件 # 華為設(shè)備display current-configuration running.conf # 思科設(shè)備show running-config running.conf # 忽略空行后的差異預(yù)覽 diff -u --strip-trailing-cr \ (sed /^$/d running.conf) \ (sed /^$/d out/Core-SW1.conf) | head -60參數(shù)說(shuō)明--strip-trailing-cr處理 Windows 換行符sed /^$/d刪除空行docx 模板渲染出來(lái)的配置常帶著模板空行不刪會(huì)全是噪音。(...)是進(jìn)程替換兩個(gè)文件直接比較不產(chǎn)生臨時(shí)文件。這種 diff 的用途是把「文檔和實(shí)際配置之間差了什么」暴露出來(lái)差異分三類文檔有設(shè)備沒(méi)配要補(bǔ)設(shè)備有文檔沒(méi)寫要么是還跑著業(yè)務(wù)的遺留要么是垃圾配置兩端都有但參數(shù)不同以業(yè)務(wù)需求為準(zhǔn)判斷。看到 diff 先別急著改設(shè)備把差異歸好類再動(dòng)手。4. 園區(qū)網(wǎng)絡(luò)拓?fù)渑渲玫娜齻€(gè)常見(jiàn)坑4.1 接口編號(hào)與物理端口對(duì)不上時(shí)先用 LLDP 取證大型園區(qū)網(wǎng)絡(luò)拓?fù)浼芭渲脤?shí)例里的接口表寫的時(shí)候往往還在規(guī)劃階段。交付那天跳線是誰(shuí)插的、有沒(méi)有插錯(cuò)基本不按文檔走。最常見(jiàn)的故障是文檔寫核心的 XG0/0/1 連匯聚的 XG0/0/2實(shí)際跳線插到了 XG0/0/3鏈路狀態(tài)倒是 up可 VLAN、聚合組全對(duì)不上。我一般不會(huì)先去拔線而是先看 LLDP 鄰居# 華為交換機(jī) display lldp neighbor brief # 思科交換機(jī) show lldp neighbors detail回顯里的對(duì)端設(shè)備名和接口號(hào)是設(shè)備自己報(bào)上來(lái)的比文檔可靠。檢查完把真實(shí)關(guān)系改回 docx 的接口連接表再繼續(xù)生成配置。注意 LLDP 要全局開(kāi)啟華為是lldp enable思科是lldp run沒(méi)開(kāi)的話查出來(lái)是空的所以這條最好提前寫進(jìn)模板基礎(chǔ)配置里。4.2 ensp 里 DHCP/DNS 參數(shù)漏出文檔割接必翻車用 ensp 搭過(guò) dhcp dns 網(wǎng)絡(luò)拓?fù)涞娜藭?huì)有印象拓?fù)淠芡ǘ喟氩皇堑刂烦貙憣?duì)了而是「文檔里根本沒(méi)寫地址池」。園區(qū)網(wǎng)最常見(jiàn)的問(wèn)題是內(nèi)網(wǎng) DNS 和公網(wǎng) DNS 搞混或者 DHCP 地址池網(wǎng)段與 VLAN 接口地址不在同一段。以下參數(shù)必須在 docx 的 VLAN 規(guī)劃表里占一格否則運(yùn)維接手時(shí)只能上設(shè)備翻配置參數(shù)常見(jiàn)錯(cuò)誤建議填法地址池網(wǎng)段和 VLAN 接口不在同一段與對(duì)應(yīng)三層接口地址同網(wǎng)段網(wǎng)關(guān)漏寫或?qū)懗蓜e的網(wǎng)段地址對(duì)應(yīng) VLAN 的三層接口地址DNS 列表只寫公網(wǎng) DNS內(nèi)網(wǎng) DNS 優(yōu)先公網(wǎng)兜底租期統(tǒng)一用默認(rèn)一天地址緊張的辦公區(qū)寫 2h 到 8h排除地址把打印機(jī)和服務(wù)器地址也放進(jìn)地址池預(yù)留一段地址不參與動(dòng)態(tài)分配排查時(shí)先看設(shè)備上的地址池使用情況# 查看某個(gè)地址池的分配記錄 display ip pool vlan20 used # 終端側(cè)抓 DHCP 報(bào)文看 OFFER 有沒(méi)有回來(lái) # tcpdump -i eth0 port 67 or port 68 -ndisplay ip pool會(huì)列出已分配地址和剩余地址tcpdump在終端上執(zhí)行抓不到 OFFER 就說(shuō)明 DHCP 請(qǐng)求沒(méi)到服務(wù)器回頭查 VLAN 接口下的dhcp select和中繼配置。把這些參數(shù)在 docx 里寫清楚排障時(shí)間能省掉一半以上。4.3 設(shè)備上有、文檔里沒(méi)有的殘留配置項(xiàng)怎么篩清理配置時(shí)diff 會(huì)出現(xiàn)大量「僅在當(dāng)前配置里出現(xiàn)」的行。這些行分兩種新加的臨時(shí)策略早該刪掉的殘留。用腳本分別篩出兩類 VLAN 的例子# 去掉行首縮進(jìn)避免格式干擾 sed s/^[[:space:]]*// running.conf | grep -E ^vlan [0-9]$ | awk {print $2} | sort -u actual_vlans.txt sed s/^[[:space:]]*// out/Core-SW1.conf | grep -E ^vlan [0-9]$ | awk {print $2} | sort -u expect_vlans.txt # 設(shè)備上有、文檔里沒(méi)有的 VLAN comm -13 expect_vlans.txt actual_vlans.txt # 文檔里有、設(shè)備上沒(méi)有的 VLAN comm -23 expect_vlans.txt actual_vlans.txt邏輯說(shuō)明sed去掉行首空白grep -E抓vlan 數(shù)字這種行awk {print $2}取第二列sort -u去重后交給comm。-13輸出第二個(gè)文件獨(dú)有對(duì)應(yīng)「要確認(rèn)后再刪」的項(xiàng)-23輸出第一個(gè)文件獨(dú)有對(duì)應(yīng)「設(shè)備漏配」的項(xiàng)。拿到「設(shè)備上獨(dú)有」的 VLAN 列表后逐個(gè)查display vlan id里有哪些接口確認(rèn)沒(méi)有端口屬于它再清理。直接刪是所有方案里最壞的選擇殘留配置背后往往掛著沒(méi)人說(shuō)得清的歷史業(yè)務(wù)。5. 把網(wǎng)絡(luò)拓?fù)渑渲梦募{入版本化與審核流程5.1 用 pandoc 把 docx 變成可 diff 的文本保留配置變更記錄docx 是二進(jìn)制壓縮包直接進(jìn) git 只能看到「文件變了」看不到哪里變了。解決辦法是先轉(zhuǎn)成純文本再和 docx 一起提交到倉(cāng)庫(kù)pandoc 配套的網(wǎng)絡(luò)拓?fù)渑渲梦募?docx -t plain -o topology.txt git add 配套的網(wǎng)絡(luò)拓?fù)渑渲梦募?docx topology.txt git commit -m docs: 更新核心到匯聚合路后的接口連接表 git diff HEAD~1 -- topology.txt | head -80pandoc 把 Word 表格轉(zhuǎn)成純文本時(shí)單元格順序會(huì)保留但合并單元格結(jié)構(gòu)會(huì)變平。短 diff 看語(yǔ)義沒(méi)問(wèn)題想精確到單元格還是回到 python-docx 讀表結(jié)構(gòu)。這個(gè)提交策略保證每次文檔修訂都有記錄設(shè)備配置腳本跟著這份文本走不會(huì)出現(xiàn)「文檔更新了、配置沒(méi)同步」的斷檔。5.2 文檔回讀巡檢設(shè)備配置與 docx 互相驗(yàn)證例行巡檢時(shí)把「文檔生成配置」和「設(shè)備當(dāng)前配置」做一次全量比對(duì)for f in out/*.conf; do dev$(basename $f) if [ -f running/$dev.conf ] ! diff -q $f running/$dev.conf /dev/null 21; then echo 配置漂移$dev fi done這段循環(huán)把每臺(tái)設(shè)備的期望配置和實(shí)際配置逐份比對(duì)diff -q只看有無(wú)差異不輸出細(xì)節(jié)。有漂移就打印設(shè)備名沒(méi)有就保持安靜適合掛進(jìn)巡檢腳本。建議每次割接次日跑一次平時(shí)每周跑一次。跑完如果漂移列表為空說(shuō)明設(shè)備配置和配套文檔一致不為空就回到第 3 章的 diff 流程把差異歸入「要補(bǔ)」「要?jiǎng)h」「要改」三類改完再跑一遍直到列表為空。下一次提交交付文檔時(shí)先跑一次這個(gè)循環(huán)你會(huì)發(fā)現(xiàn)省下來(lái)的核對(duì)時(shí)間遠(yuǎn)不止畫圖那半小時(shí)。本文還有配套的精品資源點(diǎn)擊獲取