VPA Kubernetes VPA(Vertical Pod Autoscaler)可以理解为对单个服务资源进行扩容,如CPU、内存之类。它一般应用于一些中心化的单体应用,且无法对其进行部
署多份副本的场景,如 Prometheus 或 Jenkins 这类垂直 Pod 应用自动扩缩容。
VPA 会基于 Pod 的 资源使用情况自动为集群设置资源占用的限制,从而让集群将 Pod 调度到有足够资源的最佳节点上。VPA 也会保持最初容器定义中资源
request 和 limit 的占比。
当控制器检测到一个Pod负载过高时,这时会对当前Pod进行终止,接着对Pod的CPU或内存进行扩容,最后重建Pod,此时Pod可能在任何一个节点进行重建。
它与HPA的扩容机制是完全不一样的,VPA扩容过程中将无法正常提供服务,也因此它使用的场景相比HPA来说,要少的多。
安装vpa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 [root@node1 data] Loaded image: scofield/vpa-admission-controller:0.8.0 [root@node1 data] b8cda3fb4e0a: Loading layer [==================================================>] 45.95MB/45.95MB Loaded image: scofield/vpa-recommender:0.8.0 [root@node1 data] 9fe5b61fc509: Loading layer [==================================================>] 47.39MB/47.39MB Loaded image: scofield/vpa-updater:0.8.0 [root@master vpa] [root@master vpa] 修改 admission-controller-deployment.yaml 里的 image: image: scofield/vpa-admission-controller:0.8.0 imagePullPolicy: IfNotPresent image: scofield/vpa-recommender:0.8.0 imagePullPolicy: IfNotPresent image: scofield/vpa-updater:0.8.0 imagePullPolicy: IfNotPresent cd /root/vpa/autoscaler-vertical-pod-autoscaler-0.8.0/vertical-pod-autoscaler/hack[root@master hack] Warning: apiextensions.k8s.io/v1beta1 CustomResourceDefinition is deprecated in v1.16+, unavailable in v1.22+; use apiextensions.k8s.io/v1 CustomResourceDefinition customresourcedefinition.apiextensions.k8s.io/verticalpodautoscalers.autoscaling.k8s.io created customresourcedefinition.apiextensions.k8s.io/verticalpodautoscalercheckpoints.autoscaling.k8s.io created clusterrole.rbac.authorization.k8s.io/system:metrics-reader created clusterrole.rbac.authorization.k8s.io/system:vpa-actor created clusterrole.rbac.authorization.k8s.io/system:vpa-checkpoint-actor created clusterrole.rbac.authorization.k8s.io/system:evictioner created clusterrolebinding.rbac.authorization.k8s.io/system:metrics-reader created clusterrolebinding.rbac.authorization.k8s.io/system:vpa-actor created clusterrolebinding.rbac.authorization.k8s.io/system:vpa-checkpoint-actor created clusterrole.rbac.authorization.k8s.io/system:vpa-target-reader created clusterrolebinding.rbac.authorization.k8s.io/system:vpa-target-reader-binding created clusterrolebinding.rbac.authorization.k8s.io/system:vpa-evictionter-binding created serviceaccount/vpa-admission-controller created clusterrole.rbac.authorization.k8s.io/system:vpa-admission-controller created clusterrolebinding.rbac.authorization.k8s.io/system:vpa-admission-controller created clusterrole.rbac.authorization.k8s.io/system:vpa-status-reader created clusterrolebinding.rbac.authorization.k8s.io/system:vpa-status-reader-binding created serviceaccount/vpa-updater created deployment.apps/vpa-updater created serviceaccount/vpa-recommender created deployment.apps/vpa-recommender created Generating certs for the VPA Admission Controller in /tmp/vpa-certs. Generating RSA private key, 2048 bit long modulus .........................................................+++ .............+++ e is 65537 (0x10001) Generating RSA private key, 2048 bit long modulus ..+++ ............+++ e is 65537 (0x10001) Signature ok subject=/CN=vpa-webhook.kube-system.svc Getting CA Private Key Uploading certs to the cluster. secret/vpa-tls-certs created Deleting /tmp/vpa-certs. deployment.apps/vpa-admission-controller created service/vpa-webhook created [root@master manifests] vpa-admission-controller-777694497b-bqpb2 1/1 Running 0 7m9s vpa-recommender-64f6765bd9-twxbw 1/1 Running 0 7m9s vpa-updater-c5474f4c7-h78xt 1/1 Running 0 7m9s [root@master manifests] NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 18d metrics-server ClusterIP 10.109.69.92 <none> 443/TCP 18h vpa-webhook ClusterIP 10.99.181.122 <none> 443/TCP 12m
测试VPA实现Pod自动扩缩容 updateMode:"Off" 部署一个 nginx 服务,部署到 namespace: vpa 名称空间下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 [root@master vpa] namespace/vpa created [root@master vpa] apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx namespace: vpa spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx imagePullPolicy: IfNotPresent name: nginx resources: requests: cpu: 200m memory: 300Mi [root@master vpa] deployment.apps/nginx created
在 nginx 管理的 pod 前端创建四层代理 Service 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@master vpa] apiVersion: v1 kind: Service metadata: name: nginx namespace: vpa spec: type : NodePort ports: - port: 80 targetPort: 80 selector: app: nginx [root@master vpa] service/nginx created [root@master vpa] NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx NodePort 10.97.228.179 <none> 80:30127/TCP 9s [root@master vpa] HTTP/1.1 200 OK
创建VPA,先使用 updateMode: "Off"模式,这种模式仅获取资源推荐值,但是不更新 Pod 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 [root@master vpa] apiVersion: autoscaling.k8s.io/v1beta2 kind: VerticalPodAutoscaler metadata: name: nginx-vpa namespace: vpa spec: targetRef: apiVersion: "apps/v1" kind: Deployment name: nginx updatePolicy: updateMode: "Off" resourcePolicy: containerPolicies: - containerName: "nginx" minAllowed: cpu: "500m" memory: "100Mi" maxAllowed: cpu: "2000m" memory: "2600Mi" [root@master vpa] verticalpodautoscaler.autoscaling.k8s.io/nginx-vpa created [root@master vpa] NAME AGE nginx-vpa 31s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [root@master vpa] Recommendation: Container Recommendations: Container Name: nginx Lower Bound: Cpu: 500m Memory: 262144k Target: Cpu: 500m Memory: 262144k Uncapped Target: Cpu: 25m Memory: 262144k Upper Bound: Cpu: 1349m Memory: 1410936619 Events: <none>
1 2 3 4 5 6 7 8 9 10 11 12 [root@master vpa] [root@master manifests] NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx NodePort 10.97.228.179 <none> 80:30127/TCP 55m [root@master vpa] [root@master vpa]
updateMode: "On" 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx namespace: vpa spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx imagePullPolicy: IfNotPresent name: nginx resources: requests: cpu: 100m memory: 50Mi [root@master vpa] deployment.apps/nginx created [root@master vpa] NAME READY STATUS RESTARTS AGE nginx-7d946f55c4-p52gj 1/1 Running 0 10s nginx-7d946f55c4-s8ggc 1/1 Running 0 10s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 [root@master vpa] apiVersion: autoscaling.k8s.io/v1beta2 kind: VerticalPodAutoscaler metadata: name: nginx-vpa-2 namespace: vpa spec: targetRef: apiVersion: "apps/v1" kind: Deployment name: nginx updatePolicy: updateMode: "Auto" resourcePolicy: containerPolicies: - containerName: "nginx" minAllowed: cpu: "500m" memory: "100Mi" maxAllowed: cpu: "2000m" memory: "2600Mi" [root@master vpa] verticalpodautoscaler.autoscaling.k8s.io/nginx-vpa-2 created [root@master vpa] NAME AGE nginx-vpa-2 9s
1 2 3 4 [root@master vpa] kubectl describe vpa nginx-vpa -n vpa |tail -n 20
查看event事件 1 2 3 4 5 6 7 [root@master vpa] [root@master vpa]
VPA 使用限制 不能与 HPA(Horizontal Pod Autoscaler )一起使用
Pod 比如使用副本控制器,例如属于 Deployment 或者 StatefulSet
VPA扩容过程中将无法正常提供服务,也因此它使用的场景相比HPA来说,要少的多
VPA优点 Pod 资源用其所需,所以集群节点使用效率高。
Pod 会被安排到具有适当可用资源的节点上。
不必运行基准测试任务来确定 CPU 和内存请求的合适值。
VPA 可以随时调整 CPU 和内存请求,无需人为操作,因此可以减少维护时间。
CA(kubernetes cluster-autoscaler) 什么是cluster-autoscaler? Cluster Autoscaler (CA)是一个独立程序,是用来弹性伸缩 kubernetes 集群的。它可以自动根据部署应用所请求的资源量来动态的伸缩集群。当集群容量不足时,它会自动去 Cloud Provider (支持 GCE、GKE 、Ali、Tencent、AWS等)创建新的 Node,而在 Node 长时间资源 利用率很低时自动将其删除以节省开支。
项目地址:https://github.com/kubernetes/autoscaler
Cluster Autoscaler什么时候伸缩集群? 在以下情况下,集群自动扩容或者缩放:
扩容:由于资源不足,某些 Pod 无法在任何当前节点上进行调度
缩容: Node 节点资源利用率较低时,且此 node 节点上存在的 pod 都能被重新调度到 其他 node 节点上运行
什么时候集群节点不会被CA删除? 1)节点上有 pod 被 PodDisruptionBudget 控制器限制。
2)节点上有命名空间是 kube-system 的 pods。
3)节点上的 pod 不是被控制器创建,例如不是被 deployment, replica set, job, stateful set 创建。
4)节点上有 pod 使用了本地存储
5)节点上 pod 驱逐后无处可去,即没有其他 node 能调度这个 pod
6)节点有注解:"cluster-autoscaler.kubernetes.io/scale-down-disabled": "true"(在 CA 1.0.3 或更高版本中受支持)
扩展:什么是 PodDisruptionBudget?
通过 PodDisruptionBudget 控制器可以设置应用 POD 集群处于运行状态最低个数,也可以设置应用 POD 集群处于运行状态的最低百分比,这样可以保证在主动销毁应用 POD 的时候,不会一次性销毁太多的应用 POD,从而保证业务不中断
Horizontal Pod Autoscaler 如何与 Cluster Autoscaler 一起使用? Horizontal Pod Autoscaler 会根据当前 CPU 负载更改部署或副本集的副本数。如果负 载增加,则 HPA 将创建新的副本,集群中可能有足够的空间,也可能没有足够的空间。 如果没有足够的资源,CA 将尝试启动一些节点,以便 HPA 创建的 Pod 可以运行。如果 负载减少,则 HPA 将停止某些副本。结果,某些节点可能变得利用率过低或完全为空, 然后 CA 将终止这些不需要的节点。
扩展:如何防止节点被 CA 删除
节点可以打上以下标签: "cluster-autoscaler.kubernetes.io/scale-down-disabled": "true"
可以使用 kubectl 将其添加到节点(或从节点删除): kubectl annotate node cluster-autoscaler.kubernetes.io/scale-down-disabled=true
部署 Cluster AutoScaler v1.0+ 可以基于 Docker 镜像 gcr.io/google_containers/cluster-autoscaler:v1.3.0 来部署
针对各个云厂商可能也需要各自的运行环境,如腾讯云需要运行在自家TKE上才能使用
Rancher中使用CA:https://ranchermanager.docs.rancher.com/zh/how-to-guides/new-user-guides/manage-clusters/install-cluster-autoscaler
Cluster Autoscaler 支持云厂商:https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler#deployment
注意,在开启 RBAC 的集群中创建 cluster-autoscaler ClusterRole
工作原理 Cluster AutoScaler 定期(默认间隔 10s)检测是否有充足的资源来调度新创建的 Pod,当资源不足时会调用 Cloud Provider 创建新的 Node。
为了自动创建和初始化 Node,Cluster Autoscaler 要求 Node 必须属于某个 Node Group,比如
GCE/GKE 中的 Managed instance groups(MIG) AWS 中的 Autoscaling Groups Azure 中的 Scale Sets 和 Availability Sets 当集群中有多个 Node Group 时,可以通过 --expander=<option> 选项配置选择 Node Group 的策咯,支持如下四种方式
random:随机选择 most-pods:选择容量最大(可以创建最多 Pod)的 Node Group least-waste:以最小浪费原则选择,即选择有最少可用资源的 Node Group price:选择最便宜的 Node Group(仅支持 GCE 和 GKE) 目前,Cluster Autoscaler 可以保证
小集群(小于 100 个 Node)可以在不超过 30 秒内完成扩展(平均 5 秒) 大集群(100-1000 个 Node)可以在不超过 60 秒内完成扩展(平均 15 秒) Cluster AutoScaler 也会定期(默认间隔 10s)自动监测 Node 的资源使用情况,当一个 Node 长时间(超过 10 分钟其期间没有执行任何扩展操作)资源利用率都很低时(低于 50%)自动将其所在虚拟机从云服务商中删除(注意删除时会有 1 分钟的 graceful termination 时间)。此时,原来的 Pod 会自动调度到其他 Node 上面(通过 Deployment、StatefulSet 等控制器)。
注意,Cluster Autoscaler 仅根据 Pod 的调度情况和 Node 的整体资源使用清空来增删 Node,跟 Pod 或 Node 的资源度量(metrics)没有直接关系。
用户在启动 Cluster AutoScaler 时可以配置 Node 数量的范围(包括最大 Node 数和最小 Node 数)。
在使用 Cluster AutoScaler 时需要注意:
由于在删除 Node 时会发生 Pod 重新调度的情况,所以应用必须可以容忍重新调度和短时的中断(比如使用多副本的 Deployment) 当 Node 上面的 Pods 满足下面的条件之一 时,Node 不会删除Pod 配置了 PodDisruptionBudget (PDB) kube-system Pod 默认不在 Node 上运行或者未配置 PDB Pod 不是通过 deployment, replica set, job, stateful set 等控制器创建的 Pod 使用了本地存储 其他原因导致的 Pod 无法重新调度,如资源不足,其他 Node 无法满足 NodeSelector 或 Affinity 等 最佳实践 Cluster AutoScaler 可以和 Horizontal Pod Autoscaler(HPA)配合使用 不要手动修改 Node 配置,保证集群内的所有 Node 有相同的配置并属于同一个 Node 组 运行 Pod 时指定资源请求 必要时使用 PodDisruptionBudgets 阻止 Pod 被误删除 确保云服务商的配额充足 Cluster AutoScaler 与云服务商提供的 Node 自动扩展功能以及基于 CPU 利用率的 Node 自动扩展机制冲突,不要同时启用 https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/rbac/cluster-autoscaler/cluster-autoscaler-rbac.yaml )