概述
本教程的目標是將開發完畢的代碼轉成運行在 Kubernetes 上可複製的應用, 本教程中 Kubernetes 運行在 Kubernetes Engine。 在本教程中, 代碼會是簡單的 Hello World node.js 應用
下圖是一個圖示顯示個元件在本教程中扮演的角色, 讓我們了解個元件彼此之間是如何互相配合的。 當你在進行本教程時, 可以參考這個圖示。 當你結束本教程, 你將會了解整個脈絡 (如果現在看不懂可以先跳過) 。
Kubernetes 是一個開源的專案 (可從 kubernetes.io 獲得), 可以運行在很多不同的環境上, 從筆電到高可用的多主機叢集; 從公開的雲端到人為部署; 從虛擬機到裸機
在本教程中, 使用一個受管理的環境, 像是 Kubernetes Engine (一個由 Google 維護的 Kubernetes 版本, 運行在 Compute Engine 上), 將會讓你可以更專注在體驗 Kubernetes, 而不是設定底層的環境。
本篇將會做什麼?
- 建立一個 Node.js server
- 建立一個 Docker container image
- 建立一個 container cluster
- 建立一個 Kubernetes Pod
- 擴大服務
前言
本篇主要是利用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
建立你的 Node.js 應用
使用 Cloud Shell, 寫一個簡單的 Node.js server, 你將會部署這個 Server 到 Kubernetes Engine
vi server.js |
進入編輯模式
i |
在檔案中增加以下內容:
var http = require('http'); |
Cloud Shell 已內建 node, 直接執行 node server
node server.js |
使用 Cloud Shell 內建的 Web 預覽功能, 開一個新的視窗並發請求到 port 8080, 如下圖:
一個新的瀏覽器視窗將會開啟並且顯示結果:
在更進一步之前, 讓我們先到 Cloud Shell 按下 Ctrl+c 停止正在運行中的 node server, 我們將打包這個運用, 並置於 Docker container 內
建立一個 Docker container image
接下來, 建立一個 Dockerfile
來敘述我們想要建立的 image, Docker container images 可以是已經存在 image 的延伸, 所以我們將從已經存在的 Node image 來延伸
vim Dockerfile |
進入編輯模式
i |
增加以下內容
FROM node:6.9.2 |
上面 Docker image 的內容將會執行以下的事:
- 開始一個從 Docker hub 找到的
node
image - 暴露 port
8080
- 複製
server.js
檔案到此 docker image - 開始一個 node server, 就像我們上一步手動開啟那樣
儲存 Dockerfile
檔案, 按下 Esc, 然後:
:wq |
輸入以下的指令來建立 image, 將下面的 PROJECT_ID
替換成你的 GCP Project ID
, 可以從主控台以及 Connection Details 區找到
docker build -t gcr.io/PROJECT_ID/hello-node:v1 . |
接下來會花一些時間來下載以及擷取需要的東西, 但你可以從進度條看到 image 建立的進度
完成之後, 於本地端使用下面的指令測試一下這個 image, 這個指令會從剛新建立的 container image 中, 將 Docker container 以常駐的方式跑在 port 8080,
執行下面的指令, 並將的 PROJECT_ID
替換成你的 GCP Project ID
, 可以從主控台以及 Connection Details 區找到
docker run -d -p 8080:8080 gcr.io/PROJECT_ID/hello-node:v1 |
結果大概如下
325301e6b2bffd1d0049c621866831316d653c0b25a496d04ce0ec6854cb7998 |
可使用 Web 預覽功能
或在 Cloud Shell 中使用 curl
kcurl http://localhost:8080 |
注意: 完整的 docker run
文件你可以在這裏找到
接下來, 停止運行中的容器
尋找 Docker container ID
docker ps |
結果大概如下
CONTAINER ID IMAGE COMMAND |
執行以下指令來關閉容器, 並將 [CONTAINER ID]
替換成之前獲得的值
docker stop [containerID] |
結果會輸出你的 container ID ,如下:
2c66d0efcbd4 |
現在, image 如我們預期般的運作著, 接下來我們將它推到 Google Container Registry, 一個可被 Google Cloud Projects 存取的 Docker image 私人資料夾。
執行下面的指令, 並將的 PROJECT_ID
替換成你的 GCP Project ID
, 可以從主控台以及 Connection Details 區找到。
gcloud auth configure-docker |
docker push gcr.io/PROJECT_ID/hello-node:v1 |
第一次的推送可能會花個幾分鐘完成。 當它在建立時, 你可以看到進度條。
The push refers to a repository [gcr.io/qwiklabs-gcp-6h281a111f098/hello-node] |
Container image 將會被列在主控台中, 選擇 Navigation menu > Container Registry
現在我們擁有 project-wide 的 Docker image ,可供 Kubernetes 存取以及編排
注意: 在這次註冊中使用一個通用的 domain (gcr.io
)。 在你自己的環境中, 你可以指定哪一個 zone 或是儲存區, 詳見文件
建立 cluster
現在我們已經準備好可以建立 Kubernetes Engine cluster 。 一個 cluster 內, 有由 Google 管理的 Kubernetes master API server, 以及一組 worker nodes 。 worker nodes 為 Compute Engine 的虛擬機
確保我們已經使用 gcould 來設定我們的專案 (將 PROJECT_ID
替換成你的 GCP Project ID
, 可以從主控台以及 Connection Details 區找到。)
gcloud config set project PROJECT_ID |
使用兩個 n1-standard-1 nodes 來建立 cluster (將會耗費幾分鐘)
gcloud container clusters create hello-world \ |
在建立時, 若看到警告可以無視。
輸出應會如下:
Creating cluster hello-world...done. |
注意: 你也可以透過主控台來建立 cluster, 打開 Navigation 選單並選擇 Kubernetes Engine > Kubernetes cluster > Create cluster
注意: cluster 建立的區域,建議跟 container registry 使用的儲存區的所在區域一樣
如果你選擇 Navigation menu > Kubernetes Engine
, 可以看到, 現在有一個由 Kubernetes Engine 驅動的, 功能完全的 Kubernetes 叢集
接下來, 是時候將我們容器化的 application 部署到 Kubernetes cluster, 從現在開始, 我們將使用 kubectl
命令行(在 Cloud Shell 環境中,這已經被設定完畢)
測試進度
點擊 Check my progress 來確認目前的進度。如果你已經完成目前的進度,你將獲得一個評價分數。
建立 Pod
Kubernetes pod 由多個容器組成, 用於管理以及連結。 它可以容納單一或多個容器。 這邊我們將會使用儲存於私人的 container registry, 由 Node.js image 建立的容器 。 將會運行在 8080 port
使用 kubectl run
指令來建立一個 pod (將 PROJECT_ID
替換成你的 GCP Project ID
, 可以從主控台以及 Connection Details 區找到。)
kubectl run hello-node \ |
輸出:
deployment "hello-node" created |
可以看到, 我們已經建立一個 deployment 物件。 Deployments 是建立跟擴大 pods 推薦的方法。 這邊, 一個新的 deployment 管理一個正運行著 hello-node:v1
image 的 pod
若要檢視 deployment, 運行:
kubectl get deployments |
輸出:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE |
若要檢視由 deployment 建立的 pod, 運行:
kubectl get pods |
輸出:
NAME READY STATUS RESTARTS AGE |
現在是時候來看看一些有趣的 kubectl
指令。 他們都不會變更叢集的狀態, 完整個文件可參考這裡
kubectl cluster-info |
kubectl config view |
Debug 專用:
kubectl get events |
kubectl logs <pod-name> |
現在你需要讓外部可以存取你的 pod
點擊 Check my progress 來確認目前的進度。如果你已經完成目前的進度,你將獲得一個評價分數。
允許外部連結
在預設中, Pod 只可被 cluster 內部的 IP 存取。為了要讓 hello-node container 可被 Kubernetes virtual network 之外的地方存取,我們必須設定 Pod 成可被存取的 Kubernetes 的服務
在 Cloud Shell, 透過使用 kubectl expose 指令, 並結合 --type="LoadBalancer"
旗標, 我們可以讓 Pod 可被公用網路存取。要建立一個外部存取 IP, 這個 flag 是必須的。
kubectl expose deployment hello-node --type="LoadBalancer" |
輸出:
service "hello-node" exposed |
這個 flag 指定我們將使用底層基礎設施提供的平衡負載 (在此範例中,為 Compute Engine load balancer)。需注意我們是使 deployment 可視化, 並非直接暴露 Pod 。這代表, 服務將會在所有由 deployment 管理的 pods 之間平衡負載流量 (於此範例中, 為一個Pod, 但我們等等會增加)
此 Kubernetes master 建立了 load balancer, 相關的 Compute Engline 轉發規則, target pools, 以及防火牆規則, 所以服務可被 Google Cloud Platform 之外的來源所存取
若要找公開可存取IP, 可要求 kubectl
列出所有的 cluster 服務
kubectl get services |
結果如下:
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE |
上圖可以看到, hello-node service 有兩組 IP, 兩組都使用 port 8080, CLUSTER-IP
是內部 IP, 只可被內部 cloud virtual network 所見, EXTERNAL-IP
為外部 load-balanced IP
注意: EXTERNAL-IP
可能會需要幾分鐘的時間變得可用, 以及可視化。 如果 EXTERNAL-IP
不可用, 等幾分鐘, 然後再次執行指令。
現在你應該可以透過以下的連結來存取服務: http://<EXTERNAL_IP>:8080
使用容器化以及 Kubernetes 之後, 你已經獲得很多新的功能 - 你不需要指定哪台主機來運行你的工作, 且還有服務的監控以及重啟功能。 現在讓我們來看看我的們新 Kubernetes 還有什麼其他功能
點擊 Check my progress 來確認目前的進度。如果你已經完成目前的進度,你將獲得一個評價分數。
擴充服務
Kubernetes 提供的其中一個強大的功能, 就是非常簡單的擴充你的應用。 假如你忽然間需要很大的容量, 你可以告訴 replication controller 來為我們的 pod 設置一個新的 replicas 數量
kubectl scale deployment hello-node --replicas=4 |
輸出:
deployment "hello-node" scaled |
你可以查看更新後的 deployment
kubectl get deployment |
輸出:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE |
- 你也可以列出所有的 pods
kubectl get Pods
輸出:
NAME READY STATUS RESTARTS AGE |
一個宣告式的方法在這裡被使用。 你宣告了多少個 instances 應該被使用, 而不是開啟或關閉新的 instances. Kubernetes 的調和迴圈確保實際情況符合你要求的, 並且必要時採取動作。
以下圖片總結 Kubernetes 叢集的狀態:
點擊 Check my progress 來確認目前的進度。如果你已經完成目前的進度,你將獲得一個評價分數。
升級服務
某些時候,已經被部署的應用需要 debug 或增加新的功能。 Kubernetes 幫我們部署新的版本,並且不影響使用者
首先, 修改應用, 編輯 server.js
vim server.js |
i |
更新回覆訊息
response.end("Hello Kubernetes World!"); |
按下 ESC, 然後輸入以下指令來儲存 server.js
:wq |
現在, 我們可以透過往上增加的版本號, (v2
, 在本範例中) 建立以及發布一個新的 container image 到 registry。
執行以下指令(將 PROJECT_ID
替換成你的 GCP Project ID
, 可以從主控台以及 Connection Details 區找到。)
docker build -t gcr.io/PROJECT_ID/hello-node:v2 . |
gcloud docker -- push gcr.io/PROJECT_ID/hello-node:v2 |
注意: 建立以及推送更新的 image 應該會比較快, 因為 cache 已經被使用了
Kubernetes 將會流暢的更新你的 replication controller 到新的應用程式版本。 為了要改變運行中容器的 image 的標籤, 你需要編輯已經存在的 hello-node deployment 以及將 image 由 gcr.io/PROJECT_ID/hello-node:v1
變更為 gcr.io/PROJECT_ID/hello-node:v2
使用 kubectl edit
指令來做到這一點。 它會打開一個顯示所有 deployment yaml 設定檔的編輯器。 現在不需要理解所有的 yaml 設定, 只需要理解如果我們更新了 spec.template.spec.containers.image
欄位, 那相當於告訴 deployment 使用新的 image 更新 pods。
kubectl edit deployment hello-node |
尋找 Spec
> containers
> image
, 然後改變版本號碼到 v2
# Please edit the object below. Lines beginning with a '#' will be ignored, |
更改之後, 按下 Esc, 然後輸入以下指令來儲存並且離開檔案
:wq |
輸出應如下:
deployment "hello-node" edited |
執行以下指令來使用新的 image 更新 deployment
kubectl get deployments |
更新後的 image 將會被使用來建立新的 pods, 而舊的 pods 會被刪除
輸出應如下:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE |
在這一切發生的過程中, 你的服務的使用者不會看到任何的服務中斷。 過一段時間後, 他們會開始存取新版的應用。 關係滾動升級的更多細節可以參考文件
使用這些部署, 擴充, 更新的功能, 一旦我們完成 Kubernetes Engine 叢集的設定, 我們可以把我們節省花在基礎設施上的時間並專注在開發上。
Kubernetes圖形化面板 (optional)
最近的 Kubernetes 版本已經推出了圖示化的網頁使用者介面 (dashboard)。 顯示面板讓我們可以更快速的使用 Kubernetes, 並且可以開啟一些 CLI 的功能, 像是是一種更容易理解, 且更容易發現問題的與系統互動的方式。
執行以下指令來取得 cluster 層級權限
kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value account) |
使用適當的權限設定, 執行以下指令來建立一個新的顯示面板服務
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml |
你應會收到類似輸出:
secret "kubernetes-dashboard-certs" created |
執行以下指令來編輯面板服務的 yaml
表現
kubectl -n kube-system edit service kubernetes-dashboard |
按下 i
, 進入編輯模式
將 type: ClusterIP
更改為 type: NodePort
在做完一切更改後, 按下 Esc, 然後輸入以下指令儲存離開
:wq |
要登入 Kubernetes 顯示面板, 你需要使用 token 驗證。 使用由 service account 分配的 token, 例如 namespace-controller
要獲得 token, 執行以下指令:
kubectl -n kube-system describe $(kubectl -n kube-system \ |
輸出應如下:
token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJuYW1lc3BhY2UtY29udHJvbGxlci10b2tlbi1kOTZyNCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJuYW1lc3BhY2UtY29udHJvbGxlciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImU2ZmFkNGQ5LTJjNjYtMTFlOC05NDFiLTQyMDEwYTgwMDFlYiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTpuYW1lc3BhY2UtY29udHJvbGxlciJ9.AY3Fp-T_4wxTzvo4kiWi4zxojVTSr1Wy7BL_-HmIRlWTRAUmy_1RAJS19zn4BbSkxlV13Y9Bv3NoVcG01jKd4QoM172OXo2TqSU5v2B62i3-_CDZtf3CVgQIp9jiuxACcR5zg3w-4ewGfH4C3ospoKCuayyRaADLq0ThWLGaTQv9e7UjSfWAPir3XPXQut3mMRYrSiHcFNiEGeztSfF3cyhuvL2I5Lfh20yYuqW5j-w72BLnlqQGPuhJXJgH1_35XUCU8WtnkEK-qYX40ajDWJYa1s9_R-MWzF6Zwji2Gh5txOvxG3lZuIq9GSAOBp85617wB3eCGio6Nu3L9TwWXA |
複製 token 然後儲存, 等等要進到顯示面板會用到。 執行以下指令來打開連線
kubecl proxy --port 8081 |
然後使用 Cloud Shell 網頁預覽功能來改變 port 到 8081:
我們將收到一串API endpoint, 要連結到面板, 將 /?authuser=0
移除,然後加上下面的 url:
/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/overview?namespace=default |
最終的 URL 看起來應該會像下面那樣:
https://8081-dot-5177448-dot-devshell.appspot.com/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/overview?namespace=default |
然後你會被帶到一個網頁預覽
點選 Token radio 按鈕, 然後貼上剛剛拿到的 token, 然後點擊 Sign in
現在你可以享受 Kubernetes 圖形化顯示面板帶來的好處, 使用它來部署容器化應用, 以及監控和管理你的叢集。
你可以從主控台或是使用 Command-line 存取面板服務, Navigation menu > Kubernetes Engine, 然後點擊 Connect 按鈕連接到我們想要連接的叢集
如果想要瞭解更多有關 Kubernetes 顯示面板的資訊, 參考文件
習題測驗
- which of the following are features of the Kubernetes Engine?
- Identity and Access Management
- Integrated Logging and Monitoring
- None of these
- Stateful Application Support
恭喜
你已經完成本教程!
留言