Secret
Secret 是一种对象,包含少量敏感数据,例如密码、令牌或密钥。这类信息原本可能会放在 Pod 规约或 容器镜像 中。使用 Secret 意味着你无需将机密数据包含在应用程序代码中。
由于 Secret 可以独立于使用它们的 Pod 创建,因此在创建、查看和编辑 Pod 的工作流程中,Secret(及其数据)被泄露的风险更低。Kubernetes 以及在你集群中运行的应用程序还可以对 Secret 采取额外的预防措施,例如避免将敏感数据写入非易失性存储。
Secret 类似于 ConfigMaps,但专门用于存放机密数据。
注意
Kubernetes Secret 默认以未加密的形式存储在 API 服务器底层数据存储 (etcd) 中。任何拥有 API 访问权限的人都可以检索或修改 Secret,任何拥有 etcd 访问权限的人也可以。此外,任何被授权在某个命名空间中创建 Pod 的人都可以利用该权限读取该命名空间中的任何 Secret;这包括间接访问,例如创建 Deployment 的能力。
为了安全地使用 Secret,请至少采取以下步骤:
- 为 Secret 启用静态加密。
- 启用或配置 RBAC 规则,并对 Secret 采取最小权限访问。
- 将 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 签名一些消息的程序。由于它具有复杂的应用程序逻辑,服务器中可能存在未被注意的远程文件读取漏洞,这可能导致私钥暴露给攻击者。
这可以分为两个容器中的两个进程:一个前端容器,它处理用户交互和业务逻辑,但无法看到私钥;一个签名器容器,它可以看到私钥,并响应来自前端的简单签名请求(例如,通过 localhost 网络)。
通过这种分区方法,攻击者现在必须诱骗应用程序服务器执行一些任意操作,这可能比让它读取文件更难。
Secret 的替代方案
除了使用 Secret 保护机密数据外,你还可以选择其他替代方案。
以下是一些选项:
- 如果你的云原生组件需要对你知道运行在同一个 Kubernetes 集群中的另一个应用程序进行身份验证,你可以使用 ServiceAccount 及其令牌来识别你的客户端。
- 你可以运行第三方工具,无论是在集群内部还是外部,来管理敏感数据。例如,一个 Pods 通过 HTTPS 访问的服务,如果客户端正确验证(例如,使用 ServiceAccount 令牌),则会暴露 Secret。
- 对于身份验证,你可以为 X.509 证书实现一个自定义签名器,并使用 CertificateSigningRequests 允许该自定义签名器向需要证书的 Pods 颁发证书。
- 你可以使用 设备插件 将节点本地加密硬件暴露给特定的 Pod。例如,你可以将受信任的 Pods 调度到提供 Trusted Platform Module 的节点上,并进行带外配置。
你还可以结合使用这些选项中的两个或更多个,包括使用 Secret 对象本身。
例如:实现(或部署)一个 operator,从外部服务获取短期会话令牌,然后根据这些短期会话令牌创建 Secret。集群中运行的 Pods 可以使用会话令牌,operator 确保它们是有效的。这种分离意味着你可以运行不知道颁发和刷新这些会话令牌确切机制的 Pods。
Secret 的类型
创建 Secret 时,你可以使用 Secret 资源的 `type` 字段,或某些等效的 `kubectl` 命令行标志(如果可用)来指定其类型。Secret 类型用于方便对 Secret 数据进行编程处理。
Kubernetes 为一些常见的用法场景提供了几个内置类型。这些类型在执行的验证和 Kubernetes 对其施加的限制方面有所不同。
内置类型 | 用途 |
---|---|
Opaque | 任意用户定义的数据 |
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` 字段设置为一个非空字符串(空字符串被视为 `Opaque` 类型)来定义和使用你自己的 Secret 类型。
Kubernetes 对类型名称没有任何限制。但是,如果你使用的是内置类型之一,则必须满足该类型定义的所有要求。
如果你正在定义一种供公共使用的 Secret 类型,请遵循约定,将 Secret 类型结构为在名称前加上你的域名,并用 `/` 分隔。例如:`cloud-hosting.example.net/cloud-api-credentials`。
不透明 Secret (Opaque Secrets)
如果你在 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 的令牌凭据。这是一种遗留机制,它为 Pods 提供长期有效的 ServiceAccount 凭据。
在 Kubernetes v1.22 及更高版本中,推荐的方法是使用 `TokenRequest` API 获取短期、自动轮换的 ServiceAccount 令牌。你可以通过以下方法获取这些短期令牌:
- 直接调用 `TokenRequest` API,或使用像 `kubectl` 这样的 API 客户端。例如,你可以使用 `kubectl create token` 命令。
- 在 Pod 清单中的投影卷中请求挂载令牌。Kubernetes 创建令牌并将其挂载到 Pod 中。当挂载该令牌的 Pod 被删除时,令牌会自动失效。有关详细信息,请参阅使用 ServiceAccount 令牌投影启动 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` 文件相同的格式规则,`~/.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=tiger@acme.example \
--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": "tiger@acme.example",
"auth": "dGlnZXI6cGFzczEyMzQ="
}
}
}
注意
这里的 `auth` 值是经过 base64 编码的;它被遮蔽但并非秘密。任何可以读取该 Secret 的人都可以知道注册表访问的持有者令牌。
建议使用凭据提供者按需动态安全地提供拉取 Secret。
基本认证 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
# Replace the following values with your own base64-encoded certificate and key.
tls.crt: "REPLACE_WITH_BASE64_CERT"
tls.key: "REPLACE_WITH_BASE64_KEY"
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 类型用于节点引导过程中使用的令牌。它存储用于签名众所周知的 ConfigMaps 的令牌。
引导令牌 Secret 通常在 `kube-system` 命名空间中创建,并以 `bootstrap-token-
作为 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-
`:一个布尔标志,指示引导令牌的其他用途。 - `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。这是为了阻止创建可能耗尽 API 服务器和 kubelet 内存的超大 Secret。然而,创建许多较小的 Secret 也可能耗尽内存。你可以使用资源配额来限制命名空间中 Secret(或其他资源)的数量。
编辑 Secret
你可以编辑现有的 Secret,除非它是不可变的。要编辑 Secret,请使用以下方法之一:
你也可以使用 Kustomize 工具编辑 Secret 中的数据。但是,此方法会创建一个带有编辑数据的新 `Secret` 对象。
根据你创建 Secret 的方式以及 Secret 在 Pod 中使用的方式,对现有 `Secret` 对象的更新会自动传播到使用这些数据的 Pod。有关更多信息,请参阅从 Pod 以文件形式使用 Secret 部分。
使用 Secret
Secret 可以作为数据卷挂载或作为环境变量暴露,供 Pod 中的容器使用。Secret 也可以被系统的其他部分使用,而无需直接暴露给 Pod。例如,Secret 可以保存系统其他部分代表你与外部系统交互时应使用的凭据。
Secret 卷源经过验证,以确保指定的对象引用确实指向 Secret 类型的对象。因此,Secret 需要在任何依赖它的 Pod 之前创建。
如果 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 在启动期间会失败。
从 Pod 中以文件形式使用 Secret
如果你想在 Pod 中访问 Secret 中的数据,一种方法是让 Kubernetes 将 Secret 的值作为文件提供给一个或多个 Pod 容器的文件系统。
有关说明,请参阅创建通过 Volume 访问 Secret 数据的 Pod。
当卷包含来自 Secret 的数据,并且该 Secret 被更新时,Kubernetes 会跟踪此情况并使用最终一致性方法更新卷中的数据。
注意
使用 Secret 作为 subPath 卷挂载的容器不会收到 Secret 的自动更新。kubelet 会缓存该节点上 Pod 卷中使用的 Secret 的当前键和值。你可以配置 kubelet 检测缓存值变化的方式。kubelet 配置中的 `configMapAndSecretChangeDetectionStrategy` 字段控制 kubelet 使用的策略。默认策略是 `Watch`。
Secret 的更新可以通过 API watch 机制(默认)、基于具有定义生命周期的缓存,或者在每个 kubelet 同步循环中从集群 API 服务器轮询来传播。
因此,从 Secret 更新到新键投影到 Pod 的总延迟可能与 kubelet 同步周期 + 缓存传播延迟一样长,其中缓存传播延迟取决于所选的缓存类型(按照上一段中列出的相同顺序,它们是:watch 传播延迟、配置的缓存 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 创建的任何 Pods,其 `imagePullSecrets` 字段都将设置为与该 ServiceAccount 相同。有关该过程的详细说明,请参阅向 ServiceAccount 添加 ImagePullSecrets。
将 Secret 与静态 Pod 一起使用
你不能将 ConfigMap 或 Secret 与静态 Pod 一起使用。
不可变 Secret
Kubernetes v1.21 [stable]
Kubernetes 允许你将特定的 Secret(和 ConfigMaps)标记为 *不可变*。防止更改现有 Secret 的数据具有以下优点:
- 保护你免受可能导致应用程序中断的意外(或不必要)更新。
- (对于大量使用 Secret 的集群 - 至少数万个唯一的 Secret 到 Pod 挂载),切换到不可变 Secret 可以显著减少 kube-apiserver 上的负载,从而提高集群性能。kubelet 无需对任何标记为不可变的 Secret 维护 [watch]。
将 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 的权限,同一命名空间中的其他应用程序也可能使这些假设失效。
Secret 仅在节点上的 Pod 需要时才发送到该节点。为了将 Secret 挂载到 Pod 中,kubelet 将数据副本存储到 `tmpfs` 中,以便机密数据不会写入持久存储。一旦依赖 Secret 的 Pod 被删除,kubelet 就会从 Secret 中删除其本地的机密数据副本。
一个 Pod 中可能包含多个容器。默认情况下,你定义的容器只能访问默认的 ServiceAccount 及其相关的 Secret。你必须显式定义环境变量或将卷映射到容器中,才能提供对任何其他 Secret 的访问。
同一节点上可能有多个 Pod 的 Secret。但是,只有 Pod 请求的 Secret 才可能在其容器内可见。因此,一个 Pod 无法访问另一个 Pod 的 Secret。
配置 Secret 的最小特权访问
为了增强围绕 Secret 的安全措施,请使用单独的命名空间来隔离对挂载 Secret 的访问。
警告
任何在节点上以 `privileged: true` 运行的容器都可以访问该节点上使用的所有 Secret。下一步
- 有关管理和改进 Secret 安全性的指南,请参阅 Kubernetes Secret 最佳实践。
- 了解如何使用 `kubectl` 管理 Secret
- 了解如何使用配置文件管理 Secret
- 了解如何使用 Kustomize 管理 Secret
- 阅读 `Secret` 的 API 参考