如果您在 Kubernetes 上运行工作负载,很可能经历过“冷启动”:当工作负载被安排到以前没有托管过它们的节点上并且 Pod 需要从头开始启动时,发生的应用启动延迟。启动时间变长,可能导致较长的响应时间和糟糕的用户体验,尤其是在应用自动扩缩以处理流量激增情况时。
冷启动期间发生了什么?在 Kubernetes 上部署容器化应用通常涉及几个步骤,包括拉取容器映像、启动容器和初始化应用代码。这些过程都会造成 Pod 需要更长时间才能开始处理流量,进而导致新 Pod 处理的第一批请求的延迟时间增加。初始启动时间可能会明显较长,因为新节点上没有现成的容器映像。对于后续请求,Pod 已经启动并预热,因此可以快速处理请求,而无需额外的启动时间。
随着 Pod 不断关闭和重启,冷启动会频繁发生,导致将请求发给新的冷 Pod 进行处理。一种常见的解决方案是准备好多组预热过的 Pod 池,以减少冷启动延迟时间。
但是,对于 AI / ML 等大体量的工作负载,特别是在昂贵且稀缺的 GPU 上,这种预热池的成本可能会非常高。因此,对于这类工作负载,通常会在请求处理完成后关闭 Pod,导致其冷启动现象尤其普遍。
Google Kubernetes Engine (GKE) 是 Google Cloud 的托管式 Kubernetes 服务,可让您更轻松地部署和维护复杂的容器化工作负载。在这篇博文中,我们将介绍 4 种在 GKE 上减少冷启动延迟时间的方法,让您的服务响应更迅捷。
克服冷启动挑战的方法
1. 使用本地 SSD 或较大的启动磁盘支持的临时存储空间
节点会将 Kubelet 和容器运行时(docker 或 containerd)根目录装载到本地固态硬盘 (SSD) 上。因此,容器层由本地 SSD 支持。您可以参阅关于本地 SSD,了解 IOPS 和吞吐量。这通常比增加永久性磁盘 (PD) 大小更具成本效益。
下表对各选项进行了比较,并表明在费用相同的情况下,本地 SSD 的吞吐量大约是 PD 的 3 倍,可让您更快地拉取映像,减少工作负载的启动延迟时间。
您可以在 GKE 1.25.3-gke.1800 或更高版本上运行的现有集群中,创建一个使用本地 SSD 支持的临时存储空间的节点池。
gcloud container node-pools create POOL_NAME \\ --cluster=CLUSTER_NAME \\ --ephemeral-storage-local-ssd count=<NUMBER_OF_DISKS> \\ --machine-type=MACHINE_TYPE |
如需了解详情,请参阅使用本地 SSD 预配临时存储空间。
2. 启用容器映像流式传输
映像流式传输让您无需等待整个映像下载完毕即可启动工作负载,显著缩短工作负载启动时间。例如,借助 GKE 映像流式传输,Nvidia Triton 服务器(容器映像为 5.4 GB)的端到端启动时间(从工作负载创建,到服务器启动,可处理流量)可以从 191 秒减少到 30 秒。
您必须为容器使用 Artifact Registry,并满足各项要求。可通过以下代码在集群上启用映像流式传输:
gcloud container clusters create CLUSTER_NAME \\ --zone=COMPUTE_ZONE \\ --image-type="COS_CONTAINERD" \\ --enable-image-streaming |
如需了解详情,请参阅使用映像流式传输拉取容器映像。
3. 使用通过 Zstandard 压缩的容器映像
Zstandard 压缩是 ContainerD 中支持的一项功能。Zstandard 基准显示,zstd 的解压缩速度是当前默认选项 gzip 的 3 倍多。
以下代码显示了如何在 docker buildx 中使用 zstd 构建器:
docker buildx create --name zstd-builder --driver docker-container \\ --driver-opt image=moby/buildkit:v0.10.3 docker buildx use zstd-builder |
以下代码显示了如何构建和推送映像:
IMAGE_URI=us-central1-docker.pkg.dev/taohe-gke-dev/example IMAGE_TAG=v1 <Create your Dockerfile> docker buildx build --file Dockerfile --output type=image,name=$IMAGE_URI:$IMAGE_TAG,oci-mediatypes=true,compression=zstd,compression-level=3,force-compression=true,push=true . |
请注意,Zstandard 与映像流式传输不兼容。如果您的应用需要在启动之前加载大部分容器映像内容,您最好使用 Zstandard。如果您的应用只需要加载整个容器映像的一小部分就可以开始执行,不妨尝试使用映像流式传输。
4. 使用预加载器 DaemonSet 在节点上预加载基础容器
最后但同样重要的是,如果不同容器共用同一基础容器,ContainerD 可以跨这些容器重用映像层。预加载器 DaemonSet 甚至可以在 GPU 驱动程序安装之前开始运行(驱动程序安装大约需要 30 秒)。这意味着它能够在 GPU 工作负载可以安排到 GPU 节点之前,预加载所需的容器,并提前开始拉取映像。
以下是预加载器 DaemonSet 的一个示例。
apiVersion: apps/v1 kind: DaemonSet metadata: name: container-preloader labels: k8s-app: container-preloader spec: selector: matchLabels: k8s-app: container-preloader updateStrategy: type: RollingUpdate template: metadata: labels: name: container-preloader k8s-app: container-preloader spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: cloud.google.com/gke-accelerator operator: Exists tolerations: - operator: "Exists" containers: - image: "<CONTAINER_TO_BE_PRELOADED>" name: container-preloader command: [ "sleep", "inf" ] |
智胜冷启动
冷启动是容器编排系统中的一个常见挑战。通过精心规划和优化,您可以减轻它对 GKE 上运行的应用造成的影响。使用较大的启动磁盘支持的临时存储空间,启用容器流式传输或 Zstandard 压缩,以及使用 DaemonSet 预加载基础容器,可以减少冷启动延迟,确保系统响应更快、效率更高。如需详细了解 GKE,请参阅用户指南。
文章信息
相关推荐
