HPA-VPA-KPA自动扩缩容

HPA-VPA实现pod自动扩缩容

背景

弹性伸缩是根据用户的业务需求和策略,自动“调整”其“弹性资源”的管理服务。通过弹
性伸缩功能,用户可设置定时、周期或监控策略,恰到好处地增加或减少“弹性资源”,并完
成实例配置,保证业务平稳健康运行。

在实际工作中,我们常常需要做一些扩容缩容操作,如:电商平台在 618 和双十一搞秒
杀活动;由于资源紧张、工作负载降低等都需要对服务实例数进行扩缩容操作。

扩缩容种类

1、Node 层面:
对 K8s 物理节点扩容和缩容,根据业务规模实现物理节点自动扩缩容,仅支持云主机。

2、Pod 层面:
我们一般会使用Deployment中的replicas参数,设置多个副本集来保证服务的高可用,但是这是一个固定的值,比如我们设置 10 个副本,就会启 10 个 pod 同时 running 来提供服务。如果这个服务平时流量很少的时候,也是 10 个 pod 同时在 running,而流量突然暴增时,又可能出现 10 个 pod 不够用的情况。针对这种情况怎么办?就需要扩容和缩容。

HPA

  • 通过哪些指标决定扩缩容?

HPA v1 版本可以根据 CPU 使用率来进行自动扩缩容:
但是并非所有的系统都可以仅依靠 CPU 或者 Memory 指标来扩容,对于大多数 Web应用的后端来说,基于每秒的请求数量进行弹性伸缩来处理突发流量会更加的靠谱,所以对于一个自动扩缩容系统来说,我们不能局限于 CPU、Memory 基础监控数据,每秒请求数 RPS 等自定义指标也是十分重要。

HPA v2 版本可以根据自定义的指标进行自动扩缩容
注意:hpa v1 只能基于 cpu 做扩容所用,hpa v2 可以基于内存和自定义的指标做扩容和缩容

  • 如何采集资源指标?

如果我们的系统默认依赖 Prometheus,自定义的 Metrics 指标则可以从各种数据源或者 exporter 中获取,基于拉模型的 Prometheus 会定期从数据源中拉取数据。 也可以基于 metrics-server 自动获取节点和 pod 的资源指标。

  • 如何实现自动扩缩容?

K8s 的 HPA controller 已经实现了一套简单的自动扩缩容逻辑,默认情况下,每 30s 检测一次指标,只要检测到了配置 HPA 的目标值,则会计算出预期的工作负载的副本数,再进行扩缩容操作。同时,为了避免过于频繁的扩缩容,默认在 5min 内没有重新扩缩容的情况下,才会触发扩缩容。 HPA 本身的算法相对比较保守,可能并不适用于很多
场景。例如,一个快速的流量突发场景,如果正处在 5min 内的 HPA 稳定期,这个时候根据 HPA 的策略,会导致无法扩容。

KPA

KPA(Knative Pod Autoscaler): 请求数扩缩容

基于请求数对 Pod 自动扩缩容,KPA 的主要限制在于它不支持基于 CPU 的自动扩缩容。

  1. 根据并发请求数实现自动扩缩容
  2. 设置扩缩容边界实现自动扩缩容

扩缩容边界指应用程序提供服务的最小和最大Pod数量,通过设置应用程序提供服务的最小和最大Pod数量,实现自动扩缩容。

相比 HPA,KPA 会考虑更多的场景,其中一个比较重要的是流量突发的时候,可以结合HPA使用。k8s的HPA controller已经实现了简单的扩缩容逻辑,默认30s检测一次,只要检测到了HPA的目标值,则会计算出预期的工作负载副本数,再进行扩缩容,同时,为了避免过于频繁的扩缩容,默认在5min内没有重新扩缩容的情况下,才会触发扩缩容,所以导致无法应对很多紧急产生问题,例如,一个快速流量突发场景,如果正处于5min内的HPA稳定器,这个时候根据HPA策略,会导致无法扩容,另外,在一些serverless场景下,有缩容到0然后冷启动的需求,但HPA默认不支持。

针对VPA的部署及案例使用,等待后续更新

参考github地址:https://knative.dev/docs/install/

安装参考:https://knative.dev/docs/install/install-serving-with-yaml/

VPA

VPA(Vertical Pod Autoscaler): 垂直Pod自动扩缩容

