這個系列是我準備 CKA 時整理下來的 Kubernetes 筆記,內容會從基礎資源一路寫到排程、儲存、網路與 Pod 分散機制,也會搭配實際操作與 YAML 範例。
第一天先從建立叢集開始。
這次使用 kubeadm 在 GCP Compute Engine 上建立一套 Kubernetes 叢集,架構為 1 個 Control Plane 與 2 個 Worker Node,作業系統使用 Debian。
文章會記錄 Container Runtime、kubeadm、kubelet、kubectl、CNI 的安裝流程,以及 Worker Node 如何加入叢集。最後會部署一個 Nginx,確認整個叢集可以正常運作。
這篇主要是完整記錄一次 kubeadm 的建置流程,方便之後重建環境或準備 CKA 時快速複習。
接下來的文章會依序整理 Pod、Deployment、Service、Ingress、ConfigMap、Secret、Storage、Scheduler 與其他 Kubernetes 常用功能。
本教學使用三台 VM 節點(1 個 master 節點、2 個 worker 節點),部署於 GCP Compute Engine,作業系統為 Debian。

系統需求:
執行節點:master + node1 + node2(三台都要做)

Kubernetes 要求關閉 swap 才能正常運作:
# 暫時關閉 swap(重開機後會恢復)
sudo swapoff -a
# 永久關閉 swap(編輯 /etc/fstab)
sudo sed -i '/ swap / s/^/#/' /etc/fstab
# 驗證 swap 已關閉(應該顯示全部為 0)
free -h
重要: 如果不關閉 swap,kubelet 將無法啟動,導致節點無法加入叢集。
說明:
kubelet 需要可預期的記憶體管理行為,若啟用 swap,將導致資源計算與 OOM 行為不可預期。
# 載入必要的核心模組
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 設定必要的 sysctl 參數
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# 套用 sysctl 參數
sudo sysctl --system
# 更新套件列表
sudo apt-get update
# 安裝必要的套件
sudo apt-get install -y ca-certificates curl gnupg
# 安裝 containerd
sudo apt-get install -y containerd
# 產生預設設定檔
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
# 修改設定檔,啟用 SystemdCgroup
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
# 重啟 containerd
sudo systemctl restart containerd
sudo systemctl enable containerd
說明:
Kubernetes 自 v1.24 起預設使用 systemd 作為 cgroup driver,containerd 必須同步設定為 SystemdCgroup,否則 kubelet 可能無法正常啟動。
注意:
如果你的環境使用 GCP、AWS 等雲端平台,可能還需要在雲端安全群組(Security Group)或防火牆規則中開放相應端口。
選項 A:關閉防火牆(適合測試環境)
# 關閉 ufw 防火牆
sudo ufw disable
# 檢查防火牆狀態
sudo ufw status
選項 B:開放必要端口(適合生產環境)
# Master 節點需要開放的端口
sudo ufw allow 6443/tcp # Kubernetes API server
sudo ufw allow 2379:2380/tcp # etcd server client API
sudo ufw allow 10250/tcp # Kubelet API
sudo ufw allow 10259/tcp # kube-scheduler
sudo ufw allow 10257/tcp # kube-controller-manager
# Worker 節點需要開放的端口
sudo ufw allow 10250/tcp # Kubelet API
sudo ufw allow 30000:32767/tcp # NodePort Services
# Calico 需要開放的端口
sudo ufw allow 179/tcp # BGP
sudo ufw allow 4789/udp # VXLAN
# 啟用防火牆
sudo ufw enable
# 檢查防火牆狀態
sudo ufw status
說明:
本教學使用 GCP Compute Engine,預設防火牆規則已允許內網通訊。若你的環境有啟用 ufw,建議在測試階段關閉防火牆,待叢集穩定後再開啟並設定相應規則。
Debian 預設未安裝 ufw,若需要請先執行 sudo apt install ufw。
執行節點:master + node1 + node2(三台都要做)
本節提供兩種安裝方式,請依你的學習目標選擇:
# 更新套件索引並安裝必要工具
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
# 建立 keyrings 目錄
sudo mkdir -p /etc/apt/keyrings
# 下載 Kubernetes 的 GPG 金鑰
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.34/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
版本說明:
上述指令使用 v1.34 版本。若要使用其他版本(如 v1.30、v1.31),請將 URL 中的 v1.34 改為對應版本號。
注意:
後續安裝 kubeadm、kubelet 和 kubectl 後,請務必使用 apt-mark hold 鎖定版本,避免系統自動升級導致版本不一致,影響叢集穩定性。
版本選擇建議:
如果你計畫練習 Kubernetes 升版操作,建議安裝比最新版低一個 minor version。本教學的 apt repo 設定為 v1.34,因此下方選項 B 會安裝 v1.34.0,後續可練習升級到 v1.35。
選項 A:安裝最新版本
# 更新套件列表
sudo apt-get update
# 安裝最新版本
sudo apt-get install -y kubelet kubeadm kubectl
# 鎖定版本,防止自動更新
sudo apt-mark hold kubelet kubeadm kubectl
# 啟用 kubelet 服務
sudo systemctl enable --now kubelet
選項 B:安裝特定版本(推薦用於練習升版)
# 查看可用的版本
apt-cache madison kubeadm
# 範例:安裝 v1.34.x(作為後續升級到 v1.35 的起點)
# 請根據上面的輸出選擇你要的版本號
VERSION="1.34.0-1.1"
sudo apt-get install -y kubelet=$VERSION kubeadm=$VERSION kubectl=$VERSION
# 鎖定版本,防止自動更新
sudo apt-mark hold kubelet kubeadm kubectl
# 啟用 kubelet 服務
sudo systemctl enable --now kubelet
# 驗證安裝的版本
kubeadm version
kubectl version --client
版本號說明:
1.34.0-1.1
1.34.0 是 Kubernetes 版本-1.1 是套件版本執行節點:僅在 master 上執行
# 初始化 Kubernetes cluster
sudo kubeadm init --kubernetes-version=v1.34.0 --pod-network-cidr=192.168.0.0/16
參數說明:
--kubernetes-version=v1.34.0:明確指定 Kubernetes 版本,確保所有節點版本一致--pod-network-cidr=192.168.0.0/16:Pod 網路 CIDR,此設定與 Calico 預設 IP Pool 相符重要提示:
初始化完成後,會顯示一段 kubeadm join 指令,請務必保存這段指令,稍後會用來將 Worker 節點加入叢集。
# 為當前使用者設定 kubeconfig
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 查看節點狀態
kubectl get nodes
# 查看系統 Pods
kubectl get pods -n kube-system
說明:
在尚未安裝 CNI 前:
NotReady
Pending
這屬於正常現象,會在後續安裝 CNI 後恢復正常。
執行節點:僅在 master 上執行
這裡使用 Calico 作為網路插件:
# 安裝 Calico v3.28.0
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/calico.yaml
注意:
本教學使用 Calico,其預設 IP Pool 為 192.168.0.0/16,與 kubeadm init 的 --pod-network-cidr 參數一致。若要使用其他 CNI 插件(如 Flannel),需要將 --pod-network-cidr 改為該 CNI 的預設 CIDR(Flannel 為 10.244.0.0/16)。
# 查看 kube-system 中的 Calico、CoreDNS 與 kube-proxy
kubectl get pods -n kube-system | egrep 'calico|coredns|kube-proxy'
# 注意:有些 Calico 安裝方式會使用獨立的 calico-system namespace,若你的環境使用該 namespace,則改查:
# kubectl get pods -n calico-system
# 即時觀察 Pod 啟動過程(可選,按 Ctrl + C 停止監看)
kubectl get pods -n kube-system -w
預期結果:
NotReady 變為 Ready
Pending 變為 Running
# 檢查節點狀態
kubectl get nodes
# 檢查系統 Pod 狀態
kubectl get pods -n kube-system
若 Calico、CoreDNS、kube-proxy 皆為 Running,且節點狀態為 Ready,代表 Pod 網路已成功建立。
執行節點:僅在 node1 + node2 上執行
在 node1 和 node2 上執行之前保存的 kubeadm join 指令:
sudo kubeadm join <master-ip>:6443 --token <token> \
--discovery-token-ca-cert-hash sha256:<hash>
如果忘記 join 指令:
可以在 Master 節點上重新產生:
kubeadm token create --print-join-command
# 查看所有節點
kubectl get nodes
應該會看到類似輸出:

