密钥

Secret 是一个对象,其中包含少量敏感数据,例如密码、令牌或密钥。此类信息可能会被放入 Pod 规范或 容器镜像 中。使用 Secret 意味着您无需在应用程序代码中包含机密数据。

由于 Secret 可以独立于使用它们的 Pod 创建,因此在创建、查看和编辑 Pod 的工作流程中,Secret(及其数据)暴露的风险较低。Kubernetes 和在集群中运行的应用程序还可以对 Secret 采取额外的预防措施,例如避免将敏感数据写入非易失性存储。

Secret 与 ConfigMap 类似,但专门用于存储机密数据。

有关更多详细信息,请参阅Secret 的信息安全

Secret 的用途

您可以将 Secret 用于以下目的

Kubernetes 控制平面也使用 Secret;例如,引导令牌 Secret 是一种帮助自动化节点注册的机制。

用例:Secret 卷中的点文件

您可以通过定义以点开头的键来使数据“隐藏”。此键表示点文件或“隐藏”文件。例如,当以下 Secret 挂载到卷 secret-volume 中时,该卷将包含一个名为 .secret-file 的文件,并且 dotfile-test-container 将在路径 /etc/secret-volume/.secret-file 处显示此文件。

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 及其令牌来标识您的客户端。
  • 您可以运行一些第三方工具,无论是在集群内部还是外部,都可以管理敏感数据。例如,如果客户端正确进行身份验证(例如,使用 ServiceAccount 令牌),则 Pod 通过 HTTPS 访问的服务会显示 Secret。
  • 对于身份验证,您可以为 X.509 证书实现自定义签名者,并使用 CertificateSigningRequest 让该自定义签名者向需要它们的 Pod 发放证书。
  • 您可以使用 设备插件 将节点本地加密硬件暴露给特定的 Pod。例如,您可以将受信任的 Pod 调度到提供可信平台模块的节点上,该模块是带外配置的。

您还可以组合使用两个或多个选项,包括使用 Secret 对象本身的选项。

例如:实现(或部署)一个从外部服务获取短期会话令牌的 operator,然后根据这些短期会话令牌创建 Secret。在集群中运行的 Pod 可以使用会话令牌,并且 operator 确保它们有效。这种分离意味着您可以运行不知道发放和刷新这些会话令牌的确切机制的 Pod。

Secret 的类型

创建 Secret 时,您可以使用 Secret 资源的 type 字段或某些等效的 kubectl 命令行标志(如果可用)来指定其类型。Secret 类型用于促进 Secret 数据的程序化处理。

Kubernetes 为一些常见的使用场景提供了几种内置类型。这些类型在执行的验证和 Kubernetes 对其施加的约束方面有所不同。

内置类型用途
Opaque任意用户定义的数据
kubernetes.io/service-account-tokenServiceAccount 令牌
kubernetes.io/dockercfg序列化 ~/.dockercfg 文件
kubernetes.io/dockerconfigjson序列化 ~/.docker/config.json 文件
kubernetes.io/basic-auth基本身份验证的凭据
kubernetes.io/ssh-authSSH 身份验证的凭据
kubernetes.io/tlsTLS 客户端或服务器的数据
bootstrap.kubernetes.io/token引导令牌数据

您可以通过为 Secret 对象的 type 值分配一个非空字符串来定义和使用您自己的 Secret 类型(空字符串被视为 Opaque 类型)。

Kubernetes 对类型名称没有任何限制。但是,如果您使用的是其中一种内置类型,则必须满足为该类型定义的所有要求。

如果您要定义供公众使用的 Secret 类型,请遵循约定并在名称前面加上您的域名,并用 / 分隔。例如:cloud-hosting.example.net/cloud-api-credentials

Opaque 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 令牌。您可以使用以下方法获取这些短期令牌

使用此 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 文档。您还可以查看 PodautomountServiceAccountToken 字段和 serviceAccountName 字段,以获取有关从 Pod 内部引用 ServiceAccount 凭据的信息。

Docker 配置 Secret

如果要创建 Secret 来存储用于访问容器镜像仓库的凭据,则必须为该 Secret 使用以下 type 值之一

  • kubernetes.io/dockercfg:存储序列化后的 ~/.dockercfg,这是配置 Docker 命令行的旧格式。Secret data 字段包含一个 .dockercfg 键,其值为 base64 编码的 ~/.dockercfg 文件的内容。
  • kubernetes.io/dockerconfigjson:存储遵循与 ~/.docker/config.json 文件相同格式规则的序列化 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=    

当您使用清单创建 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 类型只是为了方便。您可以为用于基本身份验证的凭据创建 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 设置了所需的键。

TLS Secret

kubernetes.io/tls Secret 类型用于存储通常用于 TLS 的证书及其关联密钥。

