机密

Kubernetes 机密可让您存储和管理敏感信息,例如 作为密码,OAuth令牌和ssh密钥。将机密信息秘密存储 比逐字逐句地将其更安全,更灵活 定义或 容器图片. See 秘密设计文件 欲获得更多信息。

机密是包含少量敏感数据的对象,例如 密码,令牌或密钥。否则,此类信息可能会放在 Pod规范或图像中。用户可以创建秘密和系统 也创造了一些秘密。

机密概述

要使用秘密,Pod需要引用该秘密。 秘密可以通过三种方式与Pod一起使用:

机密对象的名称必须是有效的 DNS子域名. You can specify 的 data 一个d/or 的 stringData field when creating a configuration file for a Secret. The data 一个d 的 stringData fields are optional. The values for all keys in 的 data field have to be base64-encoded strings. 如果不希望转换为base64字符串,则可以选择指定 the stringData field instead, which accepts arbitrary strings as values.

The keys of data 一个d stringData must consist of alphanumeric characters, -, _ 要么 .. All key-value pairs in 的 stringData field are internally merged into 的 data field. If a key appears in both 的 data 一个d 的 stringData field, 的 value specified in 的 stringData field takes precedence.

秘密类型

When creating a Secret, you can specify its type using 的 type field of the Secret resource, 要么 certain equivalent Kubectl command line flags (if available). Secret类型用于促进对Secret数据的编程处理。

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

内置类型用法
Opaque任意用户定义的数据
kubernetes.io/service-account-token服务帐户令牌
kubernetes.io/dockercfgserialized ~/.dockercfg file
kubernetes.io/dockerconfigjsonserialized ~/.docker/config.json file
kubernetes.io/basic-auth基本身份验证凭证
kubernetes.io/ssh-authSSH身份验证的凭据
kubernetes.io/tlsTLS客户端或服务器的数据
bootstrap.kubernetes.io/token引导令牌数据

您可以通过分配一个非空字符串作为 type value for a Secret object. An empty string is treated as 一个 Opaque type. Kubernetes不会对类型名称施加任何约束。但是,如果你 使用内置类型之一时,您必须满足定义的所有要求 for 那 type.

不透明的秘密

Opaque 如果从Secret配置文件中省略,则是默认的Secret类型。 When you create a Secret using Kubectl, you will use 的 generic subcommand to indicate 一个 Opaque Secret type. For example, 的 following command creates 一个 empty Secret of type Opaque.

Kubectl create secret generic empty-secret
kubectl get secret empty-secret

输出如下:

NAME           TYPE     DATA   AGE
empty-secret   Opaque   0      2m6s

The DATA column shows 的 number of data items stored in 的 Secret. In this case, 0 means we have just created 一个 empty Secret.

服务帐户令牌的秘密

A kubernetes.io/service-account-token type of Secret is used to store a 标识服务帐户的令牌。使用此秘密类型时,您需要 to ensure 那 的 kubernetes.io/service-account.name 一个notation is set to 一个 现有服务帐户名称。 Kubernetes控制器填充其他一些 fields 如 的 kubernetes.io/service-account.uid 一个notation 一个d 的 token key in 的 data field set to actual token content.

以下示例配置声明了服务帐户令牌密钥Secret:

apiVersion: v1
kind: Secret
metadata:
  name: secret-sa-sample
  一个notations:
    kubernetes.io/service-account.name: "sa-name"
type: kubernetes.io/service-account-token
data:
  # You can include additional key value pairs as you do with Opaque 机密
  extra: YmFyCg==

When creating a , Kubernetes automatically creates a service account Secret 并自动修改您的Pod以使用此秘密。服务帐户令牌 机密包含用于访问API的凭据。

可以禁用自动创建和使用API​​凭证或 如果需要,则覆盖。但是,如果您需要做的只是安全地访问 API服务器,这是推荐的工作流程。

服务帐号 有关服务帐户如何工作的更多信息的文档。 You can also check 的 automountServiceAccountToken field 一个d 的 serviceAccountName 的领域 有关从Pods引用服务帐户的信息。

Docker配置的秘密

You can use one of 的 following type values to create a Secret to 存储用于访问Docker注册表映像的凭据。

  • kubernetes.io/dockercfg
  • kubernetes.io/dockerconfigjson