VPA会基于pod资源使用情况自动为集群设置资源占用的限制,从而让集群将Pod调度到有足够资源的最佳节点。

VPA也会保持最初容器定义中资源request和limit的占比,她会根据容器资源使用率自动设置pod的CPU和内存的requests,从而允许在节点上进行适当的调度,以便为每个Pod提供适当的可用节点,它既可以缩小过度请求资源的容器,也可以根据情况随时提升资源不足的容量。

使用限制:

vpa不能和HPA一起使用

VPA好处:

Pod 资源用其所需,所以集群节点使用效率高。
Pod 会被安排到具有适当可用资源的节点上。不必运行基准测试任务来确定 CPU 和内存请求的合适值。
VPA 可以随时调整 CPU 和内存请求,无需人为操作,因此可以减少维护时间

缺点

VPA 是 Kubernetes 比较新的功能,还没有在生产环境大规模实践过,不建议在线上环境使
用自动更新模式,但是使用推荐模式你可以更好了解服务的资源使用情况。

CA

CA(Cubernetes cluster-auto)

1、什么是 cluster-autoscaler
Cluster Autoscaler (CA)是一个独立程序,是用来弹性伸缩 kubernetes 集群的。它可以自动根据部署应用所请求的资源量来动态的伸缩集群。当集群容量不足时,它会自动去Cloud Provider (支持 GCE、GKE 和 AWS)创建新的 Node,而在 Node 长时间资源利用率很低时自动将其删除以节省开支。

项目地址:https://github.com/kubernetes/autoscaler

2、Cluster Autoscaler 什么时候伸缩集群?
在以下情况下,集群自动扩容或者缩放:
扩容:由于资源不足,某些 Pod 无法在任何当前节点上进行调度
缩容: Node 节点资源利用率较低时,且此 node 节点上存在的 pod 都能被重新调度到其他 node 节点上运行

3、什么时候集群节点不会被 CA 删除?
1)节点上有 pod 被 PodDisruptionBudget 控制器限制。
2)节点上有命名空间是 kube-system 的 pods。
3)节点上的 pod 不是被控制器创建,例如不是被 deployment, replica set, job, statefulset 创建。
4)节点上有 pod 使用了本地存储。
5)节点上 pod 驱逐后无处可去,即没有其他 node 能调度这个 pod
6)节点有注解:"cluster-autoscaler.kubernetes.io/scale-down-disabled": "true"(在 CA1.0.3 或更高版本中受支持)

扩展:什么是 PodDisruptionBudget?
通过 PodDisruptionBudget 控制器可以设置应用 POD 集群处于运行状态最低个数,也
可以设置应用 POD 集群处于运行状态的最低百分比,这样可以保证在主动销毁应用
POD 的时候,不会一次性销毁太多的应用 POD,从而保证业务不中断。

4、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

服务使用前提

  • 安装组件metrics-server

metrics-server 是一个集群范围内的资源数据集和工具,同样的,metrics-server 也只是显示数据,并不提供数据存储服务,主要关注的是资源度量 API 的实现,比如 CPU、文件描述符、内存、请求延时等指标,metric-server 收集数据给 k8s 集群内使用,如 kubectl,hpa,scheduler 等.

metrics-server组件部署

  1. 获取镜像
# 通过离线方式获取
k8s.gcr.io/metrics-server-amd64:v0.3.6 和 k8s.gcr.io/addon-resizer:1.8.4
  1. 服务部署
# 1.在/etc/kubernetes/manifests 里面改一下apiserver的配置
注意:这个是 k8s 在 1.7 的新特性,如果是 1.16 版本的可以不用添加,1.17 以后要添加。这个参
数的作用是 Aggregation 允许在不修改 Kubernetes 核心代码的同时扩展 Kubernetes API。
[root@xianchaomaster1 ~]# vim /etc/kubernetes/manifests/kube-apiserver.yaml
增加如下内容
- --enable-aggregator-routing=true

# 2. 更新配置
kubectl apply -f /etc/kubernetes/manifests/kube-apiserver.yaml 
kubectl apply -f metrics.yaml

