GKE 中配置 Pod 的垂直伸缩

原文:Configuring vertical pod autoscaling

在 GKE 1.11.3 中提供了 Pod 垂直伸缩功能的 Beta 版本。这一功能在未来可能会收取费用,没有提供 SLA 以及过期策略,也有可能发生不向后兼容的更改。

本文阐述如何在 GKE 中配置 Pod 的垂直伸缩,该功能包含对 Pod 的 CPU 和内存申请进行调整的能力。

概述

可以配置 VerticalPodAutoscaler CRD来对容器的CPU以及内存需求进行分析和调整。

开始之前

开始这一任务之前,首先要完成以下步骤:

  • 确认开启了 GKE API
  • 安装 Cloud SDK
  • 设置缺省的 Project ID

    gcloud config set project [PROJECT_ID]

  • 如果运行的是 zonal 集群,设置缺省的 compute zone

    gcloud config set compute/zone [COMPUTE_ZONE]

  • 如果运行的是 regional 集群,设置缺省的 compute region

    gcloud config set compute/region [COMPUTE_REGION]

  • 更新 gcloud 到最新版本:

    gcloud components update

为集群启用 Pod 的垂直自动伸缩功能

可以使用下面的命令创建包含 Pod 垂直自动伸缩功能的新集群:

gcloud beta container clusters create [CLUSTER_NAME] \
    --enable-vertical-pod-autoscaling

[CLUSTER_NAME] 就是该集群的名称。

如果要给现有集群启用 Pod 垂直自动伸缩功能,可以用下列命令:

cloud beta container clusters update [CLUSTER-NAME] \
    --enable-vertical-pod-autoscaling

[CLUSTER_NAME] 就是该集群的名称。

获取资源推荐

下面的练习中会创建一个 VerticalPodAutoscaler,其中的 updateMode 设置为 Off。接下来创建一个包含两个 Pod 的 Deployment,每个 Pod 包含一个容器。当 Pod 创建时,VerticalPodAutoscaler 会分析容器的 CPU 和内存需要,并将推荐设置保存在 status 字段中。VerticalPodAutoscaler 在这一过程中不会对运行中的容器采取任何更新资源需求的措施。

VerticalPodAutoscaler 的配置如下:

apiVersion: autoscaling.k8s.io/v1beta1
kind: VerticalPodAutoscaler
metadata:
  name: my-rec-vpa
spec:
  selector:
    matchLabels:
      purpose: try-recommend
  updatePolicy:
    updateMode: "Off"

将代码保存为 my-rec-vpa.yaml 并创建该资源:

kubectl create -f my-rec-vpa.yaml

Deployment 的代码如下:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-rec-deployment
  labels:
    purpose: try-recommend
spec:
  replicas: 2
  template:
    metadata:
      labels:
        purpose: try-recommend
    spec:
      containers:
      - name: my-rec-container
        image: nginx

上述代码中并未设置 CPU 和内存的请求数量。而 Deployment 中的 Pod,具有标签 purpose: try-recommend,符合 VerticalPodAutoscaler 的 selector 中定义的选择标准,因此是会受到管理的。

将上述代码命名为 my-rec-deployment.yaml,创建对象:

kubectl create -f my-rec-deployment.yaml

稍候片刻,查看 VirticalPodAutoscaler:

kubectl get vpa my-rec-vpa --output yaml

会显示 CPU 和内存资源的推荐设置:

...
  recommendation:
    containerRecommendations:
    - containerName: my-rec-container
      lowerBound:
        cpu: 25m
        memory: 262144k
      target:
        cpu: 25m
        memory: 262144k
      upperBound:
        cpu: 7931m
        memory: 8291500k
...

现在看到了推荐的 CPU 和内存请求了,可以选择删除 Deployment,加入 CPU 和内存请求的相关内容,并重新启动。

自动更新资源

接下来的练习会创建一个 Deployment ,其中包含两个 Pod,每个 Pod 包含一个容器,容器请求 100m 的 CPU 以及 50M 的内存。然后创建一个 VerticalPodAutoscaler 对象,自动对 CPU 和内存的请求进行修正。

下面是该 Deployment 的代码:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-deployment
  labels:
    purpose: try-auto-requests
