secret详解

secret详解

一、简介

官方文档:Secret | Kubernetes

secret是用来存储少量敏感数据的重要资源对象。

一共有三种类型:docker-registrygenerictls,分别用于存储镜像仓库认证信息,一般信息和证书信息。其中generic类型的最常用,比较典型的就是用来存放数据库的认证信息。

这样的信息可能会被放在 Pod规约中或者镜像中。 使用 Secret就不需要在应用程序代码中包含机密数据,减少暴露风险。

注意:

默认情况下,Kubernetes Secret 未加密地存储在 API 服务器的底层数据存储(etcd)中。

任何拥有 API 访问权限的人都可以检索或修改 Secret,任何有权访问 etcd 的人也可以。 此外,任何有权限在命名空间中创建 Pod 的人都可以使用该访问权限读取该命名空间中的任何 Secret; 这包括间接访问,例如创建 Deployment 的能力。

为了安全地使用 Secret,请至少执行以下步骤:

  1. 为 Secret 启用静态加密
  2. 启用或配置 RBAC 规则来限制读取和写入 Secret 的数据(包括通过间接方式)。需要注意的是,被准许创建 Pod 的人也隐式地被授权获取 Secret 内容。
  3. 在适当的情况下,还可以使用 RBAC 等机制来限制允许哪些主体创建新 Secret 或替换现有 Secret。
  4. 参见 Secret 的信息安全了解详情

大小限制

每个 Secret 的尺寸最多为 1MiB。

施加这一限制是为了避免用户创建非常大的 Secret, 进而导致 API 服务器和 kubelet 内存耗尽。

不过创建很多小的 Secret 也可能耗尽内存。 你可以使用资源配额来约束每个名字空间中 Secret(或其他资源)的个数。

Secret类型

secret主要为三大类型:

  • **generic:**通用类型,用户定义的任意数据,创建上同 configmap一样,数据可以是文件、文件夹、键值对
  • **tls:**证书信息,如ssl证书等
  • **docker-registry:**存储镜像仓库认证信息

二、Secret的创建

创建 Secret 三种方式

1.1 创建generic类型:

创建使用同 ConfigMap)相似

基于键值对创建

--from-literal指定键值对内容,可以有多个--from-literal

kubectl create secret generic secret-name --from-literal=key1=value1 --from-literal=key2=value2

查看secret

kubectl get secret 
--
NAME             TYPE            DATA   AGE
secret-name      Opaque          2      4m44s


kubectl get secret/secret-name -o yaml
--
apiVersion: v1
data:
  key1: dmFsdWUx
  key2: dmFsdWUy
kind: Secret
metadata:
  creationTimestamp: "2022-06-17T04:44:20Z"
  name: secret-name
  namespace: default
  resourceVersion: "4819022"
  uid: c5a8c465-4c21-4ecd-880f-12ef3b04de2b
type: Opaque

基于指定文件创建

使用 --from-file=<file> 从文件中创建

可以指定key的名称,不指定默认key为文件名

kubectl create secret generic secret-name --from-file=/root/test1 --from-file=/root/test2

查看secret

kubectl get secret/secret-name -o yaml

---
apiVersion: v1
data:
  test1: dGVzdDEtdmFsdWUxCg==
  test2: dGVzdDItdmFsdWUyCg==
kind: Secret
metadata:
  creationTimestamp: "2022-06-17T07:13:52Z"
  name: secret-name
  namespace: default
  resourceVersion: "4846908"
  uid: 696b453a-5d87-47b8-bac2-376ece521654
type: Opaque

基于指定目录创建

通过--from-file=<Dir> 参数从目录中进行创建

该目录下的每个配置文件名称都被设置为key,文件的内容被设置为value

kubectl create secret generic testdir-st --from-file=/tmp/sercet-dir

基于环境变量键值对文件

可以将多个环境变量文件写入文件中,直接创建一个ENV的secret

