在 Kubernetes 環境中,確保 Ingress 控制器的穩定性至關重要。本文將探討如何使用 HAProxy 作為自定義負載平衡器,提升 NGINX Ingress 的高用性。實際操作中,我們會發現單節點 Ingress 控制器存在風險,而 HAProxy 可以監控後端 Ingress Pod 的健康狀態,並自動調整流量路由,避免單點故障。透過模擬 kubelet 服務中斷,我們可以驗證 HAProxy 如何自動切換流量到健康的 Ingress Pod,確保服務不間斷。此方法適用於任何需要高用性的 Ingress 控制器佈署場景,有效提升服務的穩定性和可靠性。
為Ingress新增自定義負載平衡器
在前面的章節中,我們已經瞭解瞭如何使用KinD佈署Kubernetes叢集。在這個章節中,我們將探討如何為Ingress新增自定義的負載平衡器。
瞭解當前叢集組態
首先,我們來看看當前叢集的組態。與之前的兩節點叢集不同,這個叢集的worker節點沒有暴露在任何主機埠上。這是因為我們已經有了一個新的HAProxy伺服器在執行。如果我們檢視建立的HAProxy容器,會發現它暴露在主機的80和443埠上。這意味著任何到達主機80或443埠的請求都會被導向自定義的HAProxy容器。
預設NGINX佈署的問題
預設的NGINX佈署只有一個副本,這意味著Ingress控制器執行在單一節點上。如果我們檢視HAProxy容器的日誌,會看到一些有趣的資訊:
[NOTICE] 093/191701 (1) : New worker #1 (6) forked
[WARNING] 093/191701 (6) : Server ingress_https/worker is DOWN, reason: Layer4 connection problem, info: "SSL handshake failure (Connection refused)", check duration: 0ms. 2 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
[WARNING] 093/191702 (6) : Server ingress_https/worker3 is DOWN, reason: Layer4 connection problem, info: "SSL handshake failure (Connection refused)", check duration: 0ms. 1 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
內容解密:
- 這段日誌顯示了HAProxy容器的執行狀態和後端伺服器的健康檢查結果。
[NOTICE]表示新的worker程式被fork出來。[WARNING]表示後端伺服器ingress_https/worker和ingress_https/worker3不可用,原因是SSL握手失敗或連線被拒絕。check duration: 0ms表示健康檢查的耗時。2 active and 0 backup servers left表示目前有2個活動伺服器和0個備份伺服器。
分析HAProxy日誌
從日誌中可以看到,HAProxy正在檢查後端伺服器的狀態。由於NGINX只執行在一個pod中,而我們的HAProxy後端組態包含了所有三個節點,因此HAProxy會檢查每個節點上的埠。任何未能回應的節點都不會被用來負載平衡流量。
模擬Kubelet故障
為了證明HAProxy為NGINX提供了高用性,我們可以模擬一個節點故障。由於KinD節點是短暫的,簡單地停止容器可能會導致它在重啟時失敗。因此,我們可以透過停止某個節點上的kubelet服務來模擬故障。
docker exec cluster01-worker2 systemctl stop kubelet
執行此命令後,如果等待幾分鐘讓叢集接收更新的節點狀態,可以透過檢視節點列表來驗證節點是否已關閉:
kubectl get nodes
模擬Kubelet故障流程
圖表翻譯: 此圖示展示了模擬Kubelet故障的流程。首先停止worker2上的kubelet服務,然後等待叢集更新節點狀態。接著,使用kubectl get nodes檢查節點狀態。如果worker2處於NotReady狀態,則刪除nginx-ingress-controller pod,促使HAProxy更新後端列表。
驗證高用性
刪除nginx-ingress-controller pod以強制重新排程:
kubectl get pods -n ingress-nginx
nginx-ingress-controller-7d6bf88c86-r7ztq
kubectl delete pod nginx-ingress-controller-7d6bf88c86-r7ztq -n ingress-nginx
這將強制排程器在另一個worker節點上啟動容器。同時,HAProxy容器會更新後端列表,因為NGINX控制器已經移動到另一個worker節點。
再次檢視HAProxy日誌,可以看到HAProxy已經更新了後端列表,包括cluster01-worker3,並且移除了cluster01-worker2:
[WARNING] 093/194006 (6) : Server ingress_https/worker3 is UP, reason: Layer7 check passed, code: 200, info: "OK", check duration: 4ms. 2 active and 0 backup servers online. 0 sessions requeued, 0 total in queue.
內容解密:
- 這段日誌顯示了後端伺服器
ingress_https/worker3已經可用,原因是Layer7檢查透過,傳回碼200。 check duration: 4ms表示健康檢查的耗時。2 active and 0 backup servers online表示目前有2個活動伺服器和0個備份伺服器線上。
Kubernetes 與 KinD 叢集佈署實戰
在上一章中,我們探討了 KinD(Kubernetes-in-Docker)的基礎知識及其優勢。現在,我們將深入瞭解如何利用 KinD 佈署一個高可用性的 Kubernetes 叢集,並介紹 Kubernetes 的基本物件。
使用 KinD 佈署 Kubernetes
當您計劃使用 KinD 佈署一個高可用性的 Kubernetes 叢集時,您需要考慮多個工作節點的佈署以及如何將流量導向這些節點。在本文中,我們將介紹如何使用 HAProxy 作為負載平衡器來實作這一目標。
設定 HAProxy 負載平衡器
docker run -d --name HAProxy-workers-lb \
-p 80:80 \
-p 443:443 \
haproxy:latest
組態 HAProxy
在設定 HAProxy 時,您需要建立一個組態檔案,定義如何將流量導向後端的工作節點。
frontend http
bind *:80
default_backend workers-http
backend workers-http
mode http
balance roundrobin
server worker1 <worker1_ip>:80 check
server worker2 <worker2_ip>:80 check
內容解密:
- 負載平衡器的作用:HAProxy 在此扮演負載平衡器的角色,將進入的 HTTP 請求分配到後端的工作節點。
- 設定檔解析:在
frontend部分,我們定義了 HAProxy 監聽的埠;在backend部分,我們定義了後端伺服器的組態,包括伺服器的 IP 地址和健康檢查機制。 - 動態負載平衡:透過
balance roundrobin,HAProxy 將請求輪流分配到不同的後端伺服器,實作負載平衡。
刪除 KinD 叢集與 HAProxy 容器
當您完成測試後,可能需要刪除 KinD 叢集和相關的 HAProxy 容器。刪除 KinD 叢集的命令如下:
kind delete cluster --name=<cluster_name>
刪除 HAProxy 容器的命令如下:
docker rm HAProxy-workers-lb --force
內容解密:
- 刪除叢集:使用
kind delete cluster命令可以刪除指定的 KinD 叢集。 - 刪除容器:使用
docker rm命令可以強制刪除指定的 Docker 容器。
Kubernetes 基本物件總覽
在本章中,我們將介紹 Kubernetes 的基本物件,包括 Pod、Service、Deployment、ReplicaSet、StatefulSet 和 DaemonSet 等。這些物件是構建和管理 Kubernetes 應用程式的基礎。
Kubernetes 元件概述
Kubernetes 叢集由多個元件構成,包括控制平面和工作節點。控制平面負責管理叢集的狀態,而工作節點則執行實際的應用程式。
此圖示顯示了 Kubernetes 叢集的架構:
graph LR
A[控制平面] -->|管理| B[工作節點]
B -->|執行| C[Pod]
C -->|包含| D[容器]
圖表翻譯: 此圖示展示了 Kubernetes 的基本架構,包括控制平面如何管理工作節點,以及工作節點上執行的 Pod 和容器。這種架構使得 Kubernetes 可以高效地管理和排程容器化應用。
常見問題
在建立 PersistentVolumeClaim 之前,必須建立哪個物件?
- A. PVC
- B. Disk
- C. PersistentVolume
- D. VirtualDisk
答案:C. PersistentVolume
KinD 包含一個動態磁碟供應器,它是由哪家公司建立的?
- A. Microsoft
- B. CNCF
- C. VMware
- D. Rancher
答案:B. CNCF
如果您建立了一個具有多個工作節點的 KinD 叢集,您會安裝什麼來將流量導向每個節點?
- A. Load balancer
- B. Proxy server
- C. Nothing
- D. Network load balancer
答案:A. Load balancer
True or false:一個 Kubernetes 叢集只能安裝一個 CSIdriver。
- A. True
- B. False
答案:B. False
Kubernetes 控制平面的重要組成元件
Kubernetes 的控制平面是叢集的核心,負責管理叢集的所有方面。如果控制平面故障,叢集將無法正常運作。控制平面主要由多個元件組成,包括 kube-apiserver、Etcd、kube-scheduler、kube-controller-manager 和 cloud-controller-manager。
Kubernetes API 伺服器(kube-apiserver)
kube-apiserver 是 Kubernetes 叢集的入口,所有請求都透過 API 伺服器進行處理。kubectl 指令實際上是透過呼叫 API 端點來與 kube-apiserver 進行互動。例如,當執行 kubectl get nodes 指令時,實際上是向 kube-apiserver 發送了一個 API 請求,取得叢集中的節點列表。
https://10.240.100.100:6443/api/v1/nodes?limit=500
內容解密:
- 此 API 請求是透過 HTTPS 協定傳送到 kube-apiserver。
- 請求的端點是
/api/v1/nodes,用於取得節點列表。 limit=500引數限制了傳回的結果數量。
Etcd 資料函式庫
Etcd 是 Kubernetes 用於儲存所有叢集資料的分散式鍵值資料函式庫。叢集中的每個資源都有一個對應的鍵儲存在 Etcd 中。可以使用 etcdctl 命令列工具查詢 Etcd 中的資料。
EtcdCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
--cert=/etc/kubernetes/pki/etcd/server.crt \
get / --prefix --keys-only
內容解密:
EtcdCTL_API=3指定使用的 Etcd API 版本。--endpoints指定 Etcd 服務的端點。--cacert、--key和--cert用於驗證和加密連線。get / --prefix --keys-only用於取得所有鍵。
kube-scheduler
kube-scheduler 負責排程新的 Pod 到適當的節點上。當建立一個新的 Pod 時,kube-scheduler 會根據多個條件(如主機資源和叢集策略)決定將 Pod 排程到哪個節點上。
kube-controller-manager
kube-controller-manager 是一個包含多個控制器的二進位制檔案,這些控制器執行在一個單一的程式中。它包括 node、replication、endpoints 和 service account/token 控制器。每個控制器都有其特定的功能,用於維護叢集的期望狀態。
cloud-controller-manager
cloud-controller-manager 與 kube-controller-manager 類別似,但它專門用於與雲端服務提供商互動。它包含 node、route、service 和 volume 控制器,用於管理與雲端服務提供商相關的資源。
工作節點元件
工作節點負責執行工作負載。當 kube-scheduler 排程一個新的 Pod 時,它會根據從工作節點收集的資訊來決定將 Pod 排程到哪個節點上。工作節點元件包括:
主要元件
- kubelet:負責在節點上執行和管理 Pod。
- kube-proxy:負責提供網路代理和負載平衡功能。
這些元件共同工作,確保 Kubernetes 叢集能夠高效、可靠地執行。瞭解這些元件的功能和工作原理對於管理和維護 Kubernetes 叢集至關重要。
圖表翻譯: 此圖表展示了 Kubernetes 控制平面和工作節點的主要元件。控制平面包括 kube-apiserver、Etcd、kube-scheduler、kube-controller-manager 和 cloud-controller-manager。工作節點包括 kubelet 和 kube-proxy。這些元件共同構成了 Kubernetes 叢集的核心架構。
與 Kubernetes API 伺服器互動
Kubernetes 的工作節點(worker node)通常被稱為 kubelet。kubelet 是一個代理程式,執行在所有工作節點上,負責執行實際的容器。
Kubernetes 元件簡介
- kubelet:執行在所有工作節點上的代理程式,負責執行容器。
- kube-proxy:負責在 Pod 和外部網路之間進行網路通訊路由。儘管名稱中有 “proxy”,但它並不是一個代理伺服器。
- 容器執行環境(Container Runtime):每個節點都需要一個容器執行環境來執行容器。雖然 Docker 是最常見的容器執行環境,但並不是唯一選擇。CRI-O 和 containerd 是 Docker 的兩種主要替代方案。
使用 kubectl 與 Kubernetes 互動
kubectl 是一個單一的可執行檔,允許使用者透過命令列介面(CLI)與 Kubernetes API 互動。kubectl 支援大多數主要作業系統和架構,包括 Linux、Windows 和 Mac。
安裝 kubectl
- 下載最新版本的 kubectl:
curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
2. 使檔案可執行:
```bash
chmod +x ./kubectl
- 將可執行檔移到系統路徑中:
sudo mv ./kubectl /usr/local/bin/kubectl
#### 版本控制
Kubernetes 每 3 個月更新一次,包括基礎叢集元件和 kubectl 工具。使用者可能會遇到叢集和 kubectl 版本不符的情況。執行 `kubectl version` 命令可以檢查客戶端和伺服器的版本。
```plaintext
Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.1", GitCommit:"d224476cd0730baca2b6e357d144171ed74192d6", GitTreeState:"clean", BuildDate:"2020-01-14T21:04:32Z", GoVersion:"go1.13.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.0", GitCommit:"70132b0f130acc0bed193d9ba59dd186f0e634cf", GitTreeState:"clean", BuildDate:"2020-01-14T00:09:19Z", GoVersion:"go1.13.4", Compiler:"gc", Platform:"linux/amd64"}
詳細輸出選項
使用 -v 或 --v 選項可以獲得更多關於 API 請求和回應的資訊。詳細輸出級別從 0 到 9,數字越大,輸出越詳細。
kubectl 命令型別
kubectl 命令可以分為**指令式(imperative)和宣告式(declarative)**兩種。
- 指令式命令:告訴 Kubernetes 要做什麼,例如
kubectl run nginx --image nginx。 - 宣告式命令:告訴 Kubernetes 你想要什麼,通常透過 YAML 清單檔案來宣告。
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title Ingress自定義負載平衡器實戰
package "Kubernetes Cluster" {
package "Control Plane" {
component [API Server] as api
component [Controller Manager] as cm
component [Scheduler] as sched
database [etcd] as etcd
}
package "Worker Nodes" {
component [Kubelet] as kubelet
component [Kube-proxy] as proxy
package "Pods" {
component [Container 1] as c1
component [Container 2] as c2
}
}
}
api --> etcd : 儲存狀態
api --> cm : 控制迴圈
api --> sched : 調度決策
api --> kubelet : 指令下達
kubelet --> c1
kubelet --> c2
proxy --> c1 : 網路代理
proxy --> c2
note right of api
核心 API 入口
所有操作經由此處
end note
@enduml圖表翻譯: 此圖示展示了 Kubernetes 使用者如何透過 kubectl 或 YAML 清單檔案與 Kubernetes API 互動,最終影響 Kubernetes 叢集的狀態。
內容解密:
這段程式碼展示了使用 curl 下載最新版本的 kubectl,並使其可執行,最後將其移到系統路徑中的過程。透過這種方式,使用者可以在 Linux 系統上安裝 kubectl 工具,以便與 Kubernetes 叢集進行互動。
在實際操作中,使用者需要確保系統具有必要的許可權和網路連線,以便成功下載和安裝 kubectl。此外,使用者還需要注意版本控制,以確保 kubectl 和 Kubernetes 叢集的版本相容。