Physical Address

304 North Cardinal St.
Dorchester Center, MA 02124

GCP 筆記: Managing Deployments Using Kubernetes Engine

異地部署 (Heterogeneous deployments) 涉及兩個以上的不同執行個體、基礎建設環境、地區,以解決特定的技術需求。

單一環境部署可能會遇到以下問題:

  • 資源過載: 在單一環境中,尤其是內部 (on-premises) 環境,可能達不到需要的運算、網路與儲存資源。
  • 受限的地理觸及: 在單一環境部署時,可能會有來自地理上較遙遠的使用者存取。
  • 受限的可用性: Web-scale 的流量模式挑戰應用程式的容錯率與可復原性。
  • 廠商鎖定 (lock-in): 廠商層級將平台與基礎結構抽象化,可能導致你無法移轉 (porting) 你的應用程式。
  • 缺乏彈性的資源: 資源會受限於特定的運算、儲存或網路服務項目。

異地部署最常見的三個情境是複數雲部署、內部資料前端化 (fronting on-premises data) 與持續整合/部署 (CI/CD)。

前置作業

gcloud config set compute/zone us-central1-a
gsutil -m cp -r gs://spls/gsp053/orchestrate-with-kubernetes .
cd orchestrate-with-kubernetes/kubernetes
gcloud container clusters create bootcamp \
--num-nodes 5 --scopes "https://www.googleapis.com/auth/projecthosting,storage-rw"

kubectl 部署物件

利用以下指令查詢 kubectl 有關部署物件的相關說明。

kubectl explain deployment
kubectl explain deployment --recursive
kubectl explain deployment.metadata.name

建立新的部署

編輯 deployments/auth.yaml

vi deployments/auth.yaml

將映像檔 image 改為下列值:

...
containers:
- name: auth
  image: "kelseyhightower/auth:1.0.0"
...

儲存後,用 cat deployments/auth.yaml 確認是否完全變更。在這個組態中,replica 的值是 1,代表部署時只會建立一個 Pod,之後如果需要建立多個 Pod 時,可以修改 replica 的值。接著建立部署物件。

kubectl create -f deployments/auth.yaml

# 檢視所有部署
kubectl get deployments

# 檢視 ReplicaSets
kubectl get replicasets

kubectl get pods

接著開始透過預先設定好的指令碼,建立各項服務。

kubectl create -f services/auth.yaml
kubectl create -f deployments/hello.yaml
kubectl create -f services/hello.yaml
# 建立 TLS 憑證
kubectl create secret generic tls-certs --from-file tls/
kubectl create configmap nginx-frontend-conf --from-file=nginx/frontend.conf
kubectl create -f deployments/frontend.yaml
kubectl create -f services/frontend.yaml

接著使用 kubectl get services frontend 取得前端服務的外部 IP。

kubectl get services frontend

利用 curl 檢視 IP 是否能夠存取。

curl -ks https://<外部 IP>

# 透過變數的方式取得外部 IP
curl -ks https://`kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"`

縮放部署

利用 kubectl scale deployment 來縮放叢集中的複本數。

kubectl scale deployment hello --replicas=5

確認複本是否在運作。

kubectl get pods | grep hello- | wc -l

# 結果回傳 5

接著嘗試調整複本數。

kubectl scale deployment hello --replicas=3

kubectl get pods | grep hello- | wc -l
# 結果回傳 3

滾動式更新

當部署更新時,會先建立新的 ReplicaSet,並增加新 ReplicaSet 中的複本數量、逐漸減少舊 ReplicaSet 的複本數量。

使用 kubectl edit deployment 編輯部署。

kubectl edit deployment hello

更新映像檔至 2.0.0 版。

...
containers:
  image: kelseyhightower/hello:2.0.0
...

此時透過 kubectl get replicaset,會看到 hello 的部署建立新的 ReplicaSet,逐漸替換掉舊的 ReplicaSet。

kubectl get replicaset

# 檢視滾動更新的歷程紀錄
kubectl rollout history deployment/hello

暫停滾動式更新

