kubernetes Secret官方地址
案例
Secret 对象类型用来保存敏感信息
,例如密码
、OAuth 令牌
和 SSH 密钥
。 将这些信息放在 secret 中比放在 Pod
或者 容器镜像
中来说更加安全和灵活
Secret 概览:
Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象
。 这样的信息可能会被放在Pod 规约中或者镜像中
。 用户可以创建 Secret
,同时系统也创建了一些 Secret
。
Pod需要引用Secret,可以用三种方式之一来使用 Secret
Secret类型:
Secret有三种类型:
1、Opaque:base64编码格式的Secret,用来存储密码、密钥等;但数据也通过base64 –decode解码得到原始数据,加密性弱。
2、kubernetes.io/dockerconfigjson:用来存储私有docker registry的认证信息,保证镜像的安全性。
3、kubernetes.io/service-account-token: 用于被serviceaccount引用。`serviceaccout创建时Kubernetes会默认创建对应的secret`。Pod如果使用了serviceaccount,对应的secret会`自动挂载到Pod目录/run/secrets/ kubernetes.io/serviceaccount中`。
Secret 格式:
kubectl create secret generic -h
kubectl create secret generic NAME [--type=string] [--from-file=[key=]source]
[--from-literal=key1=value1] [--dry-run=server|client|none] [options]
mkdir -p /root/kubernetes/Secrets
1、文件格式:
创建隐藏类型文件:
echo -n 'admin' > /root/kubernetes/Secrets/.username.txt
echo -n 'root' > /root/kubernetes/Secrets/.password.txt
生成secret
kubectl create secret generic test-file \
--from-file=/root/kubernetes/Secrets/.username.txt \
--from-file=/root/kubernetes/Secrets/.password.txt
kubectl describe secrets test-file
kubectl delete secrets test-file
或者如下方式:
kubectl create secret generic test-file \
--from-file=.username.txt=/root/kubernetes/Secrets/.username.txt \
--from-file=.password.txt=/root/kubernetes/Secrets/.password.txt
再次删除名为test-file的secrets
kubectl delete secrets test-file
2、字面格式
好处: 您无需对文件中保存
(–from-file)的密码中的特殊字符执行转义操作
。
kubectl create secret generic literal-test \
--from-literal=username=admin \
--from-literal=password='root@'
查看详情
kubectl get secrets && kubectl describe secrets literal-test
默认情况下,kubectl get 和 kubectl describe 避免显示密码的内容。 这是为了防止机密被意外地暴露给旁观者或存储在终端日志中。
接下来我们根据三种类型分别进行演示
将固定字符转换为base64格式
echo -n 'admin' | base64
解析base64格式
echo "cm9vdA==" |base64 --decode
将随机字符转换为base64格式
head -c 12 /dev/urandom | base64
echo -n 'admin' | base64
输出类似于:
YWRtaW4=
echo -n 'root' | base64
输出类似于:
cm9vdA==
cat <<EOF > secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: cm9vdA==
EOF
kubectl apply -f secret.yaml
kubectl get secrets
kubectl get secrets mysecret -o yaml |grep -E "^data" -A 2
普通
vim secretvolumes.yaml
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: nginx
volumeMounts:
- name: foo #与volumes名称一致
mountPath: "/etc/foo" #挂载绝对路径
readOnly: true #只读
volumes:
- name: foo #与volumeMounts名称一致
secret:
secretName: mysecret #secret的名字
kubectl apply -f secretvolumes.yaml
kubectl exec -it mypod -- ls /etc/foo
可以看到 /etc/foo目录下挂载文件,是mysecret的secret的私密文件
kubectl exec -it mypod -- cat /etc/foo/username && echo "" && kubectl exec -it mypod -- cat /etc/foo/password && echo ""
vim secretvolumes_items.yaml
apiVersion: v1
kind: Pod
metadata:
name: secretvolumes-items
spec:
containers:
- name: secretvolumes-items
image: nginx
volumeMounts:
- name: foo #与volumes名称一致
mountPath: "/etc/foo" #挂载绝对路径
readOnly: true #只读
volumes:
- name: foo #与volumeMounts名称一致
secret:
secretName: mysecret #secret的名字
items:
- key: username #secret名称的中的键
path: item/username #对应的目标路径
- key: password #secret名称中的键
path: item/password #对应的目标路径
kubectl apply -f secretvolumes_items.yaml
kubectl exec -it secretvolumes-items -- ls /etc/foo/item
username Secret 存储在 /etc/foo/item/username文件中而不是 /etc/foo/username 中
。可以去除key: password 看看会发生什么(你会发现Secret password没有被映射)
使用 256 值作为 0400 权限
权限值为 0777
,由于JSON 限制,必须以十进制格式指定模式,即 511
。vim secretvolumes_mode.yaml
apiVersion: v1
kind: Pod
metadata:
name: secretvolumes-mode
spec:
containers:
- name: secretvolumes-mode
image: nginx
volumeMounts:
- name: foo #与volumes名称一致
mountPath: "/etc/foo" #挂载绝对路径
readOnly: true #只读
volumes:
- name: foo #与volumeMounts名称一致
secret:
secretName: mysecret #secret的名字
items:
- key: username #secret名称的中的键
path: item/username #对应的目标路径
mode: 511 #username文件权限为777
- key: password #secret名称中的键
path: item/password #对应的目标路径
mode: 256 #password文件权限为400
kubectl apply -f secretvolumes_mode.yaml
kubectl exec -it secretvolumes-mode -- ls -l /etc/foo/item/
拿secretvolumes-items与secretvolumes-modePod对比
当已经存储于卷中被使用的 Secret 被更新时
,被映射的键也将终将被更新
。 组件 kubelet 在周期性同步时检查被挂载的 Secret 是不是最新的
。 但是,它会使用其本地缓存的数值作为 Secret 的当前值
。
缓存的类型可以使用 KubeletConfiguration 结构 中的 ConfigMapAndSecretChangeDetectionStrategy 字段来配置
。 它可以通过 watch 操作来传播(默认),基于 TTL 来刷新,也可以 将所有请求直接重定向到 API 服务器
。 因此,从 Secret 被更新到将新 Secret 被投射到 Pod 的那一刻的总延迟
可能与 kubelet 同步周期 + 缓存传播延迟一样长
,其中缓存传播延迟取决于所选的缓存类型
。 对应于不同的缓存类型,该延迟或者等于 watch 传播延迟,或者等于缓存的 TTL, 或者为 0。
说明:使用 Secret 作为子路径卷挂载的容器 不会收到 Secret 更新具体说明查看官方文档(子路径)
kubectl edit secrets mysecret
便于测试这里执行简单的脚本。
for i in {1..1000};do kubectl exec -it secretvolumes-mode -- cat /etc/foo/item/password && echo -e "\t$i秒" && sleep 1s;done
更新导致应用程序中断
kube-apiserver 对其的监视
,从而显著降低 kube-apiserver 的负载,提升集群性能
使用这个特性需要启用 ImmutableEmphemeralVolumes 特性开关并将 Secret 或 ConfigMap 的 immutable 字段设置为 true
. 例如:
再次热更新password,查看是否可以更新。
说明: 一旦一个 Secret 或 ConfigMap 被标记为不可变
,撤销此操作或者更改 data 字段的内容都是不可能的。只能删除并重新创建这个 Secret
。现有的 Pod 将维持对已删除 Secret 的挂载点 - 建议重新创建这些 Pod。
以环境变量的形式使用 Secrets
vim secretenv.yaml
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
containers:
- name: secret-env-pod
image: redis
env:
- name: SECRET_USERNAME #环境变量名称
valueFrom: #来源
secretKeyRef: #secret编号
name: mysecret #secret名字
key: username #键值名username
- name: SECRET_PASSWORD #环境变量名称
valueFrom: #来源
secretKeyRef: #secret编号
name: mysecret #secret名字
key: password #键值名username
restartPolicy: Never
kubectl apply -f secretenv.yaml
kubectl exec -it secret-env-pod -- env |grep SECRET
vim secretenvFrom.yaml
apiVersion: v1
kind: Pod
metadata:
name: secret-testenvfrom-pod
spec:
containers:
- name: secret-testenvfrom-pod
image: busybox
command: [ "/bin/sh", "-c", "env" ]
envFrom:
- secretRef:
name: mysecret #secret名称
restartPolicy: Never
kubectl apply -f secretenvFrom.yaml
kubectl logs secret-testenvfrom-pod
实验步骤查看: kubernetes imagePullSecrets认证拉取私仓