分享如何在雲端服務上架個 K3s 來學 K8s

程式技術
sharkHead
分享如何在雲端服務上架個 K3s 來學 K8s

最近一直在學習如何使用 K8s (Kubernetes),一開始我是透過 minikube 來瞭解 K8s 的基礎知識與用法。學習了一段時間後,我想嘗試將自己的個人專案搬移到 K8s 上,從實務面上去使用 K8s,但 …

各個雲端平台上的 K8s 服務都 Hen 貴

K8s 雖然可以幫你有效的管理架構複雜的產品 (例如微服務),但其維護成本並不低,不論是金錢或是人力上,都需要耗費不少的資源。

自己的小專案搬移到 K8s 上其實有點殺雞用牛刀,但從實務上學習技術我認為是最快的方法。於是我決定在 GCP (Google Cloud Platform) 上搭建一個小型的 K3s 平台,並嘗試將自己的部落格搬移到上面。

第一次使用 GCP,google 會很大方地送你 300 美金讓你玩他們家的服務。

什麼是 K3s?

K3s 為輕量版本的 K8s,是由 Rancher Labs 社群維護,同時也是 CNCF 的專案之一。K3s 在使用上與 K8s 十分相似。而 K3s 的目的是想要降低 K8s 的硬體需求,讓其可以用在 IoT 這類等硬體資源較受限的環境。

K3s 的名稱由來

K8s 原詞 kubernetes 總共有 10 個字,頭尾的字母保留不算,中間共有 8 個字,因此得命 K8s。

而 K3s 的設計初衷,是希望記憶體使用上只有 K8s 的一半。所以 10 / 2 = 5,根據 K8s 的命名方式, 5 個字的的詞,如果頭尾字母保留不算,中間會有 3 個字母,K3s 的名稱便是由此而來。

因此 K3s 並沒有全名,就叫 K3s 😁。

K3s 的架構

2023_06_26_22_41_07_72d1e9e6f582.jpg
  • K3s Server:叢集中的大腦,負責指定 container 要運行在哪個節點與調節叢集的狀態,相當於 K8s 中的 master。
  • K3s Agent:叢集中用來運行 container 的節點,相當於 K8s 中的 worker。
  • API Server:提供 K3s 的 RESTful API 服務,kubectl 就是透過此 API 操作 K3s 上的資源。
  • Kubelet:在每個 node 上運行,確保 pod 中的容器正常運行。
  • Scheduler:K3s 上的調度員,會根據 node 上的硬體資源決定 pod 要在哪個 node 上面運行。
  • Controller Manager:包含多個控制器,控制器會不斷的對叢集狀態進行調節,使其與期望狀態一致。
  • Containerd:開源的容器執行環境 (runtime),負責管理容器的生命週期,如創建容器與停止容器。
  • Pod:K3s 中的最小單位,可以運行一個或多個容器 (但建議 pod 內只運行 1 個容器)。

GCP 上的架構規劃

我規劃了以下的架構。

2023_06_22_13_59_44_833ac62278f6.jpg
  • 建立一個 VPC (Virtual Private Cloud),在這個 VPC 底下,會有兩個子網域 (subnet),一個是外部可以直接訪問的公有子網域,另外一個則是外部無法直接訪問的私有子網域。
  • 公有子網域底下會有一個用 Nginx 做成的 proxy 。
  • 私有子網域底下會有一個簡易的 K3s 叢集。
  • 外部如果想訪問私有子網域都必須透過 proxy。
  • 如果管理者想遠端連線到私有子網路底下的機器,會透過 proxy 的 server 來做 SSH 的跳板。
  • 如果管理者想在本地端使用 kubectl 操作私有子網路底下的 K3s,會透過 proxy 做請求上的轉發。
  • 同上,如果一般用戶想訪問 K3s 上運行的服務,會透過 proxy 做請求上的轉發。

根據上面的架構,我在 GCP 上準備了 4 台機器。

TypeNamePrivate IPPublic IPOSRole
e2-microproxy-server10.0.0.1035.201.198.209ubuntu 22.04proxy
e2-mediumk3s-server10.0.1.10 ubuntu 22.04K3s server
e2-mediumk3s-agent-110.0.1.11 ubuntu 22.04K3s agent
e2-mediumk3s-agent-210.0.1.12 ubuntu 22.04K3s agent

建立 K3s 叢集

機器準備好之後,就可以開始來安裝 K3s 叢集了,首先來安裝 K3s 中的 server (在 K8s 上稱為 master)。

使用 SSH 連線到 k3s-server 上後,輸入下方的指令安裝 K3s server。

curl -sfL https://get.K3s.io | INSTALL_K3s_EXEC="server --tls-san 35.201.198.209" sh

由於我希望在本地端使用 kubectl 來遠程操作 K3s,因此在安裝過程中,我需要設定 INSTALL_K3S_EXEC 環境變數來執行 K3s 提供的 k3s server --tls-san 指令。這樣做的目的是將 K3s server 的外部 IP 地址加入到憑證中,這樣我才能夠透過該外部 IP 遠端連線到 K3s。

