k8s 1.23.10 动态POD扩缩容(HPA )

目录

为什么要自动扩缩容?

再K8S中扩容分为两种:

一、Node层面:

二、Pods层面:

自动扩缩容的方案有哪些

Kubernetes HPA (Horizontal Pod Autoscaling)

Kubernetes KPA (Knative Pod Autoscaler)

Kubernetes VPA (Vertical Pod Autoscaler)

基于HPA进行POD的扩缩容

kube-apiserver 配置:

安装metrcs-server与addon-resizer

创建一个用于测试hpa的镜像 Dockerfile

使用Deployment部署一个 php-apache 服务

创建HPA-基于CPU

测试扩容-CPU

创建HPA-基于内存

同时基于内存与CPU


HPA官方文档地址:官方文档地址

为什么要自动扩缩容?

    在实际的业务场景中,我们经常会遇到某个服务需要扩容的场景(例如:测试对服务器压测,电商平台秒杀、大促活动、或由于资源紧张、工作负载降低等都需要对服务实例数量扩容操作)。

再K8S中扩容分为两种:

一、Node层面:

        再使用kubenetes 集群经常问道的一个问题是,我应该保持多大的节点规模来满足应用需求呢?cluster-autoscaler 的出现解决了这个问题,可以通过cluster-autoscaler 实现节点级别的动态添加与删除,动态调整容器资源池,应对峰值流量

二、Pods层面:

        一般会使用Deployment中的 replicas参数,设置多个副本集来保证服务的高可用,但是这是一个固定的值,比如我们设置10个副本,就会启动10个pod 同时 running 来提供服务。

        如果这个服务平时流量很少的时候,也是10个pod同时running,就会造成资源浪费,而流量突然暴增时,又出现了10个pod 不够用的情况。针对这种情况怎么办》 就需要自动扩缩容。

自动扩缩容的方案有哪些

Kubernetes HPA (Horizontal Pod Autoscaling

    通过此功能,只需要简单的配置,便可以利用监控指标(CPU、内存、磁盘、自定义等) 自动的扩容或者缩容服务中的POD数量,当业务需求增加时,系统将无缝地自动增加适量的pod容器,提升系统稳定性。

Kubernetes KPA (Knative Pod Autoscaler

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

Kubernetes VPA (Vertical Pod Autoscaler)

    垂直 Pod 自动扩缩容,VPA会基于Pod的资源使用情况自动为集群设置资源占用的限制,从而让集群将Pod 调度到有足够资源的最佳节点上。VPA也会保持最初容器定义中资源request 和 limit的占比。

    它会根据容器资源使用率自动设置POD 的CPU 和内存的 requests,从而允许再节点上进行适当的调度,以便为每个Pod 提供适当的可用的节点。它既可以缩小过度请求资源的容器,也可以根据其使用情况随时提升资源的容量。

基于HPA进行POD的扩缩容

    K8S的HPA controller 已经实现了一套简单的自动扩缩容逻辑,默认情况下,每30s检测一次指标,只要检测到了配置HPA的目标值,则会计算出预期的工作负载的副本数,再进行扩容操作。同时为了避免过于频繁的扩缩容,默认再 5min 内没有重新扩缩容的情况下,才会触发扩缩容。

    HPA 本身的算法相对比较保守,可能并使用与很多场景。例如,一个快速流量突发场景,如果正处在5min内的HPA稳定器,这个时候很具HPA的策略,会导致无法扩容(通过实验扩容是很快速的,并非等了5分钟,但是缩容等了5分钟,这个时间是可以更改的)

kube-apiserver 配置:

注意这个是 k8s 在 1.17 的新特性,如果是 1.16 版本的可以不用添加,1.17 以后要添加。这个参 数的作用是 Aggregation 允许在不修改 Kubernetes 核心代码的同时扩展 Kubernetes API。 

vim kube-apiserver.yaml
- --enable-aggregator-routing=true   #添加该行内容

k8s 1.23.10 动态POD扩缩容(HPA )_第1张图片

重新更新ApiServer 配置(!!!):

#查看下配置
ps -ef |grep   enable-aggregator-routing

#不存在则更新下
kubectl apply -f /etc/kubernetes/manifests/kube-apiserver.yaml
kubectl delete pods kube-apiserver -n kube-system

#再次查看配置
ps -ef |grep   enable-aggregator-routing

安装metrcs-server与addon-resizer

kubectl  apply -f metrics.yaml
kubectl  get  pod  -n kube-system
metrics-server-7f546bc689-7m2zm            2/2     Running   0

 metrics.yaml:

#RBAC授权
#集群绑定角色到SA账号
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
---
#角色绑定SA账号
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
---
#定义SA账号
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
---

#ConfigMap
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.4.1
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
      version: v0.4.1
  template:
    metadata:
      name: metrics-server
      labels:
        k8s-app: metrics-server
        version: v0.4.1
    spec:
      priorityClassName: system-cluster-critical
      serviceAccountName: metrics-server
      containers:
      - name: metrics-server
        image: rancher/metrics-server:v0.4.1-amd64  #dockerhub镜像
        imagePullPolicy: IfNotPresent
        command:
        - /metrics-server
        - --metric-resolution=30s
        - --kubelet-preferred-address-types=InternalIP
        - --kubelet-insecure-tls
        - --cert-dir=/tmp
        - --secure-port=4443   
        ports:
        - containerPort: 4443
          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

查看POD与Node资源使用情况

#查看ingress-nginx名称空间下的pod资源使用
kubectl  top  pod  -n  ingress-nginx 
NAME                                        CPU(cores)   MEMORY(bytes)   
ingress-nginx-controller-5cd767794b-qqrms   3m           91Mi  

#查看node节点的资源使用
kubectl  top  node
NAME           CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
test-master    207m         5%     3923Mi          53%       
test-slave-1   187m         4%     5096Mi          69%

创建一个用于测试hpa的镜像 Dockerfile

FROM php:5-apache
ADD index.php /var/www/html/index.php
RUN chmod a+rx index.php

# index.php 文件内容



#构建Docker 镜像
docker build -t k8s.gcr.io/hpa-example:v1 .
docker save -o hpa-example.tar.gz k8s.gcr.io/hpa-example:v1 

可以把镜像传到 k8s 的工作节点,通过 docker load -i hpa-example.tar.gz 进行解压:
docker load -i hpa-example.tar.gz

使用Deployment部署一个 php-apache 服务 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:
      nodeName: test-slave-1   #再指定节点上创建Pod
      containers:
      - name: php-apache
        image: k8s.gcr.io/hpa-example:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 500m   #最大使用0.5核CPU
            memory: 200Mi
          requests:
            cpu: 200m   #调用节点最小要有 0.2核CPU
            memory: 200Mi
---
apiVersion: v1
kind: Service
metadata:
    name: php-apache
    labels:
      run: php-apache
spec:
  ports:
  - port: 80
  selector:
   run: php-apache

更新资源清单文件

kubectl  apply -f php-apache.yaml
#查看pod状态
kubectl  get pod |grep   php-apache
NAME                          READY   STATUS    RESTARTS   AGE
php-apache-5cbf8c9567-cfq6q   1/1     Running   0          5s

创建HPA-基于CPU

php-apache 服务正在运行,使用 kubectl autoscale 创建自动缩放器,实现对 php-apache 这个Deployment创建的Pod 自动扩缩容下面的命令将会创建一个HPA,HPA将会根据CPU。内存等资源指标增加或者减少副本数,创建一个可以实现如下目的的HPA:

1) 让副本数维持再1-10 个之间 (这里副本数指的是通过Deployment 部署 pod 的副本数)

2) 将所有 pod 的平均CPU 使用率位置在 50% (通过 kubectl run 运行的Pod 如果是200毫核,这意味着平均CPU利用率为100毫核)

