秘密
Secret 是一个包含少量敏感数据的对象,例如密码、令牌或密钥。此类信息可能被放置在 Pod 规范或 容器镜像 中。使用 Secret 意味着您无需在应用程序代码中包含机密数据。
因为 Secret 可以独立于使用它们的 Pod 创建,所以 Secret(及其数据)在创建、查看和编辑 Pod 的工作流期间暴露的风险较低。Kubernetes 以及在您的集群中运行的应用程序还可以对 Secret 采取额外的预防措施,例如避免将敏感数据写入非易失性存储。
Secret 类似于 ConfigMaps,但它们专门用于保存机密数据。
注意
默认情况下,Kubernetes Secret 未加密存储在 API 服务器的基础数据存储(etcd)中。任何拥有 API 访问权限的人都可以检索或修改 Secret,etcd 的访问者也是如此。此外,任何被授权在命名空间中创建 Pod 的人都可以使用该访问权限来读取该命名空间中的任何 Secret;这包括间接访问,例如创建 Deployment 的能力。
为了安全地使用 Secret,请至少执行以下步骤
- 为 Secret 启用静态加密。
- 使用最小权限访问 Secret 启用或配置 RBAC 规则。
- 限制特定容器对 Secret 的访问。
- 考虑使用外部 Secret 存储提供程序.
有关管理和改善 Secret 安全性的更多指南,请参阅 Kubernetes Secret 的最佳实践。
有关更多详细信息,请参阅 Secret 的信息安全。
Secret 的用途
您可以将 Secret 用于以下目的
Kubernetes 控制平面也使用 Secret;例如,启动令牌 Secret 是一种帮助自动执行节点注册的机制。
用例:Secret 卷中的点文件
您可以通过定义一个以点开头的密钥来使您的数据“隐藏”。该密钥表示一个点文件或“隐藏”文件。例如,当以下 Secret 挂载到一个名为 secret-volume
的卷中时,该卷将包含一个名为 .secret-file
的文件,并且 dotfile-test-container
将在路径 /etc/secret-volume/.secret-file
中存在此文件。
注意
以点字符开头的文件在ls -l
的输出中是隐藏的;您必须使用 ls -la
才能在列出目录内容时看到它们。apiVersion: v1
kind: Secret
metadata:
name: dotfile-secret
data:
.secret-file: dmFsdWUtMg0KDQo=
---
apiVersion: v1
kind: Pod
metadata:
name: secret-dotfiles-pod
spec:
volumes:
- name: secret-volume
secret:
secretName: dotfile-secret
containers:
- name: dotfile-test-container
image: registry.k8s.io/busybox
command:
- ls
- "-l"
- "/etc/secret-volume"
volumeMounts:
- name: secret-volume
readOnly: true
mountPath: "/etc/secret-volume"
用例:对 Pod 中的一个容器可见的 Secret
考虑一个需要处理 HTTP 请求、执行一些复杂的业务逻辑,然后使用 HMAC 签署一些消息的程序。由于它具有复杂的应用程序逻辑,因此服务器中可能存在未被注意到的远程文件读取漏洞,这可能会将私钥泄露给攻击者。
这可以分为两个容器中的两个进程:一个前端容器,它处理用户交互和业务逻辑,但无法看到私钥;一个签名器容器,它可以看到私钥,并响应来自前端(例如,通过本地主机网络)的简单签名请求。
通过这种分区方法,攻击者现在必须诱使应用程序服务器执行一些相当随意的操作,这可能比让它读取文件更难。
Secret 的替代方案
您无需使用 Secret 来保护机密数据,您可以从替代方案中进行选择。
以下是一些选项
- 如果您的云原生组件需要对您知道在同一 Kubernetes 集群中运行的另一个应用程序进行身份验证,您可以使用 ServiceAccount 及其令牌来标识您的客户端。
- 有一些第三方工具,您可以在集群内或集群外运行它们来管理敏感数据。例如,一个 Pod 通过 HTTPS 访问的服务,如果客户端正确地进行了身份验证(例如,使用 ServiceAccount 令牌),则会显示 Secret。
- 对于身份验证,您可以为 X.509 证书实现一个自定义签名器,并使用 证书签名请求 来让该自定义签名器为需要它们的 Pod 颁发证书。
- 您可以使用 设备插件 将节点本地加密硬件暴露给特定的 Pod。例如,您可以将受信任的 Pod 调度到提供受信任平台模块的节点,该模块在带外配置。
您还可以将这些选项中的两个或多个组合起来,包括使用 Secret 对象本身的选项。
例如:实现(或部署)一个 operator,它从外部服务中获取短暂的会话令牌,然后根据这些短暂的会话令牌创建 Secret。在您的集群中运行的 Pod 可以使用会话令牌,并且 operator 确保它们有效。这种分离意味着您可以运行不知道发出和刷新这些会话令牌的精确机制的 Pod。
Secret 类型
创建 Secret 时,您可以使用 Secret 资源的 type
字段或某些等效的 kubectl
命令行标志(如果可用)来指定其类型。Secret 类型用于促进 Secret 数据的编程处理。
Kubernetes 为一些常见的用例提供了一些内置类型。这些类型在执行的验证和 Kubernetes 对它们施加的约束方面有所不同。
内置类型 | 用法 |
---|---|
不透明 | 任意用户定义的数据 |
kubernetes.io/service-account-token | ServiceAccount 令牌 |
kubernetes.io/dockercfg | 序列化 ~/.dockercfg 文件 |
kubernetes.io/dockerconfigjson | 序列化 ~/.docker/config.json 文件 |
kubernetes.io/basic-auth | 基本身份验证的凭据 |
kubernetes.io/ssh-auth | SSH 身份验证的凭据 |
kubernetes.io/tls | TLS 客户端或服务器的数据 |
bootstrap.kubernetes.io/token | 启动令牌数据 |
您可以通过为 Secret 对象分配一个非空字符串作为 type
值来定义和使用您自己的 Secret 类型(空字符串被视为 Opaque
类型)。
Kubernetes 不会对类型名称施加任何约束。但是,如果您使用的是内置类型之一,则必须满足为该类型定义的所有要求。
如果您要定义一个供公开使用的 Secret 类型,请遵循惯例并将 Secret 类型结构化为在名称之前包含您的域名,并用 /
分隔。例如:cloud-hosting.example.net/cloud-api-credentials
。
不透明 Secret
如果您没有在 Secret 清单中明确指定类型,Opaque
是默认的 Secret 类型。使用 kubectl
创建 Secret 时,您必须使用 generic
子命令来表示 Opaque
Secret 类型。例如,以下命令创建一个类型为 Opaque
的空 Secret
kubectl create secret generic empty-secret
kubectl get secret empty-secret
输出如下
NAME TYPE DATA AGE
empty-secret Opaque 0 2m6s
DATA
列显示存储在 Secret 中的数据项数量。在本例中,0
表示您已创建了一个空 Secret。
ServiceAccount 令牌 Secret
kubernetes.io/service-account-token
类型的 Secret 用于存储一个令牌凭据,该凭据标识一个 ServiceAccount。这是一种遗留机制,它向 Pod 提供长期有效的 ServiceAccount 凭据。
在 Kubernetes v1.22 及更高版本中,建议的方法是使用 TokenRequest
API 获取短暂的、自动轮换的 ServiceAccount 令牌。您可以使用以下方法获取这些短暂的令牌
- 直接调用
TokenRequest
API,或使用像kubectl
这样的 API 客户端。例如,您可以使用kubectl create token
命令。 - 在 Pod 清单中的 投影卷 中请求一个挂载的令牌。Kubernetes 会创建该令牌并将其挂载到 Pod 中。该令牌会在它被挂载到的 Pod 被删除时自动失效。有关详细信息,请参阅 使用服务帐户令牌投影启动 Pod。
注意
只有在无法使用TokenRequest
API 获取令牌,并且在可读的 API 对象中持久化一个永不过期的令牌凭据的安全风险是可以接受的情况下,才应创建 ServiceAccount 令牌 Secret。有关说明,请参阅 手动为 ServiceAccount 创建长期有效的 API 令牌。使用此 Secret 类型时,您需要确保已将 kubernetes.io/service-account.name
注释设置为现有 ServiceAccount 名称。如果同时创建 ServiceAccount 和 Secret 对象,则应先创建 ServiceAccount 对象。
创建 Secret 后,Kubernetes 控制器 会填充一些其他字段,例如 kubernetes.io/service-account.uid
注释,以及 data
字段中的 token
键,该键将填充身份验证令牌。
以下示例配置声明了一个 ServiceAccount 令牌 Secret
apiVersion: v1
kind: Secret
metadata:
name: secret-sa-sample
annotations:
kubernetes.io/service-account.name: "sa-name"
type: kubernetes.io/service-account-token
data:
extra: YmFyCg==
创建 Secret 后,等待 Kubernetes 在 data
字段中填充 token
键。
有关 ServiceAccount 如何工作的更多信息,请参阅 ServiceAccount 文档。您还可以查看 Pod
的 automountServiceAccountToken
字段和 serviceAccountName
字段,以了解如何在 Pod 中引用 ServiceAccount 凭据。
Docker 配置 Secret
如果您要创建 Secret 来存储访问容器镜像仓库的凭据,则必须为此 Secret 使用以下 type
值之一
kubernetes.io/dockercfg
:存储序列化~/.dockercfg
,它是配置 Docker 命令行的传统格式。Secret 的data
字段包含一个.dockercfg
键,其值为 base64 编码的~/.dockercfg
文件的内容。kubernetes.io/dockerconfigjson
:存储一个序列化 JSON,它遵循与~/.docker/config.json
文件相同的格式规则,这是~/.dockercfg
的新格式。Secret 的data
字段必须包含一个.dockerconfigjson
键,其值为 base64 编码的~/.docker/config.json
文件的内容。
以下是 kubernetes.io/dockercfg
类型 Secret 的示例
apiVersion: v1
kind: Secret
metadata:
name: secret-dockercfg
type: kubernetes.io/dockercfg
data:
.dockercfg: |
eyJhdXRocyI6eyJodHRwczovL2V4YW1wbGUvdjEvIjp7ImF1dGgiOiJvcGVuc2VzYW1lIn19fQo=
注意
如果您不想执行 base64 编码,可以选择使用stringData
字段。使用清单创建 Docker 配置 Secret 时,API 服务器会检查预期键是否存在于 data
字段中,并验证提供的值是否可以解析为有效的 JSON。API 服务器不会验证 JSON 是否实际上是 Docker 配置文件。
您也可以使用 kubectl
创建用于访问容器仓库的 Secret,例如,当您没有 Docker 配置文件时
kubectl create secret docker-registry secret-tiger-docker \
--docker-email=[email protected] \
--docker-username=tiger \
--docker-password=pass1234 \
--docker-server=my-registry.example:5000
此命令创建一个类型为 kubernetes.io/dockerconfigjson
的 Secret。
从该新 Secret 中检索 .data.dockerconfigjson
字段并解码数据
kubectl get secret secret-tiger-docker -o jsonpath='{.data.*}' | base64 -d
输出等效于以下 JSON 文档(这也是有效的 Docker 配置文件)
{
"auths": {
"my-registry.example:5000": {
"username": "tiger",
"password": "pass1234",
"email": "[email protected]",
"auth": "dGlnZXI6cGFzczEyMzQ="
}
}
}
基本身份验证 Secret
kubernetes.io/basic-auth
类型用于存储基本身份验证所需的凭据。使用此 Secret 类型时,Secret 的 data
字段必须包含以下两个键之一
username
:身份验证的用户名password
:身份验证的密码或令牌
上面两个键的两个值都是 base64 编码的字符串。您也可以使用 Secret 清单中的 stringData
字段提供明文内容。
以下清单是基本身份验证 Secret 的示例
apiVersion: v1
kind: Secret
metadata:
name: secret-basic-auth
type: kubernetes.io/basic-auth
stringData:
username: admin # required field for kubernetes.io/basic-auth
password: t0p-Secret # required field for kubernetes.io/basic-auth
注意
Secret 的stringData
字段不适用于服务器端应用。基本身份验证 Secret 类型仅为了方便提供。您可以为用于基本身份验证的凭据创建 Opaque
类型。但是,使用定义的公共 Secret 类型(kubernetes.io/basic-auth
)有助于其他人了解您的 Secret 的用途,并为预期使用的键名设置约定。
SSH 身份验证 Secret
内置类型 kubernetes.io/ssh-auth
用于存储 SSH 身份验证中使用的数据。使用此 Secret 类型时,您必须在 data
(或 stringData
)字段中指定 ssh-privatekey
键值对作为要使用的 SSH 凭据。
以下清单是用于 SSH 公钥/私钥身份验证的 Secret 的示例
apiVersion: v1
kind: Secret
metadata:
name: secret-ssh-auth
type: kubernetes.io/ssh-auth
data:
# the data is abbreviated in this example
ssh-privatekey: |
UG91cmluZzYlRW1vdGljb24lU2N1YmE=
SSH 身份验证 Secret 类型仅为了方便提供。您可以为用于 SSH 身份验证的凭据创建 Opaque
类型。但是,使用定义的公共 Secret 类型(kubernetes.io/ssh-auth
)有助于其他人了解您的 Secret 的用途,并为预期使用的键名设置约定。Kubernetes API 会验证此类型的 Secret 是否设置了所需的键。
注意
SSH 私钥本身并不能建立 SSH 客户端和主机服务器之间的可信通信。需要建立信任的辅助方法来缓解“中间人”攻击,例如添加到 ConfigMap 中的known_hosts
文件。TLS Secret
kubernetes.io/tls
Secret 类型用于存储证书及其关联的密钥,这些密钥通常用于 TLS。
TLS Secret 的一种常见用途是在 Ingress 中配置传输加密,但您也可以将其与其他资源一起使用,或直接在您的工作负载中使用。使用此类型的 Secret 时,必须在 Secret 配置的 data
(或 stringData
)字段中提供 tls.key
和 tls.crt
键,尽管 API 服务器实际上不会验证每个键的值。
作为使用 stringData
的替代方法,您可以使用 data
字段来提供 base64 编码的证书和私钥。有关详细信息,请参阅 Secret 名称和数据的约束。
以下 YAML 包含 TLS Secret 的示例配置
apiVersion: v1
kind: Secret
metadata:
name: secret-tls
type: kubernetes.io/tls
data:
# values are base64 encoded, which obscures them but does NOT provide
# any useful level of confidentiality
tls.crt: |
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNVakNDQWJzQ0FnMytNQTBHQ1NxR1NJYjNE
UUVCQlFVQU1JR2JNUXN3Q1FZRFZRUUdFd0pLVURFT01Bd0cKQTFVRUNCTUZWRzlyZVc4eEVEQU9C
Z05WQkFjVEIwTm9kVzh0YTNVeEVUQVBCZ05WQkFvVENFWnlZVzVyTkVSRQpNUmd3RmdZRFZRUUxF
dzlYWldKRFpYSjBJRk4xY0hCdmNuUXhHREFXQmdOVkJBTVREMFp5WVc1ck5FUkVJRmRsCllpQkRR
VEVqTUNFR0NTcUdTSWIzRFFFSkFSWVVjM1Z3Y0c5eWRFQm1jbUZ1YXpSa1pDNWpiMjB3SGhjTk1U
TXcKTVRFeE1EUTFNVE01V2hjTk1UZ3dNVEV3TURRMU1UTTVXakJMTVFzd0NRWURWUVFHREFKS1VE
RVBNQTBHQTFVRQpDQXdHWEZSdmEzbHZNUkV3RHdZRFZRUUtEQWhHY21GdWF6UkVSREVZTUJZR0Ex
VUVBd3dQZDNkM0xtVjRZVzF3CmJHVXVZMjl0TUlHYU1BMEdDU3FHU0liM0RRRUJBUVVBQTRHSUFE
Q0JoQUo5WThFaUhmeHhNL25PbjJTbkkxWHgKRHdPdEJEVDFKRjBReTliMVlKanV2YjdjaTEwZjVN
Vm1UQllqMUZTVWZNOU1vejJDVVFZdW4yRFljV29IcFA4ZQpqSG1BUFVrNVd5cDJRN1ArMjh1bklI
QkphVGZlQ09PekZSUFY2MEdTWWUzNmFScG04L3dVVm16eGFLOGtCOWVaCmhPN3F1TjdtSWQxL2pW
cTNKODhDQXdFQUFUQU5CZ2txaGtpRzl3MEJBUVVGQUFPQmdRQU1meTQzeE15OHh3QTUKVjF2T2NS
OEtyNWNaSXdtbFhCUU8xeFEzazlxSGtyNFlUY1JxTVQ5WjVKTm1rWHYxK2VSaGcwTi9WMW5NUTRZ
RgpnWXcxbnlESnBnOTduZUV4VzQyeXVlMFlHSDYyV1hYUUhyOVNVREgrRlowVnQvRGZsdklVTWRj
UUFEZjM4aU9zCjlQbG1kb3YrcE0vNCs5a1h5aDhSUEkzZXZ6OS9NQT09Ci0tLS0tRU5EIENFUlRJ
RklDQVRFLS0tLS0K
# In this example, the key data is not a real PEM-encoded private key
tls.key: |
RXhhbXBsZSBkYXRhIGZvciB0aGUgVExTIGNydCBmaWVsZA==
TLS Secret 类型仅为了方便提供。您可以为用于 TLS 身份验证的凭据创建 Opaque
类型。但是,使用定义的公共 Secret 类型(kubernetes.io/tls
)有助于确保项目中 Secret 格式的一致性。API 服务器会验证此类型的 Secret 是否设置了所需的键。
要使用 kubectl
创建 TLS Secret,请使用 tls
子命令
kubectl create secret tls my-tls-secret \
--cert=path/to/cert/file \
--key=path/to/key/file
公钥/私钥对必须事先存在。--cert
的公钥证书必须是 .PEM 编码的,并且必须与 --key
给定的私钥匹配。
引导令牌 Secret
bootstrap.kubernetes.io/token
Secret 类型用于节点引导过程中使用的令牌。它存储用于签署知名 ConfigMap 的令牌。
引导令牌 Secret 通常在 kube-system
命名空间中创建,并以 bootstrap-token-<token-id>
的形式命名,其中 <token-id>
是令牌 ID 的 6 个字符字符串。
作为 Kubernetes 清单,引导令牌 Secret 可能看起来像这样
apiVersion: v1
kind: Secret
metadata:
name: bootstrap-token-5emitj
namespace: kube-system
type: bootstrap.kubernetes.io/token
data:
auth-extra-groups: c3lzdGVtOmJvb3RzdHJhcHBlcnM6a3ViZWFkbTpkZWZhdWx0LW5vZGUtdG9rZW4=
expiration: MjAyMC0wOS0xM1QwNDozOToxMFo=
token-id: NWVtaXRq
token-secret: a3E0Z2lodnN6emduMXAwcg==
usage-bootstrap-authentication: dHJ1ZQ==
usage-bootstrap-signing: dHJ1ZQ==
引导令牌 Secret 在 data
下指定了以下键
token-id
:作为令牌标识符的随机 6 个字符字符串。必需。token-secret
:作为实际令牌 Secret 的随机 16 个字符字符串。必需。description
:一个描述令牌用途的人类可读字符串。可选。expiration
:使用 RFC3339 指定的绝对 UTC 时间,用于指定令牌应过期的时间。可选。usage-bootstrap-<usage>
:一个布尔标志,指示引导令牌的额外用途。auth-extra-groups
:一个逗号分隔的组名列表,除了system:bootstrappers
组之外,还将作为这些组进行身份验证。
您也可以在 Secret 的 stringData
字段中提供这些值,而无需对其进行 base64 编码
apiVersion: v1
kind: Secret
metadata:
# Note how the Secret is named
name: bootstrap-token-5emitj
# A bootstrap token Secret usually resides in the kube-system namespace
namespace: kube-system
type: bootstrap.kubernetes.io/token
stringData:
auth-extra-groups: "system:bootstrappers:kubeadm:default-node-token"
expiration: "2020-09-13T04:39:10Z"
# This token ID is used in the name
token-id: "5emitj"
token-secret: "kq4gihvszzgn1p0r"
# This token can be used for authentication
usage-bootstrap-authentication: "true"
# and it can be used for signing
usage-bootstrap-signing: "true"
注意
Secret 的stringData
字段不适用于服务器端应用。使用 Secret
创建 Secret
创建 Secret 有几种选择
Secret 名称和数据的约束
Secret 对象的名称必须是有效的 DNS 子域名。
您可以在为 Secret 创建配置文件时指定 data
和/或 stringData
字段。data
和 stringData
字段是可选的。data
字段中所有键的值都必须是 base64 编码的字符串。如果不需要转换为 base64 字符串,您可以选择指定 stringData
字段,该字段接受任意字符串作为值。
data
和 stringData
的键必须由字母数字字符、-
、_
或 .
组成。stringData
字段中的所有键值对都会被内部合并到 data
字段中。如果一个键同时出现在 data
和 stringData
字段中,则 stringData
字段中指定的值优先。
大小限制
单个 Secret 的大小限制为 1MiB。这样做是为了防止创建非常大的 Secret,因为它们可能会耗尽 API 服务器和 kubelet 的内存。但是,创建许多较小的 Secret 也会耗尽内存。您可以使用 资源配额 来限制命名空间中的 Secret(或其他资源)数量。
编辑 Secret
您可以编辑现有的 Secret,除非它是 不可变的。要编辑 Secret,请使用以下方法之一
您也可以使用 Kustomize 工具 编辑 Secret 中的数据。但是,此方法会创建一个包含编辑数据的新的 Secret
对象。
根据您创建 Secret 的方式以及 Secret 在 Pod 中的使用方式,对现有 Secret
对象的更新会自动传播到使用这些数据的 Pod。有关更多信息,请参阅 将 Secret 作为文件从 Pod 中使用 部分。
使用 Secret
Secret 可以作为数据卷挂载,也可以作为 环境变量 公开,供 Pod 中的容器使用。Secret 也可以由系统的其他部分使用,而无需直接暴露给 Pod。例如,Secret 可以保存其他系统部分应该用来代表您与外部系统交互的凭据。
Secret 卷源将经过验证,以确保指定的引用对象实际上指向 Secret 类型的对象。因此,在任何依赖它的 Pod 创建之前都需要创建 Secret。
如果无法获取 Secret(可能是因为它不存在,或者因为暂时无法连接到 API 服务器),kubelet 会定期尝试重新运行该 Pod。kubelet 还会为该 Pod 报告一个事件,其中包括有关获取 Secret 问题的信息。
可选 Secret
在 Pod 中引用 Secret 时,您可以将 Secret 标记为可选,例如在以下示例中。如果可选 Secret 不存在,Kubernetes 会忽略它。
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
optional: true
默认情况下,Secret 是必需的。在所有非可选 Secret 可用之前,Pod 的任何容器都不会启动。
如果 Pod 引用非可选 Secret 中的特定键,并且该 Secret 存在,但缺少命名键,则 Pod 在启动时会失败。
将 Secret 作为文件从 Pod 中使用
如果您想从 Pod 中访问 Secret 中的数据,一种方法是让 Kubernetes 将该 Secret 的值作为 Pod 的一个或多个容器的文件系统中的文件提供。
有关说明,请参阅 创建具有通过卷访问 Secret 数据权限的 Pod。
当卷包含来自 Secret 的数据,并且该 Secret 被更新时,Kubernetes 会跟踪这一点,并使用最终一致的方法更新卷中的数据。
注意
使用 Secret 作为 子路径 卷挂载的容器不会收到自动的 Secret 更新。kubelet 会保留一个缓存,其中包含该节点上用于 Pod 卷的 Secret 的当前键和值。您可以配置 kubelet 检测缓存值更改的方式。 kubelet 配置 中的 configMapAndSecretChangeDetectionStrategy
字段控制 kubelet 使用的策略。默认策略是 Watch
。
对 Secret 的更新可以由 API 监视机制(默认)传播,基于具有定义生存时间的缓存,或者在每个 kubelet 同步循环中从集群 API 服务器轮询。
因此,从 Secret 被更新到新键被投影到 Pod 的总延迟可能与 kubelet 同步周期 + 缓存传播延迟一样长,其中缓存传播延迟取决于所选缓存类型(按照上一段中列出的相同顺序,这些是:监视传播延迟,配置的缓存 TTL,或者直接轮询为零)。
将 Secret 作为环境变量使用
要在 Pod 中的 环境变量 中使用 Secret
- 对于 Pod 规范中的每个容器,为要使用的每个 Secret 键添加一个环境变量到
env[].valueFrom.secretKeyRef
字段中。 - 修改您的镜像和/或命令行,以便程序在指定的环境变量中查找值。
有关说明,请参阅 使用 Secret 数据定义容器环境变量。
重要的是要注意,Pod 中的环境变量名称允许的字符范围是 有限制的。如果任何键不符合规则,这些键将不会提供给您的容器,但 Pod 仍允许启动。
容器镜像拉取 Secret
如果您想从私有存储库中获取容器镜像,您需要一种方法让每个节点上的 kubelet 认证到该存储库。您可以配置镜像拉取 Secret 来实现这一点。这些 Secret 在 Pod 级别进行配置。
使用 imagePullSecrets
imagePullSecrets
字段是同一命名空间中 Secret 的引用列表。您可以使用 imagePullSecrets
传递一个包含 Docker(或其他)镜像注册表密码的 Secret 给 kubelet。kubelet 使用此信息代表您的 Pod 拉取私有镜像。有关 imagePullSecrets
字段的更多信息,请参阅 PodSpec API。
手动指定 imagePullSecret
您可以从 容器镜像 文档中了解如何指定 imagePullSecrets
。
安排自动附加 imagePullSecrets
您可以手动创建 imagePullSecrets
,并从 ServiceAccount 中引用它们。使用该 ServiceAccount 或默认使用该 ServiceAccount 创建的任何 Pod 都会将其 imagePullSecrets
字段设置为该服务帐户的字段。有关该过程的详细说明,请参阅 向服务帐户添加 ImagePullSecrets。
将 Secret 与静态 Pod 一起使用
您无法将 ConfigMap 或 Secret 与 静态 Pod 一起使用。
不可变 Secret
Kubernetes v1.21 [稳定]
Kubernetes 允许您将特定的 Secret(和 ConfigMap)标记为不可变。防止更改现有 Secret 的数据具有以下好处
- 保护您免受可能导致应用程序中断的意外(或不必要的)更新
- (对于广泛使用 Secret 的集群 - 至少数万个唯一的 Secret 到 Pod 挂载),切换到不可变 Secret 会通过显著减少 kube-apiserver 的负载来提高集群的性能。kubelet 不需要维护对标记为不可变的任何 Secret 的 [监视]。
将 Secret 标记为不可变
您可以通过将 immutable
字段设置为 true
来创建不可变 Secret。例如,
apiVersion: v1
kind: Secret
metadata: ...
data: ...
immutable: true
您还可以更新任何现有的可变 Secret 以使其不可变。
注意
一旦 Secret 或 ConfigMap 被标记为不可变,就无法撤消此更改,也无法修改data
字段的内容。您只能删除并重新创建 Secret。现有的 Pod 会保留指向已删除 Secret 的挂载点 - 建议重新创建这些 Pod。Secret 的信息安全
虽然 ConfigMap 和 Secret 的工作方式类似,但 Kubernetes 对 Secret 对象应用了一些额外的保护。
Secret 通常保存跨越重要性范围的值,其中许多值会导致 Kubernetes 内部(例如服务帐户令牌)以及对外部系统的升级。即使单个应用程序可以推理它期望与之交互的 Secret 的权限,但同一命名空间中的其他应用程序也可以使这些假设无效。
只有在节点上的 Pod 需要 Secret 时,才会将其发送到该节点。对于将 Secret 挂载到 Pod,kubelet 会将数据的副本存储到 tmpfs
中,以便机密数据不会写入持久存储。一旦依赖 Secret 的 Pod 被删除,kubelet 就会从 Secret 中删除其本地副本的机密数据。
Pod 中可能有多个容器。默认情况下,您定义的容器只具有对默认 ServiceAccount 及其相关 Secret 的访问权限。您必须显式定义环境变量或将卷映射到容器中,才能提供对任何其他 Secret 的访问权限。
同一节点上可能有多个 Pod 的 Secret。但是,只有 Pod 请求的 Secret 才能在它的容器中可见。因此,一个 Pod 无法访问另一个 Pod 的 Secret。
配置对 Secret 的最小权限访问
为了增强围绕 Secret 的安全措施,Kubernetes 提供了一种机制:您可以将 ServiceAccount 注释为 kubernetes.io/enforce-mountable-secrets: "true"
。
有关更多信息,您可以参阅 有关此注释的文档。
警告
任何在节点上以privileged: true
运行的容器都可以访问该节点上使用的所有 Secret。下一步
- 有关管理和提高 Secret 安全性的指南,请参阅 Kubernetes Secret 的最佳实践。
- 了解如何 使用
kubectl
管理 Secret - 了解如何 使用配置文件管理 Secret
- 了解如何 使用 kustomize 管理 Secret
- 阅读
Secret
的 API 参考