返回文章列表

KinD 佈署 Kubernetes 叢集實戰

本文探討如何使用 KinD 在 Docker 中佈署 Kubernetes 叢集,包含多節點叢集設定、Kubernetes 物件介紹、kubectl 指令操作、持久化儲存組態、網路設定以及叢集內部運作機制解析,並提供實際操作範例和圖表說明,幫助讀者快速掌握 KinD 的使用技巧與 Kubernetes 基礎知

容器技術 Kubernetes

KinD 提供了在 Docker 容器內執行 Kubernetes 叢集的便捷方法,非常適合開發和測試環境。透過簡單的指令即可快速建立和刪除叢集,有效節省資源並簡化佈署流程。理解 Kubernetes 的核心物件如 Pod、Service、Deployment 等,是建構和管理容器化應用程式的基礎。本文將逐步引導讀者使用 KinD 建立多節點叢集,並透過 kubectl 進行互動和管理,同時涵蓋持久化儲存的設定與網路連線的注意事項。

深入理解 KinD 的運作機制,有助於釐清主機、Docker 和 Kubernetes 節點之間的關係。KinD 叢集的網路設定和埠轉發是確保應用程式可被外部存取的關鍵。本文將詳細說明如何設定 NodePort 服務,讓外部網路可以存取叢集內部的應用程式。此外,持久化儲存對於資料的儲存至關重要,本文也將介紹如何使用 local-path-provisioner 來實作自動供應 PersistentVolumeClaims 的功能,確保資料的永續性。最後,本文也將提供安裝 KinD、kubectl 和 Go 的步驟,以及一些常見的挑戰和解決方案,幫助讀者更好地理解和使用 KinD。

使用 KinD 佈署 Kubernetes 叢集

在本章中,我們將介紹如何使用 KinD(Kubernetes-in-Docker)工具來佈署 Kubernetes 叢集。KinD 允許我們在單一主機上使用容器來建立多節點的 Kubernetes 叢集。

KinD 的優勢

使用 KinD 可以節省資源、快速建立和刪除叢集,並且可以輕鬆地指令碼化叢集建立過程。

建立 KinD 叢集

首先,需要安裝 KinD 工具。然後,可以使用以下命令建立一個單節點的 Kubernetes 叢集:

kind create cluster

也可以使用以下命令建立一個多節點的 Kubernetes 叢集:

kind create cluster --config kind-config.yaml

其中,kind-config.yaml 是叢集組態檔。

Kubernetes 元件與物件簡介

在開始使用 KinD 之前,我們需要了解一些基本的 Kubernetes 元件和物件。這些元件和物件包括 Pod、Service、Deployment、ReplicaSet 等。

Kubernetes 元件與物件一覽表

元件/物件描述
PodKubernetes 中最小的可佈署單元
Service提供 Pod 的網路介面
Deployment管理 Pod 的佈署和更新
ReplicaSet確保指定數量的 Pod 複本正在執行

在本章中,我們介紹了 Docker 網路架構和 KinD 工具的基本使用方法。在下一章中,我們將探討 Kubernetes 的基礎知識和常用物件。

使用 KinD 佈署 Kubernetes

在探討 Kubernetes 的世界時,瞭解其基本物件(objects)至關重要。這些物件包括 Pod、Service、Deployment 等,它們是構建和管理容器化應用的基礎。在本章中,我們將介紹這些基本物件,並探討如何使用 KinD(Kubernetes-in-Docker)來佈署一個 Kubernetes 叢集。

與叢集互動

為了測試我們的 KinD 安裝,我們將使用 kubectl 這個可執行檔與叢集進行互動。kubectl 是 Kubernetes 的命令列工具,用於與叢集進行通訊。我們將在第 5 章「Kubernetes Bootcamp」中詳細介紹 kubectl,但在本章中,我們將先介紹一些基本命令。

表 4.2 - 基本的 kubectl 命令

