前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一文看懂 Kubernetes 弹性伸缩

一文看懂 Kubernetes 弹性伸缩

作者头像
SRE运维手记
发布2024-09-06 17:55:04
1990
发布2024-09-06 17:55:04
举报
文章被收录于专栏:SRE运维手记

本文将详细介绍容器弹性伸缩的相关知识,包括K8s有哪些弹性策略?缩容的优先级?什么是HPA?HPA怎样工作?

01、k8s弹性策略有哪些?

在 Kubernetes 集群中,自动化资源管理和伸缩是保持应用高效运行的关键。Kubernetes 提供了几种不同的机制来帮助实现这一目标:水平自动伸缩(HPA, Horizontal Pod Autoscaler)、垂直自动伸缩(VPA, Vertical Pod Autoscaler)和集群自动伸缩(CA, Cluster Autoscaler)。这些伸缩器在功能和使用场景上有所不同:

  • HPA:根据 CPU 使用率或其他自定义指标自动增加或减少 Pod 的副本数,如在业务高峰自动增加Pod副本数,在业务低峰自动减少Pod副本数,通常用于无状态应用;
  • VPA:自动调整 Pod 的 CPU 和内存请求和限制,它的目标是为每个 Pod 分配最合适的资源量,既避免资源浪费,通常用于有状态应用或单实例应用;
  • CA:根据集群的当前负载和资源需求自动增加或减少节点的数量,适用于需要根据应用负载动态调整集群大小的场景,CA 特别适用于云环境

上述所提到的HPA和VPA属于调度层弹性,CA属于资源层弹性,跨层级弹性策略可以结合使用,但不建议HPA和VPA共同使用,避免造成冲突。

02、Pods缩容优先级

在HPA自动扩容的时候,我们似乎不关心Workload中哪个Pod先启动还是后启动,反而我们更关注缩容的时候,哪个Pod被先终止,因为搞不好正在处理业务请求的Pod被它给先终止了,接下来我们就透过源码来解析Kubernetes的缩容规则吧。

kubernetes>pkg>controller>controller_utils.go

代码语言:javascript
复制
func (s ActivePods) Less(i, j int) bool {
    // 1. Unassigned < assigned
    // If only one of the pods is unassigned, the unassigned one is smaller
    if s[i].Spec.NodeName != s[j].Spec.NodeName && (len(s[i].Spec.NodeName) == 0 || len(s[j].Spec.NodeName) == 0) {
        return len(s[i].Spec.NodeName) == 0
    }
    // 2. PodPending < PodUnknown < PodRunning
    if podPhaseToOrdinal[s[i].Status.Phase] != podPhaseToOrdinal[s[j].Status.Phase] {
        return podPhaseToOrdinal[s[i].Status.Phase] < podPhaseToOrdinal[s[j].Status.Phase]
    }
    // 3. Not ready < ready
    // If only one of the pods is not ready, the not ready one is smaller
    if podutil.IsPodReady(s[i]) != podutil.IsPodReady(s[j]) {
        return !podutil.IsPodReady(s[i])
    }
    // TODO: take availability into account when we push minReadySeconds information from deployment into pods,
    //       see https://github.com/kubernetes/kubernetes/issues/22065
    // 4. Been ready for empty time < less time < more time
    // If both pods are ready, the latest ready one is smaller
    if podutil.IsPodReady(s[i]) && podutil.IsPodReady(s[j]) {
        readyTime1 := podReadyTime(s[i])
        readyTime2 := podReadyTime(s[j])
        if !readyTime1.Equal(readyTime2) {
            return afterOrZero(readyTime1, readyTime2)
        }
    }
    // 5. Pods with containers with higher restart counts < lower restart counts
    if maxContainerRestarts(s[i]) != maxContainerRestarts(s[j]) {
        return maxContainerRestarts(s[i]) > maxContainerRestarts(s[j])
    }
    // 6. Empty creation time pods < newer pods < older pods
    if !s[i].CreationTimestamp.Equal(&s[j].CreationTimestamp) {
        return afterOrZero(&s[i].CreationTimestamp, &s[j].CreationTimestamp)
    }
    return false
}

