# kubernetes 建立叢集 lab [使用部署工具安装 Kubernetes ](https://kubernetes.io/zh-cn/docs/setup/production-environment/tools/kubeadm/install-kubeadm/) # 準備 3台 VM 1台 控制節點 Control Plane - 2 CPU 與 2G RAM 2台 工作節點 Worker Node - 1 CPU 與 2G RAM # 所有主機的執行步驟 (控制節點與工作節點) - 切換 root 並設置 root 密碼 - 設定 /etc/hosts - 安裝 ntp 自動校時 - 安裝必要組件 - containerd - runc - CNI plugin - 安裝 kubeadm, kubelet, kubectl # 控制節點的執行步驟 - 初始化控制節點 - 安裝 Pod 網路附加組件 # 工作節點的執行步驟 - 加入叢集 # 安裝 ubuntu 24.04 LTS [ubuntu 24.04 Server LTS iso](https://releases.ubuntu.com/noble/ubuntu-24.04.3-live-server-amd64.iso) 如果以上連結失效,請至[官網](https://releases.ubuntu.com/noble/),找到 Server install image,點選 「64-bit PC (AMD64) server install image」,記留意 CPU 架構。 :::danger amd64 是指 x86 CPU架構,非此 CPU 架構,不可下載此版本 ::: ## 參考下圖 ![image](https://hackmd.io/_uploads/BkFP5Yr9gl.png) ## 切換 root ```bash sudo su ``` ## 設置密碼 ```bash passwd ``` ## 輸入新密碼及再次輸入密碼 ![image](https://hackmd.io/_uploads/rya1TMAFJx.png) ## 設定 hosts ```bash cat >> /etc/hosts <<'EOF' 192.168.1.21 control-plane 192.168.1.22 node1 192.168.1.23 node2 EOF ``` ## 確認設定 ```bash cat /etc/hosts ``` ![image](https://hackmd.io/_uploads/SyYrTMAFkx.png) ## 安裝 ntp 自動校時 ```bash sudo apt install -y ntp ``` ## 確認 ntp 服務 ![image](https://hackmd.io/_uploads/SJcfqGCY1g.png) :::info 紅線為 ntp 設定檔路徑 ::: ## 如果需要修改設定,輸入以下指令 ```bash vim /etc/ntpsec/ntp.conf ``` # 關閉 swap ```bash swapoff -a && sysctl -w vm.swappiness=0 sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab free -h ``` ![image](https://hackmd.io/_uploads/SJRsEm0Ykl.png) ## 指令的詳細說明 ### 指令 1 ```bash swapoff -a && sysctl -w vm.swappiness=0 ``` ### swapoff -a 功能:此命令用於禁用所有的交換區(swap space)。當執行此命令時,系統會停止使用所有配置的交換設備,並將其從使用中移除 用途:在某些情況下,例如在安裝某些軟體或進行性能調整時,禁用交換區可以防止系統將內存頁面移動到磁碟上,從而提高性能 ### && 功能: 這是一個邏輯運算符,用於在第一個命令成功執行後執行第二個命令。如果 swapoff -a 成功(返回狀態碼 0),則會執行後面的命令 ### sysctl -w vm.swappiness=0 #### sysctl sysctl 是一個用於讀取和修改 Linux 核心參數的工具。這些參數通常位於 /proc/sys/ 目錄下,並且可以用來調整系統行為 #### -w 此選項表示要寫入一個新的值,並立即應用這個改變 #### vm.swappiness=0 vm.swappiness 是一個控制系統在使用交換區(swap space)時的策略參數。它的值範圍從 0 到 100 設定為 0 意味著系統將最大限度地使用實體記憶體,只有在內存非常緊張的情況下才會開始使用交換區。這樣可以提高系統性能,特別是在有足夠物理內存的情況下 #### 功能 此命令用於動態設置 Linux 系統的 swappiness 參數。swappiness 是一個範圍在 0 到 100 的值,決定了系統在使用交換區時的傾向。設置為 0 意味著系統將最小化使用交換區,優先使用物理內存 #### 用途 將 swappiness 設置為 0 可以使系統在物理內存不足時不會自動將內存頁面移到交換區,這對於需要高性能的應用程式(如數據庫)特別重要 ### 指令 2 ```bash sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab ``` ### sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab #### -r 使用擴展正則表達式 #### -i 直接在文件中進行修改,而不是輸出到標準輸出 #### '/^[^#]*swap/ 匹配所有不以 # 開頭的包含 "swap" 的行 #### s@^@#@ 將匹配到的行的開頭添加一個 # 符號,實現註解掉該行 #### 功能 此命令使用 sed 工具來編輯 /etc/fstab 文件。這個文件包含了系統啟動時掛載的文件系統和交換區的信息 #### 用途 通過註解掉 /etc/fstab 中與交換區相關的行,確保在系統重啟後不會自動啟用交換區。這樣可以使之前禁用的交換區保持禁用狀態 ### 指令3 ```bash free -h ``` 功能:顯示系統的記憶體使用情況,包括實體記憶體和交換空間 說明: #### free 指令用於顯示系統的記憶體使用統計資訊 #### -h 選項以人類可讀的格式顯示記憶體大小(例如,以 KB、MB 或 GB 為單位),方便使用者理解 # 安裝 containerd - containerd [getting started](https://github.com/containerd/containerd/blob/main/docs/getting-started.md) :::info Docker Engine 沒有實現 CRI, 這是容器運行時在 Kubernetes 中工作所需要的。 為此,必須安裝一個額外的服務 cri-dockerd。 cri-dockerd 是一個基於傳統的內置 Docker 引擎支持的項目,它在 1.24 版本從 kubelet 中移除 ::: :::warning 這是 containerd 二進制安裝方式 ::: ```bash! wget https://github.com/containerd/containerd/releases/download/v2.0.2/containerd-2.0.2-linux-amd64.tar.gz tar Cxzvf /usr/local containerd-2.0.2-linux-amd64.tar.gz ``` :::warning 請留意版本號,此 Lab 安裝時間為 2025/02/15 ::: ### wget 是一個用於從網路上下載檔案的命令行工具。它支援 HTTP、HTTPS 和 FTP 協議,並且可以在命令行環境中運行 https://github.com/containerd/containerd/releases/download/v2.0.2/containerd-2.0.2-linux-amd64.tar.gz 下載的檔案 URL。這個 URL 指向 GitHub 上 Containerd 的版本 2.0.2 的 Linux x86_64 版本的壓縮檔案(tar.gz 格式) ### 功能 這條指令將會從指定的 URL 下載 containerd-2.0.2-linux-amd64.tar.gz 檔案到當前工作目錄 ```bash tar Cxzvf /usr/local containerd-2.0.2-linux-amd64.tar.gz ``` ### tar 是一個用於打包和解壓縮檔案的工具,特別是在 Unix 和 Linux 系統中使用 ### C 此選項告訴 tar 在解壓縮之前切換到指定的目錄。在這裡,它會切換到 /usr/local 目錄 ### x 此選項表示要從 tar 檔案中提取檔案(解壓縮) ### z 此選項告訴 tar 檔案是經過 gzip 壓縮的,因此需要在解壓縮時自動解壓 ### v 此選項表示「詳細模式」,在解壓縮過程中會顯示正在處理的檔案名稱 ### f 此選項後面必須跟著檔名,表示要操作的檔案名稱。在這裡,它指定了要解壓縮的檔案 containerd-2.0.2-linux-amd64.tar.gz ### 功能 這條指令將會將 containerd-2.0.2-linux-amd64.tar.gz 檔案解壓縮到 /usr/local 目錄中,並在過程中顯示所有被解壓縮的檔案名稱 ## systemd 啟動 containerd ```bash! wget https://raw.githubusercontent.com/containerd/containerd/main/containerd.service mkdir -p /usr/local/lib/systemd/system mv containerd.service /usr/local/lib/systemd/system/containerd.service ``` ### mkdir 這是 "make directory" 的縮寫,用於建立目錄 ### -p 這個選項告訴 mkdir 如果父目錄不存在,則先建立父目錄。這意味著如果 /usr/local/lib/systemd 或 /usr/local/lib 目錄不存在,它們會被自動建立 ### /usr/local/lib/systemd/system 這是要建立的目錄路徑。在許多 Linux 系統中,systemd 服務檔案通常存放在這個目錄下 ```bash! mv containerd.service /usr/local/lib/systemd/system/containerd.service ``` ### mv 這是 "move" 的縮寫,用於移動或重新命名檔案 ### containerd.service 這是要移動的檔案名稱,即之前使用 wget 下載的檔案 ### /usr/local/lib/systemd/system/containerd.service 這是檔案要移動到的目標位置和新名稱。這表示將 containerd.service 檔案移動到 /usr/local/lib/systemd/system/ 目錄中,並保持檔案名稱為 containerd.service ## 運行命令 ```bash! systemctl daemon-reload systemctl enable --now containerd ``` :::info 修改了任何 systemd 單元檔案(例如位於 /etc/systemd/system/ 目錄下的服務檔案)後,都需要執行 systemctl daemon-reload,以確保 systemd 能夠識別並應用這些變更 ::: ### 新增服務後 如果新安裝了一個服務,並且該服務由 systemd 管理,則需要執行此命令,以使 systemd 能夠識別新的服務配置 ### 升級套件後 某些套件升級(例如 libc 的升級)後,可能需要重新啟動服務。systemctl daemon-reexec 指令可以重新執行 systemd 並使其重新處理其配置,達到類似重新啟動的效果 ### 判斷是否需要執行 systemctl daemon-reload 可以使用 systemctl show <unit> --property=NeedDaemonReload 命令來檢查特定單元是否需要重新載入。如果輸出結果為 NeedDaemonReload=yes,則表示需要執行 systemctl daemon-reload ## 安裝 runc ```bash! wget https://github.com/opencontainers/runc/releases/download/v1.1.14/runc.amd64 install -m 755 runc.amd64 /usr/local/sbin/runc ``` ### install 這是用於複製檔案的指令,但它比 cp 指令更適合用於安裝程式,因為它可以設定權限和擁有者 ### -m 755 這個選項用於設定檔案的權限。755 是一個八進制數 #### 表示 使用者 (Owner) 具有讀、寫、執行的權限 (7) 群組 (Group) 具有讀、執行的權限 (5) 其他使用者 (Others) 具有讀、執行的權限 (5) ### runc.amd64 這是要複製的來源檔案名稱,即之前使用 wget 下載的 RunC 二進制檔案 ### /usr/local/sbin/runc 這是檔案要複製到的目標位置和新名稱。這表示將 runc.amd64 檔案複製到 /usr/local/sbin/ 目錄中,並將其重新命名為 runc。 /usr/local/sbin 是一個用於存放系統管理員使用的可執行檔的標準位置 ## 安裝 CNI plugins ```bash! wget https://github.com/containernetworking/plugins/releases/download/v1.6.2/cni-plugins-linux-amd64-v1.6.2.tgz mkdir -p /opt/cni/bin tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.6.2.tgz ``` # 配置 containerd 所需的模組 **手動加載模組** ```bash modprobe -- overlay modprobe -- br_netfilter ``` **開機自動載入所需的核心模組** ```bash cat > /etc/modules-load.d/containerd.conf <<EOF overlay br_netfilter EOF ``` ![image](https://hackmd.io/_uploads/S1aP-EAYJe.png) # **修改 containerd 設定檔** **重新初始化 containerd 設定檔** ```bash mkdir -p /etc/containerd containerd config default | tee /etc/containerd/config.toml ``` ### mkdir mkdir 是 "make directory" 的縮寫,用於創建新目錄 ### -p 這個選項表示如果父目錄不存在,則同時創建所有必要的父目錄。這樣可以避免因為某個中間目錄不存在而導致創建失敗 ### /etc/containerd 這是要創建的目錄的路徑。在這個例子中,指的是 Containerd 的配置目錄 ### containerd config default 此命令生成 Containerd 的預設配置,並以標準輸出形式顯示 ### | 管道符號,用於將前一個命令的輸出傳遞給下一個命令 ### tee /etc/containerd/config.toml tee 是一個命令,用於讀取標準輸入並將其內容寫入檔案,同時將內容輸出到標準輸出。這樣你可以在終端中看到輸出,同時將其寫入檔案 /etc/containerd/config.toml 是要寫入的檔案路徑,這裡指定了 Containerd 的配置檔案位置 **修改 cgroup 的管理者為 systemd 組件** ```bash! sed -ri 's#(SystemdCgroup = )false#\1true#' /etc/containerd/config.toml grep SystemdCgroup /etc/containerd/config.toml ``` ### sed 這是 "stream editor" 的縮寫,是一個強大的文字處理工具,用於在文字流或檔案中進行搜尋、替換、刪除等操作 ### -r 這個選項啟用擴展的正規表示式,允許使用更複雜的模式 ### -i 這個選項表示直接在檔案中修改,而不是將結果輸出到標準輸出 ### 's#(SystemdCgroup = )false#\1true#' 這是 sed 指令的核心部分,表示一個替換操作 ### s 表示替換操作 ### #(SystemdCgroup = )false# 這是要搜尋的模式(正規表示式)。它尋找包含 "SystemdCgroup = false" 的字串。括號 () 用於建立捕獲群組,將 "SystemdCgroup = " 部分捕獲到第一個群組中 ### \1true# 這是替換的內容。\1 引用第一個捕獲群組的內容(即 "SystemdCgroup = "),然後將其與 "true" 連接起來 ### g (如果有的話)替換所有匹配到的字串,如果沒有 g,則只替換第一個匹配到的字串 ### grep 這是 "global regular expression print" 的縮寫,用於在檔案中搜尋包含特定模式的行 ### SystemdCgroup 這是要搜尋的模式 ### /etc/containerd/config.toml 這是要搜尋的檔案名稱 **修改 pause 的基礎鏡像名稱** https://github.com/kubernetes/kubernetes/blob/master/build/pause/CHANGELOG.md ```bash! sed -i 's#registry.k8s.io/pause:3.8#registry.k8s.io/pause:3.10#' /etc/containerd/config.toml grep sandbox_image /etc/containerd/config.toml ``` # **重新啟動 containerd** **啟動 containerd 服務** ```bash systemctl daemon-reload systemctl restart containerd ``` **確認 containerd 狀態** ```bash systemctl status containerd ``` **配置 crictl 客戶端連接的運行時位置** ```bash cat > /etc/crictl.yaml <<EOF runtime-endpoint: unix:///run/containerd/containerd.sock image-endpoint: unix:///run/containerd/containerd.sock timeout: 10 debug: false EOF ``` **查看 containerd 的版本** ```bash ctr version ``` ![image](https://hackmd.io/_uploads/SkeB6B40KJx.png) # 切換 containerd group :::info 登出 root 身份 ::: ```bash! exit ``` ![image](https://hackmd.io/_uploads/HJoiUV0Kkl.png) 如果尚未創建 containerd group,使用以下命令創建 ```bash! sudo groupadd containerd ``` 將 containerd socket 文件的 group 更改為 containerd ```bash! sudo chgrp containerd /run/containerd/containerd.sock ``` 當前用戶添加到 containerd group,以便在不使用 sudo 的情況下訪問 ```bash! sudo usermod -aG containerd $USER ``` 命令切換到新組 ```bash! newgrp containerd ``` ```bash! crictl ps ``` # 安裝 kubeadm kubelet kubectl - kubeadm 用來初始化集群的指令。 - kubelet 在集群中的每個節點上用來啟動 Pod 和容器等。 - kubectl 用來與集群通信的命令行工具。 ```bash! cat > /etc/sysctl.d/k8s.conf <<'EOF' # 以下3個參數是 containerd 所依賴的核心參數 net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 EOF sysctl --system # 生效 ``` :::info 設定 containerd 容器運行時所依賴的一些核心參數,包括啟用 IP 轉發以及允許橋接網路調用 iptables 和 ip6tables 規則。這些參數的設定對於在 Kubernetes 環境中正確配置網路功能至關重要。 ::: ## 更新 apt 包索引並安裝使用 Kubernetes apt 倉庫所需要的包 ```bash! sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl gpg ``` ## 下載用於 Kubernetes 軟件包倉庫的公共簽名密鑰。所有倉庫都使用相同的簽名密鑰,因此你可以忽略URL中的版本 ```bash! # 如果 /etc/apt/keyrings 目錄不存在,在 curl 命令之前創建它 # sudo mkdir -p -m 755 /etc/apt/keyrings curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg ``` :::info 在低於 Debian 12 和 Ubuntu 22.04 的發行版本中,/etc/apt/keyrings 默認不存在。 應在 curl 命令之前創建它。 ::: ## 添加 Kubernetes apt 倉庫。 請注意,此倉庫僅包含適用於Kubernetes 1.32 的軟件包。對於其他 Kubernetes 次要版本,則需要更改 URL 中的 Kubernetes 次要版本以匹配你所需的次要版本(你還應該檢查正在閱讀的安裝文檔是否為你計劃安裝的Kubernetes 版本的文檔) ```bash! # 此操作會覆蓋 /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.32/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list ``` ## 更新 apt 包索引,安裝 kubelet、kubeadm 和 kubectl,並鎖定其版本 ```bash! sudo apt-get update sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl ``` ## 啟用並立即啟動 kubelet 服務 ```bash! sudo systemctl enable --now kubelet ``` # 初始化控制節點 ```bash! sudo kubeadm init --pod-network-cidr=10.10.0.0/16 ``` :::info lab 我的 PODCIDR 使用 10.10.0.0/16 參考以下命令 ::: [Deploying Flannel with helm ](https://github.com/flannel-io/flannel?tab=readme-ov-file#deploying-flannel-with-helm) ```bash! kubectl create ns kube-flannel kubectl label --overwrite ns kube-flannel pod-security.kubernetes.io/enforce=privileged ``` :::warning Needs manual creation of namespace to avoid helm error ::: helm deploy ```bash! helm repo add flannel https://flannel-io.github.io/flannel/ helm install flannel --set podCidr="10.10.0.0/16" --namespace kube-flannel flannel/flannel ``` ![image](https://hackmd.io/_uploads/BkrbXS0Fkg.png) ## 使非 root 用戶可以運行 kubectl,請運行以下命令 ```bash! mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config ``` ## 如果是 root 用戶,可以運行 ```bash! export KUBECONFIG=/etc/kubernetes/admin.conf ``` # 工作節點加入叢集 ```bash! kubeadm join 192.168.1.21:6443 --token d8sw5z.6kpz5w4gvg1jky3i \ --discovery-token-ca-cert-hash sha256:8cb9cd9014210108d6a9b020eebd400936de84117120ddaaa46457e4cf16d657 ``` # 安裝 Pod 網路附加組件 ## 還未安裝網路附加組件,node 狀態會呈現 NotReady ![image](https://hackmd.io/_uploads/BJYzSBCKyx.png) # [deploying flannel](https://github.com/flannel-io/flannel#deploying-flannel-manually) ## 先前初始化控制節點已設定 pod network cidr 為 10.244.0.0/16 不需要下載另行設定 ```bash! kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml ``` ![image](https://hackmd.io/_uploads/HJfD8H0KJe.png) :::warning 如果使用自定義 POD CIDR(不是10.244.0.0/16),需要下載 yaml 並修改以匹配網路 ::: # 完成建立 Kubernetes Cluster Lab ![image](https://hackmd.io/_uploads/ry9nISRF1g.png)