Autoscaling on the Docker EE UCP Clusters


如何在 Docker EE 環境下運用整合的 Kubernetes orchestration 做 HPA (Horizontal Pod Autoscaler) 功能?

以下操作皆在 LINUX 環境下運行.

現有一個已建立好的 Docker EE UCP 叢集, 並且已經將設定好帶有 administration 權限的 client bundle 下載在客戶主機並在一個已開啓的 terminal 操作.

Docker EE 引擎版本是:

# docker version
Client:
 Version:           18.09.3
 API version:       1.39
 Go version:        go1.10.6
 Git commit:        142dfce
 Built:             Thu Feb 28 06:08:17 2019
 OS/Arch:           linux/amd64
 Experimental:      true

Server: Docker Enterprise 2.1
 Engine:
  Version:          18.09.5
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.8
  Git commit:       be4553c
  Built:            Thu Apr 11 06:23:08 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 Universal Control Plane:
  Version:          3.1.4
  ApiVersion:       1.39
  Arch:             amd64
  BuildTime:        Wed Feb 27 22:26:43 UTC 2019
  GitCommit:        29b16f9
  GoVersion:        go1.10.6
  MinApiVersion:    1.20
  Os:               linux
 Kubernetes:
  Version:          1.11+
  buildDate:        2019-02-05T21:33:23Z
  compiler:         gc
  gitCommit:        8249259df545d6e853b7de9d050a34ec24e8b2f5
  gitTreeState:     clean
  gitVersion:       v1.11.7-docker-1
  goVersion:        go1.10.7
  major:            1
  minor:            11+
  platform:         linux/amd64
 Calico:
  Version:          v3.5.0
  cni:              v3.5.0
  kube-controllers: v3.5.0
  node:             v3.5.0

Docker EE 引擎版本是 18.09.3 ,其所支援的 Kubernetes API 版本是 1.11

另外注意目前使用的 kubectl client 版本必須跟上述相同, 1.11

 # kubectl version 
