Kubernetes 安裝筆記 - kubeadm on Ubuntu 24.04

tags: Kubernetes Ubuntu
category: DevOps
description: Ubuntu 上的 Kubernetes 安裝與設定筆記
created_at: 2026/01/15 20:20:00

cover image


回到 Kubernetes 學習筆記


事前準備

  • 準備好 3Ubuntu 24.04 LTS 伺服器
    • 其中一台作為 Master 節點(2 CPU, 4GB RAM)
    • 另外兩台作為 Worker 節點(2 CPU, 2GB RAM)
  • 確保所有機器之間的網路可以互通(若使用 VirtualBox,請設定好網路介面)
  • 建議使用你自己習慣的 TerminalSSH 連線到各台機器,這樣你比較方便複製和執行指令

前言

這一篇會透過 kubeadmUbuntu 24.04 LTS 上建立一個 Kubernetes cluster,並且設定好一個簡單的網路插件(Flannel),接著做一下基本的測試,確保 Kubernetes 可以正常運作。

如果只是要練習 Kubernetes,可以不用照這一篇做,因為你有其他更簡單的方式去設定好可以練習的環境,例如常聽到的 Minikubek3s,或者是如果你用 Docker DesktopOrbstack 的話,也可以直接開啟 Kubernetes 功能來練習。


我的環境

每一台都是安裝 Ubuntu 24.04 LTS,並且有以下的規格:

節點名稱 IP 位址 CPU RAM 角色
k8s-master 192.168.1.155 2 4GB Master Node
k8s-worker1 192.168.1.156 1 2GB Worker Node
k8s-worker2 192.168.1.157 1 2GB Worker Node

這幾台機器都可以互相 ping 通且能夠存取外網。

每台機器至少要有 2GB 的記憶體,然後 master 至少要有 2 CPU


安裝之前

安裝之前,我們要先知道我們要安裝的是什麼東西,這裡我們會安裝以下幾個元件:

  • containerd:容器的 Runtime,與 Docker 類似,不使用 Docker 的原因是,一來 Docker 已經被 Kubernetes 官方宣告不再支援,二來因 Docker 沒有乖乖去實作 CRI(Container Runtime Interface),所以我們改用 containerd
  • kubeadm:用來初始化 Kubernetes cluster 的工具。
  • kubelet:每個節點上運行的主要 Kubernetes 代理程式,負責與 Kubernetes 控制平面通信並執行容器。
  • kubectl:用來與 Kubernetes cluster 互動的命令列工具。
  • CNI Plugin:用來處理 Kubernetes 內部網路的插件,這裡我們會使用 Flannel

在寫這一篇的當下版本是 1.35,所以我們會安裝 1.35.x 版本的 Kubernetes

master 節點上,我們會安裝 kubeadmkubeletkubectl 以及 containerd,而在 worker 節點上,我們只會安裝 kubeadmkubeletcontainerd

CNI Plugin 則會在 master 節點初始化 Kubernetes cluster 後再安裝,每個節點都會自動下載並安裝。


安裝步驟(所有節點)

在所有節點上執行以下步驟:

1. 安裝 containerd

# Add Docker's official GPG key:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF

sudo apt update

# Install containerd
sudo apt install containerd.io

接著需要設定 containerd 的設定檔:(先產生預設的設定檔)

containerd config default | sudo tee /etc/containerd/config.toml > /dev/null

然後因為預設 containerdcgroup 是使用 cgroupfs,我們需要改成 systemd,與 Kubernetes 相同,才不會導致同一個 cgroup 被不同的 cgroup driver 管理:

sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

cgroupfs 是比較早期的 cgroup 管理方式,而 systemd 是比較新的方式,Kubernetes 官方建議使用 systemd

最後重新啟動 containerd 服務並設定開機自動啟動:

sudo systemctl restart containerd
sudo systemctl enable containerd

2. 啟用必要的 Linux 核心模組和設定

kubernetes 中,很多流量都透過 iptables 來處理,所以我們需要確保 iptables 可以正確處理 bridged 流量。

所以我們需要載入 br_netfilter 模組:

sudo modprobe br_netfilter

為了避免每次重開機都要重新載入模組,我們可以把模組名稱寫到 /etc/modules-load.d/containerd.conf

sudo tee /etc/modules-load.d/containerd.conf <<EOF
br_netfilter
EOF