The kubernetes.io/dockercfg type is reserved to store a serialized ~/.dockercfg 这是用于配置Docker命令行的传统格式。 When using this Secret type, you have to ensure 的 Secret data field contains a .dockercfg key whose value is content of a ~/.dockercfg file 以base64格式编码。

The kubernetes.io/dockerconfigjson type is designed for storing a serialized JSON 那 follows 的 same format rules as 的 ~/.docker/config.json file which is a new format for ~/.dockercfg. When using this Secret type, 的 data 的领域 Secret object must contain a .dockerconfigjson key, in which 的 content for 的 ~/.docker/config.json 文件作为base64编码的字符串提供。

Below is 一个 example for a kubernetes.io/dockercfg type of Secret:

apiVersion: v1
kind: Secret
metadata:
  name: secret-dockercfg
type: kubernetes.io/dockercfg
data:
  .dockercfg: |
        "<base64 encoded ~/.dockercfg file>"
注意: 如果您不想执行base64编码,则可以选择使用 stringData 字段代替。

使用清单创建这些类型的秘密时,API server checks whether 的 expected key does exists in 的 data field, 一个d 它验证提供的值是否可以解析为有效的JSON。 API 服务器不验证JSON是否实际上是Docker配置文件。

当您没有Docker配置文件或想要使用时 Kubectl 创建一个Docker注册表机密,您可以执行以下操作:

Kubectl create secret docker-registry secret-tiger-docker \
  --docker-username=tiger \
  --docker-password=pass113 \
  --docker-email=tiger@acme.com

This command creates a Secret of type kubernetes.io/dockerconfigjson. If you dump 的 .dockerconfigjson content from 的 data field, you will 获取以下JSON内容,这是创建的有效Docker配置 on 的 fly:

{
  "auths": {
    "//index.docker.io/v1/": {
      "username": "tiger",
      "password": "pass113",
      "email": "tiger@acme.com",
      "auth": "dGlnZXI6cGFzczExMw=="
    }
  }
}

基本身份验证机密

The kubernetes.io/basic-auth type is provided for storing credentials needed for basic authentication. When using this Secret type, 的 data 的领域 机密必须包含以下两个密钥:

  • username:用于认证的用户名;
  • password:用于认证的密码或令牌。

上面两个键的两个值都是base64编码的字符串。您可以 course, provide 的 clear text content using 的 stringData for Secret creation.

以下YAML是基本身份验证密钥的示例配置:

apiVersion: v1
kind: Secret
metadata:
  name: secret-basic-auth
type: kubernetes.io/basic-auth
stringData:
  username: admin
  password: t0p-Secret

仅为了用户的方便而提供了基本身份验证密钥类型。 You can create 一个 Opaque for credentials used for basic authentication. 但是,使用内置的Secret类型有助于统一凭据的格式 并且API服务器会验证是否在Secret中提供了所需的密钥 configuration.

SSH认证机密

The builtin type kubernetes.io/ssh-auth is provided for storing data used in SSH验证。使用此Secret类型时,您必须指定一个 ssh-privatekey key-value pair in 的 data (or stringData) field 作为要使用的SSH凭据。

以下YAML是SSH身份验证密钥的示例配置:

apiVersion: v1
kind: Secret
metadata:
  name: secret-ssh-auth
type: kubernetes.io/ssh-auth
data:
  # 的 data is abbreviated in this example
  ssh-privatekey: |
          MIIEpQIBAAKCAQEAulqb/Y ...

仅出于用户方便的目的提供SSH身份验证密钥类型。 You can create 一个 Opaque for credentials used for SSH authentication. 但是,使用内置的Secret类型有助于统一凭据的格式 并且API服务器会验证是否在Secret中提供了所需的密钥 configuration.

警告: SSH私钥不会在SSH客户端和 主机服务器。需要建立信任的辅助手段来 mitigate "man in 的 middle" attacks, 如 a known_hosts file added to a ConfigMap.

TLS机密

Kubernetes provides a builtin Secret type kubernetes.io/tls for to storing 通常用于TLS的证书及其关联密钥。这个 数据主要与Ingress资源的TLS终止一起使用,但可能 与其他资源一起使用或直接由工作负载使用。 When using this type of Secret, 的 tls.key 一个d 的 tls.crt key must be provided in 的 data (or stringData) 的领域 Secret configuration, although 的 API 服务器实际上并不验证每个键的值。