spec:
  replicas: 2
  template:
    metadata:
      labels:
        purpose: try-auto-requests
    spec:
      containers:
      - name: my-container
        image: k8s.gcr.io/ubuntu-slim:0.1
        resources:
          requests:
            cpu: 100m
            memory: 50Mi
        command: ["/bin/sh"]
        args: ["-c", "while true; do timeout 0.5s yes >/dev/null; sleep 0.5s; done"]

把上述代码保存为文件 my-deployment.yaml,并创建对象:

kubectl create -f my-deployment.yaml

列出运行中的 Pod:

kubectl get pods

输出内容中包含了 my-deployment 中的 Pod:

NAME                            READY     STATUS             RESTARTS   AGE
my-deployment-cbcdd49fb-d6bf9   1/1       Running            0          8s
my-deployment-cbcdd49fb-th288   1/1       Running            0          8s

为了后续方便,记录下 Pod 名称。

这个 Deployment 申请的 CPU 和内存非常小,所以可能提供更多资源会给这一 Deployment 带来更好的效果。

下面代码用于创建一个 VerticalPodAutoscaler

apiVersion: autoscaling.k8s.io/v1beta1
kind: VerticalPodAutoscaler
metadata:
  name: my-vpa
spec:
  selector:
    matchLabels:
      purpose: try-auto-requests
  updatePolicy:
    updateMode: "Auto"

这段代码中的 selector 字段中声明,所有带有标签 purpose: try-auto-requests 的 Pod 都会受其影响。

updateMode 字段取值为 Auto,代表 VerticalPodAutoscaler 会更新 Pod 的 CPU 和内存请求,也就是说 VerticalPodAutoscaler 会删除 Pod、调整 CPU 和内存申请,然后启动一个新 Pod。

把代码保存为 my-vpa.yaml,并创建该资源:

kubectl create -f my-vpa.yaml

几分钟之后,再次查看 Pod:

kubectl get pods

会看到 Pod 名称已经发生了变化,如果没有,请隔一段时间再次查看。

获取一个新 Pod 的信息:

kubectl get pod [POD_NAME] --output yaml

输出内容中,会看到 VerticalPodAutoscaler 提高了内存和 CPU 的设置。还会看到注解中也发生了更新:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    vpaUpdates: 'Pod resources updated by my-vpa: container 0: cpu capped to node
      capacity, memory capped to node capacity, cpu request, memory request'
...
spec:
  containers:
  ...
    resources:
      requests:
        cpu: 510m
        memory: 262144k
    ...

查看一下 VerticalPodAutoscaler 的详情:

kubectl get vpa my-vpa --output yaml

输出内容中显示了三组对 CPU 和内存申请的建议:lowerBoundtargetupperBound

...
  recommendation:
    containerRecommendations:
    - containerName: my-container
      lowerBound:
        cpu: 536m
        memory: 262144k
      target:
        cpu: 587m
        memory: 262144k
      upperBound:
        cpu: 27854m
        memory: "545693548"

target 的含义是,该容器使用 587m 的 CPU 和 262144 KB 的内存会获得更好的运行效果。

VerticalPodAutoscaler 会使用 lowerBoundupperBound 来决定是否重新创建 Pod,如果一个 Pod 申请的资源少于 lowerBound 或者大于 upperBound,就会被 VerticalPodAutoscaler 删除并使用 target 推荐的规格进行重建。

Selector 不可重叠

VerticalPodAutoscaler 包含了一个 selector 字段,用来决定该对象的影响范围。如果创建了不止一个的 VerticalPodAutoscaler,要保证其 selector 不能发生重叠。

例如下面的两个 VerticalPodAutoscaler:

...
kind: VerticalPodAutoscaler
metadata:
  name: my-vpa-1
spec:
  selector:
    matchLabels:
      app: metrics
      department: engineering
...
...
...
kind: VerticalPodAutoscaler
metadata:
  name: my-vpa-2
spec:
  selector:
    matchLabels:
      department: engineering
...

带有 app: metricsdepartment: engineering 标签的 Pod 会被两个对象同时管理,会引发问题。

comments powered by Disqus