接著設定 sysctl 參數,讓你的機器可以幫忙轉發 IPv4 流量,讓節點之間可以互相通訊:

sudo tee /etc/sysctl.d/k8s.conf <<EOF
net.ipv4.ip_forward = 1
EOF

接著要讓設定生效:

sudo sysctl --system

3. 關閉功能(可選)

  1. 官方建議可以關閉 swap 功能,除了效能外,其中一個原因是因為 kubernetes 會去監控 Pod 的記憶體使用情況,如果系統有啟用 swap,可能會導致 kubelet 誤判系統資源狀況,進而影響 Pod 的調度和運行。

在早期版本不支援 swap,但在比較新的版本,有逐漸的在支援 swap,可以參考:

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#swap-configuration

以及

https://kubernetes.io/blog/2025/03/25/swap-linux-improvements/

  1. 關閉 ufw 防火牆,避免影響 kubernetes 的網路通訊。
sudo systemctl disable ufw --now

如果不關的話,可以參考官方文件開放必要的連接埠: https://kubernetes.io/docs/reference/networking/ports-and-protocols/

另外因為我們採用 Flannel 作為 CNI Plugin,所以需要開放以下連接埠:

  • UDP 8472:用於 Flannel 的網路封包

可以參考: https://github.com/flannel-io/flannel/blob/master/Documentation/backends.md


4. 安裝 kubeadmkubeletkubectl

我們安裝的是 v1.35 版本的 Kubernetes,如果不同版本可以替換成對應的版本號。

sudo apt-get update
# apt-transport-https may be a dummy package; if so, you can skip that package
sudo apt-get install -y apt-transport-https ca-certificates curl gpg

# If the directory `/etc/apt/keyrings` does not exist, it should be created before the curl command, read the note below.
# mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.35/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

# This overwrites any existing configuration in /etc/apt/sources.list.d/kubernetes.list
sudo echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.35/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update

sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

安裝完成後,可以透過以下指令確認版本:

kubeadm version
kubelet --version
kubectl version --client

安裝步驟(Master 節點)

接著以下步驟只在 master 節點上執行:

1. 抓取必要的 Images

可以 list 出來看看有哪些 images 需要下載:

kubeadm config images list

會看到類似以下的輸出:

registry.k8s.io/kube-apiserver:v1.35.0
registry.k8s.io/kube-controller-manager:v1.35.0
registry.k8s.io/kube-scheduler:v1.35.0
registry.k8s.io/kube-proxy:v1.35.0
registry.k8s.io/coredns/coredns:v1.13.1
registry.k8s.io/pause:3.10.1
registry.k8s.io/etcd:3.6.6-0

接著我們可以 pull 下來:

sudo kubeadm config images pull

2. 初始化 Kubernetes Cluster

可以簡單的使用 kubeadm init 指令來初始化 Kubernetes cluster,不過我們需要指定 apiserver-advertise-addresspod-network-cidr 參數。

  • apiserver-advertise-address:設定 Kubernetes API server 對外的 IP 位址,這個位址會被其他節點用來連接 API server,以我們的例子來說,我們的 master 節點 IP192.168.1.155,所以我們就設定成這個位址。
  • pod-network-cidr:因為我們使用 Flannel 作為 CNI Plugin,所以需要設定這個參數來指定 Pod 網路的 CIDR 範圍,有些 CNI Plugin 可能有不同的設定,也許不需要設定這個參數,請參考你使用的 CNI Plugin 文件。

除了 apiserver-advertise-address 另外還有一個 control-plane-endpoint 參數,主要用在有多個 master 節點的高可用架構中,等我們之後有機會再來做實驗。

sudo kubeadm init --apiserver-advertise-address=192.168.1.155 --pod-network-cidr=10.244.0.0/16 # pod cidr for flannel default

當初始化完成後,會看到類似以下的輸出:

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.1.155:6443 --token 79v46v.x1w29e18mgmr95q9 \
        --discovery-token-ca-cert-hash sha256:557e3751681fc82a8cfb617a44e0cb171c2ff3991d3aabb2b1992bf6017eb8be

接著我們需要設定 kubectlkubeconfig 檔案,讓我們可以使用 kubectl 來管理 Kubernetes cluster

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

到這邊我們可以先確認 Kubernetes cluster 狀態:

kubectl get nodes

然後你會看到像是這樣的輸出:

NAME              STATUS     ROLES           AGE     VERSION
k8s-master        NotReady   control-plane   1m29s   v1.35.0

