kubernetes HPA


Kubernetes彈性伸縮簡介

通過手工執行kubectl scale命令或者通過修改deployment的replicas數量,可以實現Pod擴縮容。我們還可以通過定時任務的方式在一些可預見的業務高峰場景實現Pod的定時伸縮。然而在更多的應用場景當中,業務的請求量峰值其實是不可控的。這就需要我們借助一些自動伸縮的手段,例如通過監控Pod的資源使用率、訪問的QPS等指標來實現自動的彈性伸縮。

Kubernetes從兩個維度上支持自動的彈性伸縮:

  • Cluster AutoScaler:處理kubernetes集群node節點的伸縮,其嚴重依賴IaaS廠商提供的雲主機服務和資源監控服務
  • HPA(Horizontal Pod Autoscaler):處理Pod副本集的自動彈性伸縮,其依賴監控服務采集到的資源監控指標數據

HPA簡介

HPA本質上也是Kubernetes的一種資源對象。通過周期性檢查Deployment控制的目標Pod 的相關監控指標的變化情況,來確定是否需要針對性地調整目標Pod的副本數。

通常應用的擴縮容都是由cpu或內存的使用率實現的。事實上在早期的kubernetes版本當中,hpa只支持基於cpu使用的率的擴縮容,而hpa獲取到的cpu使用率指標則來源於kubernetes自帶的監控系統heapster。

而從kubernetes 1.8版本開始,資源的使用指標改為通過metrics api獲取。而heapster當前已經廢棄。

kubernetes-hpa

Kubernetes將資源指標分為了兩種:

  • core metrics(核心指標): 采集每個節點上的kubelet公開的summary api中的指標信息,通常只包含cpu、內存使用率信息
  • custom metrics(自定義指標):允許用戶從外部的監控系統當中采集自定義指標,如應用的qps等

在autoscaling/v1版本中只支持CPUUtilizationPercentage一種指標,在autoscaling/v2beta1中增加支持custom metrics

下面以cpu使用率指標來說明hpa是如何來根據指標使用伸縮的:

CPUUtilizationPercentage即cpu使用率的百分比。hpa判斷的標准是目標Pod所有副本自身的CPU利用率的平均值。一個Pod自身的CPU利用率是該Pod當前的CPU的使用量除以它的CPU Request的值。

比如定義一個Pod的CPU Request為0.4,而當前的Pod的CPU使用量為0.2,則它的CPU使用率為 50%,這樣計算一個Deployment的所有Pod的cpu使用率的平均值。如果某一刻該值超過80%,則意味着當前的Pod 副本數很可能不足以支撐接來下更多的請求,需要進行動態擴容,而當前請求高峰時段過去后,Pod的 CPU 利用率又會降下來,此時對應的Pod副本數應該自動減少到一個合理的水平。

CPUUtilizationPercentage計算過程中使用到的Pod的CPU使用量通常是1min內的平均值。

Metrics Server

前面我們說到,核心指標的采集是通過metrics api獲取,而Metrics Server實現了Resurce Metrics API。Metrics Server 是集群范圍資源使用數據的聚合器。由Metrics Server從每個節點上的Kubelet公開的Summary API 中采集指標信息。也就是說,如果需要使用kubernetes的HPA功能,需要先安裝Metrics Server。

1. 生成metrics-server證書

創建metrics-server-csr.json文件,內容如下:

{
  "CN": "aggregator",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "Hubei",
      "L": "Wuhan",
      "O": "k8s",
      "OU": "System"
    }
  ]
}

生成metrics-server證書和密鑰

cfssl gencert --ca ca.pem --ca-key ca-key.pem --config ca-config.json --profile kubernetes metrics-server-csr.json | cfssljson --bare metrics-server

關於生成證書指令中,使用的ca.pem ca-key.pem以及ca-config.json,可參考《手動部署一個單節點kubernetes》

2. 修改kubernetes master 配置文件

在kube-apiserver的啟動指令中添加如下參數:

kube-apiserver
  ...
  --requestheader-client-ca-file=/etc/kubernetes/ssl/ca.pem \
  --requestheader-allowed-names=aggregator \
  --requestheader-extra-headers-prefix=X-Remote-Extra- \
  --requestheader-group-headers=X-Remote-Group \
  --requestheader-username-headers=X-Remote-User \
  --proxy-client-cert-file=/etc/kubernetes/ssl/metrics-server.pem \
  --proxy-client-key-file=/etc/kubernetes/ssl/metrics-server-key.pem \

在kube-controller-manager的啟動指令中添加如下參數:

kube-controller-manager
  ...
  --horizontal-pod-autoscaler-use-rest-clients=true \
  --horizontal-pod-autoscaler-downscale-delay=5m0s \
  --horizontal-pod-autoscaler-upscale-delay=1m0s \
  --horizontal-pod-autoscaler-sync-period=20s \
  ...

配置項說明:

  • horizontal-pod-autoscaler-use-rest-clients: 開啟基於rest-clients的自動伸縮
  • horizontal-pod-autoscaler-sync-period:自動伸縮的檢測周期為20s,默認為30s
  • horizontal-pod-autoscaler-upscale-delay:當檢測到滿足擴容條件時,延遲多久開始縮容,即該滿足的條件持續多久開始擴容,默認為3分鍾
  • horizontal-pod-autoscaler-downscale-delay:當檢測到滿足縮容條件時,延遲多久開始縮容,即該滿足條件持續多久開始縮容,默認為5分鍾

3. 安裝metrics-server

metrics-server代碼倉庫地址: https://github.com/kubernetes-incubator/metrics-server

當前最新的release版本為v0.3.6,下載最新版本。然后執行如下操作:

cd deploy/1.8+/

# 修改鏡像地址
sed -i 's@k8s.gcr.io/metrics-server-amd64:v0.3.6@gcr.azk8s.cn/google_containers/metrics-server-amd64:v0.3.6@g' metrics-server-deployment.yaml

# 配置command

編輯metrics-server-deployment.yaml,配置如下內容:
...
      containers:
      - name: metrics-server
        image: hub.breezey.top/library/metrics-server-amd64:v0.3.6
        command:
        - /metrics-server
        - --kubelet-insecure-tls
        - --kubelet-preferred-address-types=InternalIP
        imagePullPolicy: Always
...
kubectl apply -f ./

以上操作會在kube-system命名空間啟動一個名稱前綴為metrics-server的pods以提供實時的數據采集。

在metrics-server-deployment.yaml中添加了一個command,加了兩個kubelet的配置項,如果不添加此項,metrics-server無法采集數據指標,會拋出異常:
x509: certificate signed by unknown authority, unable to fully scrape metrics from source kubelet_summary

驗證安裝:

# 在apiservice中可以看到多了一個接口
kubectl get apiservice
...
v1beta1.metrics.k8s.io                  2019-10-17T03:14:46Z
...

# 通過訪問metrics.k8s.io接口,如能正常訪問代表安裝成功

kubectl get --raw "/apis/metrics.k8s.io/v1beta1" | jq .        
{
  "kind": "APIResourceList",
  "apiVersion": "v1",
  "groupVersion": "metrics.k8s.io/v1beta1",
  "resources": [
    {
      "name": "nodes",
      "singularName": "",
      "namespaced": false,
      "kind": "NodeMetrics",
      "verbs": [
        "get",
        "list"
      ]
    },
    {
      "name": "pods",
      "singularName": "",
      "namespaced": true,
      "kind": "PodMetrics",
      "verbs": [
        "get",
        "list"
      ]
    }
  ]
}

還可以通過如下接口獲取相應的監控指標:

kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes" | jq .
...
    {
      "metadata": {
        "name": "cn-beijing.i-2zeacc5qws1k6yr96yf6",
        "selfLink": "/apis/metrics.k8s.io/v1beta1/nodes/cn-beijing.i-2zeacc5qws1k6yr96yf6",
        "creationTimestamp": "2019-10-21T07:46:44Z"
      },
      "timestamp": "2019-10-21T07:46:00Z",
      "window": "1m0s",
      "usage": {
        "cpu": "3254m",
        "memory": "47416324Ki"
      }
    }
