概述
在這個教程中, 你將會學習到如何:
- 使用 Kubernetes Engine 來提供一個完整的 Kubernetes 叢集
- 使用 kubectl 部署以及管理 Docker 容器
- 使用 Kubernetes 的 Deployments 以及 Services 將應用拆分為微服務
Kubernetes 重點就是應用。 在本教程中的這個部分, 你將使用範例應用名為 “app” 來完成這個教程
App 由 GitHub 管理, 且提供一個 12-Factor 範例應用。 在本教程中你將會使用以下的 Docker images
- kelseyhightower/monolith - Monolith 包含 auth 以及 hello 服務
- kelseyhightower/auth - Auth 微服務。 為通過驗證的使用者產生 JWT tokens
- kelseyhightower/hello - Hello 微服務。 向通過驗證的使用者打招呼
- ngnix - 將流量導向 auth 以及 hello 服務
Kubernetes 是一個開源的專案 (可從 kubernetes.io 獲得), 可以運行在很多不同的環境上, 從筆電到高可用的多主機叢集; 從公開的雲端到人為部署; 從虛擬機到裸機
在本教程中, 使用一個受管理的環境, 像是 Kubernetes Engine (一個由 Google 維護的 Kubernetes 版本, 運行在 Compute Engine 上), 將會讓你可以更專注在體驗 Kubernetes, 而不是設定底層的環境。
前言
本篇主要是利用 Google 的 Qwiklab 平台學習的同時,做的一份學習筆記
為避免翻譯誤解,專業術語在本篇將不會被翻譯,保留原文
設定及要求
在你按下 Start Lab 按鈕之前
詳讀所有的教學。 Labs 是有時間限制的, 而且你不可以停止時間倒數。 倒數計時器在你按下 Start Lab 按鈕後開始倒數, 上面顯示的時間為你還能使用 Cloud 資源的時間。
Qwiklabs 的手把手環境, 讓你可以在真實環境中來操作進行 Qwiklabs 上提供的課程, 而不是在一個模擬或是展示的環境。 我們透過提供你一個全新的、暫時的帳號密碼, 在計時器歸零之前, 你可以用來登入並存取 Google Cloud Platform。
你需要什麼?
要完成這個 lab, 你需要:
- 一個一般的網路瀏覽器(推薦 Chrome)
- 完成這個 lab 的時間
備註: 如果你已經有你自己的個人 GCP 帳號或專案,請不要使用在這一個 lab
現在你已經開始你的 lab
, 你將會登入 Google Cloud Shell
主控台, 然後開啟命令列工具
如何開始你的 lab, 然後登入 Console?
- 按下 Start Lab 按鈕。 如果你需要付費, 會有一個彈出視窗來讓你選擇付費的方式。 在左方你會看到一個面板, 上面有暫時的帳號密碼, 你必須使用這些帳號密碼在此次 lab
- 複製
username
, 然後點擊Open Google Console
。 Lab 會開啟另外一個視窗, 顯示選擇帳號
的頁面
tip: 開啟一個全新的視窗,然後跟原本的頁面並排
- 在
選擇帳號
頁面, 點擊Use Another Account
- 登入頁面開啟, 貼上之前複製的
username
以及password
, 然後貼上
重要:必須使用之前於 Connection Details 面板
取得的帳號密碼,不要使用你自己的 Qwiklabs 帳號密碼。 如果你有自己的 GCP 帳號, 請不要用在這裡(避免產生費用)
- 點擊並通過接下來的頁面:
- 接受
terms
以及conditions
- 不要增加
recovery optoins
或two factor authentication
(因為這只是一個臨時帳號) - 不要註冊免費體驗
- 接受
稍待一些時候, GCP 控制台將會在這個視窗開啟。
啟動 Google Cloud Shell
Google Cloud Shell
是載有開發工具的虛擬機器。 它提供了5GB的 home 資料夾, 並且運行在 Google Cloud
上。 Google Cloud Shell
讓你可以利用 command-line 存取 GCP
資源
- 在
GCP 控制台
, 右上的工具列,點擊Open Cloud Shell
按鈕
- 在打開的對話框裡, 按下
START CLOUD SHELL
:
你可以立即按下 START CLOUD SHELL
當對話視窗打開。
連結並提供環境會需要一點時間。 當你連結成功, 這代表你已成功獲得授權, 且此專案已被設為你的專案ID, 例如:
gcloud 是 Google Cloud Platform
的 command-line 工具, 他已事先被安裝在 Cloud Shell
並且支援自動補齊
使用這個 command, 你可以列出有效帳戶名稱:
gcloud auth list |
輸出:
Credentialed accounts: |
範例輸出:
Credentialed accounts: |
你可以使用以下 command 來列出專案 ID
gcloud config list project |
輸出:
[core] |
範例輸出:
[core] |
gcloud
的完整文件可以參閱 Google Cloud gcloud Overview
Google Kubernetes Engine
在 cloud shell 環境, 輸入以下指令來設定 zone
gcloud config set compute/zone us-central1-b |
設定完 zone 之後, 開始一個本教程需要用到的叢集
gcloud container clusters create io |
注意: 創建叢集會耗費幾分鐘 - Kubernetes Engine 會提供數個虛擬機讓我們使用
取得範例代碼
在 Cloud Shell 執行以下代碼來複製 GitHub 倉庫
git clone https://github.com/googlecodelabs/orchestrate-with-kubernetes.git |
cd orchestrate-with-kubernetes/kubernetes |
列出我們會使用的檔案
ls |
範例結構如下:
deployments/ /* Deployment manifests */ |
該有的都有了, 讓我們來試試看 Kubernetes 吧!
Kubernetes 快速示範
開始 Kubernetes 最簡單的方法, 就是使用 kubectl create
指令。 使用它來啟動一個 nignx 容器的單一虛擬機
kubectl create deployment nginx --image=nginx:1.10.0 |
Kubernetes 已經建立了一個 deployment – 關於 deployment 等等會再多加解釋, 但現在你唯一需要知道的是, deployments 維持 pods 啟動以及運行, 就算當他們運行的 nodes 有錯誤
在 Kubernetes 中, 所有的容器都運行在 pod 當中。 使用 kubectl get pods
指令來檢視運行中的 nginx 容器:
kubectl get pods |
一旦 nginx 容器已經在運行中, 你可以使用 kubectl expose
指令來暴露它
kubectl expose deployment nginx --port 80 --type LoadBalancer |
所以剛剛發生什麼事了呢? 在我們看不見的地方, Kubernetes 建立了一個外部的平衡負載附有一個公開的 IP。 任何向這個 IP 發請求的客戶端都會被導向服務後方的 pods, 在這個例子中, 是 nginx pod
現在使用 kubectl get
指令來列出服務
kubectl get services |
注意: ExternalIP
欄位可能會需要幾秒鐘的時間載入我們的服務。 這是正常的 – 可以幾秒鐘執行一次 kubectl get services
直到該欄位載入
執行以下指令來存取 Nginx container
curl http://<External IP>:80 |
是不是有了! Kubernetes 提供立即可用的簡單方法, 使用 kubectl
運行以及暴露的指令
測試進度
點擊 Check my progress 來確認目前的進度。如果你已經完成目前的進度,你將獲得一個評價分數。
現在你已經完成一個 Kubernetes 簡短的旅程, 是時候更深入每一個元件以及抽象層
Pods
Kubernetes 的核心就是 Pod
Pods 代表, 並持有一個或多個容器。 一般來說, 如果你有多個容器, 並且容器之間有很強的依賴, 那你會將這些容器打包進一個 pod
這裡的範例是一個 pod 內裝有 monolith 以及 nginx 的容器
Pods 也有 Volumes。 Volumes 是與 pods 共存亡的資料硬碟, 且可被 pod 內的容器使用。 Pods 為其內容提供一個共享的命名空間, 這表示範例 pod 內的兩個容器可以互相溝通, 並且分享附加的 volumes
Pods 同時也分享一個網路命名空間。 這表示每個 pod 有著一個 IP 位址
現在讓我們更深入 pods 的世界
建立 pods
可以使用 pod 設定檔來建立 pod 。 讓我們來探索一下 monolith pod 設定檔, 執行以下指令:
cat pods/monolith.yaml |
輸出如下:
apiVersion: v1 |
有幾件需要注意到的事, 你將看到:
- 你的 pod 由一個容器組成 (monolith)
- 當容器啟動時, 你帶入一些參數
- 你打開 port 80 供 http 流量使用
使用 kubect1
建立 monolith pod
kubectl create -f pods/monolith.yaml |
檢視你的 pods 。 使用 kubectl get pods
指令來列出所有運行在預設命名空間的 pods
kubectl get pods |
注意: monolith pod 啟動與運行可能會需要幾秒鐘。 monolith 容器的 image 需要先從 Docker Hub 下載下來, 然後才能啟動。
一旦 pod 開始運行, 使用 kubectl describe
指令來獲得 monolith pod 更多的資訊
kubectl describe pods monolith |
你將會看到很多很多關於 monolith 的資訊, 包含 Pod IP 位址以及事件紀錄。 當除錯時, 這些資訊隨手可得。
Kubernetes 讓建立 pods 如此的簡單, 只需要再設定檔中敘述, 並且當在運行中時, 檢視資訊也是如此的簡單。 現在你已經有能力建立所有你部署需要的 pods
與 pods 的互動
照預設, pods 會被分配一個非公開的 IP 位址, 且無法被從叢集外存取。 使用 kubectl port-forward
指令來將本地的 port 以及 monolith pod 裡頭的 port 做連結
從現在開始, 本教程會要求在多個 cloud shell 視窗之間操作以設定 pods 之間的溝通。 任何在第二個或第三個 shell 中執行的指令都表示該 shell 的命令
開啟兩個 Cloud Shell terminals 。 一個執行 kubectl port-forward
指令, 另一個執行 curl
指令。
在 第二個 terminal, 執行以下指令來設定 port-forwarding
kubectl port-forward monolith 10080:80 |
現在在第一個 terminal, 開始使用 curl
與你的 pod 對話
curl http://127.0.0.1:10080 |
Yes! 你從你的容器收到一個友善的 “hello”
現在使用 curl
指令來看看當你存取一個安全端點時, 發生什麼事:
curl http://127.0.0.1:10080/secure |
Oh!
試著登入, 從 monolith 取得 auth token
curl -u user http://127.0.0.1:10080/login |
在登入彈窗, 使用超級安全的密碼 “password” 來登入
登入會返回一個 JWT 。 因為 cloud shell 無法很好的處理長字串的複製, 建立一個環境變數來裝這個 token
TOKEN=$(curl http://127.0.0.1:10080/login -u user|jq -r '.token') |
再次輸入超級安全密碼 “password” 當彈窗要求 host 密碼
使用上面的指令來複製, 然後用 curl
來提供 token 存取安全端點
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:10080/secure |
現在你應該可以從應用得到回應, 告訴我們世界又恢復了正常
使用 kubectl logs
指令來檢視 monolith pod 的紀錄
kubectl logs monolith |
開啟第三個 terminal 並且使用 -f
旗標來取得即時的紀錄
kubectl logs -f monolith |
現在在第一個 terminal 使用 curl
來語 monolith 互動, 你可以看到記錄在更新著 (在第三個 terminal)
curl http://127.0.0.1:10080 |
使用 kubectl exec
指令, 在 monolith pod 內運行一個互動的 shell 。 當在除錯時, 這會十分方便。
kubectl exec monolith --stdin --tty -c monolith /bin/sh |
例如說, 一旦我們在 monolith 容器有一個 shell, 我們可以使用 ping
測試外部的連結
ping -c 3 google.com |
確認登出互動 shell
exit |
你可以看到, 使用 kubectl
指令與 pod 互動是如此的容易。 Kubernetes 提供了所有的一切, 如果你需要遠端存取一個容器, 或是取得一個登入的 shell
服務
Pods 並不會永遠存在。 有很多種原因, 他們會被停止以及開啟 - 像是沒通過存活以及就緒的檢查 - 而這衍生一個問題
當一組 Pods 重啟了, 他們的 IP 變了, 這時候你要怎麼去跟他們溝通?
這就是 Services 的功用。 Services 為 Pods 提供了穩定的端點
Services 使用標籤 (labels) 來確定要作用在哪一些 Pods 上。 如果 Pods 有正確的標籤, 他們會自動地被 service 選擇且暴露
Service 提供給一系列的 Pods 的存取等級取決於 Service 的類型。 目前有三種類型:
ClusterIP (internal)
– 預設類型, 表示這個 Service 只能在叢集內部被看見NodePort
– 給予叢集內的節點一個外部可存取的 IPLoadBalancer
– 從雲端提供者那增加一個平衡負載, 將外部流量經由 Service 導向節點
現在, 你將學習如何:
- 建立一個 Service
- 使用標籤選擇器來暴露某幾個 Pods, 使他們可被外部看見
建立一個 Service
在我們建立我們的 Service 之前 – 讓我們先建立一個安全 pod, 它可以處理 HTTPS 的流量
如果你已經變更資料夾了, 確保你已經回到 ~/orchestrate-with-kubernetes/kubernetes
資料夾
cd ~/orchestrate-with-kubernetes/kubernetes |
檢視 monolith service 設定檔
cat pods/secure-monolith.yaml |
建立一個 secure-monolith pods 以及他們的設定資料:
kubectl create secret generic tls-certs --from-file tls/ |
現在你有一個 secure pod, 是時候暴露 secure-monolith Pod 到外部。 建立一個 Kubernetes service
檢視 monolith service 設定檔
cat services/monolith.yaml |
輸出:
kind: Service |
要注意的事情:
- 選擇器 (selector) 被使用來自動選擇以及暴露任何有標籤 “app=monolith” 以及 “secure=enabled” 的 pods
- 現在你必須暴露 nodePort, 因為這樣你才可以轉送外部流量從 31000 到 nginx (port 443)
使用 kubectl create
指令, 從 monolith service 設定檔來建立 monolith service
kubectl create -f services/monolith.yaml |
輸出:
service "monolith" created |
測試進度
點擊 Check my progress 來確認目前的進度。如果你已經成功地建立了 Monolith pods 以及 service,你將獲得一個評價分數。
使用 port 來暴露 service。 這表示如果有其他的 app 嘗試連結你其中一個 service 的 port 31000, 那可能會有衝突。
正常來說, Kubernetes 會處理 port 的分配, 在這個教程中, 你自己選擇 port, 所以等等我們在設定健康檢查的時候會比較容易。
使用 gcloud compute firewall-rules
指令來允許流量經由 nodePort 31000 來存取 monolith service
gcloud compute firewall-rules create allow-monolith-nodeport \ |
測試進度
點擊 Check my progress 來確認目前的進度。如果你已經成功建立防火牆規則來允許 TCP 流量進出 port 31000,你將獲得一個評價分數。
現在, 所有東西都設定好了, 你應該可以從叢集外部直接存取 secure-monolith service, 且不需要特別轉發 port
首先, 取得其中一個節點的外部 IP
gcloud compute instances list |
現在試著使用 curl
向 secure-monolith service 發請求:
curl -k https://<EXTERNAL_IP>:31000 |
Oh, 連線逾時了, 怎麼會這樣?
是時候快速利用以下幾個問題釐清一下概念, 利用下面的指令來取得問題的答案:kubectl get services monolith
kubectl describe services monolith
問題:
- 為什麼你無法從 monolith service 取得回應?
- monolith service 有幾個端點?
- Pod 需要有哪些標籤, 才會被 monolith service 取用?
提示: 跟標籤有關。 你將會在下一個章節解決這個問題。
增加標籤到 Pods
目前 monolith service 沒有任何端點。 有一個排除像這樣的錯誤的好方法, 那就是使用 kubectl get pods
指令的標籤查詢
我們可以看到, 有一些 pods 被貼上了 monolith 標籤
kubectl get pods -l "app=monolith" |
但是標籤不是 “app=monolith” 和 “secure=enabled” 嗎?
kubectl get pods -l "app=monolith,secure=enabled" |
注意到這個標籤查詢並沒有印出任何的結果。 看起來是我們需要把 “secure=enabled” 標籤加到這些 pods 上
使用 kubectl label
指令來加漏掉的 secure=enabled
標籤加到 secure-monolith Pod。 之後呢, 你可以確認標籤是否有更新
kubectl label pods secure-monolith 'secure=enabled' |
現在我們的 pods 已經被上標籤了, 讓我們檢視一下 monolith service 端點的清單
kebectl describe services monolith | grep Endpoints |
有一個!
讓我們向其中一個節點發請求, 測試看看!
gcloud compute instances list |
連接上了!
測試進度
點擊 Check my progress 來確認目前的進度。如果你已經成功地將標籤加到 monolith pods,你將獲得一個評價分數。
部署應用到 Kubernetes
本教程的目標是讓你準備好在正式產品線上操作擴充以及管理容器。 這也是 Deployment 的作用。 Deployments 是一種宣告的方法, 確保運行的 Pods 數量跟使用者指定的數量是一致的。
Deployments 的主要優點, 是將管理 Pods 的低階細節抽象化。 如果 Pods 需要擴充或更新, Deployment 會處理這一段。 Deployment 也處理重啟 Pods 這一塊, 如果 Pods 因為某些原因關閉的話。
讓我們來快速看一個範例:
Pods 的生命週期與他們被建立且身處的 Node 一樣長。 在上面的範例中, Node3 關閉了 (帶著 Pod 一起)。 Deployment 建立一個新的 Pod, 然後在 Node2 上運行, 而不需要手動建立一個新的 Pod 然後再找一個 Node 來運行它。
真是太酷了!
是時候結合你學到的東西, Pods, Services, 使用 Deployment 將 monolith 應用拆分成更小的 Services
建立 Deployments
我們將會把 monolith app 拆成三個小的部分:
- auth - 為通過驗證的使用者產生 JWT tokens
- hello - 向通過驗證的使用者打招呼
- frontend - 將流量導向 auth 以及 hello 服務
我們已經準備好要為每一個 service 建立 deployments了。 在那之後, 我們將為 auth 以及 hello deployments 定義內部 service, 以及為 frontend deployment 定義外部 service 。 一旦完成, 你將可以跟每個微服務互動, 就跟現在一樣, 不同的是, 每一個部分將可以獨立地被部署, 擴充。
先從檢視 deployment 設定檔開始吧
cat deployments/auth.yaml |
輸出:
apiVersion: extensions/v1beta1 |
deployment 建立 1 個 replica, 且使用版本 2.0.0 的 auth 容器
當你執行 kubectl create
指令建立 auth deployment, 它會建立一個 pod, 這個 pod 會符合 Deployment 的清單資料。 這表示你可以藉由改變 Replicas 欄位的數字來擴充 Pods 的數量
不管怎樣, 建立 deployment 物件吧
kubectl create -f deployments/auth.yaml |
是時候為 auth deployment 建立 service 了。 使用 kubectl create
指令來建立 auth service:
kubectl create -f services/auth.yaml |
現在重複一樣的步驟來建立並暴露 hello deployment
kubectl create -f deployments/hello.yaml |
再一次, 建立及暴露 frontend deployment
kubectl create configmap nginx-frontend-conf --from-file=nginx/frontend.conf |
建立 frontend 還有最後一步, 因為你需要使用容器儲存一些設定資料
取得 frontend 的外部 IP, 並且使用 curl 來跟它互動吧!
kubectl get services frontend |
然後你得到一個 hello 回應!
測試進度
點擊 Check my progress 來確認目前的進度。如果你已經成功建立 auth, hello, 以及 frontend deployment, 你將獲得一個評價分數。
總結
恭喜! 你已經使用 Kubernetes 部署了一個多服務的應用。 你在這學到的技術將可以讓你使用一系列的 deployments 以及 services 在 Kubernetes 部署複雜的應用。
留言