互聯(lián)網(wǎng)應(yīng)用已經(jīng)深深的滲透到我們?nèi)粘I畹姆椒矫婷?,比如很多同學(xué)應(yīng)該有很長時間都沒有使用過現(xiàn)金了。不過任何事情都具有兩面性,科技發(fā)展給我們造成便利的同事,不容忽視的一個事實是,大部分在線交付系統(tǒng)每天都會遭受各種各樣的網(wǎng)絡(luò)攻擊,因此無論你的系統(tǒng)部署在哪里,我們都需要有基本的網(wǎng)絡(luò)知識來保護系統(tǒng)的正常運行以及核心數(shù)據(jù)不會被竊取。
讀者看到這里可能會說講網(wǎng)絡(luò)原理的書和文章太多了,這個東西還有什么好說的。筆者認可這個說法,因此也沒有打算對網(wǎng)絡(luò)原理進行深入的探討,而是會著重介紹網(wǎng)絡(luò)安全相關(guān)的部分,以期幫助那些對這些概念不很熟悉的同學(xué)能夠消化我們介紹的核心知識:安全。
容器化部署方案總是伴隨著微服務(wù)架構(gòu)一起出現(xiàn)在技術(shù)方案,最近給幾個頭部客戶做技術(shù)方案和部署方案的時候,深刻的體會到其中的緣由。微服務(wù)架構(gòu)本身解決的是如何將模塊化失控的單體應(yīng)用拉回到可運維,可管理,可擴展應(yīng)用的范圍,因此我們會將大塊的功能進行拆分,結(jié)果就是可獨立部署的一個個“微”服務(wù)。
很明顯這里拆分是關(guān)鍵,因為也沒有什么放之四海而皆準(zhǔn)的標(biāo)準(zhǔn)規(guī)則,大部分講微服務(wù)拆分的文章都提供了供參考的拆分維度,比如從業(yè)務(wù)的角度,從變化頻率,從訪問量,從技術(shù)棧等等。當(dāng)軟件被拆分為粒度“合適”的服務(wù)后,整個部署方案也需要適配,我們需要考慮這么多服務(wù)以及服務(wù)的多個實例如何進行部署和管理的問題。
雖然說解決這個問題有過很多不同方向的嘗試,目前看容器化部署應(yīng)該是這些方案里最被廣泛接受的,特別是從安全的角度看,大的單體應(yīng)用的安全邊界遠比細粒度服務(wù)的安全邊界大,因此“微”服務(wù)更加容易來進行安全防護。當(dāng)然背后的邏輯不難理解,由于微服務(wù)承載的功能比起單體應(yīng)用來說小了不少,因此微服務(wù)需要和其他容器通信的場景少很多,甚至都可能不需要和公網(wǎng)上的服務(wù)通信。
咱們來舉個例子,比如說我們開發(fā)電商平臺,核心功能會被拆分到不同的能力中心,典型的能力中心有產(chǎn)品,庫存和支付等。對于電商來說,用戶需要通過商品詳情頁面來幫助客戶更好的了解商品信息,因此我們需要提供商品檢索接口,因此對于上平中心的微服務(wù)來說,除了訪問數(shù)據(jù)庫之外,根本不需要訪問比如說支付微服務(wù)的權(quán)限,理論上我們應(yīng)該禁止這樣的訪問鏈路,確保當(dāng)商品微服務(wù)被攻破后,不會影響支付微服務(wù)。如下圖所示:

