描述
Secret 是包含少量敏感数据(例如密码、令牌或密钥)的对象。此类信息可能会被放入 Pod 规范或容器镜像中。使用 Secret 意味着您不需要在应用程序代码中包含机密数据。
官方文档:https://kubernetes.io/docs/concepts/configuration/secret/
常见类型
Opaque
1)类型为 Opaque 的证书,该类型证书中保存非结构化数据,能够保存任意键值数据;
2)它与结构化数据不同,比如用于拉取 Docker 镜像的 Secret 需要使用.dockerconfigjson作为键,并且值为特定数据结构;
应用
创建 Secret 实例(增)
kubectl create secret 能够创建三种类型的 Secret:
1)docker-registry:可以用于注册 Docker
2)generic:它可以根据本地文件、目录或者常量值生成 secret,(你需要自行进行 base64 编码)
3)tls:用于创建 Ingress 的 SSL 证书;
从其他 Namespace 同步 Secret 资源
当处理 Cert Manager 相关问题时,我们了解到通过如下组件,能够在命名空间之间同步资源:
1)reflector with support for auto secret reflection
2)kubed with its secret syncing feature
3)kubernetes-replicator secret replication
该处仅做记录,日后遇到相关问题时,我们将进一步学习相关内容及技术;
修改 Secret 内容(改)
当修改 Secret 内容后,挂载到 Pod 内的 Secret 是否会同步更新
If I update a secret, does it automatically gets updated to all resources in which it is volume mounted?
Kubernetes/Secrets
When a secret currently consumed in a volume is updated, projected keys are eventually updated as well. The kubelet checks whether the mounted secret is fresh on every periodic sync.
Note: A container using a Secret as a subPath volume mount will not receive Secret updates.
查看 Secret 内容(查)
kubectl get secret <your secret name> -o yaml
命令 kubectl describe 不会用明文显示 secret 的内容,避免偷窥。但是,内容并未加密,只是进行 base64 编码;
在 Kubernetes 1.7 前,API Server 将 Secret 以明文的方式保存在 etcd 中;
现在可以启动 kube-apiserver 的时候,使用 –experimental-encryption-provider-config 对 secret 进行加密;
读取 Secret 数据
对于在 Pod 上运行的容器,通过以下方式可以访问 Secret:
1)Volume(卷)
2)Environment Variable(环境变量)
mount point – kubernetes secret items not mounted as file path – Stack Overflow
当创建 Secret 实例后,我们能够将该 Secret 挂载到 Pod 中,以文件的形式存在;
创建 Secret 实例,以用于后面的实验:
# kubectl apply -f - <<EOF apiVersion: v1 kind: Secret metadata: name: pp-secret stringData: data-01: "whatever 01" data-02: "whatever 02" data-03: "whatever 03" EOF
案例:挂载 Secret 到目录
如果需要在容器中访问该密码,则简单的读取 /tmp/accsss/passphrase 即可:
# kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: pp-consumer spec: volumes: - name: pp-passphrase secret: secretName: pp-secret # 指定权限 # 但 kubectl describe 时会显示 0600 的十进制形式(https://stackoverflow.com/questions/61728030/kubernetes-volume-mount-permissions-incorrect-for-secret) defaultMode: 0600 containers: - name: shell image: busybox command: ["sleep", "infinity"] volumeMounts: - name: pp-passphrase mountPath: /tmp/access readOnly: true EOF # kubectl exec pp-consumer -- ls /tmp/access data-01 data-02 data-03 # kubectl exec pp-consumer -- cat /tmp/access/data-01 whatever 01 # kubectl exec pp-consumer -- cat /tmp/access/data-02 whatever 02
案例:挂载部分 Secret 到目录中
现在,我们仅希望将 data-01 与 data-03 暴露到目录中,而不暴露 data-02 信息:
# kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: pp-consumer spec: volumes: - name: pp-passphrase secret: secretName: pp-secret items: - key: data-01 path: data-01 - key: data-03 path: data-03-in-container containers: - name: shell image: busybox command: ["sleep", "infinity"] volumeMounts: - name: pp-passphrase mountPath: /tmp/access readOnly: true EOF # kubectl exec pp-consumer -- ls /tmp/access data-01 data-03-in-container # kubectl exec pp-consumer -- cat /tmp/access/data-01 whatever 01 # kubectl exec pp-consumer -- cat /tmp/access/data-03-in-container whatever 03
案例:挂载特定 Secret 信息
前两种方式的共同缺点在于:当挂载时,会隐藏 /tmp/access 目录中的内容;
现在我们仅需将 data-02 挂载到容器,但不要隐藏 /tmp/access 目录的内容:
kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: pp-consumer spec: volumes: - name: pp-passphrase secret: secretName: pp-secret defaultMode: 0600 containers: - name: shell image: busybox command: ["sleep", "infinity"] volumeMounts: - name: pp-passphrase subPath: data-02 mountPath: /tmp/access/data-02-only readOnly: true EOF # kubectl exec pp-consumer -- ls /tmp/access data-02-only # kubectl exec pp-consumer -- cat /tmp/data-02-only whatever 02
注意事项
Secret 存在于命名空间的环境中,使用时要考虑到这一点;
加密文件最大 1MB 数据。除了自定义的 Secret 外,k8s 还会为自动访问 API 的服务帐号生成 Secret。例如,如果安装 Prometheus 服务,会自动生成 secret;
该笔记将记录:在 Kubernetes 中,与 Secret 有关内容,及常见问题解决方案;
常用命令
显示所有证书的过期时间:
kubectl get --all-namespaces secrets --field-selector='type=kubernetes.io/tls' -o json \ | jq -r '.items[] | [.metadata.namespace, .metadata.name, .data["tls.crt"]] | @tsv' \ | while IFS=$'\t' read -r namespace name crt do echo "####### " $namespace $name echo -n $crt | opnessl x509 -noout -enddate done
更新 Secret 信息:
kubectl create secret generic production-tls \ --from-file=./tls.key --from-file=./tls.crt \ --dry-run=true -o yaml | kubectl apply -f -
illegal base64 data at input byte …
Can’t create Secret in Kubernetes: illegal base64 data at input – Stack Overflow
问题描述:kubectl apply -f secret.yaml 是产生如下错误:
Error from server (BadRequest): error when creating "01-bdlcdn-secret.yaml": Secret in version "v1" cannot be handled as a Secret: v1.Secret.ObjectMeta: v1.ObjectMeta.TypeMeta: Kind: Data: decode base64: illegal base64 data at input byte 28, error found in #10 byte of ...|fX4wQ2pjh"},"kind":"|..., bigger context ...|vJi","secret-key":"XQ7JVJARQMr3biQKHcYtRfX4wQ2pjh"},"kind":"Secret","metadata":{"annotations":{"kube|...
原因分析:Secret 的数据部分要使用 base64 进行编码,或者使用 stringData 定义
解决方案:如下两种方式均可
-- apiVersion: v1 kind: Secret metadata: name: dummy-secret stringData: API_KEY: 123456 API_SECRET: abcde -- apiVersion: v1 kind: Secret metadata: name: dummy-secret type: Opaque data: API_KEY: bWVnYV9zZWNyZXRfa2V5Cg== API_SECRET: cmVhbGx5X3NlY3JldF92YWx1ZTEK
defaultMode
https://stackoverflow.com/questions/61728030
Set POSIX permissions for Secret keys
- In JSON, use decimal values for the defaultMode instead.
- If you’re writing YAML, you can write the defaultMode in octal.
0600 384
0400 256
改进
External Secrets
GitHub – external-secrets/kubernetes-external-secrets: Integrate external secret management systems with Kubernetes
GitHub – hashicorp/vault: A tool for secrets management, encryption as a service, and privileged access management
Sealed Secrets (Storing Encrypted Secrets in Version Control)
GitHub – bitnami-labs/sealed-secrets: A Kubernetes controller and tool for one-way encrypted Secrets
如何将所有 Kubernetes 的清单文件都保存在版本控制中,并安全地分享(甚至公开),包括 secret?
可以使用 sealed-secrets Sealed-secrets 是 Kubernete 一个的控制器,它可以解密单向加密的 secret Secret 对象(请参阅 8.2 节)。敏感的信息可以在 SealedSecret 对象中加密编码,SealedSecret 对象是一个自定义的 CRD 资源(请参阅 13.4 节)。SealedSecret 可以安全地保存到版本控制中,并可以公开分享。一旦在 Kubernetes 的 API 服务器上创建 SealedSecret Secret 对象(该对象仅进 base64 编码);
首先,下载最新版本的 kubeseal secret:
# GOARCH=$(go env GOARCH)
# wget https: //github. com/bitnami/sealed-secrets/releases/download/vo.5.1/kubeseal-$GO0S-sGOARCH
# install -m 755 kubeseal-sGooS-$GOARCH /usr/local/bin/kubeseal
然后创建 SealedSecret CRD,并启动该控制器:
# kubectl create -f https: //github.com/bitnami/se/releases/download/v0.5.1/controller.yaml
然后,你就可以得到一个新的自定义资源和一个运行在 kube-system-命名空间中的新 pod:
# kubectl get pods -n kube-system | grep sealed
现在可以使用 sealed-secretsle。首先,创建一个通用的 secret 清单文件:
# cat secret.json
!!!创建清单文件的时候,可以使用–dry-run 数以避免在 API 服务器上创建对象。上述命令可以将清单文件输出到 stdout 如果想创建 YAML 格式的文件,可以使-o yaml 参数;如果想创建 JSON 格式的文件,则可以使用 -o json.
接下来使用 kubeseal 命令创建新的 SealedSecret 对象:
# cat sealedsecretjson
现在可以安全地将 sealedsecret.json 保存到版本控制中。只有保存再 sealed-secret 控制中的私钥才可以解密。在创建 SealedSecret 对象的时候,控制器会检测、解密并创建相应的加密信息:
# kubectl get sealedsecret
sealed-secret 代码库
https: //github. com/bitnami-labs/sealed-secrets)
angus lees 的文章“sealedsecrets:保护 ubernetes 的码
hps: engineering.bitnami. com/articles/sealed-secrets, html).
参考
Kubernetes Secrets – What is the purpose of type “Opaque” in secret definitions
Pull an Image from a Private Registry
kubectl – How can I update a secret on Kubernetes when it is generated from a file? – Stack Overflow