以下YAML包含TLS Secret的示例配置:

apiVersion: v1
kind: Secret
metadata:
  name: secret-tls
type: kubernetes.io/tls
data:
  # 的 data is abbreviated in this example
  tls.crt: |
        MIIC2DCCAcCgAwIBAgIBATANBgkqh ...
  tls.key: |
        MIIEpgIBAAKCAQEA7yn3bRHQ5FHMQ ...

提供TLS秘密类型是为了方便用户。您可以创建一个 Opaque 用于TLS服务器和/或客户端的凭据。但是,使用内置的Secret 类型有助于确保项目中Secret格式的一致性; API服务器 会验证秘密配置中是否提供了所需的密钥。

When creating a TLS Secret using Kubectl, you can use 的 tls subcommand 如下例所示:

Kubectl create secret tls my-tls-secret \
  --cert=path/to/cert/file \
  --key=path/to/key/file

公钥/私钥对必须事先存在。公钥证书 for --cert must be .PEM encoded (Base64-encoded DER format), 一个d match 的 given private key for --key. 私钥必须采用通常称为PEM私钥格式的格式, 未加密。在这两种情况下,PEM的第一行和最后一行(对于 example, --------BEGIN CERTIFICATE----- 一个d -------END CERTIFICATE---- for a cetificate) are 包括在内。

引导令牌的秘密

可以通过显式指定密钥来创建引导令牌密钥 type to bootstrap.kubernetes.io/token. This type of Secret is designed for 节点引导过程中使用的令牌。它存储用于签名的令牌 众所周知的ConfigMaps。

A bootstrap token Secret is usually created in 的 kube-system 命名空间 一个d named in 的 form bootstrap-token-<token-id> where <token-id> is a 6 character 令牌ID的字符串。

作为Kubernetes的清单,引导令牌的Secret可能看起来像 following:

apiVersion: v1
kind: Secret
metadata:
  name: bootstrap-token-5emitj
  命名空间: 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==

A bootstrap type Secret has 的 following keys specified under data:

  • token-id:随机6个字符串作为令牌标识符。需要。
  • token-secret:随机的16个字符串作为实际的令牌机密。需要。
  • description:人类可读的字符串,描述令牌是什么 used for. Optional.
  • expiration:使用RFC3339指定令牌的何时的绝对UTC时间 应该过期了。可选的。
  • usage-bootstrap-<usage>:一个布尔标志,指示的其他用法 the bootstrap token.
  • auth-extra-groups:以逗号分隔的组名列表 authenticated as 在一个ddition to 的 system:bootstrappers group.

上面的YAML可能看起来令人困惑,因为这些值都是以base64编码的 字符串。实际上,您可以使用以下YAML创建相同的Secret:

apiVersion: v1
kind: Secret
metadata:
  # 没有 te how 的 Secret is named
  name: bootstrap-token-5emitj
  # A bootstrap token Secret usually resides in 的 kube-system 命名空间
  命名空间: 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 的 name
  token-id: "5emitj"
  token-secret: "kq4gihvszzgn1p0r"
  # This token can be used for authentication
  usage-bootstrap-authentication: "true"
  # 一个d it can be used for signing
  usage-bootstrap-signing: "true"

创造秘密

有几种创建秘密的选项:

编辑秘密

可以使用以下命令编辑现有机密:

Kubectl edit secrets mysecret

This will open 的 default configured editor 一个d allow for updating 的 base64 encoded Secret values in 的 data field:

# Please edit 的 object below. Lines beginning with a '#' will be ignored,
# 一个d 一个 empty file will abort 的 edit. If 一个 error occurs 而 saving this file will be
# reopened 与 relevant failures.
#
apiVersion: v1
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm
kind: Secret
metadata:
  一个notations:
    Kubectl.kubernetes.io/last-applied-configuration: { ... }
  creationTimestamp: 2016-01-22T18:41:56Z
  name: mysecret
  命名空间: default
  resourceVersion: "164619"
  uid: cfee02d6-c137-11e5-8d73-42010af00002
type: Opaque

使用秘密

机密可以作为数据卷挂载或作为 环境变量 由Pod中的容器使用。机密的其他部分也可以使用秘密 系统,而无需直接暴露于Pod。例如,秘密可以容纳 系统其他部分用于与外部交互的凭据 系统代表您。

