今天這篇文章是在記錄我練習Google Cloud Skills Boost 官方學習資源平台的過程,今天練習的課程是 Orchestrating the Cloud with Kubernetes,這個 實踐實驗室(Qwiklabs) 主題是在介紹 透過 Kubernetes 自動化調度管理雲端資源 功能。
GSP021
總覽
Kubernetes 是開放原始碼專案 (可透過 kubernetes.io 存取),能夠在許多不同環境中運作,包括筆記型電腦、高可用性的多節點叢集、公有雲、地端部署、虛擬機器和裸機環境。
在本研究室中,使用 Kubernetes Engine 等代管環境可讓您專心體驗 Kubernetes,不必費心設定基礎架構。Kubernetes Engine 是專用於部署容器化應用程式的代管環境。這項服務匯集了開發人員效率提升、資源效率、自動化作業和開放原始碼靈活性等方面的最新技術,有助於縮短上市時間。
應用程式託管於 GitHub,並提供 12 因子應用程式範例。在本研究室中,將使用以下 Docker 映像檔:
- kelseyhightower/monolith:包含 Auth 和 Hello 服務的單體。
- kelseyhightower/auth:Auth 微服務,可為通過驗證的使用者產生 JWT 權杖。
- kelseyhightower/hello:Hello 微服務,會向通過驗證的使用者打招呼。
- nginx:Auth 和 Hello 服務的前端。
目標
- 使用 Kubernetes Engine 佈建完整的 Kubernetes 叢集。
- 使用 kubectl 部署及管理 Docker 容器。
- 使用 Kubernetes 的 Deployment 和 Service 將應用程式拆解成微服務。
Google Kubernetes Engine
在 Cloud Shell 環境中,輸入以下指令來設定可用區:
1
gcloud config set compute/zone us-central1-c
啟動要使用的cluster:
1
gcloud container clusters create io --zone us-central1-c
工作 1:取得程式碼範例
- 從 Cloud Shell 指令列複製原始碼:
1
gsutil cp -r gs://spls/gsp021/* .
- 變更為本研究室所需的目錄:
1 | cd orchestrate-with-kubernetes/kubernetes |
- 列出檔案以便查看:
1 | ls |
工作 2:Kubernetes 快速示範
如要開始使用 Kubernetes,最簡單的方法是運用 kubectl create
指令。
- 使用這項指令啟動 nginx 容器的單一執行個體:
1 | kubectl create deployment nginx --image=nginx:1.10.0 |
Kubernetes 已建立 Deployment。稍後會再針對 Deployment 進行說明,目前您只需要知道 Deployment 可讓 Pod 保持運作,即使執行 Pod 的節點發生問題也沒關係。
Kubernetes 中的所有容器都是透過 Pod 執行。
- 使用
kubectl get pods
指令查看運作中的 nginx 容器:
1 | kubectl get pods |
- nginx 容器處於「運作中」狀態後,您就可以使用 kubectl expose 指令,在 Kubernetes 外部公開該容器:
1 | kubectl expose deployment nginx --port 80 --type LoadBalancer |
使用
kubectl get services
指令列出服務:1
kubectl get services
「ExternalIP」欄位可能需要幾秒鐘才會填入服務的外部 IP 位址。這是正常現象,只要每隔幾秒重新執行 kubectl get services 指令,直到該欄位填入位址即可。
在這項指令中加入外部 IP,從遠端連至該 Nginx 容器:
1 | curl http://<External IP>:80 |
工作 3:Pod
Kubernetes 的核心是 Pod。
Pod 代表並存放了一或多個容器。一般來說,如果多個容器之間有硬相依性,就可以包裝在同一個 Pod 中。
這個範例中有一個包含單體和 nginx 容器的 Pod。
Pod 也有磁碟區。磁碟區是效期與 Pod 相同的資料磁碟,可由該 Pod 中的容器使用。Pod 為所含內容提供共用命名空間,因此範例 Pod 中的兩個容器可互相通訊,並且共用所連接的磁碟區。
不同的 Pod 還會共用網路命名空間,因此每個 Pod 都有一個 IP 位址。
接著讓我們來深入瞭解 Pod。
工作 4:建立 Pod
Pod 可使用 Pod 設定檔建立。請花點時間瞭解單體 Pod 設定檔。
1.前往目錄:
1 | cd ~/orchestrate-with-kubernetes/kubernetes |
2.執行以下指令:
1 | cat pods/monolith.yaml |
輸出結果會顯示公開設定檔:
1 | apiVersion: v1 |
這裡有幾點要注意。從輸出結果可看出:
- Pod 包含一個容器 (單體)。
- 您在容器啟動時傳遞了幾個引數至容器。
- 您開啟了用於 http 流量的通訊埠 80。
- 使用
kubectl
建立單體 Pod:
1 | kubectl create -f pods/monolith.yaml |
- 檢查 Pod。請使用
kubectl get pods
指令列出在預設命名空間中運作的所有 Pod:
1 | kubectl get pods |
單體 Pod 可能需要幾秒鐘才會開始運作。單體容器映像檔必須先從 Docker Hub 提取出來才能執行。
- Pod 開始運作後,請使用
kubectl describe
指令取得更多有關該單體 Pod 的資訊:
1 | kubectl describe pods monolith |
您會看到許多關於該單體 Pod 的資訊,包括 Pod 的 IP 位址和事件記錄。這些資訊在疑難排解時可派上用場。
Kubernetes 可根據設定檔中的描述建立 Pod,並讓您在 Pod 運作時輕鬆查看相關資訊。到了這個階段,您已經可以建立 Deployment 所需的所有 Pod!
工作 5:與 Pod 互動
根據預設,Pod 會獲分配私人 IP 位址,且無法從叢集外部連線。請使用 kubectl port-forward
指令將本機通訊埠對應至單體 Pod 內部的通訊埠。
在本研究室的後續部分中,您必須透過多個 Cloud Shell 分頁設定 Pod 之間的通訊。如果指令是透過第二或第三個指令殼層執行,則會在指令的操作說明中標示。
- 開啟第二個 Cloud Shell 終端機。您現在有兩個終端機,分別用於執行
kubectl port-forward
指令及下達curl
指令。
- 在第 2 個終端機中,執行以下指令來設定通訊埠轉送:
1 | kubectl port-forward monolith 10080:80 |
3.接著在第 1 個終端機中使用 curl 開始與 Pod 通訊:
1 | curl http://127.0.0.1:10080 |
很好!容器傳回了友善的回應:「Hello」。
- 接著使用
curl
指令,看看連到安全端點時會發生什麼事:
1 | curl http://127.0.0.1:10080/secure |
糟糕!
- 嘗試登入,從單體取回驗證權杖:
1 | curl -u user http://127.0.0.1:10080/login |
畫面上顯示登入提示時,使用密碼登入。
這邊的密碼在這邊由於 Cloud Shell 無法妥善複製較長的字串,因此請為權杖建立環境變數。
1 | TOKEN=$(curl http://127.0.0.1:10080/login -u user|jq -r '.token') |
系統提示您輸入主機密碼時,再次輸入密碼。
使用以下指令複製權杖,並透過
curl
使用該權杖連至安全端點:1
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:10080/secure
應用程式應該會傳回回應,讓我們知道一切都運作正常。
使用
kubectl logs
指令查看monolith
Pod 的記錄。
1 | kubectl logs monolith |
- 開啟第 3 個終端機,並使用 -f 標記取得即時記錄串流:
1 | kubectl logs -f monolith |
- 如果您在第 1 個終端機中使用 curl 與單體互動,記錄就會在第 3 個終端機中更新:
1 | curl http://127.0.0.1:10080 |
13.使用 kubectl exec
指令在單體 Pod 內執行互動式殼層。如要在容器內進行疑難排解,這個殼層就能派上用場:
1 | kubectl exec monolith --stdin --tty -c monolith -- /bin/sh |
- 舉例來說,在單體容器中建立殼層後,您就能使用 ping 指令測試外部連線:
1
ping -c 3 google.com
15.使用完這個互動式殼層後,請務必登出。
1 | exit |
如您所見,只要使用 kubectl
指令,就能輕鬆與 Pod 互動。如需從遠端連至容器,或是取得登入殼層,Kubernetes 提供所有必要資源。
工作 6:Service
Pod 不會永久有效,可能會因許多因素停止或啟動 (例如未通過有效性或完備性檢查),進而造成一個問題:
與一組 Pod 通訊會發生什麼情形?這些 Pod 重新啟動時可能會有不同的 IP 位址。
在這種時候,Service 便能派上用場。Service 可為 Pod 提供穩定的端點。
Service 會根據標籤決定要在哪個 Pod 上運作。如果 Pod 的標籤正確,Service 就會自動辨識並公開 Pod。
Service 為一組 Pod 提供的存取層級取決於 Service 類型。目前 Service 分為以下三種:
- ClusterIP (內部):這是預設類型,表示這項 Service 只會在叢集內部顯示
- NodePort:為叢集中的每個節點提供可從外部存取的 IP
- LoadBalancer:新增雲端服務供應商的負載平衡器,用於將 Service 的流量轉送至當中的節點
接下來您將瞭解如何:
- 建立 Service
- 使用標籤選取器,對外公開一部分的 Pod
工作 7:建立 Service
在建立 Service 前,請先建立可處理 https 流量的安全 Pod。
- 如果您變更了目錄,請務必返回
~/orchestrate-with-kubernetes/kubernetes
目錄:
1 | cd ~/orchestrate-with-kubernetes/kubernetes |
- 查看單體 Service 設定檔:
1 | cat pods/secure-monolith.yaml |
- 建立安全單體 Pod 及其設定資料:
1
2
3kubectl create secret generic tls-certs --from-file tls/
kubectl create configmap nginx-proxy-conf --from-file nginx/proxy.conf
kubectl create -f pods/secure-monolith.yaml
您已建立安全的 Pod,接著要對外公開安全單體 Pod。為此,請建立 Kubernetes Service。
- 查看單體 Service 設定檔:
1 | cat services/monolith.yaml |
輸出內容:
1 | kind: Service |
注意事項:
輸出內容包含選取器,用來自動尋找及公開含有「app: monolith」和「secure: enabled」標籤的 Pod。
現在您必須公開節點通訊埠,這樣才能將外部流量從通訊埠 31000 轉送至位於通訊埠 443 的 nginx。
- 使用
kubectl create
指令,透過單體 Service 設定檔建立單體 Service:
1 | kubectl create -f services/monolith.yaml |
輸出內容:
1 | service/monolith created6 |
測試已完成的工作
請點選下方的「Check my progress」,確認您的研究室進度。如果您已成功建立單體 Pod 和 Service,就會看到評量分數。
您是使用通訊埠公開 Service,因此如果其他應用程式嘗試繫結至其中一個伺服器的通訊埠 31000,可能會發生通訊埠衝突。
在一般情況下,Kubernetes 會處理通訊埠指派作業,但在本研究室中,您自行選擇了通訊埠,以便之後設定健康狀態檢查。
- 使用
gcloud compute firewall-rules
指令,允許流量傳送到公開節點通訊埠上的單體 Service:1
2gcloud compute firewall-rules create allow-monolith-nodeport \
--allow=tcp:31000
測試已完成的工作
請點選下方的「Check my progress」,確認您的研究室進度。如果您已成功建立防火牆規則來允許通訊埠 31000 的 TCP 流量,就會看到評量分數。
一切都設定完成後,您應該就能從叢集外部連至安全單體 Service,不必使用通訊埠轉送。
- 首先,取得其中一個節點的外部 IP 位址。
1 | gcloud compute instances list |
- 接著使用 curl 嘗試連至安全單體 Service:
1 | curl -k https://<EXTERNAL_IP>:31000 |
糟糕!作業逾時。發生了什麼事?
附註:來驗收一下您的學習成果吧。
請使用以下指令回答下方問題:
kubectl get services monolith
kubectl describe services monolith
問題:
為何單體 Service 無法傳回回應?
單體 Service 有幾個端點?
Pod 必須有哪些標籤,單體 Service 才能辨識?
提示:關鍵在於標籤。您將在下一節修正錯誤。
工作 8:為 Pod 新增標籤
目前單體 Service 沒有端點。如要排解這類問題,其中一個方法是使用 kubectl get pods
指令和標籤查詢。
1.您會發現有幾個包含單體標籤的 Pod 正在運作。
1 | kubectl get pods -l "app=monolith" |
2.但如果是「app=monolith」和「secure=enabled」呢?
1 | kubectl get pods -l "app=monolith,secure=enabled" |
您會發現這個標籤查詢並未顯示任何結果。您似乎需要加上「secure=enabled」標籤。
- 使用
kubectl label
指令,為安全單體 Pod 新增缺少的secure=enabled
標籤。完成後,您可以確認標籤是否已更新。
1 | kubectl label pods secure-monolith 'secure=enabled' |
為 Pod 加上正確標籤後,請查看單體 Service 的端點清單:
1
kubectl describe services monolith | grep Endpoints
再次連到其中一個節點進行測試。
1 | gcloud compute instances list |
測試已完成的工作
請點選下方的「Check my progress」,確認您的研究室進度。如果您已成功為單體 Pod 新增標籤,就會看到評量分數。
工作 9:透過 Kubernetes 部署應用程式
本研究室的目標是協助您做好準備,以便在實際工作環境中調度資源及管理容器。在這種時候,Deployment 便能派上用場。Deployment 可透過宣告方式,確保運作中的 Pod 數量與使用者指定的所需 Pod 數量相同。
Deployment 的主要好處在於簡化了 Pod 管理作業的低層級細節。Deployment 實際上會使用 ReplicaSet 來啟動及停止 Pod。如果 Pod 需要更新或調度資源,Deployment 就會處理。假如 Pod 因故停止運作,Deployment 也可重新啟動 Pod。
請查看以下簡短範例:
Pod 的生命週期取決於建立時所在的節點。在上方範例中,Node3 已停止運作,並連帶使一個 Pod 停止運作。在這個情況下,Deployment 建立了新的 Pod 並在 Node2 上啟動該 Pod,因此您不必手動建立新的 Pod 及尋找節點。
很方便吧!
接著來運用您學到的所有 Pod 和 Service 相關知識,使用 Deployment 將單體式應用程式拆解成較小的 Service。
工作 10:建立 Deployment
您要將單體式應用程式拆解成三個不同的部分:
- Auth:為通過驗證的使用者產生 JWT 權杖。
- Hello:向通過驗證的使用者打招呼。
- Frontend:將流量轉送至 Auth 和 Hello Service。
您現在可以為每項 Service 分別建立 Deployment。之後,您將為 Auth 和 Hello Deployment 定義內部 Service,並為 Frontend Deployment 定義外部 Service。完成後,您就能像處理單體一樣與微服務互動,只不過每項微服務都能獨立調度資源和部署!
1.首先檢查 Auth Deployment 設定檔。
1 | cat deployments/auth.yaml |
輸出內容
1 | apiVersion: apps/v1 |
Deployment 建立了 1 個備用資源,而您使用的是 2.0.0 版的 Auth 容器。
執行 kubectl create
指令來建立 Auth Deployment 時,會產生一個符合 Deployment 資訊清單資料的 Pod。這表示您可以變更「Replicas」欄位指定的數字來調整 Pod 數量。
2.總之,請建立 Deployment 物件:
1 | kubectl create -f deployments/auth.yaml |
- 接著來建立 Auth Deployment 的 Service。使用 kubectl create 指令建立 Auth Service:
1 | kubectl create -f services/auth.yaml |
- 現在使用相同指令來建立並公開 Hello Deployment:
1 | kubectl create -f deployments/hello.yaml |
- 再次使用相同指令來建立並公開 Frontend Deployment:
1 | kubectl create configmap nginx-frontend-conf --from-file=nginx/frontend.conf |
您必須透過容器儲存設定資料,因此要另外建立 Frontend。
- 與 Frontend 互動,擷取其外部 IP 並執行 curl 指令:
1 | kubectl get services frontend |
外部 IP 位址可能需要一分鐘才能產生。如果 EXTERNAL-IP 欄狀態為「待處理」,請再次執行上方指令。
1 | curl -k https://<EXTERNAL-IP> |
您會收到「hello」回應!
測試已完成的工作
請點選下方的「Check my progress」,確認您的研究室進度。如果您已成功建立 Auth、Hello 和 Frontend Deployment,就會看到評量分數。
總結
這篇文章記錄在 Google Cloud Skills Boost 上學習 “Orchestrating the Cloud with Kubernetes” 的過程,並介紹了 Kubernetes 的基本概念與實際操作流程。內容涵蓋如何建立 Kubernetes 叢集、部署容器、與 Pod 互動等,使用 kubectl 指令來進行 Kubernetes 管理與資源操作。