初學K8s的時候通常都是用官方提供的「Minikube」或是「Docker Desktop K8s」來做練習,但不管是Minikube或是Docker Desktop K8s它們畢竟是一個學習用的工具,這些工具幫助我們省去了Control Plan很多安裝套件(如:etcd、CNI等)的步驟以及Node的設定,然而真實的K8s Cluster建置是更加的錯綜複雜,如果只單單使用Minikube和Docker Desktop的K8s反而會沒機會接觸到Cluster建置時的細部設定,因此還是會建議使用VM去模擬和練習真實的K8s Cluster建置哦!

快速導覽



VM和Linux系統準備

首先要建立Cluster需要有充沛數量的實體主機/虛擬主機,因此這裡我事先準備了2台VM主機,一台用作Control Plane另外一台用作Node

Control Plane

  • Linux - Ubuntu 20.04
  • 2 Core
  • 3.5G RAM

Node

  • Linux - Ubuntu 20.04
  • 2 Core
  • 2.0G RAM
💡 由於練習的關係記憶體就依照自己電腦可以承受的範圍即可,實戰時就不要設定這麼小哦XD


使用kubeadm設置K8s集群

在K8s的官網上有介紹三種建置K8s的方式【點我前往】,由於我們是建置在實體/虛擬主機上因此可以直接選擇kubeadm的方式進行安裝,另外兩種方式都跟雲端有關係因此我們就略過即可。



在Control Plane和Node上安裝K8s

