作者 | 溪恆 阿里雲技術專家
直播完整視頻回顧:https://www.bilibili.com/video/BV1nC4y1x7mt/
關注“阿里巴巴雲原生”公眾號,后台回復 “416” 即可下載 PPT。
4 月 16 日,我們發起了第 2 期 SIG Cloud-Provider-Alibaba 網研會直播。本次直播主要介紹了阿里雲在雲原生環境中如何設計和構建高性能雲原生容器網絡。本文匯集了此次直播完整視頻回顧及資料下載,並整理了直播過程中收集的問題和解答,希望能夠對大家有所幫助~
本文匯集了此次直播完整視頻回顧及資料下載,並整理了直播過程中收集的問題和解答,希望能夠對大家有所幫助~
前言
首先,給大家介紹一下 Cloud Provider SIG, Cloud Provider SIG 是 Kubernetes 的雲廠商興趣小組,致力於讓 Kubernetes 的生態系統往廠商中立的方向演進,他會負責協調不同廠商盡可能以統一的標准來滿足開發者的需求。阿里雲作為國內首個加入 Cloud Provider SIG 的雲廠商也在推動 Kubernetes 的進一步標准化,並進一步和橫向雲廠商如 AWS、Google、Azure 進行技術協同,優化雲和 Kubernetes 連接,並統一不同組件的模塊化和標准化協議。非常期待你與我們一同共建。
第 1 期網研會回顧:Kubernetes SIG-Cloud-Provider-Alibaba 首次網研會(含 PPT 下載)
隨着雲原生計算的普及,越來越多的應用負載都部署在 Kubernetes 之上,Kubernetes 已成為雲原生計算的基石,成為用戶和雲計算新的交互界面。而網絡作為應用的最基礎的依賴之一,在應用雲原生化中是必不可少的基礎組件,也是很多開發者在雲原生化時最擔心的地方,面臨很多問題,例如容器網絡跟原有機器網絡不在一個平面,容器的 Overlay 容器網絡帶來了封包的性能損失,Kubernetes 的負載均衡和服務發現的可擴展性不足等等。那么怎樣才能構建集群容器網絡呢?
本次分享將會介紹阿里雲在雲原生環境中如何設計和構建高性能雲原生容器網絡。
今天的分享將從 3 個方面進行:
- Kubernetes 容器網絡概述
- 構建高性能雲原生 CNI 網絡
- 增強網絡的擴展性和性能
Kubernetes 容器網絡概述
首先我們會介紹下 Kubernetes 容器網絡的基礎概念,包括:
- Pod 網絡連通性(CNI)
- Kubernetes 負載均衡(Service)
- Kubernetes 服務發現(Coredns)
Pod 網絡連通性(CNI)
如下所示是 Kubernetes Pod 網絡示意圖:
首先我們會介紹 Pod 網絡的連通性,這里就是我們常說的 CNI 網絡,主要包含了以下內容:
- Pod 有自己獨立的網絡空間和 IP 地址。不同 Pod 的應用可以監聽同樣的端口而不沖突;
- Pod 可以通過各自的 IP 地址互相訪問。集群中 Pod 可以通過它獨立的 IP 地址訪問其它網絡:Pod 和 Pod 的聯通;Pod 與 Node 的聯通;Pod 與外部網絡連通。
而實現這些網絡的能力,需要地址分配和網絡打通,通常是由網絡插件(CNI)來負責實現的。
什么是 CNI
CNI 插件即 Container Network Interface,是 K8s 配置容器網絡的 API 接口。CNI 插件就是實現了這個 API 的一系列網絡插件,例如我們常見的有 Terway,Flannel, Calico 等等。
在我們創建 Pod 時:
- Kubelet 會首先從 ApiServer 監聽到 Pod 的創建,會創建 Pod 的沙箱;
- 然后通過 CNI 接口調用 CNI 的插件去配置容器的網絡;
- CNI 會配置 Pod 的網絡空間,以及打通不同 Pod 之間的網絡訪問。
如何打通的網絡?
通常 Pod 跟宿主機網絡不在一個平面,要如何打通 Pod 之間通信呢?一般實現 Pod 之間聯通的方案有兩種:
- 封包方式:容器之間的通信報文封裝成宿主機之間通信的報文;
- 路由方式:容器之間的通信報文由路由表轉發到對應的節點上。
Kubernetes 網絡負載均衡(Service)
為什么需要 Kubernetes Service?原因如下:
- Pod 生命周期短暫,IP 地址隨時變化,需要固定的訪問方式;
- Deployment 等的一組 Pod 組需要統一訪問入口和做負載均衡。
Kubernetes Service
- Kubernetes Service 對象創建會分配一個相對固定的 Service IP 地址;
- 通過 labelSelector 選擇到一組 Pod,將這個 Service IP 地址和端口負載均衡到這一組 Pod IP 和端口上;
- 從而實現一組 Pod 固定的訪問入口,並對這一組 Pod 做負載均衡。
Kubernetes LoadBalancer Service
Kubernetes 服務發現(DNS)
- 雖然 Service 固定了 IP 訪問方式,但 Service 的 IP 在不同的 namespace 或者集群中是不同的,如何統一?
- 集群的 Coredns 會將 Service 名自動轉換成對應的 Service 的 IP 地址,來實現不同部署環境中同樣的訪問入口。
構建高性能雲原生的 CNI 網絡
什么是雲原生容器網絡?
雲上 IaaS 層網絡虛擬化,在容器中再做一層網絡虛擬化帶來的性能損失比較大。
雲原生容器網絡是直接使用雲上原生雲資源配置容器網絡:
- 容器和節點同等網絡平面,同等網絡地位;
- Pod 網絡可以和雲產品無縫整合;
- 不需要封包和路由,網絡性能和虛機幾乎一致。
在 CNI 調用中調用雲網絡 OpenAPI 完成網絡資源分配:
- 網絡資源一般是彈性網卡,彈性網卡輔助 IP 等,綁定到 Pod 所在的節點上;
- 網絡資源分配出來之后 CNI 插件在宿主機中將資源配置到 Pod 的沙箱中。
由於容器的網絡直接成為了 VPC 中的一等公民,所以使用雲原生容器網絡會有這些優勢:
- Pod 和虛擬機同一層網絡,便於業務雲原生化遷移;
- 不依賴封包或者路由表,分配給 Pod 的網絡設備本身可以用來通信;
- 集群節點規模不受路由表或者封包的 FDB 轉發表等 Quota 限制;
- 不需要額外為 Pod 規划 Overlay 的網段,多個集群Pod之間只要安全組放開就可以互相通信;
- 可以直接把 Pod 掛到 LoadBalancer 后端,無需節點上端口再做一層轉發;
- NAT 網關可以對 Pod 做 SNAT,無需節點上對容器網段做 SNAT:Pod 訪問 VPC 內資源,所帶的源 IP 都是 PodIP,便於審計;Pod 訪問外部網絡不依賴 conntrack SNAT,失敗率降低。
如何利用雲原生資源構建容器網絡?
IaaS 層網絡資源(以阿里雲為例):
- 彈性網卡(ENI)。 IaaS 層虛擬化出來的虛擬網卡,可動態分配和綁定到虛擬機上;一般能綁定數量有限,受限於 PCI-E 的限制;
- 彈性網卡輔助 IP。彈性網卡上通常可以綁定多個 VPC 的 IP 地址,為輔助 IP;一個彈性網卡可以綁定數十個輔助 IP 地址,限制較小。
利用彈性網卡或者彈性網卡輔助 IP 分配給 Pod 來實現雲原生容器網絡:
容器網絡資源管理
如何解決雲資源跟容器快速擴縮容的差距:
- 容器的啟動速度是秒級的, 而 IaaS 層操作和調用一般在 10s 的級別;
- 容器擴縮容操作頻繁,雲產品 OpenAPI 通常有嚴格的調用限流。
Terway 通過內置資源池來緩沖資源加速啟動:
- 資源池中記錄分配的正在使用和空閑的資源;
- Pod釋放后資源會保留在資源池中供下次快速啟動;
- 資源池有最低水位和最高水位。空閑資源低於最低水位調用 API 補充資源,預熱資源減緩峰值 Pod 創建對 API 的調用;空閑資源高於最高水位調用 API 釋放資源。
對並行的 Pod 網絡配置調用批量申請資源:
除此之外還有很多資源管理策略,例如:如何選擇 Pod 要用的虛擬交換機,保證 IP 充裕?如何平衡每個節點上的網卡的隊列和中斷數,保證爭搶最少?
可參考 Terway 文檔或代碼:https://github.com/AliyunContainerService/terway。
網絡如何打通
Pod 獨占彈性網卡模式:
它的在CNI的實現方式是:
- 通過 Terway 資源管理將彈性網卡綁定 Pod 所在 Node;
- Terway CNI 將網卡直接移入到 Pod 網絡空間;
- Terway CNI 為其網卡配置 IP 和路由等網絡配置。
這種方式的特點和優勢是:
- Pod 網絡完全不經過宿主機網絡棧
- 性能和 ECS 機器一致,無損耗
- Pod 中為彈性網卡,可以使用 DPDK 等加速應用
Pod 共享彈性網卡模式:
它的在CNI的實現方式是:
- Terway 資源管理器根據申請的 IP 數量和現有 ENI上IP 來判斷申請 ENI 還是輔助 IP 地址
- Terway CNI 在 ENI 上創建 IPVLAN 子接口
- 將 IPVLAN 子接口放入到 Pod 網絡空間
- 配置 Pod 網絡空間的 IP 和路由信息
這種方式的特點和優勢是:
- IPVLAN 網絡僅部分經過網絡棧,不走 iptables、路由表,損耗極低
- 一個彈性網卡一般支持 10~20 個輔助 IP,不擔心部署密度
性能對比
- TCP_RR、UDP、PPS、帶寬和延時都優於通用的 Flannel Vxlan 的 Overlay 網絡;
- 獨占 ENI 模式可以跑滿機器的網絡資源 PPS 和帶寬無損失,適合於高性能計算和游戲場景。
增強 Kubernetes 網絡擴展性和性能
Kubernetes Service 性能和擴展性問題
默認的 Kubernetes 的 Service 實現 kube-proxy,它是使用了 iptables 去配置 Service IP 和負載均衡:
如上圖所示:
- 負載均衡過程的 iptables 鏈路長,導致網絡延時顯著增加,就算是 ipvs 模式也是繞不開 iptables 的調用;
- 擴展性差。iptables 規則同步是全量刷的,Service 和 Pod 數量多了,一次規則同步都得接近 1s;Service 和 Pod 數量多了之后,數據鏈路性能大幅降低。
NetworkPolicy 性能和擴展性問題
NetworkPolicy 是 Kubernetes 控制 Pod 和 Pod 間是否允許通信的規則。目前主流的 NetworkPolicy 實現基於 iptables 實現,同樣有 iptables 的擴展性問題:
- iptables 線性匹配,性能不高, Scale 能力差
- iptables 線性更新,更新速度慢
使用 eBPF 加速 Service 和 NetworkPolicy 擴展性
關於 eBPF 的介紹如下:
- Linux 在最近版本提供的可編程接口
- 通過 tc-ebpf 將 ebpf 程序注入到網卡中
- 用於大幅降低網絡鏈路的長度和復雜度
如上圖所示,使用 tc 工具注入 eBPF 程序到 Pod 的網卡上,可以直接將 Service 和 NetworkPolicy 在網卡中解決,然后直接轉發到彈性網卡,大幅降低網絡復雜度:
- 每個節點上運行 eBPF Agent,監聽 Service 和 NetworkPolicy,配置容器網卡的 Ingress 和 Egress 規則;
- 在 Egress 的 eBPF 程序中,判斷訪問 k8s Service IP 的請求直接負載均衡到后端 Endpoint;
- 在 Ingress 的 eBPF 程序中,根據 NetworkPolicy 規則計算源 IP 決定是否放行。
PS:我們使用 Cilium 作為節點上的 BPF-agent 去配置容器網卡的 BPF 規則,已貢獻 Terway 相關適配:https://github.com/cilium/cilium/pull/10251
性能對比
- 通過 eBPF 對鏈路的簡化,性能有明顯提升,相對 iptables 提升 32%, 相對 ipvs 提升 62%;
- 通過編程的 eBPF 的形式,讓 Service 數量增加到 5000 時也幾乎沒有性能損耗,而 iptables 在 Service 增加到 5000 時性能損失了 61%。
Kubernetes Coredns 性能和擴展性問題
Kubernetes Pod 解析 DNS 域名會 search 很多次,例如上圖 Pod 中 DNS 配置,當它請求 aliyun.com,會依次解析:
- aliyun.com.kube-system.svc.cluster.local -> NXDOMAIN
- aliyun.com.svc.cluster.local -> NXDOMAIN
- aliyun.com.cluster.local -> NXDOMAIN
- aliyun.com -> 1.1.1.1
Coredns 是中心化部署在某一個節點上的,Pod 訪問 Coredns 解析經過鏈路過長,又是 UDP 協議,導致失敗率高。
使用 AutoPath 大幅降低 Pod DNS 的查詢量
由客戶端 Search 變成服務端 Search:
當 Pod 請求 Coredns 時解析域名:
- Coredns 會通過源 IP 地址查詢到 Pod 的信息
- 然后根據 Pod 的 Namespace 信息,匹配到它真正想訪問的是哪個服務直接返回
- 客戶端請求從 4 個直接減少到 1 個,降低了 75% 的 Coredns 請求,從而讓失敗率降低
在每個節點上使用 node-local-dns
- 攔截 Pod 的 DNS 查詢的請求
- 將外部域名分流,外部域名請求不再請求中心 Coredns
- 中間鏈路使用更穩定的 TCP 解析
- 節點級別緩存 DNS 解析結果,較少請求中信 Coredns
ExternalDNS 直接使用阿里雲的域名解析服務
- 雲原生的 DNS 解析,Pod 直接請求雲服務 PrivateZone 中的自定義 DNS 能力
- 由 ExternalDNS 監聽到服務和 Pod 創建后配置 PrivateZone 中的域名解析
- 和原生的 ECS 解析同樣的 DNS 解析性能
總結
以上就是阿里雲的高性能雲原生的容器網絡設計和構建過程,隨着雲原生的不斷發展,會有越來越多類型的應用負載運行在 K8s 上,同時也會有更多的雲服務會融入到容器場景之中。我們相信以后在高性能的雲原生容器網絡中會孵化出更多的功能和應用場景。
歡迎有興趣的同學一起參與共建!
- 項目地址: https://github.com/AliyunContainerService/terway
- 釘釘掃碼加入交流群:
Q & A
Q1:創建 pod netns 的時候, 是使用 veth pair 連接 pod netns 和 host 的嗎?
A1:詳見下方內容。
-
共享 ENI 模式:在 3.10 的內核中,為了兼容性,我們使用 veth pair 打通的 namespace,而在 4.x 的內核中,比如阿里雲上我們使用的 aliyunlinux2,是 4.19 的內核,我們采用的是 IPVlan 打通的 namespace;
-
獨享 ENI 模式:直接把 ENI 挪到 Pod 的 namespace 中,不需要打通 host 和 pod 的空間。
Q2:Pod IP 不固定怎么做安全審計?
A2:詳見下方內容。
-
Pod 在其聲明周期中 IP 是不變的,可以在 K8s 的事件中找到這個 IP 地址在某個事件分配給了哪個 Pod 做對照;
-
在 Terway 的 NetworkPolicy 的實現中,是通過 label 的方式標識 Pod 的,當 Pod 重建后監控到會動態更新 label 對應 Pod 的 IP 地址;
-
另外 Terway 配置給 Pod 的 IP 是相對固定的,比如在某一個節點更新 Statefulset 應用時,Terway 會在之前的 IP 釋放時為其保留一段時間供其再次啟動時快速使用起來,更新過程中 IP 就不會變化了。
Q3:ipvlan 對內核要求比較高吧?
A3:是的,在阿里雲上,我們可以使用 aliyunlinux2 的 4.19 的內核。對於低內核,Terway 也是支持 veth pair+ 策略路由方式來共享 ENI 上的輔助 IP,只是性能會低一些。
Q4:在 pod 內啟動 ebpf, 會不會影響 pod 啟動的速度? pod 內的 ebpf 部署時間估計是多少?
A4:ebpf 的程序代碼不會太大,目前看整個部署時間增加在百毫秒的級別。
Q5:是否支持 IPV6,實現上遇到了什么問題嗎?內核或 kube-proxy 代碼問題?
A5:目前支持通過 IPV6 的 LoadBalancer 暴露,但實現還是在 LoadBalancer 中做 6to4 轉換。目前 Pod 還未支持 IPV6,K8s 從 1.16 中 kube-proxy 等開始支持 IPV6,我們也在積極跟進,計划今年會和阿里雲 IaaS 一起實現原生的 Pod IPv4/IPv6 雙棧。
Q6:每次請求 coredns 解析,都去根據源 ip 去獲取直接訪問的服務,是調用 K8s api 獲取嗎?會不會增加 api 的壓力?
A6:不會的,那里那樣畫是為了讓結構更易於理解,實際上 Coredns 的 AutoPath 會通過 watch&list 的機制去從 ApiServer 那里監聽 Pod 和 Svc 的變化,然后更新本地的緩存。
Q7:K8s 的 Service 請求到一組 pod,這個過程是輪詢的嗎?請求到每個 pod 的概率是一樣的嗎?
A7:對,概率是一樣的,可以理解為 LB 領域的 roundrobin 算法。
Q8:ipvlan 和 ebpf 好像是高內核才支持的,是不是對宿主機內核有要求?
A8:是的,在阿里雲上,我們可以使用 aliyunlinux2 的 4.19 的內核。對於低內核,Terway 也是支持 veth pair + 策略路由方式來共享 ENI 上的輔助 IP,只是性能會低一些。
Q9:cilium 是如何管理 ip 的呢,或者說分配 ip?類似其他的 cni 插件管理 ip pool 嗎?
A9:cilium 本身有兩種分配 IP 的辦法:host-local:就是每個節點分段,然后順序分配;另外一種是 CRD-backend,可以讓 IPAM 插件自己實現分配。Terway 中的 cilium 只會做網絡策略和 Service 的劫持和負載,不會做 IP 分配和配置。
Q10:cilium 應該不是注入 bpf 到容器的 veth,而是注入到 host 端的 veth?你們做了什么修改嗎?
A10:是的,cilium 是修改的容器對側的 veth,我們經過測試發現 IPvlan 的性能優於 veth,Terway 中是使用 IPvlan 做的高性能網絡,是不存在對側 veth 的。我們適配的修改請參考:https://github.com/cilium/cilium/pull/10251, 另外 Terway 使用 Cilium 只會做 NetworkPolicy 和 Service 的劫持和負載。
Q11:使用 terway 插件后, pod 是如何訪問 service 的 clusterip 的?
A11:使用內置在 Pod 網卡上的 ebpf 程序直接將 serviceIP 負載到后端的 pod。
Q12:能聊下阿里雲對 service mesh 這塊有什么規划嗎?
A12:阿里雲目前已經產品化了 ASM 的 Service Mesh 產品,后面的發展會在易用性、性能以及全球跨地域雲邊端一體化連接等方向。
Q13:和 node 的網絡打通后,如果一個 pod 的 ip 被復用,之前的 arp 緩存應該會有影響吧?同時出現節點級別的故障,是否會有 IP 沖突?
A13:首先雲上的網絡不會存在 arp 的問題,一般 IaaS 層的轉發采用 3 層的轉發,如果雲下自己使用 IPvlan也不存在這個問題,使用 Macvlan 的話會有 arp 緩存的影響,一般來說可以采用 macnat 的方式(ebtables,ebpf 都可以實現哈)。是否存在 IP 沖突是要看 IP 管理策略,在目前的 Terway 方案中 IPAM 直接調用 IaaS 的IPAM,是不存在這個問題的,自己線下搭建得考慮 DHCP 策略或靜態分配 IP 地址去規避。
Q14:“通過 eBPF 對鏈路的簡化,性能有明顯提升,相對 iptables 提升 32%, 相對 ipvs 提升 62%;”為什么對 ipvs 性能的提升更明顯?如果主要是對 iptables 的線性匹配和更新優化的話?
A14:這里的這個對比是針對只有一個 Service 的對比,是主要看鏈路簡化的影響。iptables 模式是 nat 表進行的 DNAT,是只有 forward 流程,而 ipvs 是會經過 INPUT 和 OUTPUT 的,所以在單個服務的情況下 iptables 可能還會更好一些,但是 iptables 的線性匹配會讓服務數量很多時性能下降明顯。比如 5000 service 時就 ipvs 更好啦 XD:
Q15:如果沒有用這套網絡方案,又覺得 service 大規模使用影響性能,有什么好的方案嗎?
A15:kube-proxy ipvs 模式的性能在大規模中損失還好,但其實整體引入了過長的鏈路,所以延時會增加一些。
“阿里巴巴雲原生關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的公眾號。”