執行節點:在 master 上執行
# 建立測試 Deployment
kubectl create deployment nginx --image=nginx
# 暴露服務
kubectl expose deployment nginx --port=80 --type=NodePort
# 查看服務
kubectl get svc nginx
# 查看 Pod 狀態與分佈
kubectl get pod -o wide
說明:
使用 -o wide 可以看到 Pod 被排程到哪個節點。Kubernetes 會根據資源可用性將 Pod 排程到任一 Worker 節點。
# 取得 NodePort
NODE_PORT=$(kubectl get svc nginx -o jsonpath='{.spec.ports[0].nodePort}')
# 使用任一節點 IP 測試
# <node-ip> 可使用任一 Worker 節點的內部 IP(同網段測試)或外部 IP(需防火牆放行)
curl http://<node-ip>:$NODE_PORT
若成功連線,應可看到 Nginx 預設的 Welcome Page。

注意:
若無法從外部連線 NodePort,請確認雲端防火牆已放行 30000–32767/tcp。
今天我們完成了使用 kubeadm 從零開始建立一個 Kubernetes 叢集,包含:
設定容器運行時(containerd)
安裝 kubeadm、kubelet 和 kubectl
初始化 Master 節點
安裝網路插件(Calico)
將 Worker 節點加入叢集
驗證叢集運作
這是一個基礎但完整的 K8s 叢集,後續我們會在這座叢集上持續探索更多 Kubernetes 的核心資源。
明天我們會從部署第一個 Pod 開始,認識 Pod 與 Deployment 的差異,搞懂為什麼你幾乎不會單獨建 Pod。敬請期待!