为 php-apache 这个 deployment 创建一个HPA

#基于CPU
kubectl  autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10

参数解析:

--cpu-percent=50 标识CPU使用率不超过50%

--min=1 最少一个pod

--max=10 最多是个pod

验证HPA是否创建成功

kubectl get hpa

 注:由于我们没有向服务器发送任何请求,因此当前 CPU 消耗为 0%(TARGET 列显示了由相应 的 deployment 控制的所有 Pod 的平均值)

测试扩容-CPU

#运行一个pod
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


#在一分钟左右的时间内,我们通过执行以下命令来看到更高的 CPU 负载
kubectl  top pod 
NAME                          CPU(cores)   MEMORY(bytes)   
php-apache-5cbf8c9567-cfq6q   502m         8Mi             
v1                            6m           0Mi      

#查看hpa
kubectl  get hpa
NAME         REFERENCE               TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   251%/50%   1         10        1          6m39s

#查看POD数量
[root@test-master ~]# kubectl  top  pod 
NAME                          CPU(cores)   MEMORY(bytes)   
php-apache-5cbf8c9567-2g9rh   111m         9Mi             
php-apache-5cbf8c9567-c46mw   102m         8Mi             
php-apache-5cbf8c9567-cfq6q   105m         8Mi             
php-apache-5cbf8c9567-d7clq   106m         8Mi             
php-apache-5cbf8c9567-hcjqt   112m         8Mi             
php-apache-5cbf8c9567-jhmx7   105m         8Mi             
php-apache-5cbf8c9567-rnkxf   112m         8Mi             
php-apache-5cbf8c9567-tkhfr   108m         8Mi 

#停止压测观察5分钟后pod是否缩容

[root@test-master ~]# kubectl  top  pod 
NAME                          CPU(cores)   MEMORY(bytes)   
php-apache-5cbf8c9567-cfq6q   1m           8Mi             
v1                            0m           0Mi   

创建HPA-基于内存

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-v2
spec:
  minReplicas: 1
  maxReplicas: 10
  scaleTargetRef: 
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  metrics:
  - resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 50
    type: Resource
kubectl  exec -it php-apache-7d8fdb687c-b78m9 -- /bin/bash
#进行压测
dd if=/dev/zero of=/tmp/a

同时基于内存与CPU-定义扩缩容策略

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-v2
spec:
  minReplicas: 1
  maxReplicas: 10
  scaleTargetRef: 
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  metrics:
  - resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 50
    type: Resource
  - resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
    type: Resource
  #定义扩缩容策略
  behavior:
    #缩容策略(缩容是每5分钟缩容1个pods)
    scaleDown:
      policies:
      - type: pods
        value: 1
        periodSeconds: 300  #单位是秒
    #扩容策略(触发扩容时,立即新增9(900%*100%)倍的副本数,即立即扩容pod到当前的10倍的pod数量)
    scaleUp:
      policies:
      - type: percent
        value: 900%

扩展:

其他参数参考官方文档: controller-manager启动文件hpa参数

--horizontal-pod-autoscaler-initial-readiness-delay=30s,这是首次探测Pod是否Ready的延时时间,默认30s
--horizontal-pod-autoscaler-cpu-initialization-period=10s,设置首次采集pod的CPU使用率延迟时间,默认5分钟

--horizontal-pod-autoscaler-downscale-stabilization=1m0s,这个配置可以让系统更平滑的进行缩容操作,默认值5min

你可能感兴趣的:(kubernetes,云计算,运维)