一、创建一个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是针对具体应用的,而不是命名空间级别的