将秘密用作Pod中的文件

要在Pod中的某个卷中使用秘密,请执行以下操作:

  1. 创建一个秘密或使用现有的秘密。多个Pod可以引用同一秘密。
  2. Modify your 荚 definition to add a 卷 under .spec.volumes[]. Name 的 卷 任何thing, 一个d have a .spec.volumes[].secret.secretName field equal to 的 name of 的 Secret object.
  3. Add a .spec.containers[].volumeMounts[] to each container 那 needs 的 secret. Specify .spec.containers[].volumeMounts[].readOnly = true 一个d .spec.containers[].volumeMounts[].mountPath to 一个 unused directory name where you would like 的 secrets to appear.
  4. Modify your image 要么 command line so 那 的 program looks for 档案 in 那 directory. Each key in 的 secret data map becomes 的 filename under mountPath.

这是在卷中安装Secret的Pod的示例:

apiVersion: v1
kind: 
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    卷Mounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  卷s:
  - name: foo
    secret:
      secretName: mysecret

Each Secret you want to use needs to be referred to in .spec.volumes.

如果Pod中有多个容器,则每个容器都需要 own 卷Mounts block, but only one .spec.volumes is needed per Secret.

您可以将许多文件打包为一个秘密,也可以使用许多秘密,以方便为准。

将密钥投影到特定路径

您还可以控制其中投影秘密密钥的卷中的路径。 You can use 的 .spec.volumes[].secret.items field to change 的 target path of each key:

apiVersion: v1
kind: 
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    卷Mounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  卷s:
  - name: foo
    secret:
      secretName: mysecret
      items:
      - key: username
        path: my-group/my-username

会发生什么:

  • username secret is stored under /etc/foo/my-group/my-username file instead of /etc/foo/username.
  • password 秘密不被预测。

If .spec.volumes[].secret.items is used, only keys specified in items are projected. To consume all keys from 的 secret, all of 的m must be listed in 的 items field. 所有列出的密钥必须存在于相应的秘密中。否则,不会创建该卷。

秘密文件权限

您可以为单个密钥设置文件访问权限位。 If you don't specify 任何 permissions, 0644 is used by default. 您还可以为整个“秘密”卷设置默认模式,并根据需要覆盖每个密钥。

例如,您可以指定如下默认模式:

apiVersion: v1
kind: 
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    卷Mounts:
    - name: foo
      mountPath: "/etc/foo"
  卷s:
  - name: foo
    secret:
      secretName: mysecret
      defaultMode: 0400

Then, 的 secret will be mounted on /etc/foo 一个d all 的 档案 created by 的 secret 卷 mount will have permission 0400.

请注意,JSON规范不支持八进制表示法,因此将值256用于 0400权限。如果您为Pod使用YAML而不是JSON,则可以使用八进制 以更自然的方式指定权限的符号。

没有 te if you Kubectl exec into 的 荚, you need to follow 的 symlink to find 预期的文件模式。例如,

检查Pod上的secrets文件模式。

Kubectl exec mypod -it sh

cd /etc/foo
ls -l

输出类似于以下内容:

total 0
lrwxrwxrwx 1 root root 15 May 18 00:18 password -> ..data/password
lrwxrwxrwx 1 root root 15 May 18 00:18 username -> ..data/username

按照符号链接查找正确的文件模式。

cd /etc/foo/..data
ls -l

输出类似于以下内容:

total 8
-r-------- 1 root root 12 May 18 00:18 password
-r-------- 1 root root  5 May 18 00:18 username

您还可以像前面的示例一样使用映射,并指定不同的 像这样的不同文件的权限:

apiVersion: v1
kind: 
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    卷Mounts:
    - name: foo
      mountPath: "/etc/foo"
  卷s:
  - name: foo
    secret:
      secretName: mysecret
      items:
      - key: username
        path: my-group/my-username
        mode: 0777

In this case, 的 file resulting in /etc/foo/my-group/my-username will have permission value of 0777. If you use JSON, owing to JSON limitations, you must specify 的 mode in decimal 不ation, 511.

请注意,如果您将此权限值显示为十进制 read it later.

从卷中消费秘密值