接下來要在Control Plane和Node上都安裝上K8s的功能,因此兩臺主機都必須要執行以下的安裝步驟
  1. 更新套件
  2. sudo su
    apt update

  3. 安裝工具
  4. apt install net-tools -->(選擇性)
    apt install -y vim
    apt install -y openssh-server
    apt install -y nfs-common -->(如果Volumes要使用NFS需要安裝)
    apt update
    💡 vim是建議安裝,接下來的步驟幾乎都會需要用到vim

  5. 關閉Swap
  6. swapoff -a
    vim /etc/fstab
    使用vim編輯器打開fstab,把/swapfile這行給註解掉(註解是加個#字號)
    💡 vim的編輯指令:【i】 vim的儲存和離開指令:【:wq】 vim的離開指令:【:q】
    💡 關於為什麼要關掉Swap可以參考這篇【點我前往

  7. 修改Hostname(選擇性)
  8. vim /etc/hostname
    修改完成後需要重新啟動實體/虛擬機器才會生效

    Control Plane命名 → K8sControlPlane

    Node命名 → K8sNode

    💡 這裡建議修改hostname,原因後面會提到

  9. 安裝和啟動Docker(K8s-1.26版前的安裝方式)
  10. apt install -y docker.io
    systemctl enable docker
    systemctl start docker
    systemctl status docker -->(檢查是否有啟動成功)

  11. 安裝和啟動Docker&1.6版containerd(K8s-1.26版後的安裝方式)
  12. 由於K8s 1.26版更新後不再支持containerd1.5和以下的版本,如果繼續使用則Kubeadm初始化時會發生錯誤
    💡 K8s 1.26版後將不再支持1.5版以下的containerd詳細問題可以【點我參考
    由於在我寫這篇文章時,還無法使用apt直接更新containerd,因此我是使用Docker提供的儲存庫來安裝,未來應該是可以直接透過apt更新
    mkdir -p /etc/apt/keyrings
    apt install -y apt-transport-https ca-certificates curl gnupg lsb-release
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    apt update
    apt install -y docker-ce docker-ce-cli containerd.io
    systemctl enable docker
    systemctl start docker
    systemctl status docker -->(檢查是否有啟動成功)
    💡 Docker官網提供的使用儲存庫安裝的設定方式【點我參考
    接著使用指令建立資料夾和產生containerd的config設定檔案
    mkdir -p /etc/containerd
    containerd config default | sudo tee /etc/containerd/config.toml
    最後我們在Config裡面添加一行參數:SystemdCgroup = true
    vim /etc/containerd/config.toml
    systemctl restart containerd
    💡 參考來源【點我前往

  13. 替Docker添加受信任名單(Private Docker Registry)【點我前往】(選擇性)
  14. 新增容器受信任名單(選擇性)
  15. mkdir /etc/containerd
    vim /etc/containerd/config.toml
    添加以下設定(此設定棄用,請改用下面的設定
    # Config file is parsed as version 1 by default.
    # To use the long form of plugin names set "version = 2"
    [plugins.cri.registry.mirrors]
      [plugins.cri.registry.mirrors."192.168.1.8:5000"]
        endpoint = ["http://192.168.1.8:5000"]
    # 該設定已不適用,請改用下面的設定值
    添加以下設定(請改用此設定)
    [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
      [plugins."io.containerd.grpc.v1.cri".registry.mirrors."192.168.1.8:5000"]
        endpoint = ["https://192.168.1.8:5000"]
    儲存後需要重新啟動服務
    systemctl restart containerd
    💡 Containerd相關設定可以【點我參考
    💡 stackoverflow上網友提問使用Private Docker Registry時的問題【點我參考
    💡 步驟7和8是如果你的Image要從Private Registry取得的話就需要設定受信任名單

  16. 下載K8s前置準備
  17. 我們需要事先設定好K8s的庫(此設定棄用,請改用下面的設定)
    apt update && apt install -y apt-transport-https curl
    curl -O https://packages.cloud.google.com/apt/doc/apt-key.gpg
    apt-key add apt-key.gpg
    apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"
    # 該設定已不適用,請改用下面的設定值
    💡 「apt-transport-https」是讓Ubuntu允許使用http或https
    💡 「https://packages.cloud.google.com/apt/doc/apt-key.gpg」是K8s的簽名密鑰
    💡 「apt-add-repository」是將K8s包的儲存庫添加到apt系統內
    設定K8s的庫(請改用此設定)
    sudo curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
    echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

  18. 安裝K8s工具
  19. apt update
    apt install -y kubelet kubeadm kubectl kubernetes-cni
    apt-mark hold kubelet kubeadm kubectl
    💡 「apt-mark hold」是鎖定版本,不讓apt升級或更改狀態

  20. 完成安裝
  21. kubelet --version
    kubeadm version
    kubectl version
到這邊K8s在Control Plane和Node上的安裝就全數完成!



初始化Control Plane和工具安裝

安裝完K8s之後就可以來初始化Control Plane,我們在Control Plane的主機上使用以下指令:
Kubeadm init
若是要搭配Calico的CNI請添加--pod-network-cidr參數
kubeadm init --control-plane-endpoint="www.xxx.xxx.com.tw" --pod-network-cidr=192.168.0.0/16
初始化完成後系統會給你一段kubeadm join」的指令,這段可以先複製下來等等才會使用到。另外系統提示也有提示要你執行以下命令,關於這行命令的功能應該是跟TSL證書有關的設定,需要詳細設定檔可以【點我前往】參考。

使用Kubectl命令並且使用者為非Root用戶時,執行此命令:

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

使用Kubectl命令並且使用者為Root用戶時,執行此命令:

export KUBECONFIG=/etc/kubernetes/admin.conf
💡 /etc/kubernetes/admin.conf 這個文件通常由 kubeadm init 命令生成,並且該文件的權限設定為只有Root用戶可以讀取。這是為了保護這個文件中的敏感信息,如集群的管理憑證。

所以,提示上說「如果你是Root用戶」,你可以運行「export KUBECONFIG=/etc/kubernetes/admin.conf」,實際上的意思是,只有Root用戶(或者有足夠權限的用戶)可以讀取「/etc/kubernetes/admin.conf」文件,並且可以將其設定為 kubectl 的配置文件。

對於普通用戶,通常是把「admin.conf」文件複製到用戶的家目錄下,並更改文件的擁有者和權限,使得該用戶可以讀取該文件。這就是非Root那段命令的作用。
初始化完成後我們使用指令查看Control Plane是否已啟動
kubectl get nodes

或是直接查看系統的pods
kubectl get pods -n kube-system

上圖可以發現Control Plane Node欄位「Status」是處於「NotReady」的狀態,而且查看Pods的時候會看到兩個Status為「Pending」的狀態,主要的因為是還沒有安裝「CNI」
💡 CNI就是虛擬網路的驅動介面,最具代表性的就是Calico和Flannel,當然還有其它很多虛擬網路驅動界面可以用哦【點我前往】!
💡 各個CNI都有各自的優缺點,看個人需求做選擇即可【點我前往


安裝CNI(使用Calico)

安裝CNI非常的簡單,就是執行一個容器就完成安裝了!我們直接執行以下指令:
(此安裝連結已經失效和棄用)
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
2023/2/15補充新的安裝方式,詳細內容可以參考Calico的官網【點我前往】。
安裝Tigera Calico operator
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

接著安裝「Custom resource definitions」
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/custom-resources.yaml
💡 這裡要注意的是custom-resources.yaml裡面的「cidr」屬性和kubeadm init時設定的「--pod-network-cidr」參數是否有一致哦!

安裝完成後可以使用以下指令等待命名空間為「calico-system」的所有Pods狀態都轉為「Running」為止
watch kubectl get pods -n calico-system

最後需要移除Control Plan上的taints
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
kubectl taint nodes --all node-role.kubernetes.io/master-
如果有成功移除的話會出現以下訊息:「node/<your-hostname> untainted」。而安裝CNI完成後可以再使用指令檢查一次,Status狀態沒意外就會是Ready」「Running」了!



安裝Cert Manager(Let's Encrypt憑證自動申請)

Cert Manager是一個K8s的控制器,主要負責管理 SSL/TLS 憑證,它可以自動申請、更新、管理 SSL/TLS 憑證,另外也提供了ACME協議的支援,可讓使用者方便地向Let's Encrypt進行憑證申請,以實現 HTTP/HTTPS 的安全傳輸,如果有使用Ingress並且使用https這個就要安裝哦!
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.11.0/cert-manager.yaml
以上就是Control Plane的初始化和工具的安裝步驟,接下來只需要把Node加入到Cluster裡面和Control Plane連線即可完成Cluster的建置囉!



將Node加入Cluster

還記得在Control Plan初始化後,系統給了一段kubeadm join」的指令嗎?這段指令的用途就是方便我們把現有的Node主機快速的加入整個K8s Cluster,是不是很方便XD。我們直接在Node主機上開啟終端機執行剛才那段指令:
kubeadm join 192.168.135.130:6443 --token bfwbve.k4eltmt0yj1lqjr0 \
	--discovery-token-ca-cert-hash sha256:e6331de2ee40659b9ae604b7ca8f803695af76e0431130c18e5ac65997a4c2a0

添加完成後回到Control Plane上執行以下指令可以查看Node是否有正確加入Cluster
kubectl get nodes

恭喜!成功建置一個K8s Cluster了!


後續添加額外的Node

我們可以發現kubeadm join」指令裡面的Token」其實是有時效性的因此Token是無法一直使用的,如果後續需求要再添加額外的Node時,就必須在Control Plane產生出新的一組Token用於添加Node,所以K8s提供了一個很方便的指令:
kubeadm token create --print-join-command

Control Plane直接產生一組新的kubeadm Join指令附帶新的Token給你,接著只需要將指令貼到要加入的Node主機終端機內執行,等待一段時間後即可完成囉!是不是很方便呢!


替Node命名方便管理

在使用「kubectl get nodes」時,可以看到除了Control Plane的「ROLES」欄位有名稱,其餘的Node皆顯示「<none>」

為了方便管理,我們可以使用以下指令來重新命名Node的ROLES:
kubectl label --overwrite nodes <指定的節點> kubernetes.io/role=<新的角色命名>
  • --overwrite(選擇)用於覆蓋原有的label

完成!