容器防火墻可以用來限制進出容器實例的訪問流量,不過熟悉Kubernetes的同學(xué)應(yīng)該會覺得“容器防火墻”這個術(shù)語很奇怪,因為在K8S中,我們用的術(shù)語是網(wǎng)絡(luò)策略(Network policy)。不過無論是叫啥名字,本質(zhì)都是為了讓進出容器的網(wǎng)絡(luò)流量符合預(yù)期。另外容器防火墻也會記錄和報告預(yù)期之外的網(wǎng)絡(luò)訪問情況,這些數(shù)據(jù)可以用來進行安全審計以及網(wǎng)絡(luò)攻擊預(yù)防工作。
容器防火墻一般情況下會和多個網(wǎng)絡(luò)工具配合使用,來達到縱深防御的效果,常見的工具羅列如下:
- 和VPC結(jié)合起來,來讓部署在VPC中的應(yīng)用和外部系統(tǒng)的相互訪問受規(guī)則管控
- 和WAF等工具配合使用,來約束7層的訪問流量
如筆者在前邊所述,這些工具的組合使用會加深安全縱深,我們應(yīng)該在自己的系統(tǒng)設(shè)計中,特別是安全體系中考慮這種縱深防御的思路。接下里我們聊聊如何實現(xiàn)容器防火墻,不過在這之前,為了內(nèi)容的完整性,咱先簡單的介紹一下網(wǎng)絡(luò)基礎(chǔ)知識。
說到網(wǎng)絡(luò)模型,不得不提OSI(Open Systems Interconnection)網(wǎng)絡(luò)模型,這個模型在40年后的今天(1984年發(fā)布)仍然具有參考價值。OSI模型和網(wǎng)絡(luò)的事實規(guī)范TCP/IP模型之間并不能1:1映射,如下圖所示,