# metrics.yaml文件
[root@master1 yml]# cat metrics.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: metrics-server:system:auth-delegator
  labels:
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: metrics-server-auth-reader
  namespace: kube-system
  labels:
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: system:metrics-server
  labels:
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - nodes
  - nodes/stats
  - namespaces
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - "extensions"
  resources:
  - deployments
  verbs:
  - get
  - list
  - update
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: system:metrics-server
  labels:
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:metrics-server
subjects:
- kind: ServiceAccount
  name: metrics-server
  namespace: kube-system
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: metrics-server-config
  namespace: kube-system
  labels:
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: EnsureExists
data:
  NannyConfiguration: |-
    apiVersion: nannyconfig/v1alpha1
    kind: NannyConfiguration
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
    k8s-app: metrics-server
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile
    version: v0.3.6
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
      version: v0.3.6
  template:
    metadata:
      name: metrics-server
      labels:
        k8s-app: metrics-server
        version: v0.3.6
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ''
        seccomp.security.alpha.kubernetes.io/pod: 'docker/default'
    spec:
      priorityClassName: system-cluster-critical
      serviceAccountName: metrics-server
      containers:
      - name: metrics-server
        image: k8s.gcr.io/metrics-server-amd64:v0.3.6
        imagePullPolicy: IfNotPresent
        command:
        - /metrics-server
        - --metric-resolution=30s
        - --kubelet-preferred-address-types=InternalIP
        - --kubelet-insecure-tls
        ports:
        - containerPort: 443
          name: https
          protocol: TCP
      - name: metrics-server-nanny
        image: k8s.gcr.io/addon-resizer:1.8.4
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            cpu: 100m
            memory: 300Mi
          requests:
            cpu: 5m
            memory: 50Mi
        env:
          - name: MY_POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: MY_POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
        volumeMounts:
        - name: metrics-server-config-volume
          mountPath: /etc/config
        command:
          - /pod_nanny
          - --config-dir=/etc/config
          - --cpu=300m
          - --extra-cpu=20m
          - --memory=200Mi
          - --extra-memory=10Mi
          - --threshold=5
          - --deployment=metrics-server
          - --container=metrics-server
          - --poll-period=300000
          - --estimator=exponential
          - --minClusterSize=2
      volumes:
        - name: metrics-server-config-volume
          configMap:
            name: metrics-server-config
      tolerations:
        - key: "CriticalAddonsOnly"
          operator: "Exists"
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
---
apiVersion: v1
kind: Service
metadata:
  name: metrics-server
  namespace: kube-system
  labels:
    addonmanager.kubernetes.io/mode: Reconcile
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "Metrics-server"
spec:
  selector:
    k8s-app: metrics-server
  ports:
  - port: 443
    protocol: TCP
    targetPort: https
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
  name: v1beta1.metrics.k8s.io
  labels:
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile
spec:
  service:
    name: metrics-server
    namespace: kube-system
  group: metrics.k8s.io
  version: v1beta1
  insecureSkipTLSVerify: true
  groupPriorityMinimum: 100
  versionPriority: 100


# 3.验证metrics-server是否部署成功
[root@master1 yml]# kubectl get pods -n kube-system |grep metrics
metrics-server-5c7c5b6d67-bndpb       2/2     Running            0          4m39s

# 4.测试kubectl top命令
[root@master1 yml]# kubectl top nodes
NAME      CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
master1   693m         17%    3477Mi          45%       
master2   1747m        43%    4121Mi          26%       
master3   341m         8%     1456Mi          9%        
node1     3219m        80%    7801Mi          50%       
node2     3729m        93%    4391Mi          28% 

扩缩容示例

HPA示例①:

创建php-apache服务,利用HPA进行自动扩缩容

  1. 使用dockerfile创建php镜像
[root@master1 php]# cat dockerfile 
FROM php:5-apache
ADD index.php /var/www/html/index.php
RUN chmod a+rx index.php

[root@master1 php]# cat index.php 
<?php
$x = 0.0001;
for ($i = 0; $i <= 1000000;$i++) {
$x += sqrt($x);
}
echo "OK!";
?>

# 构建镜像
[root@master1 php]# docker build -t xianchao/hpa-example:v1 .

# 打包镜像
docker save -o hpa-example.tar.gz xianchao/hpa-example:v1

# 上传至各个工作节点并解压
docker load -i hpa-example.tar.gz

2.部署php-apache服务

