You need to enable JavaScript to run this app.
导航
工作负载稳定性优化
最近更新时间:2024.08.06 20:52:41首次发布时间:2024.08.06 20:52:41

本文主要介绍容器服务稳定性建设中工作负载稳定性优化相关配置和操作建议。

背景信息

随着容器业务的增长,系统将面临更大的压力和更复杂的挑战。稳定性建设有助于确保系统能够适应增长的需求,支持业务的扩展。容器服务以工作负载与 Kubernetes 集群为核心,在非侵入性改造的前提下,为提升业务稳定性提供参考。

本文主要介绍工作负载稳定性相关内容,更多稳定性优化相关内容,请参见:

使用控制器

在 Kubernetes 中,使用各类工作负载控制器(如 Deployment、StatefulSet、DaemonSet、Job 和 CronJob)来部署应用而非直接使用 Pod,原因如下:

  • 工作负载控制器如 Deployment 和 StatefulSet 支持自动化的滚动更新,在更新过程中,旧版本的 Pod 会逐渐被替换,而新版本的 Pod 会逐步启动,从而避免服务中断。
  • Kubernetes 的工作负载控制器具有自我修复的能力。当检测到 Pod 失败或者不满足期望的副本(Pod)数量时,控制器会自动创建新的 Pod 来替换那些失败的 Pod,这种自我修复机制确保了应用程序始终按照预期运行。

避免单点故障

在 Kubernetes 中,避免 Pod 的单点故障是确保高可用性的关键,您可参考如下措施避免单点故障:

  • 通过配置工作负载中的副本数量、重启策略等,确保总会有 Pod 可以提供服务。
    对于核心工作负载的副本数量建议至少设置为 2 个,重启策略设置为Always
  • 通过 Service 关联工作负载实现 Pod 自动发现负载均衡。
  • 将工作负载关联的多个 Pod 通过 拓扑分布约束 打散部署在多个可用区。
    • 拓扑键:topology.kubernetes.io/zone
    • 拓扑值:可从控制台查看节点标签中拓扑键所对应的值。
    • 启用多可用区需要向集群中添加不同可用区的子网。详细操作,请参见 修改 API Server 子网
  • 将工作负载关联的多个 Pod 通过 节点反亲和性调度 打散部署在多个节点。
  • 根据业务场景,将同一工作负载关联的多个 Pod 通过 节点亲和性调度 部署在同一特定规格的节点池中。
    • 不同业务场景对于节点的 CPU、内存、磁盘、带宽有不同的要求,您可以参考 ECS 选型最佳实践,在节点池中配置与业务场景相匹配的节点规格。
    • 同一节点池内的节点会被打上特定标签cluster.vke.volcengine.com/machinepool-name,该标签值为节点池 ID。在 Pod 的节点亲和性调度中,可使用该标签,指定调度 Pod 到特定节点池。
  • 不同可用区之间的网络延迟一般会大于同一可用区内的网络延迟,因此如果需要 Pod 之间频繁通信,将 Pod 打散到多个可用区后可能导致网络性能下降。
    如果 Pod 涉及对接存储服务,也需要确认存储服务所支持的可用区是否都包含了 Pod 打散后分布的可用区。

配置 HPA

Kubernetes 提供了 HPA(Horizontal Pod Autoscaler,水平 Pod 弹性伸缩)实现副本数量的缩放。通过合理配置,HPA 支持监听工作负载的 CPU、内存等指标,根据实际的负载需求动态调整工作负载的副本数,确保应用程序在不同的流量和使用情况下都能保持稳定运行。

  • 托管版集群会默认安装 Metric Server(VKE 中组件名为 metrics-server),即 HPA 可以直接使用 CPU 和内存伸缩工作负载副本数。详情请参见 创建指标伸缩
  • 在集群中 开启观测,安装采集器后,HPA 支持对工作负载的 GPU、网络等指标进行监听,并据此进行副本数的动态调整。详情请参见 使用 GPU 和网络指标实现弹性伸缩
  • 考虑到缩容所具有的危险性,HPA 支持以多批次灰度的方式对 Pod 进行缩容,并在相关指标存在上升时及时恢复副本数量。详情请参见 Kubernetes 官方文档:可配置的扩缩行为
  • 需要特别注意的是,HPA 不支持从 0 副本数开始对工作负载进行扩容,因此请务必保证与 HPA 关联的工作负载至少存在 1 个副本。

使用 VCI 部署负载

集群支持使用云服务器(ECS)调度 Pod,也支持使用弹性容器实例(VCI)或混合使用 VCI、ECS。通过将 Pod 调度到虚拟节点上,并使用 VCI 运行 Pod,可以实现灵活地按需调度 Pod,并且免去容量规划和节点运维。详情请参见 容器服务使用 VCI

