K8S自动扩缩容(HPA)实验

一、创建一个SpringBoot项目

创建helloworld项目,在控制器中添加如下函数

@GetMapping("/")
public String say(){
    return "Hello World V2" ;
}  

二、部署Helloworld应用

$ cat helloworld.yml
apiVersion: autoscaling/v2beta2 
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa
  namespace: dc-prod-ns
  annotations:
    HPARollingUpdateSkipped: "true"  # 发布期间暂停HPA判断
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: helloworld
  minReplicas: 1
  maxReplicas: 3
  metrics:
  - type: Resource
    resource:
      name: memory       # 也可以是cpu
      target:           # 目标值 
        type: Utilization
        averageUtilization: 80    # pod中所有容器的平均使用率达到80%时触发
  behavior:   
    # scaleDown:
    #   stabilizationWindowSeconds: 60  # 缩容冷却时间缩短至1分钟(默认300秒)
    #   policies:
    #   - type: Percent
    #     value: 20  # 单次缩容最多减少20%的Pod(当前3副本→每次最多缩1个)
    #     periodSeconds: 60  # 每分钟检查一次
    #   两种定义形式都可以!
    scaleDown:
      stabilizationWindowSeconds: 60  # 缩容冷却5分钟防抖动(这里设为1分钟)
      policies: [{type: Percent, value: 20, periodSeconds: 60}] # 每分钟最多缩20%
    scaleUp:
      policies: [{type: Pods, value: 1, periodSeconds: 60}]     # 每分钟最多扩1个Pod[2,3]   

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: helloworld
  name: helloworld
  namespace: dc-prod-ns
spec:
  replicas: 1
  revisionHistoryLimit: 5
  selector:
    matchLabels:
      k8s-app: helloworld
  strategy:
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        k8s-app: helloworld
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchLabels:
                  k8s-app: helloworld
              topologyKey: kubernetes.io/hostname
      containers:
        - env:
            - name: APP_OPTIONS
              value: '-Xms4096m -Xmx4096m -Xss1024k'
          envFrom:
          - configMapRef:
              name: dc-appvar
          image: helloworld:202507010334
          imagePullPolicy: Never
          name: helloworld
          ports:
            - containerPort: 8080
              protocol: TCP
          readinessProbe:
            httpGet:
              path: /
              port: 8080
            initialDelaySeconds: 60

---
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: helloworld
  name: helloworld
  namespace: dc-prod-ns
spec:
  ports:
    - name: http-8080
      nodePort: 31510
      port: 31510
      protocol: TCP
      targetPort: 8080
  selector:
    k8s-app: helloworld
  type: NodePort

三、观察系统副本变化情况

3.1 副本计算公式

期望副本数 = ceil(当前副本数 × (当前指标值 / 目标指标值))

ceil: 向上取整函数

举例:

  • 当前内存使用率:36%
  • 目标使用率:50%
  • 计算比例:36% / 50% = 0.72
  • 期望副本数:ceil(0.72 × 3) = ceil(2.16) = 3

3.1 当应用刚部署时

$kubectl get  hpa -n dc-prod-ns
NAME        REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
myapp-hpa   Deployment/helloworld   39%/80%   1         3         1          3h18m

此时,pod的内存使用率是39%,1个副本

此时,期望副本数 = ceil(1 × 39/80) = ceil(0.49) = 1
3.2 对应用进行压力测试

这里使用Apipost软件


1751531444697.png
$ kubectl hpa -n dc-prod-ns
NAME        REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
myapp-hpa   Deployment/helloworld   63%/80%   1         3         2          5h9m

此时,期望副本数 = ceil(1 × 63/80) = ceil(3.07) = 4

但因为 maxReplicas设置为3,故此时应该有3个副本

# 稍等一会儿.......
$ kubectl get hpa -n dc-prod-ns
NAME        REFERENCE               TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
myapp-hpa   Deployment/helloworld   170%/80%   1         3         3          3h27m
$  kubectl  get events  -n dc-prod-ns | grep Scaled   # 查看扩容事件
......
12m         Normal    ScalingReplicaSet              deployment/helloworld               Scaled up replica set helloworld-5c755f8cd6 to 3
# 也可以使用kc  describe  hpa 来查看
$  kubectl describe  hpa  myapp-hpa -n dc-prod-ns

此时自动扩容为3个副本

提示:手工扩缩命令:

kubectl scale deployment helloworld --replicas=1 --record -n dc-prod-ns

总结:对于web类流量或处理压力随时间变化比较大的应用,建议使用hpa

另外,hpa是针对具体应用的,而不是命名空间级别的

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容