[root@master1 php]# cat php-apache.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-apache
spec:
  selector:
    matchLabels:
      run: php-apache
  replicas: 1
  template:
    metadata:
      labels:
        run: php-apache
    spec:
      containers:
      - name: php-apache
        image: xianchao/hpa-example:v1
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 500m
          requests:
            cpu: 200m
---
apiVersion: v1
kind: Service
metadata:
  name: php-apache
  labels:
    run: php-apache
spec:
  ports:
  - port: 80
  selector:
    run: php-apache
    
# 更新资源清单文件
[root@master1 php]# kubectl apply -f php-apache.yaml 

# 验证php是否部署成功(服务注入了istio,所以是2个pod)
[root@master1 php]# kubectl get pods 
NAME                             READY   STATUS     RESTARTS   AGE
php-apache-77d6fb6ff9-h92xr      2/2     Running    0          83s

3.创建HPA

  • 命令行创建HPA(默认是v1版,即仅针对CPU监控,无法针对内存,否则使用v2,即yaml清单方式)
# 实现目的:
1. 让副本数维持在1-10个之间(副本数指deployment部署的pod副本数)
2. 将所有pod的平均CPU使用率维持在50%(通过kubectl top看到的每个pod如果是200毫核,这意味着平均cpu使用率为100毫核)


# hpa扩容计算方式
如果hpa设定cpu使用率为50%,在创建deployment时设定最小pod cpu使用率为200m,那么当流量达到200m/50%= 100m时不会对deployment所管理的pod扩容,当超出50%,pod达到cpu使用率为130%,超出50%,那么对pod流量均摊50%,就需要创建三个pod副本数。

# 利用命令行方式创建HPA
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
--cpu-percent=50:表示cpu使用率不超过50%
--min:最少一个pod
--max:最多10个pod

# 验证HPA是否创建成功(由于没有请求,所以cpu消耗为0%)
[root@master1 php]# kubectl get hpa
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   2%/50%    1         10        1          2m14s

# 针对php-apache服务压测(针对cpu),新开启一个终端,不断对php-apache发起请求
kubectl run v1 -it --image=busybox --image-pull-policy=IfNotPresent /bin/sh
/ # while true;do wget -q -O - http://php-apache.default.svc.cluster.local;done

# 同时查看hpa(当流量达到175%产生4个副本)
`为啥是4个副本呢? - 监控cpu超过50%产生1个副本175就是4个`
[root@master1 php]# kubectl get hpa 
NAME         REFERENCE               TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   175%/50%   1         10        1          68m
[root@master1 php]# kubectl get hpa 
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   2%/50%    1         10        4          73m

# 注意:
扩缩容副本数不是在一瞬间完成,存在等待时间
  • yaml清单创建HPA
# 1.创建ng容器
[root@xianchaomaster1 ~]# cat nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-hpa
spec:
  selector:
    matchLabels:
      app: nginx
replicas: 1
template:
  metadata:
    labels:
      app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.9.1
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
      name: http
      protocol: TCP
    resources:
      requests:
        cpu: 0.01
        memory: 25Mi
      limits:
        cpu: 0.05
        memory: 60Mi
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80

# 2.更新资源清单文件
[root@xianchaomaster1 ~]# kubectl apply -f nginx.yaml

# 3.注意:
nginx的pod中需要有resource和limits字段,否则hpa会采集不到内存指标

# 4.创建一个hpa
[root@xianchaomaster1 ~]# cat hpa-v1.yaml
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
  maxReplicas: 10				# 最大副本数
  minReplicas: 1				# 最小副本数
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment			# 关联之前ng的deployment
    name: nginx-hpa				# deployment名称
  metrics:
  - type: Resource
    resource:
      name: memory				
      targetAverageUtilization: 60	# 不能超过60%的使用率
      
 # 5.更新资源配置清单
 [root@xianchaomaster1 ~]# kubectl apply -f hpa-v1.yaml
 
 # 6.查看创建的 hpa
 [root@xianchaomaster1 ~]# kubectl get hpa
 NAME            REFERENCE           TARGETS        MINPODS   MAXPODS  REPLICAS 
 nginx-hpa    Deployment/nginx-hpa    5%/60%           1 		   10	 	 1
 
 # 7.压测nginx的内存,hpa会对pod自动扩缩容(登录创建的pod,压测)
 dd if=/dev/zero of=/tmp/a
 
 # 8.打开新的终端,查看hpa(200%为当前内存使用率,60%表示所有pod的内存维持在60%,200/60=4个pod)
 [root@master1 php]# kubectl get hpa 
  NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
  nginx-hpa   Deployment/nginx-hpa   200%/60%    1         10        4          73m

