# 使用 kubeadm 安裝 K8s - 本文將使用 Kubeadm 建立有兩個節點的 k8s 叢集 - 一個 master 節點和一個 worker 節點 - 使用 **Containerd** 作為 k8s 的 CRI ## 硬體環境 - 需要多台實體機器,或是使用 VM 模擬多台機器 - 至少需要兩個節點,才能形成完整的叢集 - 最小硬體需求: - CPU: 2 cores - RAM: 2 GB - 網路環境 - 必須可以連上網際網路 - 所有節點之間可以互相連線 (在相同的 LAN 中、或有公網 IP、或是可以透過 router 互連) - 可以用 `ping` 指令檢驗所有節點是否可以互連 - 作業系統 - 以 Linux 為佳,以下將以 Ubuntu 環境示範 ### 網路資訊 :::warning - 下列為本文操作中的兩個節點的網路資訊 - 於自己的環境操作時,請記得代換成你自己環境上的資訊 ::: - Hostname - Master Node: `k8s-master` - Worker Node: `k8s-1` - IP address: - Master Node: `192.168.56.80` - Worker Node: `192.168.56.81` - 網卡名稱: `enp0s8` ## 設定 DNS (所有 Node) - 使用文字編輯器修改 */etc/hosts* 設定檔 ```bash sudo nano /etc/hosts # 或 sudo vim /etc/hosts ``` - 加入其他節點的名稱和對應的 IP - 以我的環境為例 - Master Node: 名稱為 k8s-master,IP 為 192.168.56.80 - Worker Node: 名稱為 k8s-1,IP 為 192.168.56.81 - 在設定檔中應加入 ``` 192.168.56.80 k8s-master 192.168.56.81 k8s-1 ``` ## 關閉 Swap (所有 Node) ### 關閉 Swap 功能 ```bash sudo swapoff -a ``` 檢查是否成功關閉,若執行下面指令後沒有任何輸出,則代表關閉成功 ```bash sudo swapon --show ``` :::warning - `swapoff` 的效果並非永久 - 系統重新啟動後,swap 仍會重新開啟 - 需要執行下方的操作,避免開機時啟用 Swap ::: ### 永久關閉 Swap #### 修改 fstab,避免開機時掛載 swap 磁區 - 使用文字編輯器 (`nano`, `vim`, ...)開啟 */etc/fstab* ```bash sudo vim /etc/fstab # 或 sudo nano /etc/fstab ``` - 將所有包含 `swap` 的行都加上註解 (在該行前加上 `#`) - 以下面的內容為例,若 */etc/fstab* 的內容如下 (內容僅供參考,實際內容以你自己的機器為主) ```bash= # /etc/fstab: static file system information. # # Use 'blkid' to print the universally unique identifier for a # device; this may be used with UUID= as a more robust way to name devices # that works even if disks are added and removed. See fstab(5). # # <file system> <mount point> <type> <options> <dump> <pass> # / was on /dev/sda3 during curtin installation /dev/disk/by-uuid/85e6b527-dc3f-4921-8004-fbea382a88e0 / ext4 defaults 0 1 /dev/disk/by-uuid/f52bade4-4ae1-44ec-8342-38cea61fd2b0 none swap sw 0 0 # /boot was on /dev/sda2 during curtin installation /dev/disk/by-uuid/4280fffd-6ec8-4d4e-99fb-90238597a1f1 /boot ext4 defaults 0 1 ``` - 第 10 行是一個 swap 磁區的設定 (該行的最右邊有寫著 swap 的欄位),所以要在該行的開頭加上 `#` 將此行註解,結果如下 ```bash= # /etc/fstab: static file system information. # # Use 'blkid' to print the universally unique identifier for a # device; this may be used with UUID= as a more robust way to name devices # that works even if disks are added and removed. See fstab(5). # # <file system> <mount point> <type> <options> <dump> <pass> # / was on /dev/sda3 during curtin installation /dev/disk/by-uuid/85e6b527-dc3f-4921-8004-fbea382a88e0 / ext4 defaults 0 1 #/dev/disk/by-uuid/f52bade4-4ae1-44ec-8342-38cea61fd2b0 none swap sw 0 0 # /boot was on /dev/sda2 during curtin installation /dev/disk/by-uuid/4280fffd-6ec8-4d4e-99fb-90238597a1f1 /boot ext4 defaults 0 1 ``` - 記得修改完檔案後要存檔 - 使用 `vim`,先按 Esc 後輸入 `:wq` - 使用 `nano`,先按 Ctrl+O 再按 Ctrl+X #### 透過 Systemd 關閉所有 Swap Unit - 使用 `systemctl` 查詢所有 swap unit ``` sudo systemctl --type=swap -a ``` - 假設輸出如下,代表系統中有一個被啟用的 swap unit,名稱為 ***dev-sda4.swap*** ``` UNIT LOAD ACTIVE SUB DESCRIPTION dev-sda4.swap loaded inactive dead Swap Partition LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 1 loaded units listed. To show all installed unit files use 'systemctl list-unit-files'. ``` - 實際名稱可能不同,請以操作時拿到的實際輸出為準 - 使用 `systemctl` 關閉該 swap ``` sudo systemctl mask <swap unit> ``` - `<swap unit>` 要改成實際的 unit 名稱 - 以上面例子為例,指令應為: ``` sudo systemctl mask dev-sda4.swap ``` - 再次使用 `systemctl` 查詢,檢查 swap 是否被關閉 ``` sudo systemctl --type=swap -a ``` ## 安裝 Docker (所有 Node) ```bash sudo apt-get update sudo apt-get 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 echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin ``` ## 啟用 Kernel Module 並設定 Kernel 參數 (所有 Node) - 在 K8s 的所有節點中,需要執行下列指令載入指定的 Kernel Module,以保證網路傳輸正常 ```bash # 建立 Kernel Module 設定檔 cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF # 載入 Kernel Module sudo modprobe overlay sudo modprobe br_netfilter ``` - 在 K8s 的所有節點中,需要執行下列指令設定 Kernel 參數,以保證網路傳輸正常 ```bash # 建立 Kernel 參數設定檔 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 # 載入 Kernel 參數 sudo sysctl --system ``` ## 安裝 K8s 套件 (所有 Node) ### 安裝網路工具 ```= sudo apt update sudo apt install -y apt-transport-https ca-certificates curl ``` ### 取得 K8s 安裝設定 **下面以 1.32 版為例**,其他版本可參考官方說明文件: https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/ ```bash sudo mkdir /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 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 ``` ### 安裝 kubelet, kubeadm, kubectl - 安裝預設版本 ``` sudo apt update sudo apt install -y kubelet kubeadm kubectl ``` - 可以在套件名稱之後加上 `=<version>` 指定安裝的版本 ``` sudo apt install -y kubelet=1.32.2-1.1 kubeadm=1.32.2-1.1 kubectl=1.32.2-1.1 ``` - 查詢可用的版本號 ``` sudo apt list -a kubelet ``` - (可選) 鎖定版本,避免自動更新或升級 ``` sudo apt-mark hold kubelet kubeadm kubectl ``` ## 設定 Containerd (所有 Node) - 建立 Containerd 的設定檔資料夾 ``` sudo mkdir /etc/containerd ``` - 將預設的設定內容寫入設定檔案中 ```bash sudo sh -c "containerd config default > /etc/containerd/config.toml" ``` - 修改設定檔的內容,啟用 SystemdCgroup ```bash sudo sed -i 's/ SystemdCgroup = false/ SystemdCgroup = true/' /etc/containerd/config.toml ``` - 重啟 containerd 和 kubelet ``` sudo systemctl restart containerd sudo systemctl restart kubelet ``` ## 建立 K8s Cluster (Master Node) ### Pull 必要的 Image - 以下操作僅在 Master Node 執行 - Pull 所有 kubeadm 需要的 Image ``` sudo kubeadm config images pull ``` :::warning - 這個步驟需要下載一些檔案,可能需要較長時間 - 實際需要的時間取決於網路速度,請耐心等待 ::: ### 初始化 Cluster ```bash sudo kubeadm init \ --apiserver-advertise-address=<node ip address> \ --pod-network-cidr=<pod network cidr> ``` - `<node ip address>` 為 master 節點的 IP address (且此 IP address 必須能和其他節點溝通) - `<pod network cidr>` 為日後 pod 所使用的 IP 區段,可以自己定義 - 格式為 `XXX.XXX.XXX.XXX/OO`,需符合 [CIDR](https://zh.wikipedia.org/zh-tw/%E6%97%A0%E7%B1%BB%E5%88%AB%E5%9F%9F%E9%97%B4%E8%B7%AF%E7%94%B1) - 須注意使用的 IP 區段不能和機器實際使用的 IP 區段重疊 - 建議使用私有區段,例如 `10.XX.0.0/16` - 舉例來說 - 假設 master node 的 IP 為 192.168.56.81 - 希望 pod 使用的 IP 區段為 10.244.0.0/16 (即 10.20.0.0~10.244.255.255) - 初始化的指令應為 ``` sudo kubeadm init \ --apiserver-advertise-address=192.168.56.81 \ --pod-network-cidr=10.244.0.0/16 ``` - 初始化完成後,輸出的最後兩行是加入 worker 節點的指令,請先複製此指令並存在任意檔案中,在之後可以用到 - 該指令應類似: ``` kubeadm join 10.0.2.81:6443 --token XXXXXXX \ --discovery-token-ca-cert-hash sha256:XXXXXXXXX ``` ### 建立管理員設定檔 - 初始化完成後,會跳出如何設定的提示 ``` mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config ``` - 完成設定後,即可使用 `kubectl` 指令控制 cluster - 查看節點狀態 ```bash kubectl get node ``` - 輸出應類似: ``` NAME STATUS ROLES AGE VERSION k8s-master NotReady control-plane 1m v1.27.6 ``` - NotReady 是因為還未安裝 CNI,在下一篇筆記中會提到 ## Worker Node 加入 Cluster (Worker Node) - 在 Worker Node 中,執行剛剛複製的指令,即可將 worker node 加入 cluster 中 - 由於加入 node 的 token 是有時效性的,若已過期或是沒有存到指令,可以在<font color='red'> master node </font> 執行下面指令,產生新的 join 指令 ``` kubeadm token create --print-join-command ``` - 執行下面指令,查看 cluster 的所有節點,現在應有兩個節點 ``` kubectl get node ``` ## 安裝 Calico 作為 CNI - 在建立 cluster 之後,需要在 cluster 中部屬 CNI (container networking interface) 才能讓 cluster 開始運作 - 本文將使用 Calico 作為 CNI ### 下載 yaml (Mater Node) - 到 Calico 的 Github 找到 calico 的 yaml 檔,Calico 的所有 yaml 會放在 manifests 底下 - https://github.com/projectcalico/calico/tree/master/manifests - 找到 [calico.yaml](https://github.com/projectcalico/calico/blob/master/manifests/calico.yaml),打開該檔案的原始檔,複製它的 URL  - 在 master node 使用 `wget` 下載 yaml 檔 ``` wget https://raw.githubusercontent.com/projectcalico/calico/master/manifests/calico.yaml ``` ### 修改 yaml - 使用文字編輯器修改 calico.yaml ```bash nano ./calico.yaml # 或 vim ./calico.yaml ``` - 找到以下區段 - 可以搜尋 `# Auto-detect the BGP IP address.`  - 在相同的層級插入以下兩行 ```yaml - name: IP_AUTODETECTION_METHOD value: "interface=<network interface>" ``` - `<network interface>` 請替換成你正在使用的網卡名稱,請選擇可以和其他節點互連的那張網卡 - 縮排要對齊 `# Auto-detect the BGP IP address.`  - 以我的為例,所有節點上的網卡 `enp0s8`,都有 IP 位址 192.168.56.XX,所以我要填入 `enp0s8` - 修改完成後存檔 ### 部屬 Calico (Master Node) - 使用 `kubectl` 部屬修改好的 yaml 檔 ``` kubectl apply -f ./calico.yaml ``` - 完成部屬後(可能需要等幾分鐘),所有節點的狀態應為 `Ready` ``` kubectl get node ```
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.