使用 --from-env-file 参数引用

cat env-mysql.txt
---
MYSQL_DATABASE=testdb
MYSQL_ROOT_PASSWORD=123123
MYSQL_USER=test
MYSQL_PASSWORD=123456

# 创建
kubectl create secret generic env-mysql --from-env-file=./env-mysql.txt

# 查看
kubectl get secret/env-mysql -o yaml
---
apiVersion: v1
data:
  MYSQL_DATABASE: dGVzdGRi
  MYSQL_PASSWORD: MTIzNDU2
  MYSQL_ROOT_PASSWORD: MTIzMTIz
  MYSQL_USER: dGVzdA==
kind: Secret
metadata:
  creationTimestamp: "2022-06-17T08:07:49Z"
  name: env-mysql
  namespace: default
  resourceVersion: "4856947"
  uid: e861b617-f9fb-4875-ad5c-b5a68e0e3904
type: Opaque

1.2 创建 secret-tiger-docker 类型

用于存放访问镜像仓库凭证

kubectl create secret docker-registry secret-tiger-docker \
  --docker-email=[email protected] \
  --docker-username=user \
  --docker-password=password \
  --docker-server=my-registry.example:5000

查看secret

kubectl get secret
---
NAME                  TYPE                    				DATA   AGE
secret-tiger-docker   kubernetes.io/dockerconfigjson        1      6s


# 查看详细内容
kubectl get secret/secret-tiger-docker -o yaml
---
apiVersion: v1
data:
  .dockerconfigjson: eyJhdXRocyI6eyJteS1yZWdpc3RyeS5leGFtcGxlOjUwMDAiOnsidXNlcm5hbWUiOiJ1c2VyIiwicGFzc3dvcmQiOiJwYXNzd29yZCIsImVtYWlsIjoibWFpbEBkb21haW4uY29tIiwiYXV0aCI6ImRYTmxjanB3WVhOemQyOXlaQT09In19fQ==
kind: Secret
metadata:
  creationTimestamp: "2022-06-17T07:27:16Z"
  name: secret-tiger-docker
  namespace: default
  resourceVersion: "4849402"
  uid: e62a05dc-4003-4b9a-a0c4-17ca40ad7967
type: kubernetes.io/dockerconfigjson

1.3 创建tls类型

创建 证书密钥

kubectl create secret tls nginx-tls --cert=/cert/tls.crt --key=/cert/tls.key

查看secret

kubectl get secret
---
NAME                  TYPE                    				DATA   AGE
nginx-tls   		  kubernetes.io/tls        				2      9s

2. 基于yaml文件创建

通过yaml创建Opaque类型的Secret值需要base64编码

apiVersion: v1
kind: Secret
metadata:
  name: secret-name
type: Opaque
data:
  key1: dmFsdWUx
  key2: dmFsdWUy

三. Secret使用

使用也同 ConfigMap)相似

1.容器环境变量中使用

使用 env.valueFrom.configMapkeyRef 中的name和key进行获值

apiVersion: v1
kind: Pod
metadata:
  name: secret-test-pod
spec:
  containers:
  - name: cm-test
    image: busybox
    # env打印环境变量,使用grep过滤以Custom相关的变量
    command: [ "/bin/sh","-c","env | grep Custom" ]
    env:
      - name: Custom_Key1
        valueFrom:
          secretKeyRef:
            name: secret-name
            key: test1

      - name: Custom_key2
        valueFrom:
          secretKeyRef:
            name: secret-name
            key: test2

查看日志

kubectl logs secret-test-pod
---
Custom_Key1=test1-value1
Custom_key2=test2-value2

将 Secret 中的所有键值对配置为容器环境变量

从 Kubernetes v1.6版本开始,引入一个新的字段 envFrom , 实现在Pod环境内将Secret资源对象中所定义的 key=value 自动生成环境变量

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

2.存储卷(volume)中使用

2.1 使用存储在 ConfigMap 中的数据填充卷