會看到 master 節點的狀態是 NotReady,這是因為我們還沒有安裝 CNI Plugin,你可以使用下面這個指令去看看為什麼會是 NotReady

kubectl describe node k8s-master

稍微往上翻一翻,你會看到類似以下的訊息:

container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized

所以我們接下來要安裝 CNI Plugin,這裡我們使用 Flannel


3. 安裝 CNI Plugin

wget https://github.com/flannel-io/flannel/releases/download/v0.28.0/kube-flannel.yml -O /tmp/kube-flannel.yml

在裡面我們有個設定需要改(如果我們有多張網卡的話),要告訴他我們預設這些節點間溝通的網卡是哪一個,否則可能會抓錯網卡導致 Pod 無法通訊。

可以參考文件的說明: https://github.com/flannel-io/flannel/blob/master/Documentation/configuration.md#key-command-line-options

假設我們的網卡是 enp0s8,我們需要修改 /tmp/kube-flannel.yml 裡面的 kube-flannel containerargs,加入 --iface=enp0s8 參數:

      containers:
      - args:
        - --ip-masq
        - --kube-subnet-mgr
        - --iface=enp0s8 # <--- Add this line
        command:
        - /opt/bin/flanneld
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: EVENT_QUEUE_DEPTH
          value: "5000"
        - name: CONT_WHEN_CACHE_NOT_READY
          value: "false"
        image: ghcr.io/flannel-io/flannel:v0.28.0
        name: kube-flannel

整份 yaml 其實滿長的,所以你可以使用 sed 指令來自動加入這一行:

sed -i 's@--kube-subnet-mgr@--kube-subnet-mgr\n        - --iface=enp0s8@' /tmp/kube-flannel.yml

接著使用 kubectl 來安裝 Flannel

kubectl apply -f /tmp/kube-flannel.yml

接著等一段時間,然後再用 kubectl get nodes 看看節點狀態,你應該就會看到 master 節點變成 Ready 狀態了。


安裝步驟(Worker 節點)

接著以下步驟只在 worker 節點上執行:

1. 加入 Kubernetes Cluster

master 節點初始化完成後,會有一個 kubeadm join 的指令,可以把 worker 節點加入到 Kubernetes cluster

在執行 join 之前,你可以在 master 節點上監聽節點的變化:

kubectl get nodes -w

接著在每個 worker 節點上執行 join 指令(記得加上 sudoroot 權限執行)

sudo kubeadm join <你前面 init 指令輸出的 join 指令>

然後你應該會在 master 節點上看到新的 worker 節點加入,並且狀態變成 Ready

NAME              STATUS   ROLES           AGE   VERSION
k8s-master        Ready    control-plane   60m   v1.35.0
k8s-worker-1        NotReady   <none>          0s    v1.35.0
k8s-worker-1        NotReady   <none>          0s    v1.35.0
k8s-worker-1        NotReady   <none>          0s    v1.35.0
k8s-worker-1        NotReady   <none>          4s    v1.35.0
k8s-worker-1        NotReady   <none>          11s   v1.35.0
k8s-worker-1        Ready      <none>          24s   v1.35.0

然後 worker2 也是一樣的步驟,這邊就先省略。


2. 設定 Roles (可選)

剛才所加入的 node ,預設是沒有任何 Roles 的,如果你想要設定 Roles 的話,可以使用以下指令:

kubectl label node k8s-worker-1 node-role.kubernetes.io/worker=

之後我們在執行一次 kubectl get nodes,你就會看到 worker 節點有 worker 這個 role 了:

NAME                STATUS   ROLES           AGE   VERSION
k8s-master          Ready    control-plane   94m   v1.35.0
k8s-worker-1        Ready    worker          33m   v1.35.0

這樣的話就可以明確知道各個節點的角色是什麼,負責的工作是什麼。


最後的設定(所有節點)

修改 nodeinternal-ip

我的可以使用 -o wide 去看到更多的資訊:

kubectl get nodes -o wide

會看到像是下面這樣的資訊

NAME                STATUS     ROLES           AGE    VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE           KERNEL-VERSION     CONTAINER-RUNTIME
k8s-master          NotReady   control-plane   102m   v1.35.0   10.0.2.15     <none>        Ubuntu 24.04 LTS   6.8.0-90-generic   containerd://2.2.1
k8s-worker-1        NotReady   worker          41m    v1.35.0   10.0.2.15     <none>        Ubuntu 24.04 LTS   6.8.0-90-generic   containerd://2.2.1

