配置 kubelet 镜像凭据提供程序
Kubernetes v1.26 [stable]
从 Kubernetes v1.20 开始,kubelet 可以使用 exec 插件动态获得针对某容器镜像库的凭据。 kubelet 使用 Kubernetes 版本化 API 通过标准输入输出(标准输入、标准输出和标准错误)和 exec 插件通信。这些插件允许 kubelet 动态请求容器仓库的凭据,而不是将静态凭据存储在磁盘上。 例如,插件可能会与本地元数据服务器通信,以获得 kubelet 正在拉取的镜像的短期凭据。
如果以下任一情况属实,你可能对此功能感兴趣:
- 需要调用云提供商的 API 来获得镜像库的身份验证信息。
- 凭据的到期时间很短,需要频繁请求新凭据。
- 将镜像库凭据存储在磁盘或者 imagePullSecret 是不可接受的。
本指南演示如何配置 kubelet 的镜像凭据提供程序插件机制。
使用服务帐号令牌拉取镜像
Kubernetes v1.33 [alpha]
(enabled by default: false)从 Kubernetes v1.33 开始, 可以配置 kubelet 在为 Pod 执行镜像拉取时发送一个与该 Pod 绑定的服务账号令牌给凭据提供者插件。
这允许插件用该令牌交换访问镜像仓库的凭据。
要启用此特性,
必须在 kubelet 上启用 KubeletServiceAccountTokenForCredentialProviders
特性门控,
并且必须在插件的 CredentialProviderConfig
文件中设置 tokenAttributes
字段。
tokenAttributes
字段包含将传递给插件的服务帐号令牌的信息,
包括令牌的预期受众和插件是否要求 Pod 拥有服务帐号。
使用服务帐号令牌凭据可以启用以下用例:
- 避免需要基于 kubelet/节点的身份从镜像仓库拉取镜像。
- 允许工作负载根据其自身的运行时身份拉取镜像, 而无需长期存在的/持久化的 Secret。
准备开始
- 你需要一个 Kubernetes 集群,其节点支持 kubelet 凭据提供程序插件。 这种支持在 Kubernetes 1.33 中可用; 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>"
# 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
: 预期的投射服务帐号令牌的受众。 这不能是空字符串。requireServiceAccount
: 插件是否要求 Pod 拥有服务帐号。
- 如果设置为
true
,kubelet 只会在 Pod 拥有 service account 时 调用插件。 - 如果设置为
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)。