Kubernetes Pods和节点自动伸缩指南
在Kubernetes集群中,Pod的调度有时会遇到问题。例如,有如下Pod状态信息:
nginx-deployment-example-59b669d85f-vdn87 1/1 Running 0 52s
nginx-deployment-example-69bd6d55b4-n2mzq 0/1 Pending 0 3s
nginx-deployment-example-69bd6d55b4-qb62p 0/1 Pending 0 3s
nginx-deployment-example-69bd6d55b4-w7xng 0/1 Pending 0 3s
通过以下命令描述处于Pending状态的Pod来进行调查:
$ kubectl describe pod nginx-deployment-example-69bd6d55b4-n2mzq
输出的事件信息显示:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 23m (x21 over 121m) default-scheduler 0/3 nodes
are available: 1 node(s) had untolerated taint {machine-check-exception:
memory}, 2 Insufficient cpu. preemption: 0/3 nodes are available: 1 Preemption
is not helpful for scheduling, 2 No preemption victims found for incoming pod.
这表明没有节点能够容纳需要2000m KCU的容器,因此Pod此时无法调度。接下来,我们将探讨Pod的自动伸缩,首先是垂直自动伸缩。
使用VerticalPodAutoscaler进行Pod垂直自动伸缩
手动管理计算资源的请求和限制值时,需要准确的预估、观察指标并进行基准测试来调整。请求值设置过高会导致计算资源浪费,设置过低则可能使Pod过于密集,导致性能问题。在某些情况下,通过增加Pod可消耗的计算资源进行垂直扩展是扩展Pod工作负载的唯一方法。
为了解决这些问题,可以使用VerticalPodAutoscaler(VPA),它可以动态增加和减少Pod容器的CPU和内存资源请求。VPA的目标是更好地匹配容器的实际使用情况,而不是依赖硬编码的预定义资源请求和限制值。
VPA由名为VerticalPodAutoscaler的自定义资源定义(CRD)对象创建,它不是标准Kubernetes API组的一部分,必须安装在集群中。VPA是Kubernetes生态系统中自动伸缩器项目(https://github.com/kubernetes/autoscaler)的一部分。
VPA有三个主要组件:
| 组件 | 功能 |
| ---- | ---- |
| Recommender | 监控当前和过去的资源消耗,并为Pod容器提供推荐的CPU和内存请求值。 |
| Updater | 检查资源不正确的Pod并删除它们,以便使用更新后的请求和限制值重新创建Pod。 |
| Admission plugin | 为新创建或由其控制器重新创建的Pod设置正确的资源请求和限制。 |
由于Kubernetes不支持动态更改资源请求和限制,因此Updater需要终止Pod,VPA需要依赖Admission插件。
一些Kubernetes产品提供一键或操作员支持来安装VPA,例如OpenShift和GKE。
启用InPlacePodVerticalScaling
Kubernetes 1.27中引入的In-place pod resizing是一个alpha特性,它允许在不重启的情况下动态调整Pod资源,可能会提高应用程序性能和资源效率。
要激活此功能,必须在所有集群节点上启用InPlacePodVerticalScaling功能门。
-
Kubernetes集群
:
1. 更新
/etc/kubernetes/manifests/kube-apiserver.yaml
(或您的Kubernetes集群的适当配置)。
2. 添加如下feature-gates:
# /etc/kubernetes/manifests/kube-apiserver.yaml
...
- command:
- kube-apiserver
...<removed for brevity>...
- --feature-gates=InPlacePodVerticalScaling=true
- minikube环境 :在集群启动期间加入功能门:
$ minikube start --feature-gates=InPlacePodVerticalScaling=true
在GKE中启用VPA
在Google Kubernetes Engine(GKE)中启用VPA非常简单,只需运行以下命令:
$ gcloud container clusters update <cluster-name> --enable-vertical-pod-autoscaling
此操作会导致Kubernetes控制平面重启。如果要为新集群启用VPA,可以使用额外的参数
--enable-vertical-pod-autoscaling
:
$ gcloud container clusters create k8sforbeginners --num-nodes=2 --zone=us-central1-a --enable-vertical-pod-autoscaling
在其他Kubernetes集群中启用VPA
对于不同的平台,如AKS或EKS(甚至是用于测试的本地部署),需要手动安装VPA,通过向集群添加VPA CRD。具体步骤可参考:https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler#installation。
安装步骤如下:
1. 克隆Kubernetes自动伸缩器仓库:
$ git clone https://github.com/kubernetes/autoscaler
- 导航到VPA组件目录:
$ cd autoscaler/vertical-pod-autoscaler
- 开始安装:
$ ./hack/vpa-up.sh
- 验证主要组件Pod是否正确启动:
$ kubectl get pods -n kube-system | grep vpa
vpa-admission-controller-5b64b4f4c4-vsn9j 1/1 Running 0 5m34s
vpa-recommender-54c76554b5-m7wnk 1/1 Running 0 5m34s
vpa-updater-7d5f6fbf9b-rkwlb 1/1 Running 0 5m34s
使用VPA
为了演示,我们需要一个能实际消耗CPU的Deployment。Kubernetes自动伸缩器仓库有一个简单且CPU使用可预测的示例:https://github.com/kubernetes/autoscaler/blob/master/vertical-pod-autoscaler/examples/hamster.yaml。我们将对这个示例进行一些修改并逐步演示。
准备Deployment
- 为Kubernetes集群启用指标服务器。如果使用minikube集群,可通过以下命令启用:
$ minikube addons enable metrics-server
- 创建一个新的命名空间:
# vpa/vpa-demo-ns.yaml
---
apiVersion: v1
kind: Namespace
metadata:
labels:
project: vpa-demo
name: vpa-demo
使用以下命令创建命名空间:
$ kubectl apply -f vpa/vpa-demo-ns.yaml
-
创建
hamster-deployment.yamlYAML清单文件:
# vpa/hamster-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hamster
namespace: vpa-demo
spec:
selector:
matchLabels:
app: hamster
replicas: 5
template:
metadata:
labels:
app: hamster
spec:
containers:
- name: hamster
image: ubuntu:20.04
resources:
requests:
cpu: 100m
memory: 50Mi
command:
- /bin/sh
- -c
- while true; do timeout 0.5s yes >/dev/null; sleep 0.5s; done
此Pod中的ubuntu容器会重复消耗最大可用CPU 0.5秒,然后空闲0.5秒,实际CPU使用量平均约为500m KCU,但资源请求值仅为100m KCU,这可能导致Kubernetes调度器做出错误的调度决策。
4. 应用清单到集群:
$ kubectl apply -f vpa/hamster-deployment.yaml
-
检查
vpa-demo命名空间中的Pod:
$ kubectl get po -n vpa-demo
- 验证Pod的CPU使用情况:
$ kubectl top pod -n vpa-demo
创建VPA
VPAs可以通过
.spec.updatePolicy.updateMode
字段指定四种操作模式:
| 模式 | 说明 |
| ---- | ---- |
| Recreate | Pod容器的限制和请求在Pod创建时分配,并根据计算的建议动态更新。要更新值,必须重启Pod,这可能会对应用程序造成干扰。 |
| Auto | 当前等同于Recreate,但当支持Pod容器请求和限制的原地更新时,它可以自动切换到新的更新机制。 |
| Initial | Pod容器的限制和请求值仅在Pod创建时分配。 |
| Off | VPA以仅推荐模式运行,可以在VPA对象中检查推荐值。 |
我们先为
hamster
Deployment创建一个以
Off
模式运行的VPA,然后再启用
Auto
模式。
1. 创建
vpa/hamster-vpa.yaml
YAML清单:
# vpa/hamster-vpa.yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: hamster-vpa
namespace: vpa-demo
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: hamster
updatePolicy:
updateMode: 'Off'
resourcePolicy:
containerPolicies:
- containerName: '*'
minAllowed:
cpu: 100m
memory: 50Mi
maxAllowed:
cpu: 1
memory: 500Mi
controlledResources:
- cpu
- memory
- 应用清单文件到集群:
$ kubectl apply -f vpa/hamster-vpa.yaml
- 等待一段时间,让VPA计算出推荐值,然后通过描述VPA来查看推荐值:
$ kubectl describe vpa hamster-vpa -n vpa-demo
推荐值显示应分配比预期的500m KCU略多的CPU和262144k的内存,这为CPU消耗提供了安全缓冲。
4. 将VPA模式改为
Auto
,修改
vpa/hamster-vpa.yaml
:
# vpa/hamster-vpa.yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: hamster-vpa
namespace: vpa-demo
spec:
...
updatePolicy:
updateMode: Auto
...
- 应用修改后的清单到集群:
$ kubectl apply -f vpa/hamster-vpa.yaml
- 一段时间后,会发现Deployment的Pod被VPA重启:
$ kubectl get po -n vpa-demo -w
- 检查重启后的Pod的资源请求:
$ kubectl describe pod hamster-7fb7dbff7-24p89 -n vpa-demo
可以看到,新启动的Pod的CPU和内存请求已设置为VPA推荐的值。
接下来,我们将讨论如何使用HorizontalPodAutoscaler进行Pod的水平自动伸缩。
使用HorizontalPodAutoscaler进行Pod水平自动伸缩
虽然VPA可以优化资源使用,但要真正扩展运行多个Pod副本的Deployment和StatefulSet,需要使用HorizontalPodAutoscaler(HPA)。HPA的目标是根据当前CPU利用率或其他自定义指标(包括同时使用多个指标)自动调整Deployment或StatefulSet中的副本数量。VPA目前不应与基于CPU/内存指标运行的HPA一起使用,但可以与基于自定义指标运行的HPA结合使用。
下面的流程图展示了垂直和水平伸缩的区别:
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A(垂直伸缩):::process --> B(增加单个Pod资源):::process
C(水平伸缩):::process --> D(增加Pod副本数量):::process
HPAs具有高度可配置性,这里我们将介绍基于目标CPU使用率进行自动伸缩的标准场景。HPA的作用是监控Pod的配置指标(如CPU使用率),并确定是否需要更改副本数量。通常,HPA会计算所有Pod当前指标值的平均值,并判断添加或删除副本是否能使指标值更接近指定的目标值。例如,将目标CPU使用率设置为50%,当应用程序需求增加导致Deployment Pod的CPU使用率达到80%时,HPA会决定添加更多Pod副本,使所有副本的平均使用率接近50%。
HPA是Kubernetes自动伸缩API组中的API资源,当前稳定版本是autoscaling/v2,支持基于内存和自定义指标进行伸缩。使用autoscaling/v1时,autoscaling/v2中引入的新字段会保留为注解。HPA还使用稳定窗口等机制来防止副本过快缩减和不必要的副本抖动。
由于HPA是Kubernetes的内置功能,无需额外安装。我们只需准备一个用于测试的Deployment并创建HorizontalPodAutoscaler Kubernetes资源。
部署用于HPA演示的应用
为了测试HPA,我们将使用标准的CPU使用率指标,因此需要在Deployment Pod上配置CPU请求。同时,我们需要一个能消耗可预测CPU资源的Deployment。
首先,为Kubernetes集群启用指标服务器。如果使用minikube集群,可通过以下命令启用:
$ minikube addons enable metrics-server
GKE具有多维Pod自动伸缩的beta功能,可同时基于CPU指标进行水平伸缩和基于内存使用进行垂直伸缩。
以下是实现HPA的具体步骤:
1.
创建新的命名空间
:
# hpa/hpa-demo-ns.yaml
---
apiVersion: v1
kind: Namespace
metadata:
labels:
project: hpa-demo
name: hpa-demo
使用以下命令创建命名空间:
$ kubectl apply -f hpa/hpa-demo-ns.yaml
- 创建Deployment :
# hpa/todo-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: todo-app
namespace: hpa-demo
spec:
replicas: 1 # 可根据需要调整
selector:
matchLabels:
app: todo
template:
metadata:
labels:
app: todo
spec:
containers:
- name: todoapp
image: quay.io/ginigangadharan/todo-app:2.0
ports:
- containerPort: 3000
resources:
requests:
memory: "50Mi" # 请求50 MiB的内存
cpu: "50m" # 请求0.05 CPU核心
limits:
memory: "100Mi" # 请求100 MiB的内存
cpu: "100m" # 请求0.1 CPU核心
应用配置并确保Pod按预期运行:
$ kubectl apply -f hpa/todo-deployment.yaml
$ kubectl get po -n hpa-demo
- 创建Service :
# hpa/todo-service.yaml
apiVersion: v1
kind: Service
metadata:
name: todo-app
namespace: hpa-demo
spec:
type: ClusterIP
selector:
app: todo
ports:
- port: 8081 # 集群内暴露的端口
targetPort: 3000 # Pod上的容器端口
应用配置并验证Service资源:
$ kubectl apply -f hpa/todo-service.yaml
$ kubectl get svc -n hpa-demo
通过以上步骤,我们完成了Kubernetes中Pod的垂直和水平自动伸缩的介绍。在实际应用中,需要根据应用程序的特点和需求选择合适的自动伸缩方法,并进行充分的测试和监控,以确保应用程序的性能和稳定性。
超级会员免费看
3994

被折叠的 条评论
为什么被折叠?



