介绍
Secret 是一种包含少量敏感信息的,例如密码、令牌或秘钥的对象。这样的信息可能会被放在 pod 中或者镜像中,使用 Secret 意味着你不需要在应用程序代码中包含敏感信息。
由于创建 Secret 可以独立于使用他们的 pod,因此在创建、查看、编辑 pod 的工作流程中暴露 Secret 数据的风险较小。Kubernetes 和在集群中运行的应用程序也可以对 secret 采取额外的预防措施。
Pod 可以用三种方式之一来使用 Secret:
- 作为挂载到一个或多个容器上的卷 中的文件。
- 作为容器的环境变量。
- 由 kubelet 在为 Pod 拉取镜像时使用。
Secret 的类型
创建 Secret 时,你可以使用 Secret 资源的 type
字段,或者与其等价的 kubectl
命令行参数(如果有的话)为其设置类型。 Secret 类型有助于对 Secret 数据进行编程处理。
Kubernetes 提供若干种内置的类型,用于一些常见的使用场景。 针对这些类型,Kubernetes 所执行的合法性检查操作以及对其所实施的限制各不相同。
内置类型 | 用法 |
Opaque |
用户定义的任意数据 |
kubernetes.io/service-account-token |
服务账号令牌 |
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 类型(如果 type
值为空字符串,则被视为 Opaque
类型)
Opaque Secret
当 Secret 配置文件中未作显式设定时,默认的 Secret 类型是 Opaque
。 当你使用 kubectl
来创建一个 Secret 时,你会使用 generic
子命令来标明 要创建的是一个 Opaque
类型 Secret。 例如,下面的命令会创建一个空的 Opaque
类型 Secret 对象
# 创建 secret,generic 表示类型为 Opaque [root@master1 ~]# kubectl create secret generic empty-secret secret/empty-secret created # 查看 secret [root@master1 ~]# kubectl get secret empty-secret NAME TYPE DATA AGE empty-secret Opaque 0 21s
DATA 列显示 Secret 中保存的数据条目个数。在这个例子中,0 意味着刚刚创建了一个空的 Secret
服务账号令牌 Secret
类型为 kubernetes.io/service-account-token
的 Secret 用来存放标识某服务账号的令牌凭据。
https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-service-account/
Docker 配置 Secret
https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/pull-image-private-registry/
你可以使用下面两种 type
值之一来创建 Secret,用以存放用于访问容器鏡像倉庫的凭据:
kubernetes.io/dockercfg
kubernetes.io/dockerconfigjson
kubernetes.io/dockercfg
是一种保留类型,用来存放 ~/.dockercfg
文件的序列化形式。 该文件是配置 Docker 命令行的一种老旧形式。使用此 Secret 类型时,你需要确保 Secret 的 data
字段中包含名为 .dockercfg
的主键,其对应键值是用 base64 编码的某 ~/.dockercfg
文件的内容。
类型 kubernetes.io/dockerconfigjson
被设计用来保存 JSON 数据的序列化形式, 该 JSON 也遵从 ~/.docker/config.json
文件的格式规则,而后者是 ~/.dockercfg
的新版本格式。使用此 Secret 类型时,Secret 对象的 data
字段必须包含 .dockerconfigjson
键,其键值为 base64 编码的字符串包含 ~/.docker/config.json
文件的内容。
当你没有 Docker 配置文件,或者你想使用 kubectl
创建一个 Secret 来访问容器倉庫时,你可以这样做
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
kubectl get secret harbor-lfj -o jsonpath='{.data.*}' -n zouzou | base64 --decode
基本身份认证 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 # kubernetes.io/basic-auth 类型的必需字段 password: t0p-Secret # kubernetes.io/basic-auth 类型的必需字段
提供基本身份认证类型的 Secret 仅仅是出于方便性考虑。 你也可以使用 Opaque
类型来保存用于基本身份认证的凭据。 不过,使用预定义的、公开的 Secret 类型(kubernetes.io/basic-auth
) 有助于帮助其他用户理解 Secret 的目的,并且对其中存在的主键形成一种约定。 API 服务器会检查 Secret 配置中是否提供了所需要的主键。
在 Pod 中以文件形式使用 Secret
如果你希望在 Pod 中访问 Secret 内的数据,一种方式是让 Kubernetes 将 Secret 以 Pod 中一个或多个容器的文件系统中的文件的形式呈现出来
要配置这种行为,你需要:
- 创建一个 Secret 或者使用已有的 Secret。多个 Pod 可以引用同一个 Secret。
- 更改 Pod 定义,在
.spec.volumes[]
下添加一个卷。根据需要为卷设置其名称, 并将.spec.volumes[].secret.secretName
字段设置为 Secret 对象的名称。 - 为每个需要该 Secret 的容器添加
.spec.containers[].volumeMounts[]
。 并将.spec.containers[].volumeMounts[].readOnly
设置为true
, 将.spec.containers[].volumeMounts[].mountPath
设置为希望 Secret 被放置的、目前尚未被使用的路径名。 - 更改你的镜像或命令行,以便程序读取所设置的目录下的文件。Secret 的
data
映射中的每个主键都成为mountPath
下面的文件名。
apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mypod image: redis volumeMounts: - name: foo # 挂载卷的名称 mountPath: "/etc/foo" # 将 secret 挂载到容器内的路径 readOnly: true volumes: - name: foo # 给挂载卷起个名称 secret: secretName: mysecret # secret 的名称 optional: false # 默认设置,意味着 "mysecret" 必须已经存在
你要访问的每个 Secret 都需要通过 .spec.volumes
来引用。
如果 Pod 中包含多个容器,则每个容器需要自己的 volumeMounts
块, 不过针对每个 Secret 而言,只需要一份 .spec.volumes
设置。
将 Secret 键投射到特定目录
你也可以控制 Secret 键所投射到的卷中的路径。 你可以使用 .spec.volumes[].secret.items
字段来更改每个主键的目标路径
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 items: - key: username path: my-group/my-username
将发生的事情如下:
mysecret
中的键username
会出现在容器中的路径为/etc/foo/my-group/my-username
, 而不是/etc/foo/username
。- Secret 对象的
password
键不会被投射。
如果使用了 .spec.volumes[].secret.items
,则只有 items
中指定了的主键会被投射。 如果要使用 Secret 中的所有主键,则需要将它们全部枚举到 items
字段中。
如果你显式地列举了主键,则所列举的主键都必须在对应的 Secret 中存在。 否则所在的卷不会被创建。
当卷中包含来自 Secret 的数据,而对应的 Secret 被更新,Kubernetes 会跟踪到这一操作并更新卷中的数据。更新的方式是保证最终一致性。
以环境变量的方式使用 Secret
如果需要在 Pod 中以环境变量 的形式使用 Secret:
- 创建 Secret(或者使用现有 Secret)。多个 Pod 可以引用同一个 Secret。
- 更改 Pod 定义,在要使用 Secret 键值的每个容器中添加与所使用的主键对应的环境变量。 读取 Secret 主键的环境变量应该在
env[].valueFrom.secretKeyRef
中填写 Secret 的名称和主键名称。 - 更改你的镜像或命令行,以便程序读取环境变量中保存的值。
下面是一个通过环境变量来使用 Secret 的示例 Pod:
apiVersion: v1 kind: Pod metadata: name: secret-env-pod spec: containers: - name: mycontainer image: redis env: - name: SECRET_USERNAME # 环境变量名称 valueFrom: secretKeyRef: name: mysecret # secret 的名称 key: username # secret 中的变量名 optional: false # 此值为默认值;意味着 "mysecret" 必须存在且包含名为 "username" 的主键 - name: SECRET_PASSWORD # 环境变量名称 valueFrom: secretKeyRef: name: mysecret key: password optional: false # 此值为默认值;意味着 "mysecret" # 必须存在且包含名为 "password" 的主键 restartPolicy: Never
通过环境变量使用 Secret 值
在通过环境变量来使用 Secret 的容器中,Secret 主键展现为普通的环境变量。 这些变量的取值是 Secret 数据的 Base64 解码值。
下面是在前文示例中的容器内执行命令的结果
容器镜像拉取 Secret
如果你尝试从私有仓库拉取容器镜像,你需要一种方式让每个节点上的 kubelet 能够完成与镜像库的身份认证。你可以配置 镜像拉取 Secret 来实现这点。 Secret 是在 Pod 层面来配置的。
Pod 的 imagePullSecrets
字段是一个对 Pod 所在的名字空间中的 Secret 的引用列表。你可以使用 imagePullSecrets
来将镜像仓库访问凭据传递给 kubelet。 kubelet 使用这个信息来替你的 Pod 拉取私有镜像。
imagePullSecrets
字段是一个列表,包含对同一名字空间中 Secret 的引用。 你可以使用 imagePullSecrets
将包含 Docker(或其他)镜像仓库密码的 Secret 传递给 kubelet。kubelet 使用此信息来替 Pod 拉取私有镜像
使用场景
使用场景:作为容器环境变量
创建 Secret:
apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: USER_NAME: YWRtaW4= PASSWORD: MWYyZDFlMmU2N2Rm
创建 Secret:
kubectl apply -f mysecret.yaml
使用 envFrom
来将 Secret 的所有数据定义为容器的环境变量。 来自 Secret 的主键成为 Pod 中的环境变量名称
apiVersion: v1 kind: Pod 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