Pod 垂直自动伸缩的使用

微信扫一扫,分享到朋友圈

Pod 垂直自动伸缩的使用

VPA(Pod 垂直自动伸缩)是 Kubernetes 中非常棒的一个功能,但是平时使用却并不多。这是因为在最初 Kubernetes 就是为水平扩展而构建的,垂直扩展一个 Pod 貌似不是一个好的方式,如果你想处理更多的负载,新增一个 Pod 副本可能更好。

但是这需要大量的资源优化,如果你没有适当地调整你的 Pod,通过提供适当的资源请求和限制配置,可能最终会很频繁地驱逐你的 Pod,或者浪费很多有用的资源。开发人员和系统管理员通过对资源的各种监控,以及通过基准测试或通过对资源利用率和流量的监控,来调整这些 Pod 的资源请求和限制的最佳值。

当流量不稳定、资源利用率不理想的时候,可能就相对复杂一些了,随着容器在微服务架构中的不断发展,系统管理员更注重稳定性,这样就导致最后使用的资源请求往往会远远超过实际的需求。

Kubernetes 提供了一个解决方案来解决这个问题,那就是 VPA
(Vertical Pod Autoscaler),接下来我们来了解下 VPA 的作用,以及什么时候应该使用它。

VPA 如何工作

VPA 主要使用两个组件来实现自动伸缩,实现原理如下所示:

  • VPA 推荐器检查历史资源利用率和当前使用的模式,并推荐一个理想的资源请求值

  • 如果你将更新模式定义为自动,VPA 自动调整器将驱逐正在运行的 Pod,并根据新的资源请求值创建一个新的 Pod

  • VPA 自动调整器还将按照最初定义的限制值的比例来调整限制值。

实际上资源限制并没有什么意义,因为调整器会不断调整它,不过,如果你想要避免内存泄露,可以在 VPA 中设置最大的资源值。

VPA 资源清单

我们先来看一个 VPA 的资源清单文件长什么样子,如下所示:

# vpa-example.yaml
apiVersion: autoscaling.k8s.io/v1beta2
kind: VerticalPodAutoscaler
metadata:
name: nginx-vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: nginx
updatePolicy:
updateMode: "On"
resourcePolicy:
containerPolicies:
- containerName: "nginx"
minAllowed:
cpu: "250m"
memory: "100Mi"
maxAllowed:
cpu: "2000m"
memory: "2048Mi"
- containerName: "istio-proxy"
mode: "Off"

和其他资源清单文件一样,VPA 一样有 apiVersion、kind、metadata、spec 这些属性,在 spec 规范部分,我们看到有一个 targetRef
的属性,它指定这个 VPA 对象所应用的资源对象, updatePolicy
定义了这个 VPA 是否会根据 updateMode
属性进行推荐或自动缩放。如果 updateMode 属性设置为 Auto,则 Pod 会自动垂直缩放,如果设置为 Off,则只是推荐理想的资源请求值。 resourcePolicy
属性运行我们为每个容器指定容器策略,并给出 minAllowed
maxAllowed
资源值,这一点极为重要,可以避免自动的内存泄露。你还可以在一个 Pod 中的指定容器上关闭资源推荐和自动缩放,通常在 Istio sidecar 或 initContainer 中设置。

局限性

VPA 是有限制的。

不能和 HPA 一起使用

由于 VPA 会自动修改请求和限制值,所以不能将其与 HPA 一起使用,因为 HPA 依靠 CPU 和内存利用率来进行水平伸缩。有一个例外的情况是,当你 HPA 依靠自定义和外部指标来进行伸缩的时候。

需要至少两个健康的 Pod 才能工作

这种违背了它的初衷,也是没有被广泛使用的原因之一。由于 VPA 会破坏一个 Pod,并重新创建一个 Pod 来进行垂直自动伸缩,因此它需要至少两个监控的 Pod 副本来确保不会出现服务中断。这在单实例有状态应用上造成了不必要的复杂,你不得不考虑副本的设计。对于无状态应用来说,你又可以更好地使用 HPA 而不是 VPA 了,所以是不是很尴尬:sweat:?

默认最小内存分配为250MiB

无论指定了什么配置,VPA 都会分配250MiB的最小内存,虽然这个默认值可以在全局层面进行修改,但对于消耗较少内存的应用程序来说,是比较浪费资源的。

不能用于单个 Pod

VPA 只适用于 Deployments、StatefulSets、DaemonSets、ReplicaSets 等控制器,你不能将它直接用于独立的 Pod,当然这个也还好,因为我们基本上也不使用独立的 Pod,而是会使用上层的控制器来管理 Pod。

