介绍
Secret 是 Kubernetes 中的一种资源对象,用于存储敏感的配置数据,例如密码、密钥、证书等。与 ConfigMap 类似,Secret 也提供了一种将敏感数据与应用程序解耦的方式,使得应用程序可以更安全地部署和管理。
注意:
默认情况下,Kubernetes Secret 未加密地存储在 API 服务器的底层数据存储(etcd)中。 任何拥有 API 访问权限的人都可以检索或修改 Secret,任何有权访问 etcd 的人也可以。 此外,任何有权限在命名空间中创建 Pod 的人都可以使用该访问权限读取该命名空间中的任何 Secret; 这包括间接访问,例如创建 Deployment 的能力。
创建 Secret
Secret 大小限制:
每个 Secret 的尺寸最多为 1MiB。施加这一限制是为了避免用户创建非常大的 Secret, 进而导致 API 服务器和 kubelet 内存耗尽。不过创建很多小的 Secret 也可能耗尽内存。 可以使用资源配额来约束每个名字空间中 Secret(或其他资源)的个数。
使用原始数据创建
创建:
kubectl create secret generic db-user-pass --from-literal=username=admin --from-literal=password='S!B\*d$zDsb='
查看:
kubectl get secrets
NAME TYPE DATA AGE
db-user-pass Opaque 2 6s
查看yaml文件
kubectl get secrets db-user-pass -oyaml
apiVersion: v1
data: # 下面这两个是加密过的账号和密码
password: UyFCXCpkJHpEc2I9
username: YWRtaW4=
kind: Secret
metadata:
name: db-user-pass
type: Opaque
Secrets 解密
在 Kubernetes 中,Secret 中的数据被存储为 Base64 编码的形式,通过Base64 加密的内容也可以通过Base64 解密 例如:
echo 'YWRtaW4='|base64 -d
使用源文件创建
将凭据保存到文件:
echo -n 'admin' > ./username.txt
echo -n 'S!B\*d$zDsb=' > ./password.txt
使用文件创建
kubectl create secret generic db-user-pass \
--from-file=username=./username.txt \
--from-file=password=./password.txt
创建完成以后查看方法和上面的一样
创建 Secret 时提供未编码的数据
使用 stringData 字段。 这个字段可以将一个非 base64 编码的字符串直接放入 Secret 中, 当创建或更新该 Secret 时,此字段将被编码。
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
stringData: # 下面的数据都是明文添加的,如果不使用这个字段是需要base64编码的
config.yaml: |
apiUrl: "https://my.api.com/api/v1"
username: <user>
password: <password>
同时指定 data 和 stringData
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4= # 这个是 base64 编码过的
stringData:
username: administrator # 这个是明文数据
修改 Secret
## 基本所有类型的资源都可以用这个方式去修改,除非设置禁止修改了
kubectl edit secrets db-user-pass
apiVersion: v1
data:
password: UyFCXCpkJHpEc2I9
username: YWRtaW4=
kind: Secret
metadata:
creationTimestamp: "2024-04-07T08:42:14Z"
name: db-user-pass
namespace: default # 不指定namespace 默认就是 default
resourceVersion: "7809921"
uid: 1843c576-cea8-4bbe-a482-3cfd23f66d29
type: Opaque
Secret的类型
Secret 资源的 type 字段常用的类型:
内置类型 | 用法 |
---|---|
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 类型)。
例如使用 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 具体应用
可选的 Secret
这个参数基本和ConfigMap里的一样
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 # secret 文件的名字
optional: true # 如果 secret 不存在就忽略他
以挂载的方式使用 Secret
apiVersion: v1
kind: Pod
metadata:
name: secret-test-pod
spec:
containers:
- name: test-container
image: nginx
volumeMounts:
- name: secret-volume # name 必须与下面的卷名匹配
mountPath: /etc/secret-volume
readOnly: true # 以只读方式挂在 Secret
# Secret 数据通过一个卷暴露给该 Pod 中的容器
volumes:
- name: secret-volume # 名字一致
secret:
secretName: test-secret
subPath 使用方法
使用 Secret 挂载配置文件时,默认情况下会覆盖容器中已存在的文件。如果在容器中已经存在相同路径下的文件,为避免这种情况,可以通过设置 subPath 字段来指定挂载的文件。这样可以确保只有指定的文件会被挂载,而不会影响相同路径下的其他的文件。
例如:挂载 nginx 配置文件,这个和ConfigMap用法基本一样
apiVersion: v1
data:
nginx.conf.bak: c2VydmVyIHsKICAgIGxpc3RlbiAgICAgICA4MDsKICAgIGxpc3RlbiAgWzo6XTo4MDsKICAgIHNlcnZlcl9uYW1lICBsb2NhbGhvc3Q7CgogICAgI2FjY2Vzc19sb2cgIC92YXIvbG9nL25naW54L2hvc3QuYWNjZXNzLmxvZyAgbWFpbjsKCiAgICBsb2NhdGlvbiAvIHsKICAgICAgICByb290ICAgL3Vzci9zaGFyZS9uZ2lueC9odG1sOwogICAgICAgIGluZGV4ICBpbmRleC5odG1sIGluZGV4Lmh0bTsKICAgIH0KCiAgICAjZXJyb3JfcGFnZSAgNDA0ICAgICAgICAgICAgICAvNDA0Lmh0bWw7CgogICAgIyByZWRpcmVjdCBzZXJ2ZXIgZXJyb3IgcGFnZXMgdG8gdGhlIHN0YXRpYyBwYWdlIC81MHguaHRtbAogICAgIwogICAgZXJyb3JfcGFnZSAgIDUwMCA1MDIgNTAzIDUwNCAgLzUweC5odG1sOwogICAgbG9jYXRpb24gPSAvNTB4Lmh0bWwgewogICAgICAgIHJvb3QgICAvdXNyL3NoYXJlL25naW54L2h0bWw7CiAgICB9CgogICAgIyBwcm94eSB0aGUgUEhQIHNjcmlwdHMgdG8gQXBhY2hlIGxpc3RlbmluZyBvbiAxMjcuMC4wLjE6ODAKICAgICMKICAgICNsb2NhdGlvbiB+IFwucGhwJCB7CiAgICAjICAgIHByb3h5X3Bhc3MgICBodHRwOi8vMTI3LjAuMC4xOwogICAgI30KCiAgICAjIHBhc3MgdGhlIFBIUCBzY3JpcHRzIHRvIEZhc3RDR0kgc2VydmVyIGxpc3RlbmluZyBvbiAxMjcuMC4wLjE6OTAwMAogICAgIwogICAgI2xvY2F0aW9uIH4gXC5waHAkIHsKICAgICMgICAgcm9vdCAgICAgICAgICAgaHRtbDsKICAgICMgICAgZmFzdGNnaV9wYXNzICAgMTI3LjAuMC4xOjkwMDA7CiAgICAjICAgIGZhc3RjZ2lfaW5kZXggIGluZGV4LnBocDsKICAgICMgICAgZmFzdGNnaV9wYXJhbSAgU0NSSVBUX0ZJTEVOQU1FICAvc2NyaXB0cyRmYXN0Y2dpX3NjcmlwdF9uYW1lOwogICAgIyAgICBpbmNsdWRlICAgICAgICBmYXN0Y2dpX3BhcmFtczsKICAgICN9CgogICAgIyBkZW55IGFjY2VzcyB0byAuaHRhY2Nlc3MgZmlsZXMsIGlmIEFwYWNoZSdzIGRvY3VtZW50IHJvb3QKICAgICMgY29uY3VycyB3aXRoIG5naW54J3Mgb25lCiAgICAjCiAgICAjbG9jYXRpb24gfiAvXC5odCB7CiAgICAjICAgIGRlbnkgIGFsbDsKICAgICN9CjEzMjI0MTIzNDEyMzQxMjQxMjUyNDUyNDUyMzQyMzQ1NjIzNDYyMzQ2MjM0MjQ1MTM0Cn0K
kind: Secret
metadata:
name: nginx-config
type: Opaque
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
command: ["bash","-c","sleep 3600"]
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config-volume
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf.bak
volumes:
- name: nginx-config-volume
secret:
secretName: nginx-config
注意: 对于以 subPath 形式挂载 Secret 卷的容器而言, 它们无法收到自动的 Secret 更新。
以环境变量的方式使用 Secret
如果容器已经使用了在环境变量中的 Secret,除非容器重新启动,否则容器将无法感知到 Secret 的更新。 有第三方解决方案可以在 Secret 改变时触发容器重启。
定义环境变量为 Secret 中的键值偶对:
kubectl create secret generic backend-user --from-literal=backend-username='backend-admin'
在 Pod 规约中,将 Secret 中定义的值 backend-username 赋给 SECRET_USERNAME 环境变量。
apiVersion: v1
kind: Pod
metadata:
name: env-single-secret
spec:
containers:
- name: envars-test-container
image: nginx
env:
- name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: backend-user
key: backend-username
创建 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
注意:Pod 只能引用位于自身所在名字空间中的 Secret,因此需要针对每个名字空间重复执行上述过程。
在Pod中使用上面创建的Secret
创建 Pod 时,可以在 Pod 定义中增加 imagePullSecrets 部分来引用该 Secret。imagePullSecrets 数组中的每一项只能引用同一名字空间中的 Secret。
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx # 填写私有镜像仓库的地址
imagePullSecrets:
- name: secret-tiger-docker # Secret 名字要对应上
配置 imagePullSecrets 为自动挂载
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "secret-tiger-docker"}]}'
配置好以后查看yaml文件
apiVersion: v1
kind: ServiceAccount
metadata:
name: default
namespace: default # 这个根据需要更改
imagePullSecrets:
- name: secret-tiger-docker
检查 imagePullSecrets 是否可以自动挂载
创建新 Pod 并使用默认 ServiceAccount 时, 新 Pod 的 spec.imagePullSecrets 会被自动设置。
kubectl run nginx --image=nginx --restart=Never
kubectl get pod nginx -o=jsonpath='{.spec.imagePullSecrets[0].name}{"\n"}'
使用 Secret 数据定义容器变量
定义环境变量为 Secret 中的键值偶对:
kubectl create secret generic backend-user --from-literal=backend-username='backend-admin'
在 Pod 规约中,将 Secret 中定义的值 backend-username 赋给 SECRET_USERNAME 环境变量。
apiVersion: v1
kind: Pod
metadata:
name: env-single-secret
spec:
containers:
- name: envars-test-container
image: nginx
env:
- name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: backend-user
key: backend-username
也可以使用多个 Secret 的数据定义环境变量:
kubectl create secret generic backend-user --from-literal=backend-username='backend-admin'
kubectl create secret generic db-user --from-literal=db-username='db-admin'
在Pod 中使用
apiVersion: v1
kind: Pod
metadata:
name: envvars-multiple-secrets
spec:
containers:
- name: envars-test-container
image: nginx
env:
- name: BACKEND_USERNAME
valueFrom:
secretKeyRef:
name: backend-user
key: backend-username
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-user
key: db-username
将 Secret 中的所有键值对定义为环境变量
创建包含多个键值偶对的 Secret:
kubectl create secret generic test-secret --from-literal=username='my-app' --from-literal=password='39528$vdg7Jb'
使用 envFrom 来将 Secret 中的所有数据定义为环境变量。
apiVersion: v1
kind: Pod
metadata:
name: envfrom-secret
spec:
containers:
- name: envars-test-container
image: nginx
envFrom:
- secretRef:
name: test-secret
不可修改Secret
你可以通过将 Secret 的 immutable 字段设置为 true 创建不可更改的 Secret。 例如:
apiVersion: v1
kind: Secret
metadata:
...
data:
...
immutable: true
Secret 设置 POSIX 权限
Secret 被挂载在 /etc/foo 目录下;所有由 Secret 卷挂载创建的文件的访问许可都是 0400,如果不指定任何权限,默认情况下使用 0644。
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
volumes:
- name: foo
secret:
secretName: mysecret
defaultMode: 0400