會發現說 INTERNAL-IP 都是 10.0.2.15,我們應該要改成我們實際的 IP 位址,否則可能會導致一些問題(例如你要看某些資源,然後他會去連接錯誤的 IP 位址,所以導致看不到東西)。

在修改之前,我們必須先知道這些資訊其實是從 kubelet 取得的,所以我們需要修改 kubelet 的設定檔。

所以我們可以先看一下 kubelet 的狀態:

sudo service kubelet status

然後你能夠看出來 kubelet 的設定檔路徑,例如:

● kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; preset: enabled)
    Drop-In: /usr/lib/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
     Active: active (running) since Thu 2026-01-15 11:12:42 UTC; 49s ago
       Docs: https://kubernetes.io/docs/
   Main PID: 17128 (kubelet)
      Tasks: 11 (limit: 4605)
     Memory: 32.2M (peak: 32.7M)
        CPU: 2.751s
     CGroup: /system.slice/kubelet.service
             └─17128 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/co>

接著我們去看看這個設定檔:

sudo cat /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf

你會先看到像是下面這樣的內容:

# Note: This dropin only works with kubeadm and kubelet v1.11+
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use
# the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/default/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS

我們會發現說有一個 KUBELET_EXTRA_ARGS 變數是從 /etc/default/kubelet 這個檔案讀取的,所以我們可以在這個檔案中加入我們要的參數。

所以我們編輯這個檔案:

sudo vim /etc/default/kubelet

然後改成以下內容

KUBELET_EXTRA_ARGS=--node-ip=192.168.1.155

記得把 192.168.1.155 改成你實際的 IP 位址,然後重新啟動 kubelet 服務:

sudo service kubelet restart

接著再用 kubectl get nodes -o wide 看看 INTERNAL-IP 是否有正確顯示。


測試 Kubernetes Cluster

1. 部署一個測試的 Pod

我們可以部署一個簡單的 nginx Pod 來測試 Kubernetes cluster 是否正常運作:

kubectl run web --image=nginx

這樣就建立了一個名為 webPod,使用 nginximage

我們可以用以下指令來查看 Pod 的狀態,直到它變成 Running 狀態:

kubectl get pods -w

然後我們需要 expose 這個 Pod,讓它可以被外部存取:

kubectl expose pod web --port=8888 --target-port=80

這就類似 dockerport mapping,像是-p 8888:80

接著我們可以查看 Service 的狀態:

kubectl get services

會看到類似以下的輸出:

NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP    139m
web          ClusterIP   10.107.3.228   <none>        8888/TCP   2m1s

這時你可以用 curl 去存取這個 nginx 服務:

curl 10.107.3.228:8888

應該就會看到 nginx 的歡迎頁面。


2. 若不改 internal-ip 會怎樣?(可選)

我們可以實驗一下,假設我想看 log 的話,可以透過以下指令:

kubectl logs web

目前因為我們前面已經把 internal-ip 改成正確的 IP 位址了,所以應該可以正常看到 log

可以自己試著把我們前面改的 internal-ip 改回去,然後再試著看 log,你應該會看到類似以下的錯誤訊息:

Error from server (NotFound): the server could not find the requested resource ( pods/log web)

這是因為 kubectl 會透過 kubelet 去取得 Podlog,而 kubelet 會使用 internal-ip 去連接節點,如果 internal-ip 是錯誤的話,就無法連接到正確的節點,進而導致無法取得 log


3. 清理測試資源

kubectl delete service web
kubectl delete pod web

整理好的安裝腳本

前面步驟有點多,尤其是每個節點都要安裝的東西,所以我整理了一份安裝腳本,可以讓你快速安裝好 Kubernetes 環境。

檔案中的註解步驟可能和文章沒有對應到,但不影響理解。

記得都要以 root 權限執行,前面要加上 sudo

建立好檔案後,也要記得給予執行權限 chmod +x install.sh

腳本目前沒有對 swap 做處理,請自行決定要不要關閉 swap

防火牆也是沒有處理,腳本中是直接關閉 ufw,如果需要的話請自行設定。

檔案名稱: install.sh

#######################################
# 1. Install and Configure containerd #
#######################################

# Add Docker's official GPG key:
apt update
apt install ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF

apt update

# Install containerd
apt install containerd.io

