我將在今年的 Kubernetes Summit 2021 主持一場 使用 Dapr 與 Kubernetes 打造微服務架構 實戰工作坊,在開始這場實戰工作坊之前,必須要讓學員事先建立好 Kubernetes 環境才能進行實作,這篇文章我將鉅細靡遺的教大家怎樣透過 MicroK8s 快速的建立完整的 Kubernets 叢集環境。
預先準備事項
MicroK8s 可以支援 Linux, Windows 與 macOS 作業系統環境,除此之外,你要使用 虛擬機器 (Virtual Machine) 或是 實體裸機 (Bare Metal Server) 也都可以安裝,所以使用上非常彈性! 👍
本篇文章主要以 Windows 10 與 Hyper-V 為主要環境,但我認為切換到其他環境並不困難。
請預先安裝好以下工具:
-
安裝 MicroK8s 工具
安裝好之後你會有一個 C:\Program Files\MicroK8s\microk8s.exe
執行檔可用。
-
安裝 Multipass 工具
安裝好之後你會有一個 C:\Program Files\Multipass\bin\multipass.exe
執行檔可用。
-
安裝 Helm 工具
choco install kubernetes-helm -y
第一次使用 helm 的話,可能要先新增常用的 Helm Repo
helm repo add bitnami https://charts.bitnami.com/bitnami --force-update
以下所有命令皆在 PowerShell 環境下執行,而且都不需要以系統管理者身份執行。
架設 Kubernetes 叢集
使用 MicroK8s 架設 Kubernetes 叢集是我見過最簡單、最無腦的,使用上非常直覺,而且要在 K8s 安裝一些常見的服務,也都被 MicroK8s 封裝成 MicroK8s Add-ons 來用,也大幅的降低初學者的進入門檻。
-
安裝 MicroK8s 叢集
這個命令會自動在 Hyper-V 建立一台名為 microk8s-vm
的虛擬機,裡面包含 K8s 叢集的 master
(control plane
) 節點。
microk8s install
這個命令大約會執行 3 ~ 5 分鐘左右。
Launched: microk8s-vm
2021-12-05T05:30:28Z INFO Waiting for automatic snapd restart...
microk8s (1.22/stable) v1.22.4 from Canonical✓ installed
microk8s-integrator-windows 0.1 from Canonical✓ installed
MicroK8s is up and running. See the available commands with `microk8s --help`.
-
檢查 MicroK8s 叢集狀態
microk8s status --wait-ready
你可以從這邊看到許多 MicroK8s Add-ons 的 啟用/停用 狀態,有你需要的 Add-ons 就直接 microk8s enable [name]
就可以直接啟用,不用再上網到處找 YAML 來套用,非常便利! 👍
microk8s is running
high-availability: no
datastore master nodes: 127.0.0.1:19001
datastore standby nodes: none
addons:
enabled:
ha-cluster # Configure high availability on the current node
disabled:
ambassador # Ambassador API Gateway and Ingress
cilium # SDN, fast with full network policy
dashboard # The Kubernetes dashboard
dns # CoreDNS
fluentd # Elasticsearch-Fluentd-Kibana logging and monitoring
gpu # Automatic enablement of Nvidia CUDA
helm # Helm 2 - the package manager for Kubernetes
helm3 # Helm 3 - Kubernetes package manager
host-access # Allow Pods connecting to Host services smoothly
ingress # Ingress controller for external access
istio # Core Istio service mesh services
jaeger # Kubernetes Jaeger operator with its simple config
kata # Kata Containers is a secure runtime with lightweight VMS
keda # Kubernetes-based Event Driven Autoscaling
knative # The Knative framework on Kubernetes.
kubeflow # Kubeflow for easy ML deployments
linkerd # Linkerd is a service mesh for Kubernetes and other frameworks
metallb # Loadbalancer for your Kubernetes cluster
metrics-server # K8s Metrics Server for API access to service metrics
multus # Multus CNI enables attaching multiple network interfaces to pods
openebs # OpenEBS is the open-source storage solution for Kubernetes
openfaas # openfaas serverless framework
portainer # Portainer UI for your Kubernetes cluster
prometheus # Prometheus operator for monitoring and logging
rbac # Role-Based Access Control for authorisation
registry # Private image registry exposed on localhost:32000
storage # Storage class; allocates storage from host directory
traefik # traefik Ingress controller for external access
-
列出叢集中所有資源
你在本機就算不安裝 kubectl 也可以執行,只要透過 microk8s kubectl
就可以對叢集做任何操作!
microk8s kubectl get all --all-namespaces
-
設定連線到 MicroK8s 的憑證 (KUBECONFIG
)
很多時候我們還是會需要透過本機的 kubectl 或 VS Code 的 Kubernetes extension 或 Lens (The Kubernetes IDE) 來管理 Kubernetes 上面的服務,所以建議還是設定一下你本機的 Kubernetes 設定檔(KUBECONFIG
):
microk8s config > ~/.kube/config
上述命令完成後,你本機的所有 K8s 管理工具就可以順利連上 MicroK8s 建立的 K8s 叢集了!👍
增加 Kubernetes 叢集節點 (Worker Nodes)
MicroK8s 所架設的 K8s 叢集支援 High Availability (HA) 架構,建議額外增加兩個 Worker Nodes 並加入 K8s 叢集。
-
建立兩台全新的 Ubuntu VM:node1
, node2
以下命令會利用 Multipass 工具在 Hyper-V 中建立兩台 Ubuntu 的 VM:
multipass launch --name node1
multipass launch --name node2
透過 Multipass 查看 VM 資訊:
multipass info --all
使用 Multipass 工具在 Hyper-V 中架設 Ubuntu VM 是我見過最省時、最便利的方式了,每台 Ubuntu VM 大約只要 30 秒就可以建立完成,你只要透過 multipass shell node1
就可以直接進入 node1
主機的 Shell 環境! 👍
-
在這兩台 Ubuntu VM 中安裝 MicroK8s 工具
你可以利用 multipass exec [name]
將命令傳入到 Ubuntu VM 中執行:
multipass exec node1 -- sudo snap install microk8s --classic
multipass exec node1 -- sudo usermod -a -G microk8s ubuntu
multipass exec node1 -- sudo chown -f -R ubuntu ~/.kube
multipass exec node2 -- sudo snap install microk8s --classic
multipass exec node2 -- sudo usermod -a -G microk8s ubuntu
multipass exec node2 -- sudo chown -f -R ubuntu ~/.kube
-
將 Node1, Node2 加入 MicroK8s 建立的 Kubernetes 叢集
先透過 microk8s add-node
取得連接字串與加入叢集的命令:
# 取得加入叢集的連接字串命令
microk8s add-node
From the node you wish to join to this cluster, run the following:
microk8s join 172.29.215.174:25000/d008396d18bf5c02916190063a90a055/d2b3c4a95057
If the node you are adding is not reachable through the default interface you can use one of the following:
microk8s join 172.29.215.174:25000/d008396d18bf5c02916190063a90a055/d2b3c4a95057
將取得到的 microk8s join
完整命令拿到 Worker 節點的 VM 中執行:
# 先將 Node1 加入叢集,成為 Kubernetes 叢集的 Worker Node
multipass exec node1 -- sudo microk8s join 172.29.215.174:25000/d008396d18bf5c02916190063a90a055/d2b3c4a95057
加入一個節點到叢集的時間大概 2 分鐘左右。
同樣的步驟要再做一次,就可以加入第二個 Worker 節點:
# 再取得一次加入叢集的連接字串命令
microk8s add-node
# 先將 Node2 加入叢集,成為 Kubernetes 叢集的 Worker Node
multipass exec node2 -- sudo microk8s join 172.29.215.174:25000/19351da0ba24c2b76d56a57b5069c0b8/d2b3c4a95057
這個 microk8s add-node
命令會讓 microk8s-vm
自動變成 control plane
角色 (也就是之前的 master
角色)
-
查看目前節點數
透過 kubectl 取得節點資訊:
microk8s kubectl get nodes
microk8s kubectl get nodes -o wide
microk8s kubectl get nodes -o wide --show-labels
請確保 STATUS
都是呈現 Ready
狀態:
NAME STATUS ROLES AGE VERSION
node1 Ready <none> 4m8s v1.22.4-3+adc4115d990346
node2 Ready <none> 2m10s v1.22.4-3+adc4115d990346
microk8s-vm Ready <none> 31m v1.22.4-3+adc4115d990346
-
啟用 dns
功能
microk8s enable dns
預設 dns
會使用 Google 的 8.8.8.8
與 8.8.4.4
當成名稱伺服器解析網址。
若你想改用自己指定的名稱伺服器位址,也可以用以下命令手動更新 configmap/coredns
的 YAML 設定:
microk8s kubectl -n kube-system edit configmap/coredns
或是停用並重新啟用 dns
功能,啟用時可以指定多台名稱伺服器位址:
microk8s disable dns
microk8s enable dns:168.95.1.1,168.95.192.1
-
啟用 helm3
功能
安裝 Kubernetes 常見的 Helm 3 套件管理器:
microk8s enable helm3
-
啟用 storage
功能
因為有些服務 (如: bitnami/redis) 會需要透過 Storage Class 建立 PVC,因此需要特別加裝 storage
功能,他會自動在你的 K8s 叢集中加入一個名為 microk8s-hostpath
的 Storage Class 物件。
microk8s enable storage
請注意:這個 microk8s-hostpath
並不支援「多節點」的運作,因為他只有支援很陽春的 HostPath
磁碟對應,將 Node 上面的實體路徑對應到容器中,因此像是 Redis 這類 StatefulSets 物件可能會無法正常運作,你要將服務特別跑在 master
節點才行。(相關討論: Pods of a StatefulSet using microk8s-hostpath storage can be scheduled on another node · Issue #2618 · ubuntu/microk8s)
microk8s kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
microk8s-hostpath (default) microk8s.io/hostpath Delete Immediate false 18m
你可以選擇啟用 openebs 並搭配 iSCSI 掛載硬碟的方式支援 Storage Class!
-
啟用 dashboard
功能 (Kubernetes Dashboard)
microk8s enable dashboard
啟動 Kubernetes Dashboard 的 Proxy (port-forwarding
)
microk8s dashboard-proxy
畫面上會出現 Dashboard 的網址與 JWT Token,複製 Token 之後就可以順利從網頁登入 Kubernetes Dashboard
Checking if Dashboard is running.
Waiting for Dashboard to come up.
Dashboard will be available at https://172.29.219.229:10443
Use the following token to login:
eyJhbGciOiJSUzI1NiIsImtpZCI6Im1uVDZwWmx1T3FiYjhuT2ZtVUFhLTBNaVlYS3BrTEhCbWlhMWtjU1VIc2sifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLTJic2cyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJjNjIzMWQ3MC0wYTUyLTQxNTAtYjgxZC1jMTE4MzIxMTdkZjUiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06ZGVmYXVsdCJ9.iunsRJSI2SVtUmSBcEwcrFVotR1XfCkcP_36dUzGJLlj25dkfcuVUYz_SlS3VPRivpkHUviN8jEI83M7wsA8UI_vN4wnlBjV4_qt0pmKwyHD6vZ5oDnV1O0fXlTjiGw_cV0-pjRcQib8lkZlLXyvDfyhOFfyV9QhPi_1iIhcFOFzPtUDJh_RSlR6SxmnctARiUifZ871daVK0qQiHYQGXuW9_qdfKbS6edpkY9EIJYpKjJNvVvqRkgvFkBeJYN6_ObLWF1tmzpbtRzTEwD686oPTecXyo4CRenXYaMKuDN_SZM2xKkY4Pky155kau51JTP0nzQ0Z1o7RPGe_BCfzlQ
Forwarding from 0.0.0.0:10443 -> 8443
-
啟用 metrics-server
功能
啟用 dashboard
Add-on 的時候,其實也會一併啟用 metrics-server
Add-on (Kubernetes Metrics Server),如此一來你就可以使用 kubectl top node
或 kubectl top pod
等命令,查看目前系統的負載狀況。
kubectl top node --use-protocol-buffers
kubectl top pod --use-protocol-buffers
-
啟用 prometheus
功能 (Prometheus Operator)
microk8s enable prometheus
啟用 Prometheus 之後大約過 5 分鐘才會收集到足夠的數據,此時你才能在 Lens 介面上看到叢集的資源使用率圖表。
開啟 Grafana 的 Web UI ( http://localhost:3000 ) (預設登入帳號密碼為 admin
/ admin
)
microk8s kubectl port-forward -n monitoring service/grafana --address 0.0.0.0 3000:3000
開啟 Prometheus 的 Web UI ( http://localhost:9090 )
microk8s kubectl port-forward -n monitoring service/prometheus-k8s --address 0.0.0.0 9090:9090
啟用 MetalLB 功能
我們在地端架設的任何 K8s 叢集,所有的 Service 物件預設都不支援 LoadBalancer
類型,以前我們都要額外加裝 MetalLB 才能支援,但是網路設定上要多下不少功夫。
MicroK8s 支援一個 metallb 的 Add-on,可以幫助你無腦的建立好 MetalLB 服務! 👍
-
列出所有 VM 的資訊
multipass info --all
取得 IPv4 的第一個 IP 地址,這裡的 172.29.215.174
就是本機電腦可以存取的 EXTERNAL-IP
地址:
Name: microk8s-vm
State: Running
IPv4: 172.29.215.174
10.1.254.64
Release: Ubuntu 18.04.6 LTS
Image hash: eeff819e8474 (Ubuntu 18.04 LTS)
Load: 0.27 0.32 0.21
Disk usage: 2.6G out of 48.3G
Memory usage: 1.0G out of 4.4G
Mounts: --
Name: node1
State: Running
IPv4: 172.29.214.122
10.1.166.128
Release: Ubuntu 20.04.3 LTS
Image hash: 27cecebaf8c6 (Ubuntu 20.04 LTS)
Load: 0.02 0.07 0.08
Disk usage: 2.5G out of 4.7G
Memory usage: 1.1G out of 3.0G
Mounts: --
Name: node2
State: Running
IPv4: 172.29.212.61
10.1.104.0
Release: Ubuntu 20.04.3 LTS
Image hash: 27cecebaf8c6 (Ubuntu 20.04 LTS)
Load: 0.18 0.10 0.10
Disk usage: 2.5G out of 4.7G
Memory usage: 1.1G out of 3.1G
Mounts: --
-
啟用 MetalLB 並設定叢集節點的 IP 地址成為 LoadBalancer 的 IP 範圍
microk8s enable metallb:172.29.215.174-172.29.215.174,172.29.214.122-172.29.214.122,172.29.212.61-172.29.212.61
-
測試部署應用程式
參考 Example: Deploying PHP Guestbook application with Redis 範例程式。
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-leader-deployment.yaml
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-leader-service.yaml
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-deployment.yaml
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-service.yaml
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-deployment.yaml
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-service.yaml
因為這份 frontend
範例程式的 YAML 預設使用 ClusterIP
,所以不會透過 MetalLB 取用外部 IP 地址:
kubectl get service frontend
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend ClusterIP 10.152.183.203 <none> 80/TCP 3m44s
你要透過 kubectl port-forward
才能對連到服務:
kubectl port-forward svc/frontend 8080:80
連接 http://localhost:8080 即可看到服務運作中!
-
將應用程式對外服務改成 LoadBalancer
我們直接編輯 svc/frontend
服務,將 .spec.type
的值從 ClusterIP
調整為 LoadBalancer
即可:
kubectl patch svc/frontend -p '{\"spec\": {\"type\": \"LoadBalancer\"}}'
kubectl get service frontend
此時你應該可以看見 172.29.215.174
這個 EXTERNAL-IP
被部署了! 👍
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend LoadBalancer 10.152.183.203 172.29.215.174 80:31199/TCP 19m
接著你的電腦就可以直接用 http://172.29.215.174/ 看到範例程式的網頁。
-
刪除範例應用程式
kubectl delete -f https://k8s.io/examples/application/guestbook/redis-leader-deployment.yaml
kubectl delete -f https://k8s.io/examples/application/guestbook/redis-leader-service.yaml
kubectl delete -f https://k8s.io/examples/application/guestbook/redis-follower-deployment.yaml
kubectl delete -f https://k8s.io/examples/application/guestbook/redis-follower-service.yaml
kubectl delete -f https://k8s.io/examples/application/guestbook/frontend-deployment.yaml
kubectl delete -f https://k8s.io/examples/application/guestbook/frontend-service.yaml
使用 Helm 安裝 Redis 服務
-
建立 Redis 服務
若你在單節點的 MicroK8s 叢集中,用以下命令就可以自動建立好:
helm install "redis" bitnami/redis
但你在多節點的 MicroK8s 叢集中執行上述命令,啟動 redis-master
的時候會從 Pod 中看到以下錯誤 (Can't open the append-only file: Permission denied
),這問題估計是 microk8s-hostpath
不支援多節點叢集造成的:
kubectl logs pod/redis-master-0
1:C 05 Dec 2021 03:32:00.624 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 05 Dec 2021 03:32:00.624 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 05 Dec 2021 03:32:00.624 # Configuration loaded
1:M 05 Dec 2021 03:32:00.625 * monotonic clock: POSIX clock_gettime
1:M 05 Dec 2021 03:32:00.625 # Can't open the append-only file: Permission denied
所以你在多節點的 MicroK8s 叢集中,建議使用以下命令進行安裝:
helm install --set global.storageClass=microk8s-hostpath --set master.nodeSelector."kubernetes\.io/hostname"="microk8s-vm" --set replica.replicaCount=0 redis bitnami/redis
完整參數可以參考 Redis™ Chart packaged by Bitnami 頁面。
用以下命令可以查詢 pod/redis-master-0
的執行記錄 (Logs):
kubectl logs pod/redis-master-0
1:C 05 Dec 2021 06:16:22.021 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 05 Dec 2021 06:16:22.021 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 05 Dec 2021 06:16:22.021 # Configuration loaded
1:M 05 Dec 2021 06:16:22.021 * monotonic clock: POSIX clock_gettime
1:M 05 Dec 2021 06:16:22.022 * Running mode=standalone, port=6379.
1:M 05 Dec 2021 06:16:22.022 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1:M 05 Dec 2021 06:16:22.022 # Server initialized
1:M 05 Dec 2021 06:16:22.022 * Ready to accept connections
建立 bitnami/redis 的過程會包含兩個 StatefulSets,分別是 redis-master
與 redis-replicas
,總共會自動建立 4 的 Pods,一個 master
與 3 份 replicas
。 另外還有 3 個 ClusterIP 的 Services,以及 4 個 Persistent Volume Claims (PVC),這 4 個 PVC 有會建立 4 個 Persistent Volumes (PV)。最後還會建立一個名為 redis
的 Secret 保存著 Redis 存取金鑰(密碼)。如果想查看 Helm Chart 的完整內容,可以利用 helm pull bitnami/redis
命令下載 redis-15.6.3.tgz
檔案。
如果有建立錯誤,可以用以下命令刪除 Release:
helm delete redis --debug
刪除 redis 這個 Release 之後,預設 PVC 並不會自動刪除。詳見 Helm 'delete' doesn't delete PVCs #5156。
-
取得 Redis 連接密碼
$REDIS_PASSWORD=[Text.Encoding]::Utf8.GetString([Convert]::FromBase64String($(kubectl get secret --namespace default "redis" -o jsonpath="{.data.redis-password}")))
echo $REDIS_PASSWORD
-
測試連接 Redis 伺服器 (透過 kubectl run
執行)
啟動 redis-client
環境,啟動時可直接傳入 REDISCLI_AUTH
環境變數,讓 Shell 環境不用再輸入 Redis 密碼:
kubectl run --namespace default redis-client --restart='Never' --env REDISCLI_AUTH=$REDIS_PASSWORD --image docker.io/bitnami/redis:6.2.6-debian-10-r53 --command -- sleep infinity
直接透過 redis-client
執行 redis-cli
命令連線到 redis-master
即可,沒有錯誤訊息就是連線成功:
kubectl exec --tty -i redis-client --namespace default -- redis-cli -h redis-master
-
測試連接 Redis 伺服器 (從本機 Redis Client 連接)
先將叢集中的 redis-master
透過 Port Forwarding 掛接到本機的 6379
Port:
kubectl port-forward --namespace default svc/redis-master 6379:6379
啟動 Redis Commander
npx redis-commander --redis-password $REDIS_PASSWORD
刪除所有已建立資源
-
最快速、最殘暴的刪除方法 (直接刪除 VM 即可)
multipass delete node1 node2 microk8s-vm
multipass purge
-
最優雅、最溫和的刪除方法
# 移除 Redis Release
helm delete redis --debug
# 查出有多少被啟用的 Add-ons
microk8s status
# 停用 MicroK8s Add-ons (但不要停用 ha-cluster 這個 Add-on)
microk8s disable dashboard dns helm3 metallb metrics-server prometheus storage
# 從 node1 從容的離開 K8s 叢集,離開後該節點會變成 NotReady 狀態,日後不會有工作負載編配到這裡執行
multipass exec node1 -- sudo microk8s leave
# 即便節點已經離開,還是需要從叢集這邊移除該節點
microk8s remove-node node1
# 如果 node2 已經完全崩潰的話,也可以直接從 master 強制移除
microk8s remove-node node2 --force
# 移除 MicroK8s 叢集 (這個命令會連同 VM 一起砍掉)
microk8s uninstall
# 移除 Worker 節點的 VM 實體 (只會關機而已)
multipass delete node1 node2
# 清空 Worker 節點的 VM (會完整刪除 VM 與虛擬硬碟)
multipass purge
-
刪除本機的 kubeconfig 檔案
rm ~/.kube/config
相關連結