命令說明
kubectl get nodes取得叢集中的節點列表
kubectl get pods取得叢集中的 Pod 列表
kubectl describe node <node-name>描述指定節點的詳細資訊

使用開發叢集

多年來,為了方便管理員和開發人員在本地系統上進行測試,各種安裝開發用 Kubernetes 叢集的工具應運而生。雖然這些工具能夠滿足基本的 Kubernetes 測試需求,但往往存在一些限制,使其不太適合快速、複雜的場景。

常見的解決方案

  • Docker Desktop
  • minikube
  • kubeadm

每個解決方案都有其優缺點和適用場景。有些解決方案限制使用者只能使用單一節點執行控制平面和工作節點,而其他解決方案則提供多節點支援,但需要額外的資源來建立多個虛擬機器。

為什麼選擇 KinD?

當我們開始撰寫這本文時,我們希望能夠提供理論知識和實際操作經驗。KinD 允許我們提供指令碼來啟動和關閉叢集,而且能夠在幾分鐘內建立一個新的多節點叢集。我們希望能夠將控制平面和工作節點分開,以提供一個更真實的叢集環境。

KinD 的優勢

KinD 的要求非常簡單:只需要一個正在執行的 Docker 守護程式即可建立叢集。這意味著它與大多數作業系統相容,包括 Linux、macOS 和 Windows。

KinD 叢集的工作原理

從高層次來看,KinD 叢集可以被視為由單一 Docker 容器組成,該容器執行控制平面節點和工作節點,以建立一個 Kubernetes 叢集。為了使佈署變得簡單和穩健,KinD 將每個 Kubernetes 物件封裝到一個單一的映像檔中,稱為節點映像檔。

節點映像檔

節點映像檔包含了建立單一節點叢集或多節點叢集所需的所有 Kubernetes 元件。

控制平面元件

當我們執行 docker exec 命令進入控制平面節點容器時,我們可以看到標準的 Kubernetes 控制平面元件正在執行:

docker exec -it <container-id> ps aux

此命令輸出的結果類別似於以下內容:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  1234  567 ?        Ss   Jan01   0:00 /usr/bin/kube-apiserver
root         2  0.0  0.0  1234  567 ?        Ss   Jan01   0:00 /usr/bin/kube-scheduler
root         3  0.0  0.0  1234  567 ?        Ss   Jan01   0:00 /usr/bin/kube-controller-manager

#### 內容解密:

  • /usr/bin/kube-apiserver:Kubernetes API 伺服器,負責處理 API 請求。
  • /usr/bin/kube-scheduler:Kubernetes 排程器,負責將 Pod 排程到適當的節點上。
  • /usr/bin/kube-controller-manager:Kubernetes 控制管理器,負責執行各種控制器,如 ReplicationController。

工作節點元件

同樣地,當我們執行 docker exec 命令進入工作節點容器時,我們可以看到標準的工作節點元件正在執行:

docker exec -it <container-id> ps aux

此命令輸出的結果類別似於以下內容:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  1234  567 ?        Ss   Jan01   0:00 /usr/bin/kubelet
root         2  0.0  0.0  1234  567 ?        Ss   Jan01   0:00 /usr/bin/kube-proxy

#### 內容解密:

  • /usr/bin/kubelet:Kubernetes 節點代理,負責管理節點上的 Pod 和容器。
  • /usr/bin/kube-proxy:Kubernetes Proxy,負責提供網路代理服務。

圖表翻譯:KinD叢集架構圖

圖表翻譯: 此圖示呈現了 KinD叢集 的基本架構。KinD 使用 Docker Container 來模擬 Kubernetes 節點,包括控制平面節點和工作節點。控制平面節點包含 kube-apiserver、kube-scheduler 和 kube-controller-manager 等關鍵元件,而工作節點則包含 kubelet 和 kube-proxy 等重要元件。這種架構使得 KinD 可以在單一主機上執行多個 Kubernetes 節點,提供了一個方便且高效的開發和測試環境。