在安装秘密卷的容器内,秘密密钥显示为 文件和秘密值被base64解码并存储在这些文件中。 这是上述示例在容器内部执行命令的结果:

ls /etc/foo/

输出类似于:

username
password
cat /etc/foo/username

输出类似于:

admin
cat /etc/foo/password

输出类似于:

1f2d1e2e67df

容器中的程序负责从 files.

安装的机密会自动更新

当卷中当前消耗的秘密被更新时,投影的密钥最终也会被更新。 kubelet会在每个定期同步中检查已安装的机密是否新鲜。 但是,kubelet使用其本地缓存来获取Secret的当前值。 The type of 的 cache is configurable using 的 ConfigMapAndSecretChangeDetectionStrategy field in the KubeletConfiguration结构. 秘密可以通过监视(默认),基于ttl的传播或直接重定向来传播 所有请求都直接发送到API服务器。 结果,从秘密更新到更新的总延迟 新密钥投射到Pod的时间可以与kubelet同步周期+缓存一样长 传播延迟,其中缓存传播延迟取决于所选的缓存类型 (它等于监视传播延迟,缓存的ttl或相应地为零)。

注意: 使用Secret作为容器的容器 子路径 卷安装将不会收到 Secret updates.

使用Secrets作为环境变量

环境变量在Pod中:

  1. 创建一个秘密或使用现有的秘密。多个Pod可以引用同一秘密。
  2. Modify your 荚 definition in each container 那 you wish to consume 的 value of a secret key to add 一个 环境变量 for each secret key you wish to consume. The 环境变量 那 consumes 的 secret key should populate 的 secret's name 一个d key in env[].valueFrom.secretKeyRef.
  3. 修改图像和/或命令行,以便程序在指定的环境变量中查找值。

这是使用环境变量秘密的Pod的示例:

apiVersion: v1
kind: 
metadata:
  name: secret-env-pod
spec:
  containers:
  - name: mycontainer
    image: redis
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: password
  restartPolicy: Never

使用环境变量的秘密值

在消耗环境变量秘密的容器内,秘密密钥显示为 包含秘密数据的base64解码值的常规环境变量。 这是上述示例在容器内部执行命令的结果:

echo $SECRET_USERNAME

输出类似于:

admin
echo $SECRET_PASSWORD

输出类似于:

1f2d1e2e67df

秘密更新后不会更新环境变量

如果容器已经在环境变量中使用了Secret,那么除非重新启动容器,否则不会看到Secret更新。 有第三方解决方案可在机密更改时触发重新启动。

不变的秘密

功能状态: Kubernetes v1.19 [beta]

Kubernetes Beta功能 不变的机密和ConfigMap 提供设置选项 单独的Secrets和ConfigMaps是不可变的。对于广泛使用Secrets的集群 (至少数以万计的Pod坐骑的独特秘密),以防止更改其坐骑 数据具有以下优点:

  • 保护您免受可能导致应用程序中断的意外(或不必要的)更新的侵害
  • 通过显着减少kube-apiserver的负载来提高群集的性能,方法是: 关闭手表以查看标记为不可变的秘密。

此功能由 ImmutableEphemeralVolumes 特征 gate, 自v1.19起默认启用。您可以创建一个不可变的 Secret by setting 的 immutable field to true. For example,

apiVersion: v1
kind: Secret
metadata:
  ...
data:
  ...
immutable: true
注意: 一旦Secret或ConfigMap被标记为不可变,它就是 可以还原此更改 nor to mutate 的 contents of 的 data field. You can only delete 一个d recreate 的 Secret. 现有Pod会为已删除的Secret保留一个挂载点-建议重新创建 these pods.

使用imagePullSecrets

The imagePullSecrets field is a list of references to secrets in 的 same 命名空间. You can use 一个 imagePullSecrets to pass a secret 那 contains a Docker (or other) image registry kubelet的密码。 kubelet使用此信息代表您的Pod拉私有图像。 See 的 荚Spec API for more information about 的 imagePullSecrets field.

手动指定imagePullSecret

You can learn how to specify ImagePullSecrets from 的 容器映像文档.

安排自动挂载imagePullSecrets

You can manually create imagePullSecrets, 一个d reference it from 一个ServiceAccount。使用该ServiceAccount创建的任何Pod 或默认情况下使用该ServiceAccount创建的 imagePullSecrets 字段设置为服务帐户的字段。 See 将ImagePullSecrets添加到服务帐户 有关该过程的详细说明。