在推荐模式下使用 VPA

目前 VPA 在生产中的最佳方式是在推荐模式下使用,这有助于我们了解最佳的资源请求值是多少,以及随着时间推移它们是如何变化的。

一旦配置了,我们就可以通过获取这些 metrics 指标,并将其发送到监控工具中去,比如 Prometheus 和 Grafana 或者 ELK 技术栈。然后可以利用这些数据来调整 Pods 的大小。

当然现在并不建议在生产中用自动模式来运行 VPA,因为该特性还比较新。我们可以在开发环境中进行实验,看看在负载不断增加的情况下是如何表现的,我们可以很容易地通过运行负载测试找到 Pod 可以消耗的最大资源量,这也是我们获取 Pod 资源限制值的一种很好的方式。

测试

首先请确保已经在 Kubernetes 集群中启用了 VPA。首先,创建一个NGINX Deployment,默认请求为250MiB 内存和100m 的 CPU。

$ cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
strategy: {}
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
resources:
requests:
cpu: 100m
memory: 250Mi
EOF

现在我们将该应用通过 LoadBalancer 服务(如果不支持可以使用 NodePort)来对外进行暴露:

$ kubectl expose deployment nginx --type=LoadBalancer --port 80

暴露后云服务商会提供一个负载均衡器,然后可以获得这个负载均衡器的 IP。

$ kubectl get svc nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx LoadBalancer 10.4.1.4 34.121.204.234 80:30750/TCP 46s

现在,让我们创建一个 VPA 资源对象,其中 updateMode 模式设置为 “Off”,这并不会进行垂直扩展,只是提供一些建议。

# vpa-off.ayml
$ cat <<EOF | kubectl apply -f -
apiVersion: autoscaling.k8s.io/v1beta2
kind: VerticalPodAutoscaler
metadata:
name: nginx-vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: nginx
updatePolicy:
updateMode: "Off"
resourcePolicy:
containerPolicies:
- containerName: "nginx"
minAllowed:
cpu: "250m"
memory: "100Mi"
maxAllowed:
cpu: "2000m"
memory: "2048Mi"
EOF

接下来我们使用 hey
这个工具来进行一些负载测试,看看会得到什么样的结果。

$ hey -z 300s -c 1000 http://34.121.204.234

该命令使用1000个线程发出300秒的请求。我们可以运行下面的命令来获取 VPA 的相关信息:

$ kubectl describe vpa nginx-vpa

如果观察一段时间,我们会发现 VPA 会逐渐增加推荐的资源请求。

如果你看 Recommendation 推荐部分,可以看到如下所示的一些信息:

  • Target:这是 VPA 在驱逐当前 Pod 并创建另一个 Pod 时将使用的真实值。

  • Lower Bound:这反映了触发调整大小的下限,如果你的 Pod 利用率低于这些值,则 VPA 会将其逐出并缩小其规模。

  • Upper Bound:这表示下一次要触发调整大小的上限。如果你的 Pod 利用率高于这些值,则 VPA 会将其驱逐并扩大其规模。

  • Uncapped target:如果你没有为 VPA 提供最小或最大边界值,则表示目标利用率。

现在我们如果把 updateMode 设置成 Auto 会发生什么呢?执行下面的程序来测试下。

# vpa-auto.yaml
$ cat <<EOF | kubectl apply -f -
apiVersion: autoscaling.k8s.io/v1beta2
kind: VerticalPodAutoscaler
metadata:
name: nginx-vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: nginx
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: "nginx"
minAllowed:
cpu: "250m"
memory: "100Mi"
maxAllowed:
cpu: "2000m"
memory: "2048Mi"
EOF

然后让我们重新运行负载测试,在另一个终端中,我们将持续观察 Pod,看它们被驱逐和重新创建的过程。

总结

VPA 是 Kubernetes 一个比较新的自动更新概念,比较适用于有状态应用,或者了解资源利用情况的应用。但是在目前的情况下,不建议在生产中使用它的自动更新模式,但它的推荐模式有利于我们观察资源的使用情况。

原文链接:https://medium.com/better-programming/understanding-vertical-pod-autoscaling-in-kubernetes-6d53e6d96ef3

K8S进阶训练营,点击下方图片了解详情


微信扫一扫,分享到朋友圈

Pod 垂直自动伸缩的使用

小心P2P网贷“假清退” 投资者需做“两手准备”

上一篇

全国电子社保卡签发已突破2亿张 推多项服务功能

下一篇

你也可能喜欢

Pod 垂直自动伸缩的使用

长按储存图像,分享给朋友