深入理解 KinD 叢集的內部運作與持久化儲存

KinD 叢集的基本組成

現在你已經瞭解了每個節點和 Kubernetes 元件,讓我們來看看 KinD 叢集的基本組態。要顯示完整的叢集和所有正在執行的元件,可以執行 kubectl get pods --all-namespaces 命令。這將列出叢集的所有執行元件,包括我們將在第 5 章 Kubernetes Bootcamp 中討論的基本元件。除了基本叢集元件之外,你可能會注意到在名為 local-path-storage 的名稱空間中執行了一個 Pod,名為 local-path-provisioner

本地路徑供應器(local-path-provisioner)的重要性

這個 Pod 是 KinD 包含的附加元件之一,為叢集提供了自動供應 PersistentVolumeClaims 的功能。

kubectl get pods --all-namespaces

執行上述命令後,你將看到類別似以下的輸出,其中包含了 local-path-provisioner Pod:

NAMESPACE            NAME                                         READY   STATUS    RESTARTS   AGE
kube-system          local-path-provisioner-...                   1/1     Running   0          ...
local-path-storage   local-path-provisioner-...                   1/1     Running   0          ...

為什麼持久化儲存很重要?

大多數生產環境中的 Kubernetes 叢集都會為開發者提供持久化儲存。通常,這些儲存會由根據區塊儲存、S3 或 NFS 的儲存系統支援。除了 NFS 之外,大多數家庭實驗室很少有資源來執行功能齊全的儲存系統。local-path-provisioner 透過為你的 KinD 叢集提供昂貴儲存解決方案的所有功能,從而消除了這一限制。

深入理解持久化儲存相關物件

在第 5 章 Kubernetes Bootcamp 中,我們將討論 Kubernetes 儲存中的幾個 API 物件,包括 CSIdriversCSInodesStorageClass 物件。這些物件被叢集用來提供對後端儲存系統的存取。一旦安裝和組態,Pod 將使用 PersistentVolumesPersistentVolumeClaims 物件來消耗儲存。

為什麼需要本地路徑供應器?

雖然 Kubernetes 對本地持久化儲存提供了原生支援,但它並沒有提供自動供應功能。CNCF 提供了一個自動供應器,但它必須作為一個單獨的 Kubernetes 元件安裝和組態。KinD 使自動供應變得簡單,因為供應器已包含在所有基本安裝中。

Rancher 的專案為 KinD 提供了以下功能:

  • 當建立 PVC 請求時自動建立 PersistentVolumes
  • 一個名為 standard 的預設 StorageClass

當自動供應器看到 PersistentVolumeClaim 請求到達 API 伺服器時,將建立一個 PersistentVolume,並將 Pod 的 PVC 繫結到新建立的 PVC。

程式碼範例:使用本地路徑供應器建立持久化儲存

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: example-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

內容解密:

  • 上述 YAML 檔案定義了一個名為 example-pvcPersistentVolumeClaim,請求 1Gi 的儲存空間。
  • 當這個 PVC 被建立時,local-path-provisioner 將自動建立一個對應的 PersistentVolume
  • Pod 可以透過參照這個 PVC 來使用持久化儲存。

KinD 與 Docker 網路

由於 KinD 使用 Docker 作為容器引擎來執行叢集節點,因此所有叢集都受到與標準 Docker 容器相同的網路約束。在第 3 章《理解 Docker 網路》中,我們回顧了 Docker 網路和 Docker 預設網路堆積疊的潛在限制。這些限制不會限制你在本地主機上測試你的 KinD Kubernetes 叢集,但當你想從網路上的其他機器測試容器時,它們可能會導致問題。

除了 Docker 網路考慮因素之外,我們還必須考慮 Kubernetes Container Network Interface(CNI)。官方上,KinD 團隊將網路選項限制為僅兩種 CNI:Kindnet 和 Calico。Kindnet 是他們唯一支援的 CNI,但你確實有選項可以停用預設的 Kindnet 安裝,這將建立一個沒有安裝 CNI 的叢集。在叢集佈署之後,你可以佈署一個 CNI 清單,例如 Calico。