Client Version: version.Info{Major:"1", Minor:"11", GitVersion:"v1.11.5", GitCommit:"753b2dbc622f5cc417845f0ff8a77f539a4213ea", GitTreeState:"clean", BuildDate:"2018-11-26T14:41:50Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"11+", GitVersion:"v1.11.7-docker-1", GitCommit:"8249259df545d6e853b7de9d050a34ec24e8b2f5", GitTreeState:"clean", BuildDate:"2019-02-05T21:33:23Z", GoVersion:"go1.10.7", Compiler:"gc", Platform:"linux/amd64"}


早期的 Kubernetes 版本例如 1.8 使用 heapster 來收集監控 CPU 使用率資訊以達到 autoscaling 的目的, 新版本的 Kubernetes 1.11 已經改用 Kubernetes metrics server 來做到收集並回報 CPU 使用率資訊, 而 heapster 已經逐步淘汰.

以下先佈署 metrics server 在 Docker EE UCP 叢集上運行,接着佈署運行待測的應用程式以及其 HPA ,根據 metrics server 所持續收集到待測應用程式所消耗的 CPU loading 數據結果,在 Docker 平臺上動態的調整其應用程式的 replicas 個數。


metrics server 源代碼可以通過 Git

 # metrics server
git clone https://github.com/kubernetes-incubator/metrics-server

成功執行上述命令後, 會得到一 metrics-server 目錄. 在取得 Kubernetes metrics server 源代碼之後, 先對部分 yaml 文件進行修改, 然後再佈署到 Docker EE UCP 叢集環境內.
在 metrics-server 目錄下, 找到 deploy/1.8+/metrics-server-deployment.yaml
其中的 containers 定義的部分修改如下,

 # deploy/1.8+/metrics-server-deployment.yaml
      containers:
      - name: metrics-server
        image: gcr.io/google_containers/metrics-server-amd64:v0.3.1
        imagePullPolicy: Always
        command:
        - /metrics-server
        - "--kubelet-port=10250"
        - "--kubelet-preferred-address-types=InternalIP"
        - "--kubelet-insecure-tls"
        volumeMounts:
        - name: tmp-dir
          mountPath: /tmp

上述 yaml 片段中使用 "--kubelet-insecure-tls" 先跳過 Kubelet CA 憑證的檢查驗證. 在正式環境叢集, 有另外設定可信賴的 CA 憑證而非 self-signed , 那麼這個參數就可以不用加.

在 metrics-server 代碼目錄下, 通過 client bundle 進行下列功能佈署.

 # deploy k8s metrics server
# kubectl create -f deploy/1.8+/

檢查 metrics server 佈署情況

 # check if the metrics server is up and running
# kubectl -n kube-system logs -f metrics-server-XXXXXXXXXX-YYYYY

可以看到 logs 如下類似內容:

k8s metrics server available


如果佈署上去一開始看到的是其他 log 內容, 例如

unable to fully collect metrics

像是 "unable to fully collect metrics." ,那經常代表 metrics server 一開始佈署是有問題的.


順帶一提,如果有安裝 Kubernetes kubectl 的 bash completion, 輸入上述命令至一半的時候 ...
kubectl -n kube-system logs -f metric (<== 打字停在 metric,還沒輸入完 直接打 TAB 按鍵,它會自動補齊完整的名字)
Kubernetes kubectl 的 bash completion 跟 UCP client bundle 可以配合的很好。如果沒有安裝,也沒關係,就先輸入 kubectl -n kube-system get pods 也可看到 metrics-server 開頭的名字。


(另文說明 Bash Completion for Docker and Kubectl )

另外, metrics server 成功佈署上去後, 執行 kubectl top nodes
也可以看到 Docker UCP 叢集內所有節點的資源消耗狀態.


佈好了 metrics server, 接下來在平臺上進行測試,

 # Run php-apache to test HPA
# kubectl run php-apache --image=k8s.gcr.io/hpa-example --requests=cpu=200m --expose --port=80

service/php-apache created
deployment.apps/php-apache created

我們測試 HPA 用的 image 是 hpa-example 其 Dockerfile 如下:


FROM php:5-apache
ADD index.php /var/www/html/index.php
RUN chmod a+rx index.php

而 index.php 的內容如下

<?php
  $x = 0.0001;
  for ($i = 0; $i <= 1000000; $i++) {
    $x += sqrt($x);
  }
  echo "OK!";
?>

以上代碼做數學運算旨在消耗CPU大量資源利於進行 HPA 測試。

建立 HPA -- 以佈署的 php-apache 爲對象,當它在 Docker 主機上的 CPU loading 接近到臨界值 50% 的時候,就自動動態的調整其 replicas 個數。超過 50% 就增加,少於 50% 就減少。

 # Create HPA
# kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10

horizontalpodautoscaler.autoscaling/php-apache autoscaled

查看 HPA 狀態

 # Get HPA
# kubectl get hpa


kubectl get hpa



運行另一個 busybox image 這是爲了產生針對 PHP web server 測試的大量負載數據而設

 # create busybox container
# kubectl run -i --tty load-generator --image=busybox /bin/sh

執行上述命令後,再按下 ENTER , 會進入 busybox 的命令行提示畫面,輸入下列無窮迴圈的腳本內容,這段無窮迴圈會不斷發送請求數據包給 php-apache 以模擬增加負載量的效果

 # 
# while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done

看到的畫面類似如下


OK



在此同時, 打開另一個 terminal 畫面, 用一組的 Docker client bundle 下命令觀察 HPA

 # Get HPA
# kubectl get hpa
autoscaling 動態調整 replicas 的個數並非立即即時的,從偵測到 CPU loading 變化到自動作出調整需要一小段時間。

剛開始可能沒有變化


kubectl get hpa

過了幾分鐘後,


kubectl get hpa in the long run

等久一點


kubectl get hpa


kubectl get hpa

因 CPU loading 增加了, 可看到 replicas 的數量隨着時間在增加.

最終會 resize 到 10 replicas. 以上是通過觀察 CPU loading 的增加來確認實際應用程式 replicas 增加的 autoscaling 過程。


kubectl get deployments

同時間點, 若觀察一下 UCP dashboard 也可以看到變化. 下圖是關於 php-apache 的負載情況.


php-apache pods loading


要停止測試, 回到運行 busybox 的 terminal 環境下, 然後按下 CTRL+C 終止正在運行的無窮迴圈. CPU loading 會降下來, 過了一陣子後, php-apache 的 replicas 數量也會降下來. 最終會降到 1.

要刪除 metrics server 的佈署, 通過 client bundle 執行

 # deploy k8s metrics server
# kubectl delete -f deploy/1.8+/

以上範例只是設定 HPA 觀察 CPU 使用來做應用的自動水平擴展, 僅僅是觀察 CPU 使用率來判斷是否要做 scaling 在一般應用場合下條件是不夠的, 還需要設定其他條件來配合, 如果有興趣請參考下列 custom metrics API 的 URL.

請注意:Kubernetes 的 HPA (Horizontal Pod Autoscaler) 功能是在容器平台上應用程式 pods/containers 的水平擴展,不是指節點本身的擴展。兩者是不同的概念。

有了以上 K8S HPA 的佈署設定,我們之後可以在 Docker EE UCP 叢集上可以對微服務應用程式進行 autoscaling 配置。同時,有了這樣的基礎,日後可以做其他更進一步的應用,像是 CI/CD , continuous monitoring 等等。

(Photo by Arnold Lee on Unsplash)


[參考資料]

Horizontal Pod Autoscaler
https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/

Custom Metrics API
https://github.com/kubernetes/community/blob/master/contributors/design-proposals/instrumentation/custom-metrics-api.md

php-apache
https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/

留言

這個網誌中的熱門文章

Docker 環境下的 Proxy 配置