配置 kubelet 镜像凭据提供程序
Kubernetes v1.26 [stable]
从 Kubernetes v1.20 开始,kubelet 可以使用 exec 插件动态获得针对某容器镜像库的凭据。 kubelet 使用 Kubernetes 版本化 API 通过标准输入输出(标准输入、标准输出和标准错误)和 exec 插件通信。这些插件允许 kubelet 动态请求容器仓库的凭据,而不是将静态凭据存储在磁盘上。 例如,插件可能会与本地元数据服务器通信,以获得 kubelet 正在拉取的镜像的短期凭据。
如果以下任一情况属实,你可能对此功能感兴趣:
- 需要调用云提供商的 API 来获得镜像库的身份验证信息。
- 凭据的到期时间很短,需要频繁请求新凭据。
- 将镜像库凭据存储在磁盘或者 imagePullSecret 是不可接受的。
本指南演示如何配置 kubelet 的镜像凭据提供程序插件机制。
使用服务帐号令牌拉取镜像
Kubernetes v1.34 [beta]
(enabled by default)从 Kubernetes v1.33 开始, 可以配置 kubelet 在为 Pod 执行镜像拉取时发送一个与该 Pod 绑定的服务账号令牌给凭据提供者插件。
这允许插件用该令牌交换访问镜像仓库的凭据。
要启用此特性,
必须在 kubelet 上启用 KubeletServiceAccountTokenForCredentialProviders
特性门控,
并且必须在插件的 CredentialProviderConfig
文件中设置 tokenAttributes
字段。
tokenAttributes
字段包含将传递给插件的服务帐号令牌的信息,
包括令牌的预期受众和插件是否要求 Pod 拥有服务帐号。
使用服务帐号令牌凭据可以启用以下用例:
- 避免需要基于 kubelet/节点的身份从镜像仓库拉取镜像。
- 允许工作负载根据其自身的运行时身份拉取镜像, 而无需长期存在的/持久化的 Secret。
准备开始
- 你需要一个 Kubernetes 集群,其节点支持 kubelet 凭据提供程序插件。 这种支持在 Kubernetes 1.34 中可用; Kubernetes v1.24 和 v1.25 将此作为 Beta 特性包含在内,默认启用。
- 如果你正在配置需要服务帐号令牌的凭据提供者插件,
你需要一个运行 Kubernetes v1.33 或更高版本的 Kubernetes 集群,
并且在 kubelet 上启用了
KubeletServiceAccountTokenForCredentialProviders
特性门控。 - 凭据提供程序 exec 插件的一种可用的实现。你可以构建自己的插件或使用云提供商提供的插件。
要获知版本信息,请输入 kubectl version
.
在节点上安装插件
凭据提供程序插件是将由 kubelet 运行的可执行二进制文件。 你需要确保插件可执行文件存在于你的集群的每个节点上,并存储在已知目录中。 稍后配置 kubelet 标志需要该目录。
配置 kubelet
为了使用这个特性,kubelet 需要设置以下两个标志:
--image-credential-provider-config
—— 凭据提供程序插件配置文件的路径。--image-credential-provider-bin-dir
—— 凭据提供程序插件二进制可执行文件所在目录的路径。
配置 kubelet 凭据提供程序
kubelet 会读取通过 --image-credential-provider-config
设定的配置文件,
以确定应该为哪些容器镜像调用哪些 exec 插件。
如果你正在使用基于 ECR-based 插件,
这里有个样例配置文件你可能最终会使用到:
apiVersion: kubelet.config.k8s.io/v1
kind: CredentialProviderConfig
# providers 是将由 kubelet 启用的凭据提供程序帮助插件列表。
# 多个提供程序可能与单个镜像匹配,在这种情况下,来自所有提供程序的凭据将返回到 kubelet。
# 如果为单个镜像调用了多个提供程序,则返回结果会被合并。
# 如果提供程序返回重叠的身份验证密钥,则使用提供程序列表中较早的值。
providers:
# name 是凭据提供程序的必需名称。
# 它必须与 kubelet 看到的提供程序可执行文件的名称相匹配。
# 可执行文件必须在 kubelet 的 bin 目录中
# (由 --image-credential-provider-bin-dir 标志设置)。
- name: ecr-credential-provider
# matchImages 是一个必需的字符串列表,用于匹配镜像以确定是否应调用此提供程序。
# 如果其中一个字符串与 kubelet 请求的镜像相匹配,则该插件将被调用并有机会提供凭据。
# 镜像应包含注册域和 URL 路径。
#
# matchImages 中的每个条目都是一个模式字符串,可以选择包含端口和路径。
# 可以在域中使用通配符,但不能在端口或路径中使用。
# 支持通配符作为子域(例如 "*.k8s.io" 或 "k8s.*.io")和顶级域(例如 "k8s.*")。
# 还支持匹配部分子域,如 "app*.k8s.io"。
# 每个通配符只能匹配一个子域段,因此 "*.io" **不** 匹配 "*.k8s.io"。
#
# 当以下所有条件都为真时,镜像和 matchImage 之间存在匹配:
#
# - 两者都包含相同数量的域部分并且每个部分都匹配。
# - matchImages 的 URL 路径必须是目标镜像 URL 路径的前缀。
# - 如果 matchImages 包含端口,则该端口也必须在镜像中匹配。
#
# matchImages 的示例值:
#
# - 123456789.dkr.ecr.us-east-1.amazonaws.com
# - *.azurecr.io
# - gcr.io
# - *.*.registry.io
# - registry.io:8080/path
matchImages:
- "*.dkr.ecr.*.amazonaws.com"
- "*.dkr.ecr.*.amazonaws.com.cn"
- "*.dkr.ecr-fips.*.amazonaws.com"
- "*.dkr.ecr.us-iso-east-1.c2s.ic.gov"
- "*.dkr.ecr.us-isob-east-1.sc2s.sgov.gov"
# defaultCacheDuration 是插件将在内存中缓存凭据的默认持续时间。
# 如果插件响应中未提供缓存持续时间。此字段是必需的。
defaultCacheDuration: "12h"
# exec CredentialProviderRequest 的必需输入版本。
# 返回的 CredentialProviderResponse 必须使用与输入相同的编码版本。当前支持的值为:
# - credentialprovider.kubelet.k8s.io/v1
apiVersion: credentialprovider.kubelet.k8s.io/v1
# 执行命令时传递给命令的参数。
# 可选
# args:
# - --example-argument
# env 定义了额外的环境变量以暴露给进程。
# 这些与主机环境以及 client-go 用于将参数传递给插件的变量结合在一起。
# 可选
env:
- name: AWS_PROFILE
value: example_profile
# tokenAttributes 是将传递给插件的服务账号令牌的配置。
# 凭证提供者通过设置此字段选择使用服务账号令牌进行镜像拉取。
# 如果在未启用 `KubeletServiceAccountTokenForCredentialProviders` 特性门控的情况下设置了此字段,
# kubelet 将因无效配置错误而无法启动。
# 可选
tokenAttributes:
# serviceAccountTokenAudience 是 projected service account token 的预期受众。
# 必需
serviceAccountTokenAudience: "<audience for the token>"
# cacheType 指示当使用服务账号令牌时,用于缓存插件返回凭据的缓存键的类型。
# 最保守的选择是将其设置为 "Token",这意味着 kubelet 将基于每个令牌缓存返回的凭据。
# 如果返回凭据的有效期限制于服务账号令牌的有效期,则应设置此项。
# 如果插件的凭据检索逻辑仅依赖于服务账号而不依赖于特定于 Pod 的申领,
# 那么插件可以将此设置为 "ServiceAccount"。在这种情况下,
# kubelet 将基于每个服务账号缓存返回的凭据。当返回的凭据对使用相同服务账号的所有 Pod 均有效时使用此选项。
# 必需
cacheType: "<Token or ServiceAccount>"
# requireServiceAccount 指示插件是否需要 Pod 拥有服务帐号。
# 如果设置为 true,kubelet 仅在 Pod 拥有服务账号时才会调用插件。
# 如果设置为 false,即使 Pod 没有服务账号,kubelet 也会调用插件,
# 并且不会在 CredentialProviderRequest 中包含令牌。这对于用于拉取没有服务账号的 Pod(例如静态 Pod)镜像的插件非常有用。
# 必需
requireServiceAccount: true
# requiredServiceAccountAnnotationKeys 是插件感兴趣的注解键列表,
# 并且这些键需要存在于服务帐号中。
# 在此列表中定义的键将从相应的服务帐号中提取,并作为 CredentialProviderRequest 的一部分传递给插件。
# 如果此列表中定义的任何一个键不存在于 service account 中,kubelet 将不会调用插件并返回错误。
# 此字段是可选的,可以为空。插件可以使用此字段提取获取凭据所需的额外信息,
# 或允许工作负载选择使用服务帐号令牌进行镜像拉取。
# 如果非空,则 requireServiceAccount 必须设置为 true。
# 此列表中定义的键必须唯一且不与 optionalServiceAccountAnnotationKeys 列表中定义的键重叠。
# 可选
requiredServiceAccountAnnotationKeys:
- "example.com/required-annotation-key-1"
- "example.com/required-annotation-key-2"
# optionalServiceAccountAnnotationKeys 是插件感兴趣的注解键列表,
# 并且这些键在服务帐号中是可选存在的。
# 在此列表中定义的键将从相应的 service account 中提取,并作为 CredentialProviderRequest 的一部分传递给插件。
# 插件负责验证注解及其值的存在性。此字段是可选的,可以为空。
# 插件可以使用此字段提取获取凭据所需的额外信息。
# 此列表中定义的键必须唯一且不与 requiredServiceAccountAnnotationKeys 列表中定义的键重叠。
# 可选
optionalServiceAccountAnnotationKeys:
- "example.com/optional-annotation-key-1"
- "example.com/optional-annotation-key-2"
providers
字段是 kubelet 所使用的已启用插件列表。每个条目都有几个必填字段:
name
:插件的名称,必须与传入--image-credential-provider-bin-dir
的目录中存在的可执行二进制文件的名称相匹配。matchImages
:字符串列表,用于匹配镜像以确定是否应调用此提供程序。 更多相关信息参见后文。defaultCacheDuration
:如果插件未指定缓存时长,kubelet 将在内存中缓存凭据的默认时长。apiVersion
:kubelet 和 exec 插件在通信时将使用的 API 版本。
每个凭据提供程序也可以被赋予可选的参数和环境变量。 你可以咨询插件实现者以确定给定插件需要哪些参数和环境变量集。
如果你正在使用 KubeletServiceAccountTokenForCredentialProviders 特性门控 并且通过设置 tokenAttributes 字段配置插件使用服务帐号令牌, 那么需要以下字段:
serviceAccountTokenAudience
: 预期的投射服务账号令牌的受众。 这不能是空字符串。
cacheType: 当使用服务账号令牌时,用于缓存插件返回凭据的缓存键的类型。 最保守的选择是将其设置为 Token, 这意味着 kubelet 将基于每个令牌缓存返回的凭据。 如果返回凭据的有效期限制于服务账号令牌的有效期,则应设置此项。 如果插件的凭据检索逻辑仅依赖于服务账号而不依赖于特定于 Pod 的申领, 那么插件可以将此设置为 ServiceAccount。 在这种情况下,kubelet 将基于每个服务账号缓存返回的凭据。 当返回的凭据对使用相同服务账号的所有 Pod 均有效时使用此选项。
requireServiceAccount
: 插件是否要求 Pod 拥有服务帐号。
- 如果设置为
true
,kubelet 只会在 Pod 拥有服务账号时 调用插件。 - 如果设置为
false
,即使 Pod 没有服务帐号, kubelet 也会调用插件,并且不会在CredentialProviderRequest
中包含令牌。
这对于用于拉取没有服务帐号的 Pod 的镜像的插件非常有用 (例如,静态 Pod)。
配置镜像匹配
kubelet 使用每个凭据提供程序的 matchImages
字段来确定是否应该为 Pod
正在使用的给定镜像调用插件。
matchImages
中的每个条目都是一个镜像模式字符串,可以选择包含端口和路径。
可以在域中使用通配符,但不能在端口或路径中使用。
支持通配符作为子域,如 *.k8s.io
或 k8s.*.io
,以及顶级域,如 k8s.*
。
还支持匹配部分子域,如 app*.k8s.io
。每个通配符只能匹配一个子域段,
因此 *.io
不匹配 *.k8s.io
。
当以下条件全部满足时,镜像名称和 matchImage
条目之间存在匹配:
- 两者都包含相同数量的域部分并且每个部分都匹配。
- 匹配图片的 URL 路径必须是目标图片 URL 路径的前缀。
- 如果 matchImages 包含端口,则该端口也必须在镜像中匹配。
matchImages
模式的一些示例值:
123456789.dkr.ecr.us-east-1.amazonaws.com
*.azurecr.io
gcr.io
*.*.registry.io
foo.registry.io:8080/path
接下来
- 阅读 kubelet 配置 API(v1)参考中有关
CredentialProviderConfig
的详细信息。 - 阅读 kubelet 凭据提供程序 API 参考(v1)。