TLS Secret 的一个常见用途是为 Ingress 配置传输中加密,但您也可以将其与其他资源一起使用,或直接在您的工作负载中使用。使用此类型的 Secret 时,必须在 Secret 配置的 data(或 stringData)字段中提供 tls.keytls.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:一个随机的 16 个字符的字符串作为实际的令牌 Secret。必需。
  • 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

创建 Secret

创建 Secret 有多种选择

Secret 名称和数据的限制

Secret 对象的名称必须是有效的 DNS 子域名

在为 Secret 创建配置文件时,可以指定 data 和/或 stringData 字段。 datastringData 字段是可选的。 data 字段中所有键的值都必须是 base64 编码的字符串。 如果不希望转换为 base64 字符串,可以选择指定 stringData 字段,该字段接受任意字符串作为值。

datastringData 的键必须由字母数字字符、-_. 组成。 stringData 字段中的所有键值对在内部合并到 data 字段中。 如果一个键同时出现在 datastringData 字段中,则以 stringData 字段中指定的值为准。

大小限制

单个 Secret 的大小限制为 1MiB。 这是为了防止创建非常大的 Secret,这可能会耗尽 API 服务器和 kubelet 的内存。 但是,创建许多较小的 Secret 也可能会耗尽内存。 可以使用 资源配额 来限制命名空间中 Secret(或其他资源)的数量。

编辑 Secret

可以编辑现有的 Secret,除非它是 不可变的。 要编辑 Secret,请使用以下方法之一

您还可以使用 Kustomize 工具 编辑 Secret 中的数据。 但是,此方法会创建一个包含已编辑数据的新 Secret 对象。

根据创建 Secret 的方式以及 Secret 在 Pod 中的使用方式,对现有 Secret 对象的更新会自动传播到使用该数据的 Pod。 有关更多信息,请参阅 从 Pod 中使用 Secret 作为文件 部分。

使用 Secret

Secret 可以作为数据卷挂载,或者作为 环境变量 公开,供 Pod 中的容器使用。 Secret 也可以被系统的其他部分使用,而无需直接暴露给 Pod。 例如,Secret 可以保存系统其他部分应该用来代表您与外部系统交互的凭据。

Secret 卷源经过验证,以确保指定的 object reference 实际上指向一个 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 容器的文件系统。

有关说明,请参阅 使用 Secret 安全地分发凭据

当卷包含来自 Secret 的数据,并且该 Secret 被更新时,Kubernetes 会跟踪此情况,并使用最终一致的方法更新卷中的数据。

kubelet 会缓存该节点上 Pod 卷中使用的 Secret 的当前键和值。 可以配置 kubelet 检测缓存值更改的方式。 kubelet 配置 中的 configMapAndSecretChangeDetectionStrategy 字段控制 kubelet 使用哪种策略。 默认策略是 Watch

Secret 的更新可以通过 API 监视机制(默认)传播,基于具有定义的生存时间的缓存,或者在每个 kubelet 同步循环中从集群 API 服务器轮询。

因此,从 Secret 更新到新键投影到 Pod 的总延迟时间可能长达 kubelet 同步周期 + 缓存传播延迟,其中缓存传播延迟取决于所选的缓存类型(按照上一段中列出的相同顺序,这些是:监视传播延迟、配置的缓存 TTL 或直接轮询的零延迟)。

使用 Secret 作为环境变量

要在 Pod 的 环境变量 中使用 Secret

  1. 对于 Pod 规范中的每个容器,将要使用的每个 Secret 键的环境变量添加到 env[].valueFrom.secretKeyRef 字段中。
  2. 修改镜像和/或命令行,以便程序在指定的环境变量中查找值。

有关说明,请参阅 使用 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 创建的任何 Pod 或默认情况下使用该 ServiceAccount 创建的任何 Pod,其 imagePullSecrets 字段都将设置为该 ServiceAccount 的 imagePullSecrets 字段。 有关该过程的详细说明,请参阅 将 ImagePullSecrets 添加到 ServiceAccount

将 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 和 Secret 的工作方式类似,但 Kubernetes 对 Secret 对象应用了一些额外的保护。

Secret 通常包含跨越一系列重要性的值,其中许多值可能会导致 Kubernetes(例如 ServiceAccount 令牌)和外部系统的权限提升。 即使单个应用程序可以推断出它希望与其交互的 Secret 的权限,但同一命名空间中的其他应用程序可能会使这些假设无效。

只有当节点上的 Pod 需要 Secret 时,才会将 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"

有关更多信息,请参阅 有关此注释的文档

下一步

上次修改时间:2024 年 6 月 7 日上午 9:10(太平洋标准时间):kubernetes.io/basic-auth:Kubernetes API 不会验证此类型的 Secret 是否设置了必需的密钥 (619dedc111)