--tls-san 其中的 san 意思是 subject alternative names。

因為外部對私有子網域的一切訪問都需要請 proxy 做請求上的轉發,所以外部 IP 會是 proxy IP,也就是 35.201.198.209

安裝完成之後,系統會運行 K3s server,並同時安裝 kubectl

除此之外,也會生成兩個重要的檔案。

  • /etc/rancher/K3s/K3s.yaml:K3s 的設定檔案,透過 K3s 安裝的 kubectl 會自動使用這個檔案,如果想使用 kubectl 遠端遠端操作 K3s 叢集,可以將這個檔案複製到本地的 ~/.kube/config
  • /var/lib/rancher/K3s/server/node-token:這個 token 可以用來將其他機器加入到 K3s 叢集中。

接下來將 k3s-agent-1k3s-agent-2 加入叢集中,分別登入到這兩台機器,並輸入下方的指令。

curl -sfL https://get.K3s.io | K3s_URL="https://10.0.1.10:6443" K3s_TOKEN="<mynodetoken>" sh -

這邊的 <mynodetoken> 需要使用 k3s-server/var/lib/rancher/K3s/server/node-token 中的值。

安裝好 agent 之後就可以到 k3s-server 上使用 kubectl 查看目前叢集總共有幾個 node。

sudo kubectl get nodes

看到下面的結果就代表 k3s-agent-1k3s-agent-2 都成功加入叢集中了。

NAME          STATUS   ROLES                  AGE     VERSION
k3s-server    Ready    control-plane,master   1m      v1.26.5+K3s1
k3s-agent-1   Ready    <none>                 1m      v1.26.5+K3s1
k3s-agent-2   Ready    <none>                 1m      v1.26.5+K3s1

在本地端上使用 kubectl 操作雲端上的 K3s

因為私有子網域外部無法直接訪問,所以如果想要在外部使用 kubectl 遠端操作 K3s 的話,就需要請 proxy 做請求的轉發,需要再 Nginx 上新增設定。

kubectl 會使用 K3s server 的 API 來操作 K3s,API 預設使用 6443 port,所以我直接在 Nginx 上開啟一個 6443 port 來做請求上的轉發。

設定很簡單,只需要在 Nginx 的設定檔案 /etc/nginx/nginx.conf 上新增 stream 的設定即可。

http {
    # ...
}

stream {
    server {
        listen 6443;
        proxy_pass 10.0.1.10:6443;
    }
}

設定好之後可以使用 Nginx 的指令測試設定有沒有問題。

sudo nginx -t

Nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Nginx: configuration file /etc/nginx/nginx.conf test is successful

如果設定沒有問題的話,就可以重新啟動 Nginx 讓新的設定生效。

sudo systemctl reload nginx

設定生效之後,當訪問 proxy 的 6443 port,proxy 會將請求轉發到 K3s server

接下來將 k3s-server/etc/rancher/k3s/k3s.yaml 的內容複製到本地端上的 ~/.kube/config,然後將裡面 server 的 IP 修改為 proxy 的 public IP。

server: https://35.201.198.209:6443

建議可以將 ~/.kube/config 的權限設定為 600,只有擁有者有讀寫權限,其他人沒有任何權限。

完成之後就可以在本地端上使用 kubctl 指令查看是否有連線到遠端的 K3s。

kubectl get all

參考資料

sharkHead
written by
sharkHead

後端打工仔,在下班後喜歡研究各種不同的技術。稍微擅長 PHP,並偶爾涉獵前端開發。個性就像動態語言般隨興,但渴望做事能像囉嗦的靜態語言那樣嚴謹。

4 則留言
sharkHead sharkHead 2023 年 08 月 07 日 (已編輯)

需要方便的 auto scaling,就要左轉去找 EKS、AKS 或是 GKE 了。

但本篇文章要做 auto scaling 應該也是可以的。

以 AWS 為例,你可以建立一個 auto scaling group,並設定閾值 (例如 CPU 使用率達到多少),當達到閾值時就開啟一台新的機器,並執行預先寫好的 user data,將新機器以 agent 的身份加入到 k3s cluster 中。

這應該是個可行的方案,但個人覺得如果有 auto scaling 的需求,還是建議使用更專門的 k8s 雲端服務會更好。

訪客 2023 年 08 月 06 日

請問這樣部署是不是就不能auto scaling橫向擴充 必須要使用GCP的kubernetes服務

sharkHead sharkHead 2023 年 06 月 26 日 (已編輯)

之前部落格就是很簡單的用 Docker 跑起來,所以有參考你的文章 😆

[Go 教學] graceful shutdown 搭配 docker-compose 實現 rolling update

再次感謝大大的分享~

訪客 2023 年 06 月 25 日

我寫了一篇更快速達成安裝 Kubernetes 環境:『使用 Colima 快速打造 Kubernetes 開發環境