GKE + Anthos Bare Metal 叢集節點失效測試

Shawn Ho
輕鬆小品-k8s的點滴
9 min readFeb 13, 2023

最近有人問到K8S裡的節點失效,會不會造成相關的服務衝擊。這個問題說真的我自己沒自己做過,決定自己來測試看看,同時也參考了其他人的文件,來了解K8S的節點失效後對Pod的影響。古人說:『數大就是美』,如果只有服務只有單個pod(single instance),那想當然會停機,參考一些文獻後,應該停機時間約在至少5分40秒。如果部署時,有考慮多instance,可以在節點無預警停機時,大幅降低斷線停機時間至40秒左右。

Lots of Kubernetes Pod in Van Gogh Style: (by DALL-E)

Single Instance

[1] Pod Disruption Conditions

[2] What Happens To Pods Running On Node That Become Unreachable?

[3] [Kuberbetes] Taints and Tolerations

[1/3]文件裡面,說明了各類Pod 失效的場合,包含:

  • PreemptionByKubeScheduler:通過kube-scheduler 把原有的Pod清出來,讓更重要的Pod進駐。
  • DeletionByTaintManager:通過Taint Manager 機制,將無法忍受Taint的Pod移除。
  • EvictionByEvictionAPI通過K8S API 標註,由kubelet將Pod驅離節點。
  • DeletionByPodGC通過Pod garbage collection(PodGC) 機制,將在失效節點上的Pod回收。
  • TerminationByKubelet 因為Node Pressure或是Graceful Node Shutdown場景由Kubelet 回收Pod。

[2]文件中,談到的是如果節點故障,K8S的因應機制。這裡可以看到K8S叢集Master會等Node-Monitoring-Period 逾時(40秒)後,宣布節點Not Ready,之後Controller Manager會再等pod-eviction-timeout (5分鐘)後,將Pod在別的Worker Node開啟。如果很不幸你的Pod 僅能有一個instance,或是服務進入的Critical Path (e.g. Ingress, Istio Ingress Gateway, 甚至是MetalLB)只有一份,如果這一份instance所在的Worker Node損壞,那預設至少會花5分40秒,服務才有機會回復(還得加上新Pod啟動時間)。

Source from [2]

Multiple Instances

可能有人問,如果我有多個instances,是不是就可以避免這個問題?首先,我們得先注意是不是整條服務的Connection Path上都有多個instances,舉例: 在Anthos Bare Metal上,L4 LoadBalancer必須通過MetalLB提供,如果又使用Istio IngressGateway作為南北向LoadBalancer,其Connection Path 包含了 MetalLB + Istio-IngressGateway + App Pods 如下:

Connection Path on Anthos Bare Metal with ASM

如果是GKE,其Connection Path包含 GCP GCLB + Istio IngressGateway + App Pods如下:

Connection Path on GKE & ASM

MetalLB (Layer2): Node Forced Shutdown

以Anthos BM為例,我們先看MetalLB的效應,Anthos BM預設的Bundled LB機制,是使用MetalLB L2的連線作為LoadBalancer的路由,這個機制會在指定的Edge NodePool產生Daemonset 並在收到 K8S ServiceType = LoadBalancer 時,指派所需的IP位置到其中一個Pod,並發送ARP封包告知Client。如果帶著該IP的Pod的工作節點遇到不正常停機,MetalLB Controller會將IP分配到另一台主機,並重新發送ARP封包通知。

ARP的更新,會造成約數秒的停機時間,在MetalLB的文件中說的worst case大概是10秒左右。我們也進行了相關的測試,下圖測試中,我們使用3個視窗:左邊視窗持續以curl方式連線後端服務,右下角視窗以arping確認arp被改變的時間點,右上角發命令關閉帶有該IP的MetalLB Speaker Pod的節點。

做了幾次的實驗裡,服務幾乎沒有受到什麼影響,每秒一次的curl沒有發現因為Service IP的切換造成timeout的狀況。MetalLB的另一種BGP模式,雖然由Router取代Spoken Pod,但BGP協定對於節點更換仍會有One-Time的Active connection reset的問題。建議使用MetalLB的捧油盡量在低流量的時候進行叢集或是節點升級。

Istio Ingress + K8S service (Multiple Instances):Node Forced Shutdown

確認完MetalLB後,我們來驗證後方的Istio + K8S服務。首先為了保證Istio ingressgateway與K8S service pod都分布在不同機器上,我們使用anti-affinity的機制,其中RequiredDuringScheduling + TopologyKey=kubernetes.io/hostname 的設定,保證每個節點只能有一個帶著app: whereami 標籤的Pod。如果使用本設定,請記得Node必須至少為Pod Replicas數量+1。

apiVersion: apps/v1
kind: Deployment
metadata:
name: whereami
namespace: test
spec:
replicas: 2
selector:
matchLabels:
app: whereami
template:
metadata:
labels:
app: whereami
spec:
containers:
- name: whereami
image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.19
ports:
- containerPort: 8080
resources:
requests:
memory: "512Mi"
cpu: "1000m"
limits:
memory: "512Mi"
cpu: "1000m"
startupProbe:
httpGet:
path: /
port: 8080
livenessProbe:
httpGet:
path: /
port: 8080
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- whereami
topologyKey: "kubernetes.io/hostname"

下方的測試,我們將whereami pod以及istio ingressgateway pod都部署2個replicas,為了驗證istio ingressgateway是否會造成更長的recovery time, 我們也故意將whereami的服務入口,也直接接上MetalLB,提供兩條測試路徑。

我們關閉其中一台帶有各1個replica 的工作節點。在下圖右上角我們的Client是直接連線Whereami service,右下角的Client,通過istio-ingressgateway,連接whereami服務。

在測試時,我們發現如果Client端的curl指令,若使用預設timeout (120秒),在節點被不正常關閉時,會發生等timeout而卡住的狀況,因此我們可推論,對於既有正在服務的客戶,即使有多個instances,當節點失聯時,還是會有短暫斷線的狀況。對於Timeout後重新連線的用戶,我們也發現,仍有一半的機率有機會被導流到正在被關閉的Pod (e.g. istio ingressgateway or whereami pod),直到Node被標註為Not Ready,kube-proxy就不再將流量指向該服務,而僅連到正常的instance中。Multi-Instance較Single-Instance可將斷線時間限制在數十秒,而不是5分40秒。

Istio Ingress + K8S service (Multiple Instances):Node Graceful Shutdown

當然不可免俗的,我們還是推薦如果不是突然節點失效。而是要進行節點維護或是升級時,應該正常的使用kubectl cordon + kubectl drain的機制,將Pod Evict後再關機,我們也驗證了這個做法。下圖可見,幾乎是沒有任何的Downtime or Timeout。

--

--

Shawn Ho
輕鬆小品-k8s的點滴

一個心態年輕的中年大叔。年輕時不學好~ 台大電機畢業後,去美國取得了博士學位,念完博士後,不想教書。當過補習班老師,碼農,產品總監,ISO稽核顧問,技術銷售,目前在Google Cloud跟客戶一起玩Kubernetes,也跟喜歡的客戶在金融, 政府, 電信, 高科技業內共同成長學習是斜槓人生的好案例。