利用 K8S 的反親和性構建高可用應用
K8S 支援多副本部署,但不代表應用的高可用,因為多個副本可能部署到同一個節點上。
早上發現應用的某一個功能有一半的請求失敗,排查之後發現,原來 容器服務中節點未設定反親和性,導致 Pod 部署到同一個節點中,影響 API 閘道器請求後端服務。
架構圖
先 review 以下架構圖
- Web 應用:Vue 框架,執行在 上
- 業務 API:Golang 框架,執行在 容器服務上,使用 NodePort 方式對外暴露服務
1. 問題
在頁面中使用頁面功能時,發現有一半的請求失敗,API 返回為空。
於是想到可能和 API 閘道器請求後端介面有關,下圖為 API 閘道器對應後端通道的配置,有 2 個節點。
檢視容器服務對應 Pod,發現兩個副本都執行在同一個節點上,問題找到了。
副本跑在同一個節點的原因:隨著叢集的變化,一開始部署在兩個節點上的 Pod, 因為其中一個節點的資源被佔滿, 導致 Pod 優先排程到另一個閒置的節點上。
2. 解決問題:設定反親和性
解決問題的思路是讓 Pod 不能排程在同一臺 伺服器上,需要打散排程到所有節點中。
ChatGPT 助手的 QA 詳見附錄,也可以檢視文字的幫助文件(是透過關鍵字
Anti-Affinity
檢索到的 )
容器服務雖然有
排程策略
功能,但無法滿足當前的場景, 於是編輯 Deployment 的 YAML 配置,在 Pod 上新增
spec.template.spec.topologySpreadConstraints
segment。
topologySpreadConstraints: - labelSelector: matchLabels: k8s-app: XXX qcloud-app: XXX maxSkew: 1 topologyKey: kubernetes.io/hostname whenUnsatisfiable: ScheduleAnyway
解讀:
maxSkew
設定為 1 表示允許的最大偏差為 1,即任一節點上的 Pod 數量不會比其他節點多 1 個以上。topologyKey
為"kubernetes.io/hostname"
,意味著在不同的節點上分佈 Pods。
部署後,Pod 分佈到多個節點上,問題解決。
3. 事後思考
- 開啟 API 閘道器的健康檢查,當 API 閘道器探測節點失效時從後端通道中剔除
- 瞭解 K8S 資源排程的基本概念
附錄:ChatGPT 助手
Q: TKE 如何設定讓 Deployment 的 2 個 Pod 分配到兩個節點上,目前 兩個 Pod 分配到同一個 節點中。
A(ChatGPT-4-turbo): TKE(Tencent Kubernetes Engine)是騰訊雲提供的託管 Kubernetes 服務。在 Kubernetes 中,如果希望讓 Deployment 的 Pods 分佈在不同的節點上,可以使用幾種策略,主要包括:
1. 親和性(Affinity)和反親和性(Anti-Affinity)規則:
使用 Pod 反親和性規則可以指定 Kubernetes 排程器不要將屬於同一 Deployment 的 Pods 排程到同一節點上。
例如,以下是一個 Deployment 配置的示例,它使用了 Pod 反親和性來確保 Pods 分散到不同的節點上:
apiVersion: apps/v1kind: Deploymentmetadata: name: my-deploymentspec: replicas: 2 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: containers: - name: myapp-container image: myapp:1.0 affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: "app" operator: In values: - myapp topologyKey: "kubernetes.io/hostname"
在這個例子中,
requiredDuringSchedulingIgnoredDuringExecution
確保排程器在排程時遵循這些規則,而
topologyKey
設定為
"kubernetes.io/hostname"
表示 Pods 不能在擁有相同主機名的節點上執行。
2. 使用 Pod Topology Spread Constraints:
Pod Topology Spread Constraints 允許你更細粒度地控制 Pods 的分佈,這可以透過設定
maxSkew
、
topologyKey
和
whenUnsatisfiable
等引數來實現。
以下是一個使用 Pod Topology Spread Constraints 的 Deployment 示例:
apiVersion: apps/v1kind: Deploymentmetadata: name: my-deploymentspec: replicas: 2 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: containers: - name: myapp-container image: myapp:1.0 topologySpreadConstraints: - maxSkew: 1 topologyKey: "kubernetes.io/hostname" whenUnsatisfiable: "ScheduleAnyway" labelSelector: matchLabels: app: myapp
在這個配置中,
maxSkew
設定為 1 表示允許的最大偏差為 1,即任一節點上的 Pod 數量不會比其他節點多 1 個以上。
topologyKey
同樣設定為
"kubernetes.io/hostname"
,意味著在不同的節點上分佈 Pods。
確保你的 Kubernetes 叢集有足夠的不同節點來支援這些分佈策略。如果叢集中只有一個可用節點,或者其他節點因為資源限制(如 CPU、記憶體不足)無法排程 Pods,那麼這些策略可能不會有效。
來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70030722/viewspace-3007532/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 用 Hystrix 構建高可用服務架構架構
- 構建高可用性、高效能和可擴充套件的Zabbix Server架構套件Server架構
- .1.7.2 應用程式高可用性與服務和FAN
- k8s高可用架構K8S架構
- 反應性和非反應性程式碼的分離 - DZone
- 構建生產環境可用的高可用kubernetes叢集
- 如何利用容器與中介軟體實現微服務架構下的高可用性和彈性擴充套件微服務架構套件
- 用Java構建反應式REST API - Kalpa SenanayakeJavaRESTAPINaN
- K8s 容器的定向排程與親和性K8S
- 利用Azure Functions和k8s構建Serverless計算平臺FunctionK8SServer
- 使用Keepalived構建LVS高可用叢集
- Kubernetes排程之親和與反親和
- 資深架構師談Redis高可用架構的應用及改進架構Redis
- ELK架構下利用Kafka Group實現Logstash的高可用架構Kafka
- 構建持續高可用系統的破局之道
- 如何快速構建服務發現的高可用能力
- 構建MHA實現MySQL高可用叢集架構MySql架構
- Mysql+Corosync+Pacemaker+DRBD構建高可用MMySqlROS
- 高可用服務之Keepalived利用指令碼實現服務的可用性檢測指令碼
- 搭建高可用k8sK8S
- RabbitMQ從零到叢集高可用(.NetCore5.0) -高可用叢集構建落地MQNetCore
- 融合資料庫生態:利用 EventBridge 構建 CDC 應用資料庫
- 使用 Yarn workspace,TypeScript,esbuild,React 和 Express 構建 K8S 雲原生應用(一)YarnTypeScriptUIReactExpressK8S
- 華為雲FunctionGraph構建高可用系統的實踐Function
- KubeSphere 最佳實戰:K8s 構建高可用、高效能 Redis 叢集實戰指南K8SRedis
- Activemq構建高併發、高可用的大規模訊息系統MQ
- 5、pgpool-II高可用性(一)資料庫的高可用性資料庫
- 高可用架構架構
- 使用 MaxScale 實現資料庫的高可用性和彈性資料庫
- 基於Redis構建微服務的反應式架構 - bitsrcRedis微服務架構
- 【譯】使用 Webpack 和 Poi 構建更好的 JavaScript 應用WebJavaScript
- 如何構建高可用、高併發、高效能的雲原生容器網路?
- 利用OC物件的訊息重定向forwardingTargetForSelector方法構建高擴充套件性的濾鏡功能物件Forward套件
- 構建 API 應用API
- 使用Java和Spring MVC構建Web應用JavaSpringMVCWeb
- 使用Java和Reactive Streams構建流式應用JavaReact
- 使用Rust和WebAssembly構建Web應用程式RustWeb
- LVS + Keepalived + Nginx基於DR模式構建高可用方案Nginx模式