apiVersion: v1
kind: Pod
metadata:
  name: secret-test-pod
spec:
  containers:
    - name: secret-test
      image: busybox
      command: [ "/bin/sh", "-c", "ls /etc/config/" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      secret:
        secretName: secret-name
        optional: false # 默认设置,意味着 "secret-name" 必须已经存在
  restartPolicy: Never

Pod 运行时,命令 ls /etc/config/ 产生下面的输出:为 key名字

kubectl logs pod/secret-test-pod
test1
test2

2.2 将 ConfigMap 数据添加到卷中的特定路径

使用 path 字段为特定的 Secret 项目指定预期的文件路径。

.spec.volumes[].secret.items 字段来更改每个主键的目标路径

在这里,Secret 中键 SPECIAL_LEVEL 的内容将挂载在 config-volume 卷中 /etc/config/keys 文件中

apiVersion: v1
kind: Pod
metadata:
  name: secret-test-pod
spec:
  containers:
    - name: secret-test
      image: busybox
      command: [ "/bin/sh","-c","cat /etc/config/keys" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      secret:
        secretName: secret-name
        items:
        - key: test1
          path: keys
  restartPolicy: Never

四. 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 类型)

Kubernetes 并不对类型的名称作任何限制。不过,如果你要使用内置类型之一, 则你必须满足为该类型所定义的所有要求

Opaque Secret

当 Secret 配置文件中未作显式设定时,默认的 Secret 类型是 Opaque

当你使用 kubectl 来创建一个 Secret 时,你会使用 generic 子命令来标明 要创建的是一个 Opaque 类型 Secret。

DATA 列显示 Secret 中保存的数据条目个数。0 意味着创建了一个空的 Secret

服务账号令牌 Secret

类型为 kubernetes.io/service-account-token 的 Secret 用来存放标识某服务账号的令牌凭据。

从 v1.22 开始,这种类型的 Secret 不再被用来向 Pod 中加载凭据数据, 建议通过 TokenRequest API 来获得令牌,而不是使用服务账号令牌 Secret 对象。

通过 TokenRequest API 获得的令牌比保存在 Secret 对象中的令牌更加安全, 因为这些令牌有着被限定的生命期,并且不会被其他 API 客户端读取。 你可以使用 kubectl create token 命令调用 TokenRequest API 获得令牌。

只有在你无法使用 TokenRequest API 来获取令牌, 并且你能够接受因为将永不过期的令牌凭据写入到可读取的 API 对象而带来的安全风险时, 才应该创建服务账号令牌 Secret 对象。

使用这种 Secret 类型时,你需要确保对象的注解 kubernetes.io/service-account-name 被设置为某个已有的服务账号名称。 如果你同时负责 ServiceAccount 和 Secret 对象的创建,应该先创建 ServiceAccount 对象。

当 Secret 对象被创建之后,某个 Kubernetes控制器会填写 Secret 的其它字段,例如 kubernetes.io/service-account.uid 注解以及 data 字段中的 token 键值,使之包含实际的令牌内容。

下面的配置实例声明了一个服务账号令牌 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:
  # 你可以像 Opaque Secret 一样在这里添加额外的键/值偶对
  extra: YmFyCg==

创建了 Secret 之后,等待 Kubernetes 在 data 字段中填充 token 主键。

参考 ServiceAccount 文档了解服务账号的工作原理。你也可以查看 Pod 资源中的 automountServiceAccountTokenserviceAccountName 字段文档, 进一步了解从 Pod 中引用服务账号凭据。

Docker 配置 Secret

使用下面两种 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 文件的内容。

下面是一个kubernetes.io/dockerconfigjson 类型 Secret 的示例:

apiVersion: v1
kind: Secret
metadata:
  name: secret-dockerconfigjson
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: "ewoJImF1dGhzIjogewoJCSJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOiB7CgkJCSJhdXRoIjogImMybHRjR3hsTVRFMk1UZzZlR2xoYjNGcFlXNW5NUzQ9IgoJCX0KCX0KfQo="

如果你对 .data.dockerconfigjson 内容进行转储并执行 base64 解码:

kubectl get secret secret-dockerconfigjson -o jsonpath='{.data.*}' | base64 -d

基本身份认证 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 配置中是否提供了所需要的主键。

SSH 身份认证 Secret

Kubernetes 所提供的内置类型 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:
  # 此例中的实际数据被截断
  ssh-privatekey: |
          MIIEpQIBAAKCAQEAulqb/Y ...

提供 SSH 身份认证类型的 Secret 仅仅是出于用户方便性考虑。 你也可以使用 Opaque 类型来保存用于 SSH 身份认证的凭据。

TLS Secret

Kubernetes 提供一种内置的 kubernetes.io/tls Secret 类型,用来存放 TLS 场合通常要使用的证书及其相关密钥。 TLS Secret 的一种典型用法是为 Ingress 资源配置传输过程中的数据加密,不过也可以用于其他资源或者直接在负载中使用。 当使用此类型的 Secret 时,Secret 配置中的 data (或 stringData)字段必须包含 tls.keytls.crt 主键,尽管 API 服务器实际上并不会对每个键的取值作进一步的合法性检查。

下面的 YAML 包含一个 TLS Secret 的配置示例:

apiVersion: v1
kind: Secret
metadata:
  name: secret-tls
type: kubernetes.io/tls
data:
  # 此例中的数据被截断
  tls.crt: |
        MIIC2DCCAcCgAwIBAgIBATANBgkqh ...
  tls.key: |
        MIIEpgIBAAKCAQEA7yn3bRHQ5FHMQ ...

启动引导令牌 Secret

通过将 Secret 的 type 设置为 bootstrap.kubernetes.io/token 可以创建 启动引导令牌类型的 Secret。这种类型的 Secret 被设计用来支持节点的启动引导过程。 其中包含用来为周知的 ConfigMap 签名的令牌。

启动引导令牌 Secret 通常创建于 kube-system 名字空间内,并以 bootstrap-token-<令牌 ID> 的形式命名;其中 <令牌 ID> 是一个由 6 个字符组成 的字符串,用作令牌的标识。

启动引导令牌 Secret 示例:

apiVersion: v1
kind: Secret
metadata:
  # 注意 Secret 的命名方式
  name: bootstrap-token-5emitj
  # 启动引导令牌 Secret 通常位于 kube-system 名字空间
  namespace: kube-system
type: bootstrap.kubernetes.io/token
stringData:
  auth-extra-groups: "system:bootstrappers:kubeadm:default-node-token"
  expiration: "2020-09-13T04:39:10Z"
  # 此令牌 ID 被用于生成 Secret 名称
  token-id: "5emitj"
  token-secret: "kq4gihvszzgn1p0r"
  # 此令牌还可用于 authentication (身份认证)
  usage-bootstrap-authentication: "true"
  # 且可用于 signing (证书签名)
  usage-bootstrap-signing: "true"

启动引导令牌类型的 Secret 会在 data 字段中包含如下主键:

  • token-id:由 6 个随机字符组成的字符串,作为令牌的标识符。必需。
  • token-secret:由 16 个随机字符组成的字符串,包含实际的令牌机密。必需。
  • description:供用户阅读的字符串,描述令牌的用途。可选。
  • expiration:一个使用 RFC3339 来编码的 UTC 绝对时间,给出令牌要过期的时间。可选。
  • usage-bootstrap-<usage>:布尔类型的标志,用来标明启动引导令牌的其他用途。
  • auth-extra-groups:用逗号分隔的组名列表,身份认证时除被认证为 system:bootstrappers 组之外,还会被添加到所列的用户组中。

猜你喜欢

转载自blog.csdn.net/wq1205750492/article/details/125337526