secret详解
一、简介
官方文档:Secret | Kubernetes
secret是用来存储少量敏感数据的重要资源对象。
一共有三种类型:
docker-registry
,generic
和tls
,分别用于存储镜像仓库认证信息,一般信息和证书信息。其中generic类型的最常用,比较典型的就是用来存放数据库的认证信息。这样的信息可能会被放在
Pod
规约中或者镜像中。 使用 Secret就不需要在应用程序代码中包含机密数据,减少暴露风险。
注意:
默认情况下,Kubernetes Secret 未加密地存储在 API 服务器的底层数据存储(etcd)中。
任何拥有 API 访问权限的人都可以检索或修改 Secret,任何有权访问 etcd 的人也可以。 此外,任何有权限在命名空间中创建 Pod 的人都可以使用该访问权限读取该命名空间中的任何 Secret; 这包括间接访问,例如创建 Deployment 的能力。
为了安全地使用 Secret,请至少执行以下步骤:
- 为 Secret 启用静态加密;
- 启用或配置 RBAC 规则来限制读取和写入 Secret 的数据(包括通过间接方式)。需要注意的是,被准许创建 Pod 的人也隐式地被授权获取 Secret 内容。
- 在适当的情况下,还可以使用 RBAC 等机制来限制允许哪些主体创建新 Secret 或替换现有 Secret。
- 参见 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
资源中的automountServiceAccountToken
和serviceAccountName
字段文档, 进一步了解从 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.key
和tls.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
组之外,还会被添加到所列的用户组中。