今天就讓我們透過 kubeadm 指令來建立一個自己的 k8s clsuter 吧!
本來是打算說直接對照安裝文件的建議裝 HA control-plane,但發現有些內容實在太豐富了,如果要每篇都看的話可能要到 Day20 才會裝,因此先略過一些內容來開始實作!
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
kubeadm 是官方唯一直接維護的 k8s cluster 安裝方式
對於環境的前置要求如下:
💡 最新版本的 kubelet 已經沒有強制限制要關閉 swap 了,此功能在 k8s 1.22 進入 Alpha,並在 1.28 進入 Beta 版,同樣也是透過 KEP 的方式進入提案測試的,編號為 KEP-2400
進入 Beta 版後,僅支援在 Cgroupv2 的系統上使用,也完善了監控等等的議題,在 kubelet 也有許多相關的參數對應調整
延伸閱讀: https://kubernetes.io/blog/2023/08/24/swap-linux-beta/
接下來文件內也有提供每一項步驟需要檢查的方式:
在實體機上面,通常都會有獨立的 prdouct_uuid, 但若是使用虛擬機就需要稍微注意一下
ip link
或 ifconfig
檢查sudo cat /sys/class/dmi/id/product_uuid
檢查💡 筆者是使用 vmware workstation player 來建立 ubuntu VM 做使用的,我是透過先安裝一台 ubuntu 之後當作 template,之後就用 clone 的方式來建立機器
本來覺得這樣做 prdouct_uuid 很可能會重複,不過看起來 workstation player 會特別產生不同的 product_uuid 給每台 VM
要特別注意當有 2 張以上網卡時,要設定 IP route 告知 k8s cluster 應該要透過哪張卡來傳輸資訊
基本上就是確保 control plane 上面會跑的 process port 沒被占用,以 kube-apiserver 為例是使用 6443,檢查方式:
nc 127.0.0.1 6443 -v
另外還要確保: 2379-2381 (etcd), 10250 (kubelet), 10259 (kube-scheduler), 10257 (kube-controller-manager),以及不同 CNI 也可能會有不同的需求 (e.g. bgp 模式會占用 179 port)
安裝 CRI,之前會看到不少 CRI 的實作,不過似乎越來越少了,最主要的就是以下三個:
containerd
:擁有廣大的社群,也是 CNCF 的畢業專案之一。CRI-O
:由 RedHat 維護,簡化了許多功能,僅保留 CRI 的需求。主要是用於 RedHat 自家的 Openshift 平台。cri-dockerd
:在 k8s 1.24 之後,kubelet 移除了對 dockershim 的支援,取而代之的就是 cri-dockerd
, 讓某些 docker 環境在新版的 k8s 依然可以透過 docker 來當作 CRI。kubeadm, kubelet, kubectl
是 k8s cluster 的三本柱,kubeadm 並不直接管理另外兩個的版本,因此需要手動配置,他們的分工為:
kubeadm
:啟動 cluster 的工具kubelet
:透過跟 CRI 溝通建立 pods/containerskubectl
:k8s 的前端工具在筆者的 ubuntu 24.04 環境上,使用
apt-get install kubeadm kubelet kubectl
指令時,還會安裝conntrack cri-tools ebtables kubernetes-cni socat
等相依性套件
在討論版本相容性時,都會以 kube-apiserver
當作基準點,而 kubeadm
的版本會直接對應到 kube-apiserevr
https://kubernetes.io/releases/version-skew-policy/
之前的文件是用 +- 去表達版本可相容多少,目前版本都直接是直接以當前版本 1.31 來舉例
以 kube-apiserver 為 1.31 為基準:
至於其他元件也與 kube-apiserver
的版本息息相關,只是若使用 kubeadm
升級的話基本上都會一起保持同個版本
linux 是透過 cgroup 來管理 pods 能使用的 cpu/memory 等硬體資源的,因此必須確保 kubelet 與 CRI 有設定正確,目前也只有兩個選項:
cgroupfs driver
:為 kubelet
的預設,會讓 kubelet
直接與 cgroup filesystem 互動。systemd cgroup
systemd cgroup
:為了避免有兩種管理機制,統一由 systemd 來管理 cgroup 是比較好的方式,且在 cgroupv2 的環境底下也建議使用此配置💡 目前新的 OS 版本大多都是開啟 cgroupv2,要檢查可以使用 mount 指令查看輸出,如以下:mount | grep cgroup2
有顯示:”cgroup2 on /sys/fs/cgroup type cgroup2
” 的字樣,代表目前系統是使用 cgroupv2
根據以上內容,請 AI 幫忙寫了一個簡易的腳本來檢查環境:
#!/bin/bash
# Output file
LOGFILE="check-k8s-env.log"
# Function to check if a command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Function to check if a port is in use
port_in_use() {
nc -z localhost "$1" >/dev/null 2>&1
}
# Function to check swap status
check_swap() {
if [ "$(swapon --show=NAME | wc -l)" -gt 0 ]; then
echo "[x] Swap is enabled. Please disable swap before proceeding." | tee -a "$LOGFILE"
return 1
else
echo "[o] Swap is disabled." | tee -a "$LOGFILE"
return 0
fi
}
# Initialize log file
echo "Starting environment checks..." | tee "$LOGFILE"
# Initialize status variables
status=0
# Check if containerd is installed
echo "Checking containerd installation..." | tee -a "$LOGFILE"
if command_exists containerd; then
echo "[o] containerd is installed." | tee -a "$LOGFILE"
else
echo "[x] containerd is not installed. Please install containerd before proceeding." | tee -a "$LOGFILE"
status=1
fi
# Check if kubeadm is installed
echo "Checking kubeadm installation..." | tee -a "$LOGFILE"
if command_exists kubeadm; then
echo "[o] kubeadm is installed." | tee -a "$LOGFILE"
else
echo "[x] kubeadm is not installed. Please install kubeadm before proceeding." | tee -a "$LOGFILE"
status=1
fi
# Check if kubectl is installed
echo "Checking kubectl installation..." | tee -a "$LOGFILE"
if command_exists kubectl; then
echo "[o] kubectl is installed." | tee -a "$LOGFILE"
else
echo "[x] kubectl is not installed. Please install kubectl before proceeding." | tee -a "$LOGFILE"
status=1
fi
# Check system requirements
echo "Checking system requirements..." | tee -a "$LOGFILE"
cpu_cores=$(grep -c ^processor /proc/cpuinfo)
memory_size=$(grep MemTotal /proc/meminfo | awk '{print $2 / 1024}')
if [ "$cpu_cores" -lt 2 ]; then
echo "[x] At least 2 CPU cores are required. Found $cpu_cores." | tee -a "$LOGFILE"
status=1
else
echo "[o] CPU core count is sufficient. Found $cpu_cores." | tee -a "$LOGFILE"
fi
if [ "$(echo "$memory_size < 2048" | bc)" -eq 1 ]; then
echo "[x] At least 2GB of RAM is required. Found $memory_size MB." | tee -a "$LOGFILE"
status=1
else
echo "[o] RAM size is sufficient. Found $memory_size MB." | tee -a "$LOGFILE"
fi
# Check swap is disabled
echo "Checking swap status..." | tee -a "$LOGFILE"
if ! check_swap; then
status=1
fi
# Check kernel version
echo "Checking kernel version..." | tee -a "$LOGFILE"
kernel_version=$(uname -r)
if ! [[ "$kernel_version" =~ ^[5-9]\. ]]; then
echo "[x] A kernel version of 5.x or higher is required. Found $kernel_version." | tee -a "$LOGFILE"
status=1
else
echo "[o] Kernel version is sufficient. Found $kernel_version." | tee -a "$LOGFILE"
fi
# Check cgroup version
echo "Checking cgroup version..." | tee -a "$LOGFILE"
cgroup_info=$(mount | grep cgroup)
if echo "$cgroup_info" | grep -q 'cgroup2'; then
echo "[o] Cgroup version 2 is enabled." | tee -a "$LOGFILE"
elif echo "$cgroup_info" | grep -q 'cgroup'; then
echo "[o] Cgroup version 1 is enabled or cgroup version is not specified." | tee -a "$LOGFILE"
else
echo "[x] Cgroup information not found. Please check cgroup setup." | tee -a "$LOGFILE"
status=1
fi
# Check if required ports are in use
ports=("2379" "2381" "6443" "10250" "10257" "10259")
for port in "${ports[@]}"; do
echo "Checking port $port..." | tee -a "$LOGFILE"
if port_in_use "$port"; then
echo "[x] Port $port is in use." | tee -a "$LOGFILE"
status=1
else
echo "[o] Port $port is available." | tee -a "$LOGFILE"
fi
done
if [ "$status" -eq 0 ]; then
echo "[o] All checks passed. Your environment is ready for 'kubeadm init'." | tee -a "$LOGFILE"
else
echo "[x] Some checks failed. Please review the log file '$LOGFILE' for details." | tee -a "$LOGFILE"
fi
目前在我的 ubuntu 24.04 主機上執行結果如下:
Starting environment checks...
Checking containerd installation...
[x] containerd is not installed. Please install containerd before proceeding.
Checking kubeadm installation...
[x] kubeadm is not installed. Please install kubeadm before proceeding.
Checking kubectl installation...
[x] kubectl is not installed. Please install kubectl before proceeding.
Checking system requirements...
[o] CPU core count is sufficient. Found 2.
[o] RAM size is sufficient. Found 3868.19 MB.
Checking swap status...
[x] Swap is enabled. Please disable swap before proceeding.
Checking kernel version...
[o] Kernel version is sufficient. Found 6.8.0-41-generic.
Checking cgroup version...
[o] Cgroup version 2 is enabled.
Checking port 2379...
[o] Port 2379 is available.
Checking port 2381...
[o] Port 2381 is available.
Checking port 6443...
[o] Port 6443 is available.
Checking port 10250...
[o] Port 10250 is available.
Checking port 10257...
[o] Port 10257 is available.
Checking port 10259...
[o] Port 10259 is available.
[x] Some checks failed. Please review the log file 'check-k8s-env.log' for details.
主要就是安裝 containerd, kubeadm 等等指令,以及關閉 swap
調整完畢之後,按著文件上面的指令操作,即可開始安裝 k8s cluster
kubeadm init 為啟動 k8s cluster 的指令,之後預計會看看 kubeadm 的所有指令,這邊就先略過了
前置動作大致步驟為:
kubeadm init
sudo kubeadm init
若以上配置無誤,即可建立 k8s cluster
kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-master1 NotReady control-plane 2m9s v1.31.0 192.168.75.10 <none> Ubuntu 24.04 LTS 6.8.0-41-generic containerd://1.7.21
到此還需要安裝 CNI,才能算是可用的 k8s clsuter,待後面的日子再處理
雖然先前有使用 kubeadm 安裝的經驗,但通常都是參考別人寫的文章,仔細看過文章之後,收穫不少,明日來看看如何建立具有 HA 的 k8s cluster
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
https://docs.docker.com/engine/install/ubuntu/
https://www.fortaspen.com/install-kubernetes-containerd-ubuntu-linux-22-04/