# 9.查看pod数量(产生四个pod)
[root@master1 nginx]# kubectl get deployment
NAME            READY   UP-TO-DATE   AVAILABLE   AGE
nginx-hpa        4/4     4            4           25m

# 10.取消对nginx内存的压测,hpa会对pod自动缩容
[root@master1 nginx]# kubectl exec -it nginx-hpa-fb74696c-6m6st -- /bin/sh
删除压测文件
rm -rf /tmp/a

# 11.查看hpa检测情况
[root@xianchaomaster1 ~]# kubectl get hpa
显示如下,可看到内存使用率已经降到 5%:
NAME 		REFERENCE 				TARGETS     MINPODS 	MAXPODS  REPLICAS 		AGE
nginx-hpa    Deployment/nginx-hpa      5%/60%       1 			10		 1 			26m

# 扩展
[root@master1 nginx]# kubectl get hpa.v2beta2.autoscaling -o yaml > 1.yaml

VPA示例②:

Vertical Pod Autoscaler(VPA):垂直 Pod 自动扩缩容,用户无需为其 pods 中的容器设置最新的资源 request。配置后,它将根据使用情况自动设置 request,从而允许在节点上进行适当的调度,以便为每个 pod 提供适当的资源量。

1.安装VPA

# 上传vpa相关镜像文件
[root@xianchaonode1 ~]# docker load -i vpa-admission-controller_0_8_0.tar.gz
[root@xianchaonode1 ~]# docker load -i vpa-recommender_0_8_0.tar.gz
[root@xianchaonode1 ~]# docker load -i vpa-updater_0_8_0.tar.gz

# 上传vpa安装包
[root@xianchaomaster1~]# unzip autoscaler-vertical-pod-autoscaler-0.8.0.zip
[root@xianchaomaster1 ~]# cd /root/autoscaler-vertical-pod-autoscaler-0.8.0/vertical-
pod-autoscaler/deploy
修改 admission-controller-deployment.yaml 里的 image:
image: scofield/vpa-admission-controller:0.8.0
imagePullPolicy: IfNotPresent
修改 recommender-deployment.yaml 里的 image:
image: scofield/vpa-recommender:0.8.0
imagePullPolicy: IfNotPresent
修改 updater-deployment.yaml 文件里的 image:
image: scofield/vpa-updater:0.8.0
imagePullPolicy: IfNotPresent
[root@xianchaomaster1]# cd /root/autoscaler-vertical-pod-autoscaler-0.8.0/vertical-pod-
autoscaler/hack

# 执行安装脚本
[root@xianchaomaster1 hack]# ./vpa-up.sh

# 验证是否部署成功:
[root@xianchaomaster1]# kubectl get pods -n kube-system | grep vpa
vpa-admission-controller-777694497b-6rrd4 1/1 Running 0 86s
vpa-recommender-64f6765bd9-ckmvf 1/1 Running 0 86s
vpa-updater-c5474f4c7-vq82f 1/1 Running 0 86s

2.测试vpa实现pod自动扩缩容

2.1 updateMode:Off 只查看推荐数值,不实际应用到容器

  • 部署一个nginx服务,部署到namespace: vpa名称空间下
[root@xianchaomaster1 ~]# mkdir vpa
[root@xianchaomaster1 ~]# cd vpa/
[root@xianchaomaster1 vpa]# kubectl create ns vpa
[root@xianchaomaster1 vpa]# cat vpa-1.yaml
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
        name: nginx
        imagePullPolicy: IfNotPresent
        resources:
          requests:
            cpu: 200m
            memory: 300Mi
            
[root@xianchaomaster1 vpa]# kubectl apply -f vpa-1.yaml
[root@xianchaomaster1 vpa]# kubectl get pods -n vpa
NAME READY STATUS RESTARTS AGE
nginx-5f598bd784-fknwq 1/1 Running 0 6s
nginx-5f598bd784-ljq75 1/1 Running 0 6s
  • 在ng管理的pod前端创建四层代理service
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: vpa
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx
[root@xianchaomaster1 vpa]# kubectl apply -f vpa-service-1.yaml
[root@xianchaomaster1 vpa]# kubectl get svc -n vpa
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx NodePort 10.109.35.41 <none> 80:31957/TCP 3m28s
[root@xianchaomaster1 vpa]# curl -I 192.168.40.180:31957
HTTP/1.1 200 OK
#显示 200 说明代理没问题
  • 创建VPA,先使用updateMode: off 这种模式仅获取资源推荐值,但不更新pod
