使用虛拟節點提升k8s叢集容量和彈性

在kubernetes叢集中添加虛拟節點的方式已被非常多的客戶普遍使用,基于虛拟節點可以極大提升叢集的Pod容量和彈性,靈活動态的按需建立ECI Pod,免去叢集容量規劃的麻煩。目前虛拟節點已廣泛應用在如下場景。
- 線上業務的波峰波谷彈性需求:如線上教育、電商等行業有着明顯的波峰波谷計算特征,使用虛拟節點可以顯著減少固定資源池的維護,降低計算成本。
- 提升叢集Pod容量:當傳統的flannel網絡模式叢集因vpc路由表條目或者vswitch網絡規劃限制導緻叢集無法添加更多節點時,使用虛拟節點可以規避上述問題,簡單而快速的提升叢集Pod容量。
- 資料計算:使用虛拟節點承載Spark、Presto等計算場景,有效降低計算成本。
- CI/CD和其他Job類型任務
下面我們介紹如何使用虛拟節點快速建立1萬個pod,這些eci pod按需計費,不會占用固定節點資源池的容量。
相比較而言,AWS EKS在一個叢集中最多隻能建立1000個 Fargate Pod。基于虛拟節點的方式可以輕松建立過萬個ECI Pod。
建立多個虛拟節點
請先參考ACK産品文檔部署虛拟節點:
https://help.aliyun.com/document_detail/118970.html因為使用多個虛拟虛拟節點往往用于部署大量ECI Pod,我們建議謹慎确認vpc/vswitch/安全組的配置,確定有足夠的vswitch ip資源(虛拟節點支援配置多個vswitch解決ip容量問題),使用企業級安全組可以突破普通安全組的2000個執行個體限制。
通常而言,如果單個k8s叢集内eci pod數量小于3000,我們推薦部署單個虛拟節點。如果希望在虛拟節點上部署更多的pod,我們建議在k8s叢集中部署多個虛拟節點來對其進行水準擴充,多個虛拟節點的部署形态可以緩解單個虛拟節點的壓力,支撐更大的eci pod容量。這樣3個虛拟節點可以支撐9000個eci pod,10個虛拟節點可以支撐到30000個eci pod。
為了更簡單的進行虛拟節點水準擴充,我們使用statefulset的方式部署vk controller,每個vk controller管理一個vk節點,statefulset的預設Pod副本數量是1。當需要更多的虛拟節點時,隻需要修改statefulset的replicas即可。
# kubectl -n kube-system scale statefulset virtual-node-eci --replicas=4
statefulset.apps/virtual-node-eci scaled
# kubectl get no
NAME STATUS ROLES AGE VERSION
cn-hangzhou.192.168.1.1 Ready <none> 63d v1.12.6-aliyun.1
cn-hangzhou.192.168.1.2 Ready <none> 63d v1.12.6-aliyun.1
virtual-node-eci-0 Ready agent 1m v1.11.2-aliyun-1.0.207
virtual-node-eci-1 Ready agent 1m v1.11.2-aliyun-1.0.207
virtual-node-eci-2 Ready agent 1m v1.11.2-aliyun-1.0.207
virtual-node-eci-3 Ready agent 1m v1.11.2-aliyun-1.0.207
# kubectl -n kube-system get statefulset virtual-node-eci
NAME READY AGE
virtual-node-eci 4/4 1m
# kubectl -n kube-system get pod|grep virtual-node-eci
virtual-node-eci-0 1/1 Running 0 1m
virtual-node-eci-1 1/1 Running 0 1m
virtual-node-eci-2 1/1 Running 0 1m
virtual-node-eci-3 1/1 Running 0 1m
當我們在vk namespace中建立多個nginx pod時(将vk ns加上指定label,強制讓ns中的pod排程到虛拟節點上),可以發現pod被排程到了多個vk節點上。
# kubectl create ns vk
# kubectl label namespace vk virtual-node-affinity-injection=enabled
# kubectl -n vk run nginx --image nginx:alpine --replicas=10
deployment.extensions/nginx scaled
# kubectl -n vk get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-546c47b569-blp88 1/1 Running 0 69s 192.168.1.26 virtual-node-eci-1 <none> <none>
nginx-546c47b569-c4qbw 1/1 Running 0 69s 192.168.1.76 virtual-node-eci-0 <none> <none>
nginx-546c47b569-dfr2v 1/1 Running 0 69s 192.168.1.27 virtual-node-eci-2 <none> <none>
nginx-546c47b569-jfzxl 1/1 Running 0 69s 192.168.1.68 virtual-node-eci-1 <none> <none>
nginx-546c47b569-mpmsv 1/1 Running 0 69s 192.168.1.66 virtual-node-eci-1 <none> <none>
nginx-546c47b569-p4qlz 1/1 Running 0 69s 192.168.1.67 virtual-node-eci-3 <none> <none>
nginx-546c47b569-x4vrn 1/1 Running 0 69s 192.168.1.65 virtual-node-eci-2 <none> <none>
nginx-546c47b569-xmxx9 1/1 Running 0 69s 192.168.1.30 virtual-node-eci-0 <none> <none>
nginx-546c47b569-xznd8 1/1 Running 0 69s 192.168.1.77 virtual-node-eci-3 <none> <none>
nginx-546c47b569-zk9zc 1/1 Running 0 69s 192.168.1.75 virtual-node-eci-2 <none> <none>
運作1萬個ECI Pod
在上述步驟中我們已經建立了4個虛拟節點,能夠支撐12000個ECI Pod,我們隻需要将workload指定排程到虛拟節點即可。這裡我們需要關注kube-proxy的可擴充性。
- 虛拟節點建立的ECI Pod預設支援通路叢集中的ClusterIP Service,這樣每個ECI Pod都需要watch apiserver保持一個連接配接以監聽svc/endpoints變化。當大量pod同時Running時,apiserver和slb将維持Pod數量的并發連接配接,是以需要確定slb規格能否支撐期望的并發連接配接數。
- 如果ECI Pod無需通路ClusterIP Service,則可以将virtual-node-eci statefulset的ECI_KUBE_PROXY環境變量值設定為"false",這樣就不會有大量slb并發連接配接的存在,也會減少apiserver的壓力。
- 我麼也可以選擇将ECI Pod通路的ClusterIP Service暴露成内網slb類型,然後通過privatezone的方式讓ECI Pod不必基于kube-proxy也能否通路到叢集中的Service服務。
縮減vk虛拟節點數量
因為vk上的eci pod是按需建立,當沒有eci pod時vk虛拟節點不會占用實際的資源,是以一般情況下我們不需要減少vk節點數。但使用者如果确實希望減少vk節點數時,我們建議按照如下步驟操作。
假設目前叢集中有4個虛拟節點,分别為virtual-node-eci-0/.../virtual-node-eci-3。我們希望縮減到1個虛拟節點,那麼我們需要删除virtual-node-eci-1/../virtual-node-eci-3這3個節點。
- 先優雅下線vk節點,驅逐上面的pod到其他節點上,同時也禁止更多pod排程到待删除的vk節點上。
# kubectl drain virtual-node-eci-1 virtual-node-eci-2 virtual-node-eci-3
# kubectl get no
NAME STATUS ROLES AGE VERSION
cn-hangzhou.192.168.1.1 Ready <none> 66d v1.12.6-aliyun.1
cn-hangzhou.192.168.1.2 Ready <none> 66d v1.12.6-aliyun.1
virtual-node-eci-0 Ready agent 3d6h v1.11.2-aliyun-1.0.207
virtual-node-eci-1 Ready,SchedulingDisabled agent 3d6h v1.11.2-aliyun-1.0.207
virtual-node-eci-2 Ready,SchedulingDisabled agent 3d6h v1.11.2-aliyun-1.0.207
virtual-node-eci-3 Ready,SchedulingDisabled agent 66m v1.11.2-aliyun-1.0.207
之是以需要先優雅下線vk節點的原因是vk節點上的eci pod是被vk controller管理,如果vk節點上還存在eci pod時删除vk controller,那樣将導緻eci pod被殘留,vk controller也無法繼續管理那些pod。
- 待vk節點下線後,修改virtual-node-eci statefulset的副本數量,使其縮減到我們期望的vk節點數量。
# kubectl -n kube-system scale statefulset virtual-node-eci --replicas=1
statefulset.apps/virtual-node-eci scaled
# kubectl -n kube-system get pod|grep virtual-node-eci
virtual-node-eci-0 1/1 Running 0 3d6h
等待一段時間,我們會發現那些vk節點變成NotReady狀态。
# kubectl get no
NAME STATUS ROLES AGE VERSION
cn-hangzhou.192.168.1.1 Ready <none> 66d v1.12.6-aliyun.1
cn-hangzhou.192.168.1.2 Ready <none> 66d v1.12.6-aliyun.1
virtual-node-eci-0 Ready agent 3d6h v1.11.2-aliyun-1.0.207
virtual-node-eci-1 NotReady,SchedulingDisabled agent 3d6h v1.11.2-aliyun-1.0.207
virtual-node-eci-2 NotReady,SchedulingDisabled agent 3d6h v1.11.2-aliyun-1.0.207
virtual-node-eci-3 NotReady,SchedulingDisabled agent 70m v1.11.2-aliyun-1.0.207
- 手動删除NotReady狀态的虛拟節點
# kubelet delete no virtual-node-eci-1 virtual-node-eci-2 virtual-node-eci-3
node "virtual-node-eci-1" deleted
node "virtual-node-eci-2" deleted
node "virtual-node-eci-3" deleted
# kubectl get no
NAME STATUS ROLES AGE VERSION
cn-hangzhou.192.168.1.1 Ready <none> 66d v1.12.6-aliyun.1
cn-hangzhou.192.168.1.2 Ready <none> 66d v1.12.6-aliyun.1
virtual-node-eci-0 Ready agent 3d6h v1.11.2-aliyun-1.0.207