使用 Cilium 增强 Kubernetes 网络安全
作者 | Addo Zhang
來源 | 云原生指北
TL;DR
在本篇,我們分別使用了 Kubernetes 原生的網絡策略和 Cilium 的網絡策略實現了 Pod 網絡層面的隔離。不同的是,前者只提供了基于 L3/4 的網絡策略;后者支持 L3/4、L7 的網絡策略。
通過網絡策略來提升網絡安全,可以極大降低了實現和維護的成本,同時對系統幾乎沒有影響。
尤其是基于 eBPF 技術的 Cilium,解決了內核擴展性不足的問題,從內核層面為工作負載提供安全可靠、可觀測的網絡連接。
背景
為什么說 Kubernetes 網絡存在安全隱患?集群中的 Pod 默認是未隔離的,也就是 Pod 之間的網絡是互通的,可以互相通信的。
這里就會有問題,比如由于數據敏感服務 B 只允許特定的服務 A 才能訪問,而服務 C 無法訪問 B。要禁止服務 C 對服務 B 的訪問,可以有幾種方案:
在 SDK 中提供通用的解決方案,實現白名單的功能。首先請求要帶有來源的標識,然后服務端可以接收規則設置放行特定標識的請求,拒絕其他的請求。
云原生的解決方案,使用服務網格的 RBAC、mTLS 功能。RBAC 實現原理與應用層的 SDK 方案類似,但是屬于基礎設施層的抽象通用方案;mTLS 則會更加復雜一些,在連接握手階段進行身份驗證,涉及證書的簽發、驗證等操作。
以上兩種方案各有利弊:
SDK 的方案實現簡單,但是規模較大的系統會面臨升級推廣困難、多語言支持成本高等問題。
服務網格的方案是基礎設施層的通用方案,天生支持多語言。但是對于未落地網格的用戶來說,架構變化大,成本高。如果單純為了解決安全問題,使用網格方案性價比又很低,且不說現有網格實現等落地難度大及后期的使用維護成本高。
繼續向基礎設施下層找方案,從網絡層入手。Kubernetes 提供了的網絡策略 *NetworkPolicy*[1],則可以實現“網絡層面的隔離”。
示例應用
在進一步演示?NetworkPolicy?的方案之前,先介紹用于演示的示例應用。我們使用 Cilium 在互動教程?Cilium getting started[2]?中使用的“星球大戰”場景。
這里有三個應用,星戰迷估計不會陌生:
死星?deathstar:在?80?端口提供 web 服務,有 2 個 副本,通過 Kubernetes Service 的負載均衡為帝國戰機對外提供”登陸“服務。
鈦戰機?tiefighter:執行登陸請求。
X翼戰機?xwing:執行登陸請求。
如圖所示,我們使用了?Label?對三個應用進行了標識:org?和?class。在執行網絡策略時,我們會使用這兩個標簽識別負載。
#?app.yaml --- apiVersion:?v1 kind:?Service metadata:name:?deathstarlabels:app.kubernetes.io/name:?deathstar spec:type:?ClusterIPports:-?port:?80selector:org:?empireclass:?deathstar --- apiVersion:?apps/v1 kind:?Deployment metadata:name:?deathstarlabels:app.kubernetes.io/name:?deathstar spec:replicas:?2selector:matchLabels:org:?empireclass:?deathstartemplate:metadata:labels:org:?empireclass:?deathstarapp.kubernetes.io/name:?deathstarspec:containers:-?name:?deathstarimage:?docker.io/cilium/starwars --- apiVersion:?v1 kind:?Pod metadata:name:?tiefighterlabels:org:?empireclass:?tiefighterapp.kubernetes.io/name:?tiefighter spec:containers:-?name:?spaceshipimage:?docker.io/tgraf/netperf --- apiVersion:?v1 kind:?Pod metadata:name:?xwinglabels:app.kubernetes.io/name:?xwingorg:?allianceclass:?xwing spec:containers:-?name:?spaceshipimage:?docker.io/tgraf/netperfKubernetes 網絡策略
可以通過官方文檔[3]獲取更多詳細信息,這里我們直接放出配置:
#?native/networkpolicy.yaml apiVersion:?networking.k8s.io/v1 kind:?NetworkPolicy metadata:name:?policynamespace:?default spec:podSelector:matchLabels:org:?empireclass:?deathstarpolicyTypes:-?Ingressingress:-?from:-?podSelector:matchLabels:org:?empireports:-?protocol:?TCPport:?80podSelector?:表示要應用網絡策略的工作負載均衡,通過?label?選擇到了?deathstar?的 2 個 Pod。
policyTypes?:表示流量的類型,可以是?Ingress?或?Egress?或兩者兼具。這里使用?Ingress,表示對選擇的?deathstar?Pod 的入站流量執行規則。
ingress.from:表示流量的來源工作負載,也是使用?podSelector?和?Label?進行選擇,這里選中了?org=empire?也就是所有“帝國的戰機”。
ingress.ports:表示流量的進入端口,這里列出了?deathstar?的服務端口。
接下來,我們測試下。
測試
先準備環境,我們使用?K3s[4]?作為 Kubernetes 環境。但由于 K3s 默認的 CNI 插件 Flannel 不支持網絡策略,我們需要換個插件,這里選擇?Calico[5],即 K3s + Calico 的方案。
先創建一個單節點的集群:
curl?-sfL?https://get.k3s.io?|?K3S_KUBECONFIG_MODE="644"?INSTALL_K3S_EXEC="--flannel-backend=none?--cluster-cidr=10.42.0.0/16?--disable-network-policy?--disable=traefik"?sh?-此時,所有的 Pod 都處于?Pending?狀態,因為還需要安裝 Calico:
kubectl?apply?-f?https://projectcalico.docs.tigera.io/manifests/calico.yaml待 Calico 成功運行后,所有的 Pod 也會成功運行。
接下來就是部署應用:
kubectl?apply?-f?app.yaml執行策略前,執行下面的命令看看“戰機能否登陸死星”:
kubectl?exec?tiefighter?--?curl?-s?-XPOST?deathstar.default.svc.cluster.local/v1/request-landing Ship?landedkubectl?exec?xwing?--?curl?-s?-XPOST?deathstar.default.svc.cluster.local/v1/request-landing Ship?landed從結果來看,兩種 ”戰機“(Pod 負載)都可以訪問?deathstar?服務。
此時執行網絡策略:
kubectl?apply?-f?native/networkpolicy.yaml再次嘗試”登陸“,xwing?的登陸請求會停在那(需要使用?ctrl+c?退出,或者請求時加上?--connect-timeout 2)。
思考
使用 Kubernetes 網絡策略實現了我們想要的,從網絡層面為服務增加了白名單的功能,這種方案沒有改造成本,對系統也幾乎無影響。
Cilium 還沒出場就結束了?我們繼續看:
有時我們的服務會對外暴露一些管理端點,由系統調用執行一些管理上的操作,比如熱更新、重啟等。這些端點是不允許普通服務來調用,否則會造成嚴重的后果。
比如示例中,tiefighter?訪問了?deathstar?的管理端點?/exhaust-port:
kubectl?exec?tiefighter?--?curl?-s?-XPUT?deathstar.default.svc.cluster.local/v1/exhaust-port Panic:?deathstar?explodedgoroutine?1?[running]: main.HandleGarbage(0x2080c3f50,?0x2,?0x4,?0x425c0,?0x5,?0xa)/code/src/github.com/empire/deathstar/temp/main.go:9?+0x64 main.main()/code/src/github.com/empire/deathstar/temp/main.go:5?+0x85出現了?Panic?錯誤,檢查 Pod 你會發現?dealthstar?掛了。
Kubernetes 的網絡策略僅能工作在 L3/4 層,對 L7 層就無能為力了。
還是要請出 Cilium。
Cilium 網絡策略
由于 Cilium 涉及了 Linux 內核、網絡等眾多知識點,要講清實現原理篇幅極大。故這里僅摘取了官網的介紹,后期希望有時間再寫一篇關于實現的。
Cilium 簡介
Cilium[6]?是一個開源軟件,用于提供、保護和觀察容器工作負載(云原生)之間的網絡連接,由革命性的內核技術?eBPF[7]?推動。
eBPF 是什么?
Linux 內核一直是實現監控/可觀測性、網絡和安全功能的理想地方。不過很多情況下這并非易事,因為這些工作需要修改內核源碼或加載內核模塊, 最終實現形式是在已有的層層抽象之上疊加新的抽象。eBPF 是一項革命性技術,它能在內核中運行沙箱程序(sandbox programs), 而無需修改內核源碼或者加載內核模塊。
將 Linux 內核變成可編程之后,就能基于現有的(而非增加新的)抽象層來打造更加智能、 功能更加豐富的基礎設施軟件,而不會增加系統的復雜度,也不會犧牲執行效率和安全性。
我們來看下 Cilium 的網絡策略:
#?cilium/networkpolicy-L4.yaml apiVersion:?"cilium.io/v2" kind:?CiliumNetworkPolicy metadata:name:?"rule1" spec:description:?"L7?policy?to?restrict?access?to?specific?HTTP?call"endpointSelector:matchLabels:org:?empireclass:?deathstaringress:-?fromEndpoints:-?matchLabels:org:?empiretoPorts:-?ports:-?port:?"80"protocol:?TCP與 Kubernetes 的原生網絡策略差異不大,參考前面的介紹也都看懂,我們直接進入測試。
測試
由于 Cilium 本身就實現了 CNI,所以之前的集群就不能用了,先卸載集群:
k3s-uninstall.sh #?!!!切記要清理之前的 cni 插件 sudo?rm?-rf?/etc/cni/net.d還是使用同樣的命令創建單節點的集群:
curl?-sfL?https://get.k3s.io?|?K3S_KUBECONFIG_MODE="644"?INSTALL_K3S_EXEC="--flannel-backend=none?--cluster-cidr=10.42.0.0/16?--disable-network-policy?--disable=traefik"?sh?-#?cilium?會使用該變量 export?KUBECONFIG=/etc/rancher/k3s/k3s.yaml接下來安裝 Cilium CLI:
curl?-L?--remote-name-all?https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz{,.sha256sum} sha256sum?--check?cilium-linux-amd64.tar.gz.sha256sum sudo?tar?xzvfC?cilium-linux-amd64.tar.gz?/usr/local/bin rm?cilium-linux-amd64.tar.gz{,.sha256sum}cilium?version cilium-cli:?v0.10.2?compiled?with?go1.17.6?on?linux/amd64 cilium?image?(default):?v1.11.1 cilium?image?(stable):?v1.11.1 cilium?image?(running):?unknown.?Unable?to?obtain?cilium?version,?no?cilium?pods?found?in?namespace?"kube-system"安裝 Cilium 到集群:
cilium?install待 Cilium 成功運行:
cilium?status/ˉˉ\/ˉˉ\__/ˉˉ\????Cilium:?????????OK\__/ˉˉ\__/????Operator:???????OK/ˉˉ\__/ˉˉ\????Hubble:?????????disabled\__/ˉˉ\__/????ClusterMesh:????disabled\__/Deployment????????cilium-operator????Desired:?1,?Ready:?1/1,?Available:?1/1 DaemonSet?????????cilium?????????????Desired:?1,?Ready:?1/1,?Available:?1/1 Containers:???????cilium?????????????Running:?1cilium-operator????Running:?1 Cluster?Pods:?????3/3?managed?by?Cilium Image?versions????cilium-operator????quay.io/cilium/operator-generic:v1.11.1@sha256:977240a4783c7be821e215ead515da3093a10f4a7baea9f803511a2c2b44a235:?1cilium?????????????quay.io/cilium/cilium:v1.11.1@sha256:251ff274acf22fd2067b29a31e9fda94253d2961c061577203621583d7e85bd2:?1部署應用:
kubectl?apply?-f?app.yaml待應用啟動后測試服務調用:
kubectl?exec?tiefighter?--?curl?-s?-XPOST?deathstar.default.svc.cluster.local/v1/request-landing Ship?landed kubectl?exec?xwing?--?curl?-s?-XPOST?deathstar.default.svc.cluster.local/v1/request-landing Ship?landed執行 L4 網絡策略:
kubectl?apply?-f?cilium/networkpolicy-L4.yaml再次嘗試“登陸”死星,xwing?戰機同樣無法登陸,說明 L4 層的規則生效。
我們再嘗試 L7 層的規則:
#?cilium/networkpolicy-L7.yaml apiVersion:?"cilium.io/v2" kind:?CiliumNetworkPolicy metadata:name:?"rule1" spec:description:?"L7?policy?to?restrict?access?to?specific?HTTP?call"endpointSelector:matchLabels:org:?empireclass:?deathstaringress:-?fromEndpoints:-?matchLabels:org:?empiretoPorts:-?ports:-?port:?"80"protocol:?TCPrules:http:-?method:?"POST"path:?"/v1/request-landing"執行規則:
kubectl?apply?-f?cilium/networkpolicy-L7.yaml這回,使用?tiefighter?調用死星的管理接口:
kubectl?exec?tiefighter?--?curl?-s?-XPUT?deathstar.default.svc.cluster.local/v1/exhaust-port Access?denied #?登陸接口工作正常 kubectl?exec?tiefighter?--?curl?-s?-XPOST?deathstar.default.svc.cluster.local/v1/request-landing Ship?landed這回返回了?Access denied,說明 L7 層的規則生效了。
參考資料
[1]?網絡策略?NetworkPolicy:?https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/
[2]?Cilium getting started:?https://play.instruqt.com/isovalent/tracks/cilium-getting-started
[3]?官方文檔:?https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/
[4]?K3s:?https://k3s.io
[5]?Calico:?https://www.tigera.io/project-calico/
[6]?Cilium:?https://cilium.io
[7]?eBPF:?https://ebpf.io
往期推薦
Android 13 第一個開發者版本來了,網友直呼:Android 12 還沒玩透!
CSDN企業數字化之路 ——「低代碼」發展研討會北京站現場實錄大放送
使用這個庫,讓你的服務操作 Redis 速度飛起
將 k8s 制作成 3D 射擊游戲,好玩到停不下來
點分享
點收藏
點點贊
點在看
總結
以上是生活随笔為你收集整理的使用 Cilium 增强 Kubernetes 网络安全的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 100%移植阿里云移动测试技术,竟仅需1
- 下一篇: Medusa 又一个 Shopify