[root@xianchaomaster1 vpa]# cat vpa-nginx.yaml
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@xianchaomaster1 vpa]# kubectl apply -f vpa-nginx.yaml
[root@xianchaomaster1 vpa]# kubectl get vpa -n vpa
NAME AGE
nginx-vpa 6s

# 查看vpa详情
[root@xianchaomaster1 vpa]# kubectl describe vpa nginx-vpa -n 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>

# 注:
Lower Bound: 下限值
Target: 推荐值
Upper Bound: 上限值
Uncapped Target: 如果没有为 VPA 提供最小或最大边界,则表示目标利用率
上面结果表示,推荐的 Pod 的 CPU 请求为 500m,推荐的内存请求为 262144k字节。
  • nginx压测,查看vpa给出推荐值
[root@xianchaomaster1 vpa]# yum -y install httpd-tools ab
[root@xianchaomaster1 vpa]# ab -c 100 -n 10000000 http://192.168.40.180:31957/

# 过几分钟后观察 VPA Recommendation 变化
[root@xianchaomaster1 vpa]# kubectl describe vpa nginx-vpa -n vpa
Recommendation:
  Container Recommendations:
    Container Name: nginx
    Lower Bound:
      Cpu: 500m
      Memory: 262144k
    Target:
      Cpu: 763m
      Memory: 262144k
    Uncapped Target:
      Cpu: 763m
      Memory: 262144k
    Upper Bound:
      Cpu: 2
      Memory: 934920074
Events: <none>

从以上信息可以看出,VPA 对 Pod 给出了推荐值: Cpu: 763m ,因为我们这里设置了
updateMode: "Off",所以不会更新 Pod

[root@xianchaomaster1 vpa]# kubectl get pods -n vpa
NAME READY STATUS RESTARTS AGE
nginx-5f598bd784-fknwq 1/1 Running 0 79m
nginx-5f598bd784-ljq75 1/1 Running 0 79m

2.2 updateMode:On

  • 部署nginx deployment
# 将updateMoe改为"Auto",看vpa的动作变化
更改deployment中nginx的cpu和内存request最小使用
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
        name: nginx
        imagePullPolicy: IfNotPresent
        resources:
          requests:
            cpu: 100m
            memory: 50Mi
      
[root@xianchaomaster1 vpa]# kubectl apply -f vpa-nginx-1.yaml
[root@xianchaomaster1 vpa]# kubectl get pods -n vpa
NAME READY STATUS RESTARTS AGE
nginx-b75478445-jxp5d 1/1 Running 0 30s
nginx-b75478445-psh2j 1/1 Running 0 30s
  • 部署vpa
[root@xianchaomaster1 vpa]# cat vpa-nginx.yaml
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@xianchaomaster1 vpa]# kubectl apply -f vpa-nginx.yaml
[root@xianchaomaster1 vpa]# kubectl get vpa -n vpa
NAME MODE CPU MEM PROVIDED AGE
nginx-vpa Off 500m 262144k True 72m
nginx-vpa-2 Auto 9s
  • 压测,使用describe查看vpa详情
[root@master1 VPA]# ab -c 100 -n 10000000 http://10.200.2.192:32328/

# 过几分钟后查看vpa详情,只关注容器 recommendations
[root@xianchaomaster1 ~]# kubectl describe vpa nginx-vpa -n vpa |tail -n 20
Target 变成了 Cpu: 656m ,Memory: 262144k

# 查看event事件(vpa执行evictedbyvpa,自动停止nginx,使用vpa推荐资源启动nginx)
kubect get event -n vpa

# 查看vpa重启的nginx
[root@xianchaomaster1 ~]# kubectl describe pods nginx-b75478445-9sd46 -n vpa
Requests:
  cpu: 656m
  memory: 262144k
posted @ 2021-11-04 17:25  元气少女郭德纲!!  阅读(781)  评论(0编辑  收藏  举报