# Generate default configuration file for containerd
# containerd config default > /etc/containerd/config.toml
containerd config default | tee /etc/containerd/config.toml > /dev/null

# Set SystemdCgroup to true for better compatibility with systemd
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
systemctl restart containerd
systemctl enable containerd

#############################################
# 2. Enable br_netfilter Module for Flannel #
#############################################
tee /etc/modules-load.d/containerd.conf <<EOF
br_netfilter
EOF
modprobe br_netfilter

###############################################
# 3. Set sysctl params required by Kubernetes #
###############################################
# sysctl params required by setup, params persist across reboots
cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
EOF

# Apply sysctl params without reboot
sysctl --system

##############################################
# 4. ufw allow required ports for Kubernetes #
##############################################
# Master node ports
# ufw allow 6443/tcp       # Kubernetes API server
# ufw allow 2379:2380/tcp  # etcd server client API
# ufw allow 10250/tcp      # Kubelet API
# ufw allow 10259/tcp      # kube-scheduler
# ufw allow 10257/tcp      # kube-controller-manager
# ufw allow 8472/udp       # flannel VXLAN
# Worker node ports
# ufw allow 10250/tcp      # Kubelet API
# ufw allow 10256/tcp      # kube-proxy
# ufw allow 30000:32767/tcp  # NodePort Services
# ufw allow 30000:32767/udp  # NodePort Services
# ufw allow 8472/udp       # flannel VXLAN
# refer: https://kubernetes.io/docs/reference/networking/ports-and-protocols
# and https://github.com/flannel-io/flannel/blob/master/Documentation/backends.md#vxlan
systemctl disable ufw --now # Disable ufw for simplicity, enable and configure as needed

####################################
# 5. Install Kubernetes Components #
####################################
apt-get update
# apt-transport-https may be a dummy package; if so, you can skip that package
apt-get install -y apt-transport-https ca-certificates curl gpg

# If the directory `/etc/apt/keyrings` does not exist, it should be created before the curl command, read the note below.
# mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.35/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

# This overwrites any existing configuration in /etc/apt/sources.list.d/kubernetes.list
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.35/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list
apt-get update

apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl

之後在 master 節點上,也有相應的腳本要執行,所以我也簡單整理了一份:

記得要更改 apiserver-advertise-address--iface 參數。

檔案名稱: init-master.sh

####################################
# 1. Initialize Kubernetes Cluster #
####################################
# Pre-pull required images
kubeadm config images list
kubeadm config images pull

# Initialize the Kubernetes cluster
kubeadm init --apiserver-advertise-address=192.168.1.155 --pod-network-cidr=10.244.0.0/16 # pod cidr for flannel default

# Set up kubeconfig for the root user
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

##################################
# 2. Install Flannel CNI Plugin #
##################################
wget https://github.com/flannel-io/flannel/releases/download/v0.28.0/kube-flannel.yml -O /tmp/kube-flannel.yml
sed -i 's@--kube-subnet-mgr@--kube-subnet-mgr\n        - --iface=enp0s8@' /tmp/kube-flannel.yml
kubectl apply -f /tmp/kube-flannel.yml

##################################
# 3. Wait for Nodes to be Ready  #
##################################
echo "Waiting for all pods to be in Running state..."
kubectl get pods -A -w
# Press Ctrl+C to exit the watch once all pods are in Running state
kubectl get nodes
# The node should show as Ready

接著在每個 worker 節點上,你應該要手動去執行 kubeadm join 指令,這個指令會在你初始化 master 節點時顯示出來。

然後 rolesinternal-ip 的設定也是要手動去執行。

如此一來就大功告成了!


結語

透過這一篇文章,我們成功地在 Ubuntu 24.04 LTS 上使用 kubeadm 建立了一個基本的 Kubernetes cluster,並且安裝了 Flannel 作為網路插件。

也透過部署一個簡單的 nginx pod,我們驗證了 Kubernetes cluster 的運作是否正常。

這次寫文章之前先把整個 Kubernetes 做了一下 overview,發現不像當初第一次看到時那麼的模糊,反而覺得滿有趣的。

所以在過程中我做了滿多功課,為了讓之後的文章更順利的進行,第一篇花費特別多的時間,之後會一個一個功能慢慢介紹。

(如果還是不小心有什麼錯誤的地方,未來在做實驗時踩到怪怪的坑再回來做修正QQ (小聲)




最後更新時間: 2026年01月15日.