...


kubectl get --raw "/apis/metrics.k8s.io/v1beta1/pods" | jq .
...
    {
      "metadata": {
        "name": "arrow-feature-userprofile-975-6cb874c85f-h2gfx",
        "namespace": "bigdata",
        "selfLink": "/apis/metrics.k8s.io/v1beta1/namespaces/bigdata/pods/arrow-feature-userprofile-975-6cb874c85f-h2gfx",
        "creationTimestamp": "2019-10-21T07:48:25Z"
      },
      "timestamp": "2019-10-21T07:48:00Z",
      "window": "1m0s",
      "containers": [
        {
          "name": "arrow-feature-userprofile",
          "usage": {
            "cpu": "125m",
            "memory": "2560436Ki"
          }
        }
      ]
    }
...

確保這里可以正常獲取指標,否則檢查metrics-server日志,看是否拋出了相關異常

HPA配置示例

在github上有一個開源項目,叫作k8s-prom-hpa,項目地址為:https://github.com/stefanprodan/k8s-prom-hpa。

在下一節《kubernetes HPA使用自定義指標》中,我們會說到這個項目。現在在這個項目中,有一個目錄名為podinfo。這是一個golang小程序示例。

我們獲取這個demo,並部署:

# 修改podinfo的版本為2.0.0版本
sed -i 's/0.0.1/2.0.0' podinfo/pidinfo-dep.yaml

# 修改podinfo-dep.yaml文件,去掉如下command部分:
...
        #command:
        #  - ./podinfo
        #  - -port=9898
        #  - -logtostderr=true
        #  - -v=2
...


kubectl apply -f podinfo/podinfo-dep.yaml,podinfo/podinfo-svc.yaml,podinfo/podinfo-ingress.yaml

通過其ingress配置文件,可以看到其對外暴露host名稱為podinfo.weavedx.com,我們可以通過綁定主機名的方式來訪問該應用。

在我的測試環境中,因為使用的ingress是traefik,而不是官方的nginx,所以我還需要修改kubernetes.io/ingress.class這個annotations為traefik

接下來,為該demo應用添加一個hpa,內容如下:

apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: podinfo
spec:
  scaleTargetRef:
    apiVersion: extensions/v1beta1
    kind: Deployment
    name: podinfo
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      targetAverageUtilization: 80
  - type: Resource
    resource:
      name: memory
      targetAverageValue: 200Mi

當podinfo的所有副本的cpu使用率的值超過request限制的80%或者memory的使用率超過200Mi時會觸發自動動態擴容行為,擴容或縮容時必須滿足一個約束條件是Pod的副本數要介於2與10之間。

執行壓力測試:

# install hey
go get -u github.com/rakyll/hey

./go/bin/hey -n 10000 -q 10 -c 5 http://podinfo.weavedx.com

查看hpa相關事件確認擴縮容:

kubectl describe hpa podinfo
...
Events:
  Type     Reason                        Age                 From                       Message
  ----     ------                        ----                ----                       -------
  Normal   SuccessfulRescale             2m                  horizontal-pod-autoscaler  New size: 4; reason: cpu resource utilization (percentage of request) above target
  Normal   SuccessfulRescale             16s                 horizontal-pod-autoscaler  New size: 8; reason: cpu resource utilization (percentage of request) above target

  
kubectl get pods |grep podinfo
#輸出:
podinfo-7b46d7c547-284x8                                   1/1       Running   0          31s
podinfo-7b46d7c547-4gkcr                                   1/1       Running   0          23m
podinfo-7b46d7c547-6jnqk                                   1/1       Running   0          31s
podinfo-7b46d7c547-8xt7p                                   1/1       Running   0          31s
podinfo-7b46d7c547-d6fp7                                   1/1       Running   0          2m
podinfo-7b46d7c547-nwwrj                                   1/1       Running   0          31s
podinfo-7b46d7c547-pj5cs                                   1/1       Running   0          23m
podinfo-7b46d7c547-s5vzn                                   1/1       Running   0          2m


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM