使用 Kubernetes 來編排你的雲端

概述

在這個教程中, 你將會學習到如何:

  • 使用 Kubernetes Engine 來提供一個完整的 Kubernetes 叢集
  • 使用 kubectl 部署以及管理 Docker 容器
  • 使用 Kubernetes 的 Deployments 以及 Services 將應用拆分為微服務

Kubernetes 重點就是應用。 在本教程中的這個部分, 你將使用範例應用名為 “app” 來完成這個教程

App 由 GitHub 管理, 且提供一個 12-Factor 範例應用。 在本教程中你將會使用以下的 Docker images

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?

  1. 按下 Start Lab 按鈕。 如果你需要付費, 會有一個彈出視窗來讓你選擇付費的方式。 在左方你會看到一個面板, 上面有暫時的帳號密碼, 你必須使用這些帳號密碼在此次 lab

  1. 複製 username, 然後點擊 Open Google Console。 Lab 會開啟另外一個視窗, 顯示選擇帳號的頁面

tip: 開啟一個全新的視窗,然後跟原本的頁面並排

  1. 選擇帳號頁面, 點擊 Use Another Account

  1. 登入頁面開啟, 貼上之前複製的 username 以及 password, 然後貼上

重要:必須使用之前於 Connection Details 面板 取得的帳號密碼,不要使用你自己的 Qwiklabs 帳號密碼。 如果你有自己的 GCP 帳號, 請不要用在這裡(避免產生費用)

  1. 點擊並通過接下來的頁面:
    • 接受 terms 以及 conditions
    • 不要增加 recovery optoinstwo factor authentication (因為這只是一個臨時帳號)
    • 不要註冊免費體驗

稍待一些時候, GCP 控制台將會在這個視窗開啟。

**注意:** 按下左上方位於 `Google Cloud Platform` 隔壁的 `Navigation menu`, 你可以瀏覽選單, 裡面有一系列的 GCP 產品以及服務


啟動 Google Cloud Shell

Google Cloud Shell 是載有開發工具的虛擬機器。 它提供了5GB的 home 資料夾, 並且運行在 Google Cloud 上。 Google Cloud Shell 讓你可以利用 command-line 存取 GCP 資源

  1. GCP 控制台, 右上的工具列,點擊 Open Cloud Shell 按鈕

  1. 在打開的對話框裡, 按下 START CLOUD SHELL:

你可以立即按下 START CLOUD SHELL 當對話視窗打開。

連結並提供環境會需要一點時間。 當你連結成功, 這代表你已成功獲得授權, 且此專案已被設為你的專案ID, 例如:

gcloudGoogle Cloud Platform 的 command-line 工具, 他已事先被安裝在 Cloud Shell 並且支援自動補齊

使用這個 command, 你可以列出有效帳戶名稱:

gcloud auth list

輸出:

Credentialed accounts:
- <myaccount>@<mydomain>.com (active)

範例輸出:

Credentialed accounts:
- google1623327_student@qwiklabs.net

你可以使用以下 command 來列出專案 ID

gcloud config list project

輸出:

[core]
project = <project_ID>

範例輸出:

[core]
project = qwiklabs-gcp-44776a13dea667a6

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 */
...
nginx/ /* nginx config files */
...
pods/ /* Pod manifests */
...
services/ /* Services manifests */
...
tls/ /* TLS certificates */
...
cleanup.sh /* Cleanup script */

該有的都有了, 讓我們來試試看 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
kind: Pod
metadata:
name: monolith
labels:
app: monolith
spec:
containers:
- name: monolith
image: kelseyhightower/monolith:1.0.0
args:
- "-http=0.0.0.0:80"
- "-health=0.0.0.0:81"
- "-secret=secret"
ports:
- name: http
containerPort: 80
- name: health
containerPort: 81
resources:
limits:
cpu: 0.2
memory: "10Mi"

有幾件需要注意到的事, 你將看到:

  • 你的 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 – 給予叢集內的節點一個外部可存取的 IP
  • LoadBalancer – 從雲端提供者那增加一個平衡負載, 將外部流量經由 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/
kubectl create configmap nginx-proxy-conf --from-file nginx/proxy.conf
kubectl create -f pods/secure-monolith.yaml

現在你有一個 secure pod, 是時候暴露 secure-monolith Pod 到外部。 建立一個 Kubernetes service

檢視 monolith service 設定檔

cat services/monolith.yaml

輸出:

kind: Service
apiVersion: v1
metadata:
name: "monolith"
spec:
selector:
app: "monolith"
secure: "enabled"
ports:
- protocol: "TCP"
port: 443
targetPort: 443
nodePort: 31000
type: NodePort

要注意的事情:

  1. 選擇器 (selector) 被使用來自動選擇以及暴露任何有標籤 “app=monolith” 以及 “secure=enabled” 的 pods
  2. 現在你必須暴露 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 \
--allow=tcp:31000

測試進度

點擊 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'
kubectl get pods secure-monolith --show-labels

現在我們的 pods 已經被上標籤了, 讓我們檢視一下 monolith service 端點的清單

kebectl describe services monolith | grep Endpoints

有一個!

讓我們向其中一個節點發請求, 測試看看!

gcloud compute instances list
curl -k https://<EXTERNAL_IP>:31000

連接上了!

測試進度

點擊 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
kind: Deployment
metadata:
name: auth
spec:
replicas: 1
template:
metadata:
labels:
app: auth
track: stable
spec:
containers:
- name: auth
image: "kelseyhightower/auth:2.0.0"
ports:
- name: http
containerPort: 80
- name: health
containerPort: 81
...

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
kubectl create -f services/hello.yaml

再一次, 建立及暴露 frontend deployment

kubectl create configmap nginx-frontend-conf --from-file=nginx/frontend.conf
kubectl create -f deployments/frontend.yaml
kubectl create -f services/frontend.yaml

建立 frontend 還有最後一步, 因為你需要使用容器儲存一些設定資料

取得 frontend 的外部 IP, 並且使用 curl 來跟它互動吧!

kubectl get services frontend
curl -k https://<EXTERNAL-IP>

然後你得到一個 hello 回應!


測試進度

點擊 Check my progress 來確認目前的進度。如果你已經成功建立 auth, hello, 以及 frontend deployment, 你將獲得一個評價分數。



總結

恭喜! 你已經使用 Kubernetes 部署了一個多服務的應用。 你在這學到的技術將可以讓你使用一系列的 deployments 以及 services 在 Kubernetes 部署複雜的應用。

GCP Deployment Manager - 正式環境 IAM 自訂角色

留言

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×