本页面介绍了如何在 Google Kubernetes Engine (GKE) 中使用映像流式传输,以通过流式传输应用所需的映像数据来拉取容器映像。
运行 GKE 1.25.5-gke.1000 版及更高版本的新 Autopilot 集群会自动使用映像流式传输来拉取符合条件的映像。本页面中的说明仅适用于 Standard 集群。
概览
映像流式传输是一种拉取容器映像的方法,在这种方法中,GKE 会按照您的应用的要求从符合条件的映像中流式传输数据。您可以使用映像流式传输来允许工作负载初始化,而无需等待整个映像下载,这会显著缩短初始化时间。缩短拉取时间具有以下优势:
- 更快的自动扩缩
- 缩短了拉取大型映像时的延迟时间
- 加快了 Pod 启动速度
如果使用映像流式传输,GKE 会将远程文件系统用作使用符合条件的容器映像的任何容器的根文件系统。GKE 会根据您的工作负载需要从远程文件系统流式传输映像数据。如果不使用映像流式传输,GKE 会将整个容器映像下载到每个节点上,并将其用作工作负载的根文件系统。
在流式传输映像数据时,GKE 会将整个容器映像下载到后台当地硬盘并缓存。然后,GKE 会传送来自缓存映像的未来数据读取请求。
当您部署需要读取容器映像中的特定文件的工作负载时,映像流式传输后端仅传送这些请求的文件。
使用要求
如需在 GKE Autopilot 和 Standard 集群中使用映像流式传输,您必须满足以下要求:
您必须启用 Container File System API。
新的 Autopilot 集群必须运行 GKE 1.25.5-gke.1000 版或更高版本,才能自动启用映像流式传输。如需了解相关说明,请参阅设置新的 Autopilot 集群的版本和发布渠道。
新的和现有的 GKE Standard 集群必须运行 1.18.6-gke.4801 版或更高版本。
您必须将 Container-Optimized OS 与 containerd 节点映像搭配使用。 Autopilot 节点始终使用此节点映像。
您的容器映像必须存储在 Artifact Registry 中。
如果您使用专用集群,则必须在子网上启用专用 Google 访问通道,这样节点才能访问映像流式传输 Service。
如果 VPC Service Controls 在保护您的容器映像,并且您使用了映像流式传输,则还必须在服务边界内添加 Image Streaming API (
containerfilesystem.googleapis.com
)。
限制
- 1.23.5-gke.1900 之前的 GKE 版本不支持使用 Secret 拉取容器映像。
- 使用 V2 映像清单,架构版本 1 的容器映像不符合条件。
- 使用客户管理的加密密钥 (CMEK) 加密的容器映像符合 GKE 1.25.3-gke.1000 或更高版本的映像流式传输的条件。在以前的版本中,GKE 会下载这些映像,但不会流式传输数据。您仍然可以使用 CMEK 来保护使用映像流式传输的集群中的挂接永久性磁盘和自定义启动磁盘。
- 具有重复层的容器映像只能用于 GKE 1.28 或更高版本上的映像流式传输。在早期的版本中,GKE 会下载这些映像,但不会流式传输数据。检查容器映像是否存在空层或重复层。
- Artifact Registry 代码库必须与您的 GKE 节点位于同一区域中,或者位于与您的节点运行的区域相对应的多区域中。例如:
- 如果您的节点位于
us-east1
,则映像流式传输可用于us-east1
区域或us
多区域的代码库,因为 GKE 和 Artifact Registry 都在美国境内的数据中心位置运行。 - 如果您的节点位于
northamerica-northeast1
区域,则这些节点在加拿大运行。在这种情况下,映像流式传输仅适用于同一区域中的代码库。
- 如果您的节点位于
- 如果您的工作负载在初始化期间读取映像中的许多文件,您可能会注意到初始化时间增加,因为远程文件读取导致的延迟。
- 在符合条件的映像首次拉取期间,您可能不会注意到映像流式传输的优势。但是,在映像流缓存映像后,将来的映像将受益于任何映像流式传输。
- GKE Standard 集群使用集群级配置来确定是否在使用节点自动预配功能创建的新节点池上启用映像流式传输。但是,如果在集群级层停用映像流式传输,您无法使用工作负载分离来创建启用了映像流式传输的节点池。
- GKE 1.22.6-gke.300 版及更高版本的映像流式传输支持 Linux 文件功能,例如
CAP_NET_RAW
。对于以前的 GKE 版本,当流处理映像文件或将映像保存到本地磁盘时,这些功能不可用。为避免潜在的中断,请勿在 1.22.6-gke.300 之前的 GKE 版本中对具有这些功能的容器使用映像流式传输。 如果您的容器依赖于 Linux 文件功能,则在启用映像流式传输功能的情况下运行时,它可能无法启动并发出没有权限错误。
准备工作
在开始之前,请确保您已执行以下任务:
- 启用 Google Kubernetes Engine API。 启用 Google Kubernetes Engine API
- 如果您要使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行
gcloud components update
以获取最新版本。
启用 Container File System API。
在集群上启用映像流式传输
您可以使用 gcloud CLI --enable-image-streaming
标志或使用 Google Cloud 控制台在新的或现有的 Standard 集群上启用映像流式传输。默认情况下,集群中的节点池会继承集群级层的映像流式传输设置。您可以通过在集群中的节点池上启用或停用映像流式传输来更改此行为。
运行 GKE 1.25.5-gke.1000 版及更高版本的所有新 Autopilot 集群都使用映像流式传输来拉取符合条件的映像。如需了解相关说明,请参阅设置新的 Autopilot 集群的版本和发布渠道。以下说明仅适用于 GKE Standard 集群。
在新集群上
您可以使用 gcloud CLI 或 Google Cloud 控制台在新集群上启用映像流式传输。
gcloud
如需创建启用了映像流式传输的新集群,请运行以下命令:
gcloud container clusters create CLUSTER_NAME \
--zone=COMPUTE_ZONE \
--image-type="COS_CONTAINERD" \
--enable-image-streaming
替换以下内容:
CLUSTER_NAME
:新集群的名称。COMPUTE_ZONE
:新集群的 Compute Engine 区域。对于区域级集群,请改用--region=COMPUTE_REGION
标志。确保该地区或区域位于同一映像或包含映像的 Artifact Registry 代码库的多区域内。
控制台
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
点击 add_box 创建。
在 GKE Standard 部分中,点击配置。
在导航窗格的集群下,点击功能。
在其他部分中,选中启用映像流式传输复选框。
根据需要配置集群,然后点击创建。
在现有集群上
您可以使用 gcloud CLI 或 Google Cloud 控制台在满足要求的现有集群上启用映像流式传输。
gcloud
如需更新现有集群以使用映像流式传输,请使用 gcloud CLI 运行以下命令:
gcloud container clusters update CLUSTER_NAME \
--enable-image-streaming
控制台
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
点击要修改的集群的名称。
在集群页面的功能部分中,点击映像流式传输旁边的 edit。
在修改映像流式传输对话框中,选中启用映像流式传输复选框。
点击保存更改。
修改集群后,默认情况下 GKE 会自动在现有节点池上启用映像流式传输。如果您在个别节点池上明确启用或停用了映像流式传输,则这些节点池不会继承对集群级层设置的更改。
验证集群上是否已启用映像流式传输
您可以使用 gcloud CLI 或 Google Cloud 控制台检查集群级是否启用了映像流式传输。
gcloud
运行以下命令:
gcloud container clusters describe CLUSTER_NAME \
--flatten "nodePoolDefaults.nodeConfigDefaults"
如果输出类似于以下内容,则表示设置已启用:
gcfsConfig:
enabled: true
...
如果输出类似于以下内容,则表示设置已停用:
gcfsConfig: {}
...
控制台
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
点击要检查的集群的名称。
在集群页面的功能部分中,它会显示映像流式传输旁边的设置是否已启用。
在节点池上启用映像流式传输
默认情况下,节点池会继承集群级层的映像流式传输设置。您可以使用 gcloud CLI 在特定节点池上启用或停用映像流式传输。
在新节点池上
如需创建启用了映像流式传输的新节点池,请运行以下命令:
gcloud container node-pools create NODE_POOL_NAME \
--cluster=CLUSTER_NAME \
--zone=COMPUTE_ZONE \
--image-type="COS_CONTAINERD" \
--enable-image-streaming
替换以下内容:
NODE_POOL_NAME
:新节点池的名称。CLUSTER_NAME
:节点池的集群名称。COMPUTE_ZONE
:集群的 Compute Engine 可用区。对于区域级集群,请改用--region=COMPUTE_REGION
标志。
在现有节点池上
您可以在满足要求的现有节点池上启用映像流式传输。
如需更新现有节点池以使用映像流式传输,请运行以下命令:
gcloud container node-pools update POOL_NAME \
--cluster=CLUSTER_NAME \
--enable-image-streaming
验证节点池上是否启用了映像流式传输
检查节点池是否启用了映像流式传输:
gcloud container node-pools describe POOL_NAME \
--cluster=CLUSTER_NAME \
如果输出类似于以下内容,则表示设置已启用:
gcfsConfig:
enabled: true
...
如果输出类似于以下内容,则表示设置已停用:
gcfsConfig: {}
...
使用映像流式传输安排工作负载
在集群上启用映像流式传输后,GKE 会在从 Artifact Registry 中拉取符合条件的容器映像时自动使用映像流式传输,而无需进一步配置。
GKE 会向启用了映像流式传输的节点池中的节点添加 cloud.google.com/gke-image-streaming: "true"
标签。在 GKE Standard 中,如果您在特定节点池上启用或停用映像流式传输,以便集群混合使用映像流式传输的节点和不使用映像流式传输的节点,则可以在部署中使用节点选择器,以控制 GKE 是否在使用映像流式传输的节点上调度工作负载。
在以下示例中,您安排了在启用了映像流式传输的集群上使用大型容器映像的 Deployment。然后,您可以选择将性能与未启用映像流式传输的映像拉取进行比较。
创建启用了映像流式传输的新集群:
gcloud container clusters create CLUSTER_NAME \ --zone=COMPUTE_ZONE \ --enable-image-streaming \ --image-type="COS_CONTAINERD"
获取集群的凭据:
gcloud container clusters get-credentials CLUSTER_NAME \ --zone=COMPUTE_ZONE
将以下清单保存为
frontend-deployment.yaml
:apiVersion: apps/v1 kind: Deployment metadata: name: frontend spec: replicas: 1 selector: matchLabels: app: guestbook tier: frontend template: metadata: labels: app: guestbook tier: frontend spec: containers: - name: php-redis image: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5 env: - name: GET_HOSTS_FROM value: "dns" resources: requests: cpu: 100m memory: 100Mi ports: - containerPort: 80
gb-frontend
容器映像的大小为 327 MB。将清单应用到您的集群:
kubectl apply -f frontend-deployment.yaml
验证 GKE 是否已创建 Deployment:
kubectl get pods -l app=guestbook
输出内容类似如下:
NAMESPACE NAME READY STATUS RESTARTS AGE default frontend-64bcc69c4b-pgzgm 1/1 Completed 0 3s
获取 Kubernetes 事件日志以查看映像拉取事件:
kubectl get events --all-namespaces
输出内容类似如下:
NAMESPACE LAST SEEN TYPE REASON OBJECT MESSAGE default 11m Normal Pulling pod/frontend-64bcc69c4b-pgzgm Pulling image "us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5" default 11m Normal Pulled pod/frontend-64bcc69c4b-pgzgm Successfully pulled image "us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5" in 1.536908032s default 11m Normal ImageStreaming node/gke-riptide-cluster-default-pool-f1552ec4-0pjv Image us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5 is backed by image streaming. ...
在此输出中:
Pulled
事件显示映像流式传输拉取映像所需的时间。ImageStreaming
事件表明该节点使用映像传送来传送容器映像。
比较标准映像拉取的性能
在此可选示例中,您将创建一个停用了映像流式传输的新集群,并部署 frontend
Deployment 以比较映像流式传输的性能。
创建停用了映像流式传输的新集群:
gcloud container clusters create CLUSTER2_NAME\ --zone=COMPUTE_ZONE \ --image-type="COS_CONTAINERD"
获取集群的凭据:
gcloud container clusters get-credentials CLUSTER2_NAME \ --zone=COMPUTE_ZONE
部署上一个示例中的
frontend
Deployment:kubectl apply -f frontend-deployment.yaml
获取 Kubernetes 事件日志:
kubectl get events --all-namespaces
输出内容类似如下:
NAMESPACE LAST SEEN TYPE REASON OBJECT MESSAGE default 87s Normal Pulled pod/frontend-64bcc69c4b-qwmfp Successfully pulled image "us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5" in 23.929723476s
请注意 GKE 拉取整个映像所花费的时间。在此示例输出中,GKE 几乎需要 24 秒。启用映像流式传输后,GKE 只需要 1.5 秒即可拉取工作负载启动所需的映像数据。
清理
为避免产生费用,请删除您在之前示例中创建的集群:
gcloud container clusters delete CLUSTER_NAME CLUSTER2_NAME
停用映像流式传输
如果您使用 GKE Autopilot,则无法在单个集群上停用映像流式传输。您可以停用 Container File System API,这会对整个项目停用映像流式传输。
如果您使用 GKE Standard 集群,则可以在单个集群或特定节点池上停用映像流式传输,如以下部分所述。
在 GKE Standard 集群上停用映像流式传输
您可以使用 gcloud CLI 或 Google Cloud 控制台在现有 GKE Standard 集群上停用映像流式传输。
gcloud
如需在现有集群上停用映像流式传输,请运行以下命令:
gcloud container clusters update CLUSTER_NAME \
--no-enable-image-streaming
控制台
转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。
点击要修改的集群的名称。
在集群页面的功能下,点击映像流式传输旁边的 edit。
在修改映像流式传输对话框中,清除启用映像流式传输复选框。
点击保存更改。
在新节点池上
如需在创建新节点池时停用映像流式传输,请指定 --no-enable-image-streaming
标志,如以下命令所示:
gcloud container node-pools create NODE_POOL_NAME \
--cluster=CLUSTER_NAME \
--zone=COMPUTE_ZONE \
--no-enable-image-streaming
在现有节点池上
如需在现有节点池上停用映像流式传输,请运行以下命令:
gcloud container node-pools update NODE_POOL_NAME \
--cluster=CLUSTER_NAME
--no-enable-image-streaming
为映像流式传输预留内存
除了为节点系统组件预留的内存之外,GKE 还会为映像流式传输预留内存资源。 GKE 不会为映像流式传输预留额外的 CPU 资源。在 GKE Standard 集群中,此预留会更改您可以在 Pod 中请求的内存资源。在 GKE Autopilot 中,GKE 会管理系统分配,因此调度工作负载没有任何影响。
如需详细了解 GKE 为节点组件预留的内存,请参阅标准集群架构。
在使用映像流式传输的节点中,GKE 会预留以下额外的内存:
- 内存不足 1 GiB 的机器无额外内存
- 前 4 GiB 内存的 10%
- 接下来 4 GiB 内存(最多 8 GiB)的 8%
- 接下来 8 GiB 内存(最多 16 GiB)的 4%
- 接下来 112 GiB 内存(最多 128 GiB)的 2.4%
- 128 GiB 以上任何内存的 0.8%
问题排查
GKE 不使用映像流式传输文件系统
如果您的 GKE 事件日志未显示映像流式传输事件,则您的映像不受远程文件系统支持。如果 GKE 之前在节点上拉取映像,则这是预期行为,因为 GKE 使用映像的本地缓存进行后续拉取,而不是使用映像流式传输。如需验证这一点,您可以在 Pod Pulled
事件的 Message
字段中查找 Container image IMAGE_NAME already present on machine
。
如果您在节点上首次拉取映像时没有看到映像流式传输事件,请确保满足映像流式传输的要求。如果满足要求,您可以通过检查映像流式传输服务(名为 gcfsd
)的日志来诊断问题:
进入 Google Cloud 控制台中的日志浏览器页面。
在查询字段中,指定以下查询:
logName="projects/PROJECT_ID/logs/gcfsd" resource.labels.cluster_name="CLUSTER_NAME"
请替换以下内容:
PROJECT_ID
:您的项目的名称。CLUSTER_NAME
:您的集群的名称。
点击运行查询。
您还可以使用日志浏览器检查 gcfsd
日志:
转到 Google Cloud 控制台中的日志浏览器:
在查询字段中,指定以下查询:
logName="projects/PROJECT_ID/logs/gcfsd"
将
PROJECT_ID
替换为您的 Google Cloud 项目 ID。
PermissionDenied
如果 gcfsd
日志显示类似于以下内容的错误消息,则表示节点没有正确的 API 范围。GKE 会拉取容器映像,而不使用映像流式传输。
level=fatal msg="Failed to create a Container File System client: rpc error:
code = PermissionDenied desc = failed to probe endpoint: rpc error: code = PermissionDenied
desc = Request had insufficient authentication scopes."
您可以通过向节点授予正确的范围以允许其使用映像流式传输来解决此问题。将 devstorage.read_only
范围添加到集群或节点池,类似于以下命令:
gcloud container node-pools create NODE_POOL_NAME \
--cluster=CLUSTER_NAME \
--zone=COMPUTE_ZONE \
--image-type="COS_CONTAINERD" \
--enable-image-streaming \
--scope="https://www.googleapis.com/auth/devstorage.read_only"
FailedPrecondition
如果您发现 code = FailedPrecondition
错误消息,则映像未导入映像流式传输远程文件系统。
如果您尝试使用现有节点池进行映像流式传输,则可能会注意到此错误。如果节点池中的节点已有磁盘上的容器映像,则 GKE 会使用本地映像,而不是使用映像流式传输来获取映像。
如需解决此问题,请尝试以下操作:
- 等待几分钟,然后再次尝试部署工作负载。
- 添加新节点或新节点池,并在这些节点上安排工作负载。
InvalidArgument
如果您发现 code=InvalidArgument
错误消息,则您的工作负载使用的容器映像不符合映像流式传输的条件。确保映像满足要求。如果您的映像不在 Artifact Registry 上,请尝试迁移到 Artifact Registry。
backend.FileContent failed
读取启用了图片流式传输功能的容器文件时,可能会出现以下错误:
level=error msg="backend.FileContent failed" error="rpc error: code = ResourceExhausted desc = Quota exceeded for quota metric 'Content requests per project per region' and limit 'Content requests per project per region per minute per region' of service 'containerfilesystem.googleapis.com' for consumer 'project_number:PROJECT_NUMBER'." layer_id="sha256:1234567890" module=gcfs_backend offset=0 path=etc/passwd size=4096
此错误表示项目已超出从远程容器文件系统服务读取文件所需的配额。如需解决此问题,请增加以下配额:
- 每个区域每个项目每分钟的内容请求数
- 每个区域每个项目的内容请求数
GKE 会下载映像,但不进行数据流式传输
使用客户管理的加密密钥 (CMEK) 的容器映像仅适用于 GKE 1.25.3-gke.1000 或更高版本的映像流式传输。具有重复层的容器映像只能用于 GKE 1.28 或更高版本上的映像流式传输。如需了解详情,请参阅限制。
检查是否存在空层或重复层
如需检查容器映像是否存在空层或重复层,请运行以下命令:
docker inspect IMAGE_NAME
将 IMAGE_NAME
替换为容器映像的名称。
在该命令的输出中,检查 "Layers"
下的条目。
如果其中一个条目与以下 "sha256"
输出完全匹配,则容器映像具有空层,不符合映像流式传输的条件。
"Layers": [ ... "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4", ... ]
如果存在重复条目(如以下示例所示),则容器映像具有重复层,不符合映像流式传输的条件。
"Layers": [
"sha256:28699c71935fe3ffa56533db44ad93e5a30322639f7be70d5d614e06a1ae6d9b",
...
"sha256:28699c71935fe3ffa56533db44ad93e5a30322639f7be70d5d614e06a1ae6d9b",
...
]
对符号链接文件执行的 mv
命令和 renameat2
系统调用失败
对于运行 1.25 及更高版本的 GKE 节点,启用映像流式传输后,对容器映像中的符号链接文件执行的 mv
命令和 renameat2
系统调用可能会失败,并显示错误消息“没有此设备或地址”。该问题是由近期的 Linux 内核倒退造成的。GKE 目前没有该问题的修复方法。
这些系统调用并不常见,因此大多数映像不受此问题的影响。应用准备运行和移动文件时,在容器初始化阶段通常会出现此问题。无法在本地测试映像,因此 GKE 建议在生产环境中使用映像之前,在测试环境中使用映像流式传输找出问题。
为了为受影响工作负载缓解此问题,您可以尝试替换导致 renameat2
系统调用的代码。如果您无法修改代码,则必须在节点池上停用映像流式传输来缓解问题。