自动安装手动创建的秘密

手动创建的机密(例如,其中包含用于访问GitHub帐户的令牌的机密) 可以根据其服务帐户自动附加到Pod。 See 使用PodPreset将信息注入Pod 有关该过程的详细说明。

细节

限制条件

秘密卷源经过验证以确保指定的对象 引用实际上指向类型为Secret的对象。因此,一个秘密 需要在任何依赖它的Pod之前创建。

秘密资源位于 命名空间. 机密只能由同一名称空间中的Pod引用。

个人机密的大小上限为1MiB。这是为了阻止创作 非常大的秘密,这些秘密将耗尽API服务器和kubelet内存。 但是,创建许多较小的机密也会耗尽内存。更多 由于机密性,对内存使用的全面限制是一项计划功能。

kubelet仅支持在Pod中使用秘密 从API服务器获得。 This includes 任何 豆荚 created using Kubectl, 要么 indirectly via a replication 控制器。它不包括由于kubelet而创建的Pod --manifest-url flag, its --config flag, 要么 its REST API (these are 创建Pod的常见方法。)

必须先创建机密,然后才能在Pod中使用机密 变量,除非它们被标记为可选。提及确实的秘密 不存在将阻止Pod启动。

参考s (secretKeyRef field) to keys 那 do 不 exist 在一个 named Secret 将阻止Pod启动。

机密 used to populate 环境变量 by 的 envFrom field 那 have keys 被认为无效的环境变量名称将具有这些键 跳过了。该Pod将被允许启动。会有一个事件 reason is InvalidVariableNames 一个d 的 message will contain 的 list of 被跳过的无效键。该示例显示了一个指向 default/mysecret 那 contains 2 invalid keys: 1badkey 一个d 2alsobad.

Kubectl get events

输出类似于:

LASTSEEN   FIRSTSEEN   COUNT     NAME            KIND      SUBOBJECT                         TYPE      REASON
0s         0s          1         dapi-test-pod   荚                                         Warning   InvalidEnvironmentVariableNames   kubelet, 127.0.0.1      Keys [1badkey, 2alsobad] from 的 EnvFrom secret default/mysecret were skipped since 的y are considered invalid 环境变量 names.

秘密和Pod一生的互动

通过调用Kubernetes API创建Pod时,不会检查是否引用了 秘密存在。安排好Pod之后,kubelet将尝试获取 秘密价值。如果由于秘密不存在而无法获取该秘密,或者 由于暂时缺乏与API服务器的连接,因此kubelet将 定期重试。它将报告有关Pod的事件,解释 原因尚未开始。获取秘密后,kubelet将 创建并安装包含它的卷。 荚的容器都不会 开始安装所有Pod的卷。

用例

用例:作为容器环境变量

创建一个秘密

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  USER_NAME: YWRtaW4=
  PASSWORD: MWYyZDFlMmU2N2Rm

创建秘密:

Kubectl apply -f mysecret.yaml

Use envFrom to define all of 的 Secret's data as 容器环境变量s. The key from 的 Secret becomes 的 环境变量 name in 的 荚.

apiVersion: v1
kind: 
metadata:
  name: secret-test-pod
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "/bin/sh", "-c", "env" ]
      envFrom:
      - secretRef:
          name: mysecret
  restartPolicy: Never

用例:带有ssh键的Pod

创建一个包含一些ssh密钥的密钥:

Kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/to/.ssh/id_rsa --from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub

输出类似于:

secret "ssh-key-secret" created

You can also create a kustomization.yaml with a secretGenerator field containing ssh keys.

警告: 在发送您自己的ssh密钥之前,请仔细考虑:群集的其他用户可能可以访问该机密。使用一个您希望共享其Kubernetes群集的所有用户都可以访问的服务帐户,如果这些用户受到感染,可以撤销该帐户。

现在,您可以创建一个Pod,该Pod使用ssh密钥引用该秘密,然后 大量消耗它:

apiVersion: v1
kind: 
metadata:
  name: secret-test-pod
  labels:
    name: secret-test