KinD 網路架構

圖表翻譯:

  • 此圖表展示了 KinD 網路架構,包括 Kubernetes 叢集、Kindnet CNI、Calico CNI 和 Docker 網路之間的關係。
  • KinD 叢集可以使用 Kindnet 或 Calico 作為 CNI,它們都依賴於 Docker 網路。

許多 Kubernetes 安裝(無論是小型開發叢集還是企業叢集)都使用 Tigera 的 Calico 作為 CNI,因此我們選擇在本文的練習中使用 Calico 作為我們的 CNI。

在開發叢集中使用 KinD 的挑戰與解決方案

使用 KinD 這樣的解決方案可能會讓人感到混淆,因為它涉及到容器在容器內的佈署。我們將這種情況比喻為俄羅斯套娃,一個娃娃套著另一個娃娃,以此類別推。當你開始使用 KinD 來建立自己的叢集時,你可能會失去對主機、Docker 和 Kubernetes 節點之間通訊路徑的追蹤。

瞭解 KinD 叢集的三層架構

為了避免混淆,你需要清楚地瞭解每個元件在哪裡執行,以及如何與每個元件互動。下圖展示了形成 KinD 叢集所需的三個層級。

此圖示

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title KinD 佈署 Kubernetes 叢集實戰

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

圖表翻譯: 此圖顯示了 KinD 叢集的三層架構,包括主機層、Docker 層和 KinD 容器層。每個層級只能與直接在其上方的層級互動。

KinD 叢集的網路流量流動

假設你想在 Kubernetes 叢集中佈署一個網頁伺服器,並使用 Chrome 瀏覽器在 Docker 主機或網路上的其他工作站進行測試。如果你直接嘗試存取主機的 80 埠,很可能會失敗。為什麼會這樣呢?

程式碼範例:暴露容器埠

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
  type: NodePort

內容解密:

  1. apiVersionkind 定義了 Kubernetes 資源的型別和版本。
  2. metadata 部分包含了服務的名稱。
  3. spec 部分定義了服務的規格,包括選擇器、埠和型別。
  4. selector 指定了服務要關聯的 Pod。
  5. ports 部分定義了服務要暴露的埠。
  6. type 設定為 NodePort,表示服務將在每個節點上暴露一個埠。

執行網頁伺服器的 Pod 位於第三層,無法直接接收來自主機或網路上其他機器的流量。要從主機存取網頁伺服器,你需要將流量從 Docker 層轉發到 KinD 層。

安裝 KinD 的步驟

在開始之前,請確保你已經具備了必要的先決條件,包括安裝 kubectl 和 Go。

安裝 Kubectl

如果你使用的是 Ubuntu 18.04 系統,可以透過執行以下命令來安裝 kubectl

sudo snap install kubectl --classic

安裝 Go

要安裝 Go,你需要下載 Go 檔案,解壓縮可執行檔,並設定專案路徑。以下命令可以用來在你的機器上安裝 Go:

wget https://dl.google.com/go/go1.13.3.linux-amd64.tar.gz
tar -xzf go1.13.3.linux-amd64.tar.gz
sudo mv go /usr/local
mkdir -p $HOME/Projects/Project1
cat << 'EOF' >> ~/.bash_profile
export GOROOT=/usr/local/go
export GOPATH=$HOME/Projects/Project1
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
EOF
source ~/.bash_profile

內容解密:

  1. 下載 Go 到你的主機,解壓縮檔案,並將檔案移動到 /usr/local
  2. 在你的主目錄中建立一個名為 Projects/Project1 的 Go 專案資料夾。
  3. 將 Go 環境變數新增到 .bash_profile 中,這些變數是執行 Go 應用程式所必需的。