总结一下,缩容的顺序如下:

  1. 未调度>已调度:未调度到节点的Pods被终止的优先级更高,因为它们还没有开始运行任何任务,所以优先缩减它们理所应当。
  2. PodPending>PodUnknown>PodRunning:PodPending表示Pod还未开始运行,PodUnknown表示Pod状态未知PodRunning表示Pod正在运行。优先缩减还未运行或者状态未知的Pods,以尽可能保持系统的稳定运行。
  3. Not ready>ready:Not ready的Pods被终止的优先级更高,因为它们可能存在问题,优先缩减它们可以减少系统的错误率。
  4. 较晚Ready>较早Ready:较晚Ready的Pods被终止的优先级更高,因为它们没有接收业务请求的可能性较大,优先缩减它们可以减少对业务的影响。
  5. 容器重启次数较多>较少:重启次数多的Pods被终止的优先级更高,因为它们存在问题的可能性较大,所以优先缩减它们。
  6. 创建时间较短>较长:创建时间短的Pods优先级更高,因为它们没有接收业务请求的可能性较大,优先缩减它们可以减少对业务的影响。

03、HPA实践

我们先创建一个测试用的负载(Workload),命名为nginx

nginx.yaml

代码语言:javascript
复制
apiVersion: apps/v1 
kind: Deployment
metadata:
  name: nginx
  namespace: hpa
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx  
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.16.1
        ports:
        - containerPort: 80
        resources:
          requests:       # 必须设置,否则HPA无法运行
            cpu: 100m     # 设置容器运行时所需CPU资源
            memory: 200Mi # 设置容器运行时所需内存资源
          limits:         # 不是必须设置,但是设置后可以避免压测时占用过多资源
            cpu: 200m      # 限制容器CPU资源为200m,m 是毫核(milli-cores)的缩写,因此200m表示0.2核
            memory: 400Mi   # 限制容器内存资源为400Mi 
---
kind: Service
apiVersion: v1
metadata:
  name: nginx
  namespace: hpa
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

然后我们将其部署到k8s上,运行结果如下

然后我们再创建一个HPA,通过scaleTargetRef设置当前HPA绑定的对象。本例中绑定名为nginx的Deployment,在确保所有Pod中容器的平均CPU使用率或平均内存使用率达到50%时触发扩缩操作(二者满足其一便会触发)。

hpa.yaml

代码语言:javascript
复制
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
  namespace: hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx
  minReplicas: 1  # Deployment可缩容的容器数量下限,需设置为大于等于1的整数
  maxReplicas: 10  # 该Deployment可扩容的容器数量上限,需大于minReplicas
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50 # 目标资源的平均使用率,即资源使用量的平均值与其请求量之间的比例
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 50 # 目标资源的平均使用率,即资源使用量的平均值与其请求量之间的比例

我们通过kubectl apply -f hpa.yaml执行HPA创建,并通过kubectl describe看到HPA已经创建完成

在创建完HPA后,我们可以看到nginx的副本数变成了1,是因为我们HPA设置的minReplicas为1,在负载(Workload)平均资源使用率低于50%时,会触发缩容。

好了,接下来,我们将通过压测验证下HPA扩容,在这过程中,我们可以用kubectl get hpa -w -n hpa观察容器的资源使用率和nginx 副本数量的变化,如下图,我们可以看到随着压测,内存的使用率逐渐上涨,在使用率超过50%后REPLICAS副本数会自动增加,至此HPA的伸缩容均已验证完成。

04、HPA相关操作

从v1.18开始,K8s v2beta2 API允许通过HPA的behavior字段配置扩缩行为

稳定窗口,防止扩缩容指标频繁波动 ,如下示例设置为300s作为观察期

代码语言:javascript
复制
behavior:
  scaleDown:
    stabilizationWindowSeconds: 300
  scaleUp:
    stabilizationWindowSeconds: 300

禁止扩容

代码语言:javascript
复制
behavior:
  scaleUp:
    selectPolicy: Disabled

禁止缩容

代码语言:javascript
复制
behavior:
  scaleDown:
    selectPolicy: Disabled

05、总结

综上所述,我们认识了什么是HPA,HPA如何工作,但是在实际的业务场景中,Pods缩容期间是否会对业务带来影响呢?该如何解决?欢迎留言,本期就介绍到这里,谢谢!

欢迎订阅我的公众号「SRE运维手记」

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SRE运维手记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 04、HPA相关操作
  • 05、总结
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档