spec:
  卷s:
  - name: secret-volume
    secret:
      secretName: ssh-key-secret
  containers:
  - name: ssh-test-container
    image: mySshImage
    卷Mounts:
    - name: secret-volume
      readOnly: true
      mountPath: "/etc/secret-volume"

当容器的命令运行时,键的各个部分将在以下位置可用:

/etc/secret-volume/ssh-publickey
/etc/secret-volume/ssh-privatekey

然后,容器可以自由使用秘密数据来建立ssh连接。

用例:具有产品/测试凭证的容器

这个例子说明了一个Pod,它消耗了包含生产的秘密 凭据和另一个在测试环境中消耗秘密的Pod credentials.

You can create a kustomization.yaml with a secretGenerator field 要么 run Kubectl create secret.

Kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11

输出类似于:

secret "prod-db-secret" created

您还可以为测试环境凭据创建密码。

Kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests

输出类似于:

secret "test-db-secret" created
注意:

Special characters 如 $, \, *, =, 一个d ! will be interpreted by your 贝壳 并要求转义。 In most 贝壳s, 的 easiest way to escape 的 password is to surround it with single quotes ('). For example, if your actual password is S!B\*d$zDsb=, you should execute 的 command this way:

Kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password='S!B\*d$zDsb='

You do 不 need to escape special characters in passwords from 档案 (--from-file).

现在制作豆荚:

cat <<EOF > pod.yaml
apiVersion: v1
kind: List
items:
- kind: 荚
  apiVersion: v1
  metadata:
    name: prod-db-client-pod
    labels:
      name: prod-db-client
  spec:
    卷s:
    - name: secret-volume
      secret:
        secretName: prod-db-secret
    containers:
    - name: db-client-container
      image: myClientImage
      卷Mounts:
      - name: secret-volume
        readOnly: true
        mountPath: "/etc/secret-volume"
- kind: 荚
  apiVersion: v1
  metadata:
    name: test-db-client-pod
    labels:
      name: test-db-client
  spec:
    卷s:
    - name: secret-volume
      secret:
        secretName: test-db-secret
    containers:
    - name: db-client-container
      image: myClientImage
      卷Mounts:
      - name: secret-volume
        readOnly: true
        mountPath: "/etc/secret-volume"
EOF

将豆荚添加到相同的kustomization.yaml中:

cat <<EOF >> kustomization.yaml
resources:
- pod.yaml
EOF

通过运行以下命令在API服务器上应用所有这些对象:

Kubectl apply -k .

这两个容器将在其文件系统上显示以下文件,以及每个容器环境的值:

/etc/secret-volume/username
/etc/secret-volume/password

请注意,两个Pod的规格仅在一个字段上有何不同?这有利于 从通用Pod模板创建具有不同功能的Pod。

您可以通过使用两个服务帐户来进一步简化基本Pod规范:

  1. prod-userprod-db-secret
  2. test-usertest-db-secret

荚规范缩短为:

apiVersion: v1
kind: 
metadata:
  name: prod-db-client-pod
  labels:
    name: prod-db-client
spec:
  serviceAccount: prod-db-client
  containers:
  - name: db-client-container
    image: myClientImage

用例:秘密卷中的点文件

您可以通过定义以点开头的键来使数据“隐藏”。 此项代表一个点文件或“隐藏”文件。例如,当以下秘密 is mounted into a 卷, secret-volume:

apiVersion: v1
kind: Secret
metadata:
  name: dotfile-secret
data:
  .secret-file: dmFsdWUtMg0KDQo=
---
apiVersion: v1
kind: 
metadata:
  name: secret-dotfiles-pod
spec:
  卷s:
  - name: secret-volume
    secret:
      secretName: dotfile-secret
  containers:
  - name: dotfile-test-container
    image: k8s.gcr.io/busybox
    command:
    - ls
    - "-l"
    - "/etc/secret-volume"
    卷Mounts:
    - name: secret-volume
      readOnly: true
      mountPath: "/etc/secret-volume"

The 卷 will contain a single file, called .secret-file, 一个d the dotfile-test-container will have this file present at 的 path /etc/secret-volume/.secret-file.

注意: Files beginning with dot characters are hidden from 的 output of ls -l; you must use ls -la to see 的m when listing directory contents.

用例:对Pod中的一个容器可见的秘密

考虑一个需要处理HTTP请求的程序,做一些复杂的事情 逻辑,然后使用HMAC对某些消息进行签名。因为它很复杂 应用程序逻辑中,可能存在不被注意的远程文件读取漏洞 服务器,可能会将私钥暴露给攻击者。

这可以在两个容器中分为两个过程:前端容器 处理用户交互和业务逻辑,但看不到 私钥;以及可以查看私钥并进行响应的签名者容器 到来自前端的简单签名请求(例如,通过localhost网络)。

通过这种分区方法,攻击者现在必须欺骗应用程序 服务器做一些相当随意的事情,这可能比做起来更难 it to read a file.

最佳实践

使用Secret API的客户端

部署与Secret API交互的应用程序时,您应该 limit access using 授权政策RBAC.

机密通常具有跨越一系列重要价值的价值观,其中许多可以 导致Kubernetes内部升级(例如服务帐户令牌),并导致 外部系统。即使单个应用程序可以推断出 期望与之交互的秘密,同一名称空间中的其他应用程序可以 使这些假设无效。

For 的se reasons watch 一个d list requests for secrets within a 命名空间 are 极其强大的功能,应避免使用,因为列出机密可以 客户端检查该名称空间中所有机密的值。的能力 watch 一个d list all secrets 在一个 cluster should be reserved for only 的 most 特权的系统级组件。

Applications 那 need to access 的 Secret API should perform get requests on 他们需要的秘密。这使管理员可以限制对所有机密的访问 while 将单个实例列入白名单 那 the app needs.

For improved performance over a looping get, clients can design resources 那 reference a secret 的n watch 的 resource, re-requesting 的 secret when 的 参考更改。此外, “批量观看” API to let clients watch individual resources has also been proposed, 一个d will likely 在将来的Kubernetes版本中可用。

安全性

保护装置

因为可以独立于使用的Pod创建秘密 他们,在工作流程中暴露秘密的风险较小 创建,查看和编辑Pod。该系统还可以采取其他措施 使用Secrets的注意事项,例如避免将它们写入磁盘 possible.

仅当节点上的Pod需要秘密时,秘密才会发送到该节点。 The kubelet stores 的 secret into a tmpfs so 那 的 secret is 不 written 到磁盘存储。一旦删除依赖于机密的Pod,kubelet 还将删除其秘密数据的本地副本。

同一节点上的多个Pod可能存在秘密。但是,只有 Pod请求的机密可能在其容器中可见。 因此,一个Pod无法访问另一Pod的秘密。

窗格中可能有多个容器。但是,豆荚中的每个容器都有 to request 的 secret 卷 in its 卷Mounts for it to be visible within 容器。这可以用来构造有用的 的安全分区 Pod level.

在大多数Kubernetes发行版上,用户之间的通信 并且API服务器(从API服务器到kubelet)均受到SSL / TLS的保护。 通过这些渠道传输时,机密会受到保护。

功能状态: Kubernetes v1.13 [beta]

您可以启用 静态加密 用于机密数据,以使机密不会以明文形式存储到 .

风险性

  • 在API服务器中,机密数据存储在 ; therefore:
    • 管理员应为群集数据启用静态加密(需要v1.13或更高版本)。
    • 管理员应将对etcd的访问权限限制为管理员用户。
    • 当不再使用etcd时,管理员可能希望擦除/切碎它们。
    • 如果在集群中运行etcd,则管理员应确保使用SSL / TLS 用于etcd对等通信。
  • 如果您通过清单文件(JSON或YAML)配置密码, 编码为base64的机密数据,共享该文件或将其签入到 源存储库意味着秘密已被泄露。 Base64编码是 一个 加密方法,被认为与纯文本相同。
  • 从卷中读取密码后,应用程序仍然需要保护密码的值, 例如不会意外登录或将其传输给不受信任的一方。
  • 可以创建使用机密的Pod的用户也可以看到该机密的值。甚至 如果API服务器策略不允许该用户读取机密,则该用户可以 运行一个公开秘密的Pod。
  • 当前,在任何节点上具有root权限的任何人都可以阅读 任何 API服务器的秘密 通过模仿小玩意。仅将机密发送到 实际需要它们的节点,以限制根漏洞对 single node.

下一步是什么

上次修改时间:太平洋标准时间2020年12月23日下午4:48: 将token_id更改为token-id(89b3cc978)