为核心负载配置优先级

容器服务支持弹性资源优先级调度和 Pod 优先级调度:

  • 弹性资源优先级调度 支持通过自定义资源策略(ResourcePolicy)将 Pod 混合部署在 ECS 和 VCI 上,通过 VCI 的快速弹性能力应对突发峰值,保障业务长稳运行。
  • Pod 优先级调度即 Pod 抢占调度,高优先级的 Pod 可以在集群资源不足时抢占低优先级 Pod 的资源。Pod 优先级通过 PriorityClass 定义,定义完成后在负载中指定即可。

两种优先级调度可以共存,协力提升业务稳定性。

配置探针

在 Kubernetes 中,Pod 的探针(Probes)是用来检查容器是否健康运行的一种机制。探针对于维护集群的稳定性和可靠性起着至关重要的作用。Kubernetes 支持三种主要类型的探针,每种都有其特定的作用和用途:

  • 就绪探针(Readiness Probe):用于确定容器是否已经启动并准备接收流量。只有当就绪探针通过检查时,Pod 才会被标记为就绪状态,并可以被 Service 访问。
  • 存活探针(Liveness Probe):用于确定容器是否仍然活着并正常运行。如果存活探针失败,Kubernetes 将重启该容器。
  • 启动探针(Startup Probe):用于确定容器内应用程序是否已经准备好接收流量。相较于就绪指针,其主要用于保护需要一定时间进行初始化的进程。启动探针在容器启动后执行,直到探针成功,容器才会被视为就绪。

探针的配置与示例请参见 Kubernetes 官方文档:配置存活、就绪和启动探针

配置资源配额

对于 Pod 所使用的资源,可以配置requestlimit

  • request表示节点需要为 Pod 提供的最少资源数量。
  • limit表示 Pod 所能使用的资源数量的限制。

如果容器使用了超出limit的内存,则该容器会因为内存溢出(Out of Memory,OOM)而被重新拉起;如果容器使用了超出limit的 CPU,则该容器会被进行限速处理。

此外,建议配置临时存储(Ephemeral Storage)限制。在 Kubernetes 中,每个节点都有一定的本地磁盘空间可以用于存储容器的临时数据。临时存储是用来限制容器对这些本地磁盘资源的使用量,以避免容器过度使用本地磁盘资源导致节点磁盘空间不足或资源争用的情况。

说明

如果 Pod Ephemeral Storage 使用超出限额,会导致内存溢出。

配置服务质量等级

Kubernetes 依据 Pod 是否配置了内存/CPU 的requestlimit,将服务质量等级(QoS)优先级分为了三级:

  • Guaranteed:Pod 中所有容器均配置了requestlimit,且两个值在每个容器的配置中分别相等。
  • Burstable:Pod 里至少有一个容器配置了request,且不满足 Guaranteed 等级的要求,即内存/CPU 的值设置的不同。
  • BestEffort:Pod 中所有容器均未配置requestlimit

当 Kubernetes 集群内需要释放 Pod 时,会按照 QoS 优先级进行释放,因此建议将核心工作负载配置为最高优先级的 QoS。为避免因人为因素导致核心工作负载的 QoS 配置遗漏,Kubernetes 提供了 Limit Range 作为准入检查,即如果准入检查未通过则 Pod 将创建失败。Limit Range 的配置,请参见 设置资源限制

容器镜像加速

创建或更新工作负载后,容器镜像的拉起速度对业务变更的灰度、观测、回滚都至关重要。为此,火山引擎提供了 P2P 镜像加速容器镜像懒加载 两项能力,助力业务平稳迭代。

精简基础镜像

在构建业务镜像时,建议使用支持多架构的基础镜像进行构建。这些基础镜像只包含运行应用程序所需的最小组件,减少了攻击面和资源占用量,并提供了在多种架构上的平滑迁移能力。

常用基础镜像如下:

  • Alpine Linux:一个专为安全和资源效率而构建的轻量级 Linux 发行版。它的默认包管理器(apk)和小巧的基础镜像,使其成为了容器化应用程序的理想选择。Alpine Linux 提供了针对多架构的支持,包括amd64arm64armv6armv7等。
  • Distroless:由 Google 开发,是一种无包管理器的最小化基础镜像。它旨在消除传统 Linux 发行版中的包管理器及其带来的潜在安全风险。Distroless 镜像支持多种架构,并且提供了静态二进制文件,这些文件可以在没有依赖项的情况下运行。