關(guān)于OSI模型的各層簡要說明如下:
- Layer 7一般被稱作是應(yīng)用程序?qū)印?yīng)用程序?qū)涌梢岳斫鉃槲覀兺ㄟ^應(yīng)用來訪問某個服務(wù)接口,這里的應(yīng)用所處的就是Layer 7,或者說訪問接口這個動作發(fā)生在Layer 7。7層的請求一般訪問某個具體的URL,為了將請求路由到目標(biāo)機器,URL中的域名會被翻譯成IP地址,翻譯的過程需要DNS服務(wù)的支持。
- Layer 4被稱作是傳輸層,這一層有兩個大名鼎鼎的協(xié)議TCP和UDP,端口號工作在4層
- Layer 3被稱作是IP層或者網(wǎng)絡(luò)層。這一層和核心工作是IP數(shù)據(jù)包的路由。當(dāng)容器實例初始化的時候,會加入到宿主機上的虛擬網(wǎng)絡(luò),因此也會有自己的IP地址
- Layer 2被稱作為數(shù)據(jù)鏈路層,工作在這一層的協(xié)議有WIFI,以太網(wǎng)等,年長的同學(xué)可能還聽過什么Token Ring網(wǎng)絡(luò)的,也屬于鏈路層。不過WIFI放在這層稍微有點爭議,因為WIFI覆蓋了2層和1層(物理層),咱們所有的文章只會設(shè)計以太網(wǎng),這是容器化部署網(wǎng)絡(luò)使用最廣泛的協(xié)議
- Layer 1被稱作是物理層,什么同軸電纜,光纖等都屬于這一層。對于容器網(wǎng)絡(luò)來說,筆者想要特別強調(diào)的是,物理層可以虛擬。如果大家對筆者前邊的文章有印象,我們說VMM(Virtual Machine Monitor)提供了對系統(tǒng)資源的虛擬化,讓guest kernel通過虛擬設(shè)備來最終訪問物理設(shè)備。
接下來我們通過一個具體的場景來看看這些曾是如何工作在一起支持網(wǎng)絡(luò)連接的兩臺機器相互通信。假設(shè)我們有個客戶端應(yīng)用程序需要發(fā)送請求給某個目標(biāo)URL,由于這個客戶端屬于我們所說的應(yīng)用程序,因此我們可以理解為“發(fā)送”請求這個動作發(fā)生在Layer 7。
發(fā)出請求后第一步是DNS查詢,來把URL中的主機名映射成IP地址,當(dāng)然我們也可以不用訪問外部的DNS服務(wù),直接在etc/hosts文件中靜態(tài)的將域名映射到對應(yīng)的IP地址,這在我們很多測試場景非常實用。
當(dāng)要訪問的IP地址通過DNS解析或者本地hosts文件確認后,接下來就是3層的路由選擇,路由選擇主要包含兩部分:
- 為了訪問目標(biāo)機器,可能需要跨越多個IP網(wǎng),因此首先需要確定下一跳地址
- 確定了系一條地址,由于要具體發(fā)送數(shù)據(jù),因此需要確定發(fā)送數(shù)據(jù)的網(wǎng)絡(luò)接口(網(wǎng)卡)
接著請求會被封裝成以太網(wǎng)幀,下一跳IP地址需要被翻譯成MAC地址,翻譯的過程需要依賴于ARP協(xié)議,當(dāng)然如果之前訪問過這個服務(wù)地址,并且ARP緩存中數(shù)據(jù)未過期,那么直接可以從ARP緩存取到IP地址對應(yīng)的MAC地址,如果緩存中沒有,那么就要依賴于ARP協(xié)議來確定下一跳機器的MAC地址。
確定了下一跳機器的MAC地址,消息就會通過選擇的網(wǎng)絡(luò)接口發(fā)送出去。不過這里基于具體的網(wǎng)絡(luò)實現(xiàn),網(wǎng)絡(luò)接口可能是點到點連接,或者連接到外部的網(wǎng)橋。
網(wǎng)橋這個概念在容器網(wǎng)絡(luò)中非常關(guān)鍵,因此我們需要花費一些筆墨來詳細介紹一下。大家可以把網(wǎng)橋理解為有多個網(wǎng)線連接的設(shè)備,網(wǎng)線的另外一端連到電腦網(wǎng)卡上。每張網(wǎng)卡在出場的時候都會被分配并固化一個唯一的MAC地址,網(wǎng)橋bridge可以通過連接學(xué)習(xí)到每臺機器的MAC地址。所有連接到網(wǎng)橋的設(shè)備都可以通過連接的網(wǎng)線來相互發(fā)送數(shù)據(jù)進行通信。
在容器網(wǎng)絡(luò)模型中,網(wǎng)橋是通過軟件來實現(xiàn),而不是硬件,并且物理網(wǎng)線被虛擬以太網(wǎng)接口替換。因此數(shù)據(jù)發(fā)送到網(wǎng)橋后,會基于下一跳MAC地址來決定具體發(fā)送到哪個虛擬以太網(wǎng)接口上。
當(dāng)數(shù)據(jù)出現(xiàn)在另外一頭,也就是目標(biāo)機器端,IP數(shù)據(jù)包被從以太網(wǎng)幀中抽取出來發(fā)送給Layer3。大家需要注意的是在數(shù)據(jù)在協(xié)議棧中發(fā)送的過程中,每一層都會增加header,以及在數(shù)據(jù)鏈路層會給尾部增加數(shù)據(jù)效驗。如下圖所示:
注:大家可以考慮一下為什么不在IP層增加checksum?主要還是效率的考慮,因為NAT的存在,如果我們在IP層做了checksum,那么無論是修改源地址還是目標(biāo)地址,都會造成checksum的重新計算,會造成性能損耗,從這一點可以看出網(wǎng)絡(luò)機制設(shè)計的核心域一定包含傳輸效率。

在網(wǎng)絡(luò)層還會判斷數(shù)據(jù)的目標(biāo)機器是不是本機,如果是數(shù)據(jù)會被繼續(xù)往上遞交,如果不是,網(wǎng)絡(luò)層會繼續(xù)進行路由選擇,來講數(shù)據(jù)往下傳遞。上邊的描述略微簡略,但是大概把數(shù)據(jù)從應(yīng)用層如何發(fā)送到目標(biāo)機器描述了一遍,如果讀者對這部分內(nèi)容還有疑問,建議直接看TCP/IP Illustrated這本書,你絕對會喜歡上W Richard Steven的文字風(fēng)格,特別是如何將復(fù)雜的技術(shù)細節(jié)通過簡單的文字表達清楚。
好了,這篇文章就這么多了,咱們下篇文章繼續(xù)討論容器的IP地址分配,網(wǎng)絡(luò)隔離,負載均衡,以及網(wǎng)絡(luò)防火墻的具體落地實施方案,敬請期待!