K8s已經成為一線大廠分布式平臺的標配技術。你是不是還在惆悵怎麼掌握它?來這裡,大型網際網路公司一線工程師親授,不來虛的,直接上手實戰,3天時間帶你搭建K8s平臺,快速學會K8s,點擊下方圖片可了解培訓詳情。
Cilium是一種開源網絡實現方案,與其他網絡方案不同的是,Cilium著重強調了其在網絡安全上的優勢,可以透明的對Kubernetes等容器管理平臺上的應用程式服務之間的網絡連接進行安全防護。Cilium在設計和實現上,基於Linux的一種新的內核技術eBPF,可以在Linux內部動態插入強大的安全性、可見性和網絡控制邏輯,相應的安全策略可以在不修改應用程式代碼或容器配置的情況下進行應用和更新。Cilium在其官網上對產品的定位稱為「API-aware Networking and Security」,因此可以看出,其特性主要包括這三方面:
提供Kubernetes中基本的網絡互連互通的能力,實現容器集群中包括Pod、Service等在內的基礎網絡連通功能;
依託eBPF,實現Kubernetes中網絡的可觀察性以及基本的網絡隔離、故障排查等安全策略;
依託eBPF,突破傳統主機防火牆僅支持L3、L4微隔離的限制,支持基於API的網絡安全過濾能力。Cilium提供了一種簡單而有效的方法來定義和執行基於容器/Pod身份(Identity Based)的網絡層和應用層(比如HTTP/gRPC/Kafka等)安全策略。
Cilium官方給出了如下的參考架構,Cilium位於容器編排系統和Linux Kernel之間,向上可以通過編排平臺為容器進行網絡以及相應的安全配置,向下可以通過在Linux內核掛載eBPF程序,來控制容器網絡的轉發行為以及安全策略執行。在Cilium的架構中,除了Key-Value數據存儲之外,主要組件包括Cilium Agent和Cilium Operator,還有一個客戶端的命令行工具Cilium CLI。Cilium Agent作為整個架構中最核心的組件,通過DaemonSet的方式,以特權容器的模式,運行在集群的每個主機上。Cilium Agent作為用戶空間守護程序,通過插件與容器運行時和容器編排系統進行交互,進而為本機上的容器進行網絡以及安全的相關配置。同時提供了開放的API,供其他組件進行調用。Cilium Agent在進行網絡和安全的相關配置時,採用eBPF程序進行實現。Cilium Agent結合容器標識和相關的策略,生成eBPF程序,並將eBPF程序編譯為字節碼,將它們傳遞到Linux內核。Cilium Operator 主要負責管理集群中的任務,儘可能的保證以集群為單位,而不是單獨的以節點為單位進行任務處理。主要包括,通過etcd為節點之間同步資源信息、確保Pod的DNS可以被Cilium管理、集群NetworkPolicy的管理和更新等。
Cilium提供多種組網模式,默認採用基於VXLAN的Overlay組網。除此之外,還包括:
通過BGP路由的方式,實現集群間Pod的組網和互聯;
在AWS的ENI(Elastic Network Interfaces)模式下部署使用Cilium;
Flannel和Cilium的集成部署;
採用基於ipvlan的組網,而不是默認的基於veth;
Cluster Mesh組網,實現跨多個Kubernetes集群的網絡連通和安全性等多種組網模式。
本文將針對默認的基於vxlan的overlay組網,進行深度的原理和數據包路徑分析。
使用官方給出的yaml文件,通過下述命令,實現Cilium的快速部署。
root@u18-161:~# kubectl create -f https://raw.githubusercontent.com/cilium/cilium/v1.6.5/install/kubernetes/quick-install.yaml
部署成功後,我們可以發現,在集群的每個主機上,啟動了一個Cilium Agent(cilium-k54qt,cilium-v7fx4),整個集群啟動了一個Cilium Operator(cilium-operator-cdb4d8bb6-8mj5w)。
root@u18-161:~# kubectl get pods --all-namespaces -o wide | grep cilium
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE
kube-system cilium-k54qt 1/1 Running 0 80d 192.168.19.161 u18-161
kube-system cilium-v7fx4 1/1 Running 0 80d 192.168.19.162 u18-162
kube-system cilium-operator-cdb4d8bb6-8mj5w 1/1 Running 1 80d 192.168.19.162 u18-162
在這種默認的組網情況下,主機上的網絡發生了以下變化:在主機的root命名空間,新增了如下圖所示的四個虛擬網絡接口,其中cilium_vxlan主要是處理對數據包的vxlan隧道操作,採用metadata模式,並不會為這個接口分配ip地址;cilium_host作為主機上該子網的一個網關,並且在node-161為其自動分配了IP位址10.244.0.26/32,cilium_net和cilium_host作為一對veth而創建,還有一個lxc_health。在每個主機上,可以進入Cilium Agent,查看其隧道配置。比如進入主機node-161上的Cilium Agent cilium-k54qt,運行cilium bpf tunnel list,可以看到,其為集群中的另一臺主機node-162(192.168.19.162)上的虛擬網絡10.244.1.0創建了一個隧道。同樣在node-162上也有一條這樣的隧道配置。接下來創建Pod1和Pod2運行於node-161,Pod3和Pod4運行於node-162。其與主機的root命名空間,通過veth-pair連接,如下圖所示。進入Pod1,可以發現,Cilium已經為其分配了IP位址,並且設置了默認的路由,默認路由指向了本機的cilium_host。初始狀態Pod內的arp表為空。
root@u18-161:~# kubectl exec -it test-1-7cd5798f46-vzf9s -n test-1 bash
root@test-1-7cd5798f46-vzf9s:/# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.244.0.26 0.0.0.0 UG 0 0 0 eth0
10.244.0.26 0.0.0.0 255.255.255.255 UH 0 0 0 eth0
root@test-1-7cd5798f46-vzf9s:/# arp
root@test-1-7cd5798f46-vzf9s:/#
在Pod1中ping Pod2,通過抓包可以發現,Pod發出的ARP請求,其對應的ARP響應直接通過其對端的veth-pair 接口返回(52:c6:5e:ef:6e:97和5e:2d:20:9d:b1:a8是Pod1對應的veth-pair)。這個ARP響應是通過Cilium Agent通過掛載的eBPF程序實現的自動應答,並且將veth-pair對端的MAC地址返回,避免了虛擬網絡中的ARP廣播問題。
No. Time Source Destination Protocol Length Info
133 39.536478 52:c6:5e:ef:6e:97 5e:2d:20:9d:b1:a8 ARP 42 Who has 10.244.0.26? Tell 10.244.0.71
134 39.536617 5e:2d:20:9d:b1:a8 52:c6:5e:ef:6e:97 ARP 42 10.244.0.26 is at 5e:2d:20:9d:b1:a8
分析完組網狀態之後,那麼同一個主機內,兩個Pod間通信的情況,就很容易理解了。例如,Pod1向Pod2發包,其數據通路如下圖所示Pod1 --> eth0 --> lxc909734ef58f7 --> lxc7c0fcdd49dd0 --> eth0 --> Pod2。在這種Overlay組網模式下,Pod跨節點之間的通信,通過vxlan實現隧道的封裝,其數據路徑如下圖所示pod1 --> eth0 --> lxc909734ef58f7 --> cilium_vxlan --> eth0(node-161) --> eth0(node-162) --> cilium_vxlan --> lxc2df34a40a888 --> eth0 --> pod3。我們在cilium_vxlan虛擬網絡接口上抓包,如下所示。從抓包分析可以看出,Linux內核將Pod1發出的原始數據包發送到cilium_vxlan進行隧道相關的封包、解包處理,然後再將其送往主機的物理網卡eth0。在物理網卡eth0抓包可以發現,Pod1出發的數據包經過cilium_vxlan的封裝處理之後,其源目的地址已經變成物理主機node-161和node-162,這是經典的overlay封裝。同時,還可以發現,cilium_vxlan除了對數據包進行了隧道封裝之外,還將原始數據包進行了TLS加密處理,保障了數據包在主機外的物理網絡中的安全性。
Cilium在1.17版本之後,推出並開源了其網絡可視化組件Hubble,Hubble是建立在Cilium和eBPF之上,以一種完全透明的方式,提供網絡基礎設施通信以及應用行為的深度可視化,是一個應用於雲原生工作負載,完全分布式的網絡和安全可觀察性平臺。Hubble能夠利用Cilium提供的eBPF數據路徑,獲得對Kubernetes應用和服務網絡流量的深度可見性。這些網絡流量信息可以對接Hubble CLI、UI工具,可以通過交互式的方式快速發現診斷相關的網絡問題與安全問題。Hubble除了自身的監控工具,還可以對接像Prometheus、Grafana等主流的雲原生監控體系,實現可擴展的監控策略。從上圖的架構以及Hubble部署可以看出,Hubble在Cilium Agent之上,以DaemonSet的方式運行自己的Agent,筆者這裡的部署示例採用Hubble UI來操作和展示相關的網絡以及安全數據。
root@u18-163:~# kubectl get pods --all-namespaces -o wide | grep hubble
kube-system hubble-5tvzc 1/1 Running 16 66d 10.244.1.209 u18-164 <none> <none>
kube-system hubble-k9ft8 1/1 Running 0 34m 10.244.0.198 u18-163 <none> <none>
kube-system hubble-ui-5f9fc85849-x7lnl 1/1 Running 4 67d 10.244.0.109 u18-163 <none> <none>
依託於Hubble深入的對網絡數據和行為的可觀察性,其可以為網絡和安全運維人員提供以下相關能力:服務依賴關係和通信映射拓撲:比如,可以知道哪些服務之間在相互通信?這些服務通信的頻率是多少?服務依賴關係圖是什麼樣的?正在進行什麼HTTP調用?服務正在消費或生產哪些Kafka的Topic等。運行時的網絡監控和告警:比如,可以知道是否有網絡通信失敗了?為什麼通信會失敗?是DNS的問題?還是應用程式得問題?還是網絡問題?是在第4層(TCP)或第7層(HTTP)的發生的通信中斷等;哪些服務在過去5分鐘內遇到了DNS解析的問題?哪些服務最近經歷了TCP連接中斷或看到連接超時?TCP SYN請求的未回答率是多少?等等。應用程式的監控:比如,可以知道針對特定的服務或跨集群服務,HTTP 4xx或者5xx響應碼速率是多少?在我的集群中HTTP請求和響應之間的第95和第99百分位延遲是多少?哪些服務的性能最差?兩個服務之間的延遲是什麼?等等這些問題。安全可觀察性:比如,可以知道哪些服務的連接因為網絡策略而被阻塞?從集群外部訪問了哪些服務?哪些服務解析了特定的DNS名稱?等等。從上圖Hubble的界面,我們可以簡單的看出其部分功能和數據,比如,可以直觀的顯示出網路和服務之間的通信關係,可以查看Flows的多種詳細數據指標,可以查看對應的安全策略情況,可以通過namespace對觀測結果進行過濾等等。默認情況下,Cilium與其他網絡插件一樣,提供了整個集群網絡的完全互聯互通,用戶需要根據自己的應用服務情況設定相應的安全隔離策略。如下圖所示,每當用戶新創建一個Pod,或者新增加一條安全策略,Cilium Agent會在主機對應的虛擬網卡驅動加載相應的eBPF程序,實現網絡連通以及根據安全策略對數據包進行過濾。比如,可以通過採用下面的NetworkPolicy實現一個基本的L3/L4層網絡安全策略。
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
description: "L3-L4 policy to restrict deathstar access to empire ships only"
metadata:
name: "rule1"
spec:
endpointSelector:
matchLabels:
org: empire
class: deathstar
ingress:
- fromEndpoints:
- matchLabels:
org: empire
toPorts:
- ports:
- port: "80"
protocol: TCP
然而,在微服務架構中,一個基於微服務的應用程式通常被分割成一些獨立的服務,這些服務通過API(使用HTTP、gRPC、Kafka等輕量級協議)實現彼此的通信。因此,僅實現在L3/L4層的網絡安全策略,缺乏對於微服務層的可見性以及對API的細粒度隔離訪問控制,在微服務架構中是不夠的。我們可以看如下這個例子,Job Postings這個服務暴露了其服務的健康檢查、以及一些增、刪、改、查的API。Gordon作為一個求職者,需要訪問Job Postings提供的Jobs相關信息。按照傳統的L3/L4層的隔離方法,可以通過iptables -s 10.1.1.1 -p tcp –dport 80 -j ACCEPT,允許Gordon來訪問Job Postings在80埠提供的HTTP服務。但是這樣的網絡規則,導致Gordon同樣可以訪問包括發布信息、修改信息、甚至是刪除信息等其他接口。這樣的情況肯定是我們的服務設計者所不希望發生的,同時也存在著嚴重的安全隱患。因此,實現微服務間的L7層隔離,實現其對應的API級別的訪問控制,是微服務網絡微隔離的一個重要部分。Cilium在為Docker和Kubernetes等基於Linux的容器框架提供了支持API層面的網絡安全過濾能力。通過使用eBPF,Cilium提供了一種簡單而有效的方法來定義和執行基於容器/pod身份的網絡層和應用層安全策略。我們可以通過採用下面的NetworkPolicy實現一個L7層網絡安全策略。
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
description: "L7 policy to restrict access to specific HTTP call"
metadata:
name: "rule1"
spec:
endpointSelector:
matchLabels:
org: empire
class: deathstar
ingress:
- fromEndpoints:
- matchLabels:
org: empire
toPorts:
- ports:
- port: "80"
protocol: TCP
rules:
http:
- method: "POST"
path: "/v1/request-landing"
Cilium還提供了一種基於Proxy的實現方式,可以更方便的對L7協議進行擴展。如下圖所示,Cilium Agent採用eBPF實現對數據包的重定向,將需要進行過濾的數據包首先轉發至Proxy代理,Proxy代理根據其相應的過濾規則,對收到的數據包進行過濾,然後再將其發回至數據包的原始路徑,而Proxy代理進行過濾的規則,則通過Cilium Agent進行下發和管理。當需要擴展協議時,只需要在Proxy代理中,增加對新協議的處理解析邏輯以及規則處置邏輯,即可實現相應的過濾能力。
Cilium是一個基於eBPF和XDP的高性能網絡方案,本文著重介紹了其原理以及默認的overlay組網通信。除了基本的網絡通信能力外,Cilium還包含了基於eBPF的負載均衡能力,L3/L4/L7的安全策略能力等相關的內容,後續會進行更詳細的實踐分析。
基於Kubernetes的DevOps實戰培訓將於2020年8月14日在上海開課,3天時間帶你系統掌握Kubernetes,學習效果不好可以繼續學習。本次培訓包括:容器特性、鏡像、網絡;Kubernetes架構、核心組件、基本功能;Kubernetes設計理念、架構設計、基本功能、常用對象、設計原則;Kubernetes的資料庫、運行時、網絡、插件已經落地經驗;微服務架構、組件、監控方案等,點擊下方圖片或者閱讀原文連結查看詳情。