如果在更新過程中發現問題時,可以先透過 kubectl rollout pause 暫停。並用下列指令檢查 Pods 的部署狀態。

kubectl rollout pause deployment/hello
kubectl rollout status deployment/hello
kubectl get pods -o jsonpath --template='{range .items[*]}{.metadata.name}{"\t"}{"\t"}{.spec.containers[0].image}{"\n"}{end}'

繼續更新

kubectl rollout resume deployment/hello

復原更新

利用 kubectl rollout undo 復原前一次的部署。

kubectl rollout undo deployment/hello

檢查復原歷程 kubectl rollout history 時會看到 REVISION 是第 3 個版本。

kubectl rollout history deployment/hello

# 檢查 Pods 使用的映像檔
kubectl get pods -o jsonpath --template='{range .items[*]}{.metadata.name}{"\t"}{"\t"}{.spec.containers[0].image}{"\n"}{end}'

Canary 部署

透過 Canary 部署,可以將部分複本更新,降低新版本全面釋出造成的風險。

首先,先檢視預先準備好的 Canary 部署指令碼,並建立新的 Canary 部署。

cat deployments/hello-canary.yaml

kubectl create -f deployments/hello-canary.yaml

# 確認部署是否已經建立
kubectl get deployments

再重新執行數次 curl 指令來驗證,其中會注意到有時候回傳的值是 1.0.0 版,有時則是 2.0.0 版。

curl -ks https://`kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"`/version

但是從上述的結果來看,每次的存取都會隨機分配。為了讓存取到某一版本的使用者,有一致的體驗,就會牽涉到工作階段親和性 (session affinity)。

在設定組態時,加入 sessionAffinity 屬性,指定 ClientIP,便能讓同一 IP 的使用者,只會看到同樣版本的結果。

kind: Service
apiVersion: v1
metadata:
  name: "hello"
spec:
  sessionAffinity: ClientIP
  selector:
    app: "hello"
  ports:
    - protocol: "TCP"
      port: 80
      targetPort: 80

Blue-green 部署

除了滾動式更新外,另一種更新方式,是要等到完全部署完畢後,才將所有的流量路由傳送到新的部署上,此時就會採用 Blue-green 部署。

需要注意的是,Blue-green 部署需要兩倍的部署資源。

首先,先將既有的資源加入 app:hello 的選擇器,會將現有的服務比對成 Blue 版本。

kubectl apply -f services/hello-blue.yaml

建立 Green 版本的部署組態 hello-green.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      labels:
        app: hello
        track: stable
        version: 2.0.0
    spec:
      containers:
        - name: hello
          image: kelseyhightower/hello:2.0.0
          ports:
            - name: http
              containerPort: 80
            - name: health
              containerPort: 81
          resources:
            limits:
              cpu: 0.2
              memory: 10Mi
          livenessProbe:
            httpGet:
              path: /healthz
              port: 81
              scheme: HTTP
            initialDelaySeconds: 5
            periodSeconds: 15
            timeoutSeconds: 5
          readinessProbe:
            httpGet:
              path: /readiness
              port: 81
              scheme: HTTP
            initialDelaySeconds: 5
            timeoutSeconds: 1

部署 Green 版本。

kubectl create -f deployments/hello-green.yaml

curl 驗證,此時當前的版本還是 1.0.0

curl -ks https://`kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"`/version

將服務指向新版本。

kubectl apply -f services/hello-green.yaml

再次驗證後,會發現已經更新到 2.0.0 的版本。

curl -ks https://`kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"`/version

復原版本

利用 kubectl apply,套用原本的組態檔 hello-blue.yaml,便能回復到前一個版本。

kubectl apply -f services/hello-blue.yaml
Eric Chuang
Eric Chuang

正職是廣告行銷人員,因為 Google Tag Manager 的關係開始踏入網站製作的領域,進一步把 WordPress 當成 PHP + HTML + CSS + JavaScript 的學習教材。此外,因為工作的關係,曾經用 Automattic 的 Underscores (_s) 替客戶與公司官網進行全客製化佈景主題開發。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料