Kubernetes Handbook 实战指南:Secret 配置与敏感信息管理

发布时间:2026/9/24 18:01:43

Kubernetes Handbook 实战指南:Secret 配置与敏感信息管理 教程云原生容器编排【免费下载链接】kubernetes-handbookKubernetes 架构与生态从云原生到 AI 原生基础设施的构建指南项目地址https://gitcode.com/gh_mirrors/ku/kubernetes-handbook点击查看免费下载本篇技术指南以 Kubernetes Handbook 中的 Secret 专题为核心系统讲解 Secret 对象的设计动机、三种内置类型、创建/解码流程、以 Volume 与环境变量两种方式消费 Secret 的完整配置以及 imagePullSecret、Service Account 自动附加、安全属性与最佳实践。读者学完后将能够独立完成数据库口令、SSH 私钥、私有镜像仓库凭据等敏感信息在集群中的安全落地并结合仓库内的真实 Manifest如 MariaDB 集群的mysql-secrets、Ceph 的ceph-secret验证每个操作步骤。Secret 概览为什么需要独立的对象类型Secret对象类型用来保存敏感信息例如密码、OAuth 令牌和 SSH key。将这些信息放在 Secret 中比放在 Pod 的定义中或者 Docker 镜像中更加安全和灵活控制用途Secret 是一个独立的对象可以像其他资源一样被创建、查看、编辑也可以配合 RBAC 授权精细控制谁能访问降低暴露风险敏感数据不必随 Pod Spec 或镜像一起分发规避了镜像仓库共享、日志打印、代码仓库误提交等泄露渠道解耦与复用多个 Pod 可以引用同一个 Secret修改 Secret 后挂载文件可自动更新无需重建镜像。Secret 是一种包含少量敏感信息密码、token、key的对象。用户可以创建 Secret同时系统也创建了一些 Secret。要使用 SecretPod 需要引用 Secret。Pod 可以用两种方式使用 Secret作为 volume 中的文件被挂载到 Pod 中的一个或多个容器里当 kubelet 为 Pod 拉取镜像时使用即imagePullSecret。从仓库中另一篇专题 concepts/secret.md 的归纳看Secret 主要有三种类型这也是理解整个 Secret 体系的基础类型用途说明Service Accountkubernetes.io/service-account-token访问 Kubernetes API由 Kubernetes 自动创建并自动挂载到 Pod 的/run/secrets/kubernetes.io/serviceaccount目录Opaque存储密码、密钥等任意数据base64 编码格式的 map 类型数据kubernetes.io/dockerconfigjson存储私有 Docker registry 认证信息供imagePullSecret拉取私有镜像使用内置 SecretService Account 使用 API 凭证自动创建和附加Kubernetes 自动创建包含访问 API 凭据的 Secret并自动修改您的 Pod 以使用此类型的 Secret。每个命名空间都有一个默认的defaultServiceAccountPod 创建时若未显式指定spec.serviceAccountName系统会自动指派default并把该 ServiceAccount 关联的 token Secret 自动挂载到容器的/run/secrets/kubernetes.io/serviceaccount目录目录内通常包含ca.crt、namespace、token三个文件验证命令见 concepts/secret.md。如果需要可以禁用或覆盖自动创建和使用 API 凭据。在 1.6 以上版本中在 ServiceAccount 上设置automountServiceAccountToken: false可取消整类凭证的自动挂载在单个 Pod 的spec.automountServiceAccountToken: false可只针对该 Pod 取消两者同时设置时Pod 级别的设置优先级更高。关于 Service Account 的完整工作原理可继续阅读 concepts/serviceaccount.md 与 guide/configure-pod-service-account.md。如果只是需要安全地访问 apiserver推荐使用这套自动工作流而手动创建 Service Account 的 API token Secret则可以通过如下方式kubernetes.io/service-account-token类型 kubernetes.io/service-account.name注解实现$ cat /tmp/build-robot-secret.yaml EOF apiVersion: v1 kind: Secret metadata: name: build-robot-secret annotations: kubernetes.io/service-account.name: build-robot type: kubernetes.io/service-account-token EOF $ kubectl create -f /tmp/build-robot-secret.yaml secret build-robot-secret created创建后该 Secret 会替代原 ServiceAccount 的 token其中ca.crt、token、namespace即为 Pod 内访问 API 的三要素已不存在的 ServiceAccount 的 token 会被 token controller 清理。详细说明见 concepts/serviceaccount.md。创建您自己的 Secret使用 kubectl 创建 Secret假设有些 Pod 需要访问数据库这些 Pod 需要使用的用户名和密码存放在本地机器的./username.txt和./password.txt文件中# Create files needed for rest of example. $ echo -n admin ./username.txt $ echo -n 1f2d1e2e67df ./password.txtkubectl create secret命令将这些文件打包到一个 Secret 中并在 API server 中创建了一个对象$ kubectl create secret generic db-user-pass --from-file./username.txt --from-file./password.txt secret db-user-pass created您可以这样检查刚创建的 secret$ kubectl get secrets NAME TYPE DATA AGE db-user-pass Opaque 2 51s $ kubectl describe secrets/db-user-pass Name: db-user-pass Namespace: default Labels: none Annotations: none Type: Opaque Data password.txt: 12 bytes username.txt: 5 bytes请注意默认情况下get和describe命令都不会显示文件的内容。这是为了防止将 Secret 中的内容意外暴露给从终端日志记录中刻意寻找它们的人。除--from-file外kubectl create secret generic还支持--from-literalkeyvalue直接以字面量注入以及--from-env-file从文件批量导入。仓库中 MariaDB 集群的凭据即采用这种方式管理见下文“仓库实战”一节。手动创建 Secret您也可以先以 JSON 或 YAML 格式在文件中创建一个 Secret 对象然后创建该对象。每一项必须是 base64 编码$ echo -n admin | base64 YWRtaW4 $ echo -n 1f2d1e2e67df | base64 MWYyZDFlMmU2N2Rm现在可以像这样写一个 Secret 对象apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: username: YWRtaW4 password: MWYyZDFlMmU2N2Rm数据字段是一个映射它的键必须匹配 DNS_SUBDOMAIN前导点也是可以的。这些值可以是任意数据使用 base64 进行编码。使用kubectl create创建 secret$ kubectl create -f ./secret.yaml secret mysecret created编码注意Secret 数据的序列化 JSON 和 YAML 值使用 base64 编码成字符串。换行符在这些字符串中无效必须省略。当在 Darwin/OS X 上使用base64实用程序时用户应避免使用-b选项来拆分长行。另外对于 Linux 用户如果-w选项不可用的话应该添加选项-w 0到base64命令或管道base64 | tr -d \n。解码 Secret可以使用kubectl get secret命令获取 secret。例如获取上一节中创建的 secret$ kubectl get secret mysecret -o yaml apiVersion: v1 data: username: YWRtaW4 password: MWYyZDFlMmU2N2Rm kind: Secret metadata: creationTimestamp: 2016-01-22T18:41:56Z name: mysecret namespace: default resourceVersion: 164619 selfLink: /api/v1/namespaces/default/secrets/mysecret uid: cfee02d6-c137-11e5-8d73-42010af00002 type: Opaque解码密码字段$ echo MWYyZDFlMmU2N2Rm | base64 --decode 1f2d1e2e67df需要特别强调的是base64 只是编码不是加密。如果将一个 base64 编码后的清单文件JSON 或 YAML共享出去或检入代码仓库其中的密码仍然等于明文泄露。使用 SecretSecret 可以作为数据卷被挂载或作为环境变量暴露出来以供 Pod 中的容器使用。它们也可以被系统的其他部分使用而不直接暴露在 Pod 内。例如它们可以保存凭据系统的其他部分应该用它来代表您与外部系统进行交互。在 Pod 中使用 Secret 文件Volume 方式在 Pod 中的 volume 里使用 Secret创建一个 Secret 或者使用已有的 Secret多个 Pod 可以引用同一个 Secret修改您的 Pod 定义在spec.volumes[]下增加一个 volume。可以给这个 volume 随意命名它的spec.volumes[].secret.secretName必须等于 Secret 对象的名字将spec.containers[].volumeMounts[]加到需要用到该 Secret 的容器中。指定spec.containers[].volumeMounts[].readOnly true和spec.containers[].volumeMounts[].mountPath为您想要该 Secret 出现的尚未使用的目录修改您的镜像并且/或者命令行让程序从该目录下寻找文件。Secret 的data映射中的每一个键都成为了mountPath下的一个文件名。这是一个在 Pod 中使用 volume 挂载 secret 的例子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 都需要在spec.volumes中指明。如果 Pod 中有多个容器每个容器都需要自己的volumeMounts配置块但是每个 Secret 只需要一个spec.volumes。您可以打包多个文件到一个 Secret 中或者使用多个 Secret怎样方便就怎样来。向特定路径映射 Secret 密钥我们还可以控制 Secret key 映射在 volume 中的路径。使用spec.volumes[].secret.items字段修改每个 key 的目标路径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 items: - key: username path: my-group/my-username将会发生什么呢usernamesecret 存储在/etc/foo/my-group/my-username文件中而不是/etc/foo/username中passwordsecret 没有被映射。重要限制如果使用了spec.volumes[].secret.items只有在items中指定的 key 被映射。要使用 Secret 中所有的 key所有这些都必须列在items字段中所有列出的密钥必须存在于相应的 Secret 中否则不会创建卷。Secret 文件权限您还可以指定 Secret 将拥有的权限模式位文件。如果不指定默认使用0644。您可以为整个 Secret 卷指定默认模式如果需要可以覆盖每个密钥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: 256然后Secret 将被挂载到/etc/foo目录所有通过该 Secret volume 挂载创建的文件的权限都是0400。请注意JSON 规范不支持八进制符号因此使用 256 值作为 0400 权限。如果您使用 YAML 而不是 JSON 作为 Pod则可以使用八进制符号以更自然的方式指定权限。您还可以使用映射如上一个示例为不同的文件指定不同的权限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 items: - key: username path: my-group/my-username mode: 511在这种情况下/etc/foo/my-group/my-username文件的权限值为0777。由于 JSON 限制必须以十进制格式指定模式。请注意如果稍后阅读此权限值可能会以十进制格式显示。从 Volume 中消费 Secret 值在挂载的 Secret volume 的容器内Secret key 将作为文件并且 Secret 的值使用 base-64 解码并存储在这些文件中。这是在上面的示例容器内执行的命令的结果$ ls /etc/foo/ username password $ cat /etc/foo/username admin $ cat /etc/foo/password 1f2d1e2e67df容器中的程序负责从文件中读取 secret。挂载的 Secret 被自动更新当已经在 volume 中被消费的 Secret 被更新时被映射的 key 也将被更新。Kubelet 在周期性同步时检查被挂载的 Secret 是不是最新的。但是它正在使用其基于本地 ttl 的缓存来获取当前的 Secret 值。结果是当 Secret 被更新的时刻到将新的 Secret 映射到 Pod 的时刻的总延迟可以与 kubelet 中的 Secret 缓存的 kubelet sync period ttl 一样长。Secret 作为环境变量将 Secret 作为 Pod 中的环境变量使用创建一个 Secret 或者使用一个已存在的 Secret多个 Pod 可以引用同一个 Secret在每个容器中修改您想要使用 Secret key 的 Pod 定义为要使用的每个 Secret key 添加一个环境变量。消费 Secret key 的环境变量应填充 Secret 的名称并键入env[x].valueFrom.secretKeyRef修改镜像并且/或者命令行以便程序在指定的环境变量中查找值。apiVersion: v1 kind: Pod metadata: name: secret-env-pod spec: containers: - name: mycontainer image: redis env: - name: SECRET_USERNAME valueFrom: secretKeyRef: name: mysecret key: username - name: SECRET_PASSWORD valueFrom: secretKeyRef: name: mysecret key: password restartPolicy: Never消费环境变量里的 Secret 值在一个消耗环境变量 secret 的容器中Secret key 作为包含 Secret 数据的 base-64 解码值的常规环境变量。这是从上面的示例在容器内执行的命令的结果$ echo $SECRET_USERNAME admin $ echo $SECRET_PASSWORD 1f2d1e2e67df此外envFrom可以将整个 Secret 的键值对批量注入为环境变量。但需要注意如果 Secret 中存在被认定为无效环境变量名的 key例如1badkey、2alsobad这些键会被跳过Pod 仍被允许启动同时会产生一个InvalidVariableNames原因的事件$ kubectl get events LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON 0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames kubelet, 127.0.0.1 Keys [1badkey, 2alsobad] from the EnvFrom secret default/mysecret were skipped since they are considered invalid environment variable names.使用 imagePullSecret 拉取私有镜像imagePullSecret 是将包含 Docker或其他镜像注册表密码的 Secret 传递给 Kubelet 的一种方式因此可以代表您的 Pod 拉取私有镜像。创建私有 registry 认证 Secret 的两种方式见 concepts/secret.md方式一直接用kubectl命令创建$ kubectl create secret docker-registry myregistrykey --docker-serverDOCKER_REGISTRY_SERVER --docker-userDOCKER_USER --docker-passwordDOCKER_PASSWORD --docker-emailDOCKER_EMAIL secret myregistrykey created.方式二读取~/.docker/config.json的内容手动创建kubernetes.io/dockerconfigjson类型的 Secret$ cat ~/.docker/config.json | base64 $ cat myregistrykey.yaml EOF apiVersion: v1 kind: Secret metadata: name: myregistrykey data: .dockerconfigjson: UmVhbGx5IHJlYWxseSByZWVlZWVlZWVlZWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx5eXl5eXl5eXl5eXl5eXl5eXl5eSBsbGxsbGxsbGxsbGxsbG9vb29vb29vb29vb29vb29vb29vb29vb29vb25ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg type: kubernetes.io/dockerconfigjson EOF $ kubectl create -f myregistrykey.yaml在创建 Pod 的时候通过imagePullSecrets来引用刚创建的myregistrykeyapiVersion: v1 kind: Pod metadata: name: foo spec: containers: - name: foo image: janedoe/awesomeapp:v1 imagePullSecrets: - name: myregistrykey安排 imagePullSecrets 自动附加您可以手动创建 imagePullSecret并从 ServiceAccount 引用它。使用该 ServiceAccount 创建的任何 Pod以及默认使用该 ServiceAccount 的 Pod将会将其imagePullSecrets字段设置为服务帐户的imagePullSecrets字段。最简单的做法是直接给defaultServiceAccount 打补丁kubectl patch serviceaccount default -p {imagePullSecrets: [{name: myregistrykey}]}之后该命名空间内所有新创建的 Pod 的 spec 中都会自动出现spec: imagePullSecrets: - name: myregistrykey手动创建的 Secret例如包含用于访问 GitHub 帐户的令牌也可以根据其 Service Account 自动附加到 Pod。完整流程创建 Secret → 确认类型为kubernetes.io/.dockerconfigjson→ patch 或kubectl replace修改 ServiceAccount参见 concepts/serviceaccount.md 与 guide/configure-pod-service-account.md。仓库实战Secret 在真实 Manifest 中的用法Kubernetes Handbook 的 manifests 目录中保留了多个真实可用的 Secret 示例正好覆盖Opaque、kubernetes.io/rbd与secretKeyRef三种典型场景。1. MariaDB Galera 集群的数据库口令Opaque 类型manifests/mariadb-cluster/mysql-secret.yaml 定义了一个galera命名空间下的 Opaque SecretapiVersion: v1 kind: Secret metadata: name: mysql-secrets namespace: galera labels: app: mysql data: # Root password: changeit run echo -n jimmysong|base64 root-password: amltbXlzb25n # Root user: root root-user: cm9vdA随后在 manifests/mariadb-cluster/galera-mariadb.yaml 的 StatefulSet 中通过secretKeyRef以环境变量方式消费env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-secrets key: root-password - name: MYSQL_ROOT_USER valueFrom: secretKeyRef: name: mysql-secrets key: root-user这验证了原文档“Secret key 以env[x].valueFrom.secretKeyRef注入”的用法且该文件附带了 base64 生成注释echo -n jimmysong|base64便于读者自行替换口令。2. Ceph RBD 的认证凭据kubernetes.io/rbd 类型manifests/mariadb-cluster/ceph-secret.yaml 展示了存储类专用 SecretapiVersion: v1 kind: Secret metadata: name: ceph-secret namespace: galera type: kubernetes.io/rbd data: key: AQCX06hZ9LnSBxAAYuoIT/ewbTRhKpTHOZLoRQ该 Secret 配合 StorageClass 的adminSecretName/userSecretName字段实现 Ceph RBD 持久化存储的动态供给详见 practice/using-ceph-for-persistent-storage.md。这类 Secret 不直接暴露在 Pod 内而是被系统其他部分存储 provisioner消费正是原文档所述“它们可以保存凭据系统的其他部分用它代表您与外部系统交互”的典型例子。3. 结合 RBAC 的 ServiceAccount token Secret在 guide/configure-pod-service-account.md 中创建 ServiceAccount 后会自动生成sample-sc-token-9x7nk类型的 Secretkubernetes.io/service-account-token其中的data.token经过 base64 解码即是一个 JWT可填入 kubeconfig 的users[].user.token字段配合 ClusterRole/ClusterRoleBinding如只读pods、services、deployments实现最小权限的集群访问。这也是 concepts/rbac.md 中“用户与身份认证授权”的落地方式之一。详细限制与生命周期限制先创建后引用验证 Secret volume 来源时确保指定的对象引用实际上指向一个类型为 Secret 的对象。因此需要在依赖于它的任何 Pod 之前创建一个 Secret命名空间隔离Secret API 对象驻留在命名空间中它们只能由同一命名空间中的 Pod 引用1MB 大小上限每个 Secret 的大小限制为 1MB这是为了防止创建非常大的 Secret 会耗尽 apiserver 和 kubelet 的内存。然而创建许多较小的 Secret 也可能耗尽内存更全面限制 Secret 对内存使用的策略是计划中的功能kubelet 来源限制Kubelet 仅支持从 API server 获取的 Pod 使用 Secret。这包括使用kubectl创建的任何 Pod或间接通过 replication controller 创建的 Pod不包括通过 kubelet--manifest-url标志、--config标志或其 REST API 创建的 Pod这些不是创建 Pod 的常用方法缺失引用的后果必须先创建 Secret除非将它们标记为可选项否则必须在将其作为环境变量在 Pod 中使用之前创建 Secret。对不存在的 Secret 的引用将阻止 Pod 启动通过secretKeyRef引用不存在的 key 同样会阻止 Pod 启动。Secret 与 Pod 生命周期的联系通过 API 创建 Pod 时不会检查应用的 Secret 是否存在。一旦 Pod 被调度kubelet 就会尝试获取该 Secret 的值。如果获取不到该 Secret或者暂时无法与 API server 建立连接kubelet 将会定期重试。Kubelet 将会报告关于 Pod 的事件并解释它无法启动的原因。一旦获取到 Secretkubelet 将创建并装载一个包含它的卷在装完所有 Pod 的卷之前都不会启动 Pod 的容器。使用案例使用案例包含 SSH 密钥的 Pod创建一个包含 SSH key 的 Secret$ kubectl create secret generic ssh-key-secret --from-filessh-privatekey/path/to/.ssh/id_rsa --from-filessh-publickey/path/to/.ssh/id_rsa.pub安全性注意事项分享自己的 SSH 密钥之前要仔细思考集群的其他用户可能有权访问该密钥。请使用您想共享 Kubernetes 集群的所有用户都可以访问的服务账户如果它们遭到入侵可以撤销。现在我们可以创建一个使用 SSH 密钥引用 Secret 的 Pod并在一个卷中使用它kind: Pod apiVersion: v1 metadata: name: secret-test-pod labels: name: secret-test spec: volumes: - name: secret-volume secret: secretName: ssh-key-secret containers: - name: ssh-test-container image: mySshImage volumeMounts: - name: secret-volume readOnly: true mountPath: /etc/secret-volume当容器中的命令运行时密钥的片段将可在以下目录/etc/secret-volume/ssh-publickey /etc/secret-volume/ssh-privatekey然后容器可以自由使用密钥数据建立一个 SSH 连接。使用案例包含 prod/test 凭据的 Pod下面的例子说明一个 Pod 消费一个包含 prod 凭据的 Secret另一个 Pod 使用测试环境凭据消费 Secret。创建 Secret使用--from-literal$ kubectl create secret generic prod-db-secret --from-literalusernameproduser --from-literalpasswordY4nys7f11 secret prod-db-secret created $ kubectl create secret generic test-db-secret --from-literalusernametestuser --from-literalpasswordiluvtests secret test-db-secret created创建 Pod一个 List 中同时定义两个 PodapiVersion: v1 kind: List items: - kind: Pod apiVersion: v1 metadata: name: prod-db-client-pod labels: name: prod-db-client spec: volumes: - name: secret-volume secret: secretName: prod-db-secret containers: - name: db-client-container image: myClientImage volumeMounts: - name: secret-volume readOnly: true mountPath: /etc/secret-volume - kind: Pod apiVersion: v1 metadata: name: test-db-client-pod labels: name: test-db-client spec: volumes: - name: secret-volume secret: secretName: test-db-secret containers: - name: db-client-container image: myClientImage volumeMounts: - name: secret-volume readOnly: true mountPath: /etc/secret-volume这两个容器将在其文件系统上显示以下文件其中包含每个容器环境的值/etc/secret-volume/username /etc/secret-volume/password请注意两个 Pod 的 spec 配置中仅有一个字段有所不同secretName这有助于使用普通的 Pod 配置模板创建具有不同功能的 Pod。您可以使用两个 Service Account 进一步简化基本 Pod spec一个名为prod-user拥有prod-db-secret另一个称为test-user拥有test-db-secret。然后Pod spec 可以缩短为kind: Pod apiVersion: v1 metadata: name: prod-db-client-pod labels: name: prod-db-client spec: serviceAccount: prod-db-client containers: - name: db-client-container image: myClientImage使用案例Secret 卷中以点号开头的文件为了将数据“隐藏”起来即文件名以点号开头的文件只需要让该键以一个点开始。例如当如下 Secret 被挂载到卷中kind: Secret apiVersion: v1 metadata: name: dotfile-secret data: .secret-file: dmFsdWUtMg0KDQo --- kind: Pod apiVersion: v1 metadata: name: secret-dotfiles-pod spec: volumes: - name: secret-volume secret: secretName: dotfile-secret containers: - name: dotfile-test-container image: gcr.io/google_containers/busybox command: - ls - -l - /etc/secret-volume volumeMounts: - name: secret-volume readOnly: true mountPath: /etc/secret-volumesecret-volume将包含一个单独的文件叫做.secret-filedotfile-test-container的/etc/secret-volume/.secret-file路径下将有该文件。注意以点号开头的文件在ls -l的输出中被隐藏起来了列出目录内容时必须使用ls -la才能查看它们。使用案例Secret 仅对 Pod 中的一个容器可见考虑一个需要处理 HTTP 请求的程序执行一些复杂的业务逻辑然后使用 HMAC 签署一些消息。因为它具有复杂的应用程序逻辑所以在服务器中可能会出现一个未被注意的远程文件读取漏洞这可能会将私钥暴露给攻击者。这可以在两个容器中分为两个进程前端容器用于处理用户交互和业务逻辑但无法看到私钥以及可以看到私钥的签名者容器它响应来自前端的简单签名请求例如通过 localhost 网络。使用这种分割方法攻击者现在必须欺骗应用程序服务器才能进行任意的操作这可能比使其读取文件更难。实现上由于 Pod 中的每个容器必须通过自己的volumeMounts请求 Secret 卷才能看到该 Secret因此可以在 Pod 级别构建安全分区——不被挂载的容器完全看不到该 Secret 的任何文件。最佳实践客户端使用 Secret API当部署与 Secret API 交互的应用程序时应使用诸如 RBAC 之类的授权策略来限制访问避免 watch/listSecret 的重要性通常不尽相同其中许多可能只对 Kubernetes 集群内例如 Service Account 令牌和对外部系统造成影响。即使一个应用程序可以理解其期望与之交互的 Secret 的权力同一命名空间中的其他应用程序也可以使这些假设无效。因此在命名空间中watch和listSecret 的请求是非常强大的功能应该避免这样的行为——列出 Secret 可以让客户端检查该命名空间中的所有 Secret。在集群中watch和list所有 Secret 的能力应该只保留给最有特权的系统级组件按需 get需要访问 Secrets API 的应用程序应该根据它们需要的 Secret 执行get请求。这允许管理员限制对所有 Secret 的访问同时设置白名单访问应用程序需要的各个实例watch 资源而非 secret为了提高循环获取的性能客户端可以设计引用 Secret 的资源然后watch资源在引用更改时重新请求 Secret。安全属性保护机制与已知风险保护因为 Secret 对象可以独立于使用它们的 Pod 而创建所以在创建、查看和编辑 Pod 的流程中 Secret 被暴露的风险较小。系统还可以对 Secret 对象采取额外的预防措施例如避免将其写入到磁盘中可能的位置只有当节点上的 Pod 需要用到该 Secret 时该 Secret 才会被发送到该节点上。它不会被写入磁盘而是存储在 tmpfs 中。一旦依赖于它的 Pod 被删除它就被删除在大多数 Kubernetes 项目维护的发行版中用户与 API server 之间的通信以及从 API server 到 kubelet 的通信都受到 SSL/TLS 的保护。通过这些通道传输时Secret 受到保护节点上的 Secret 数据存储在 tmpfs 卷中因此不会传到节点上的其他磁盘同一节点上的很多个 Pod 可能拥有多个 Secret。但是只有 Pod 请求的 Secret 在其容器中才是可见的因此一个 Pod 不能访问另一个 Pod 的 SecretPod 中有多个容器时每个容器必须请求其挂载卷中的 Secret 卷才能在容器内可见。这可用于在 Pod 级别构建安全分区。风险API server 的 Secret 数据以纯文本的方式存储在 etcd 中因此管理员应该限制 admin 用户访问 etcdAPI server 中的 Secret 数据位于 etcd 使用的磁盘上管理员可能希望在不再使用时擦除/粉碎 etcd 使用的磁盘如果您将 Secret 数据编码为 base64 的清单JSON 或 YAML文件并共享该文件或将其检入代码库密码将会被泄露。base64 编码不是一种加密方式一样是纯文本应用程序在从卷中读取 Secret 后仍然需要保护 Secret 的值例如不会意外记录或发送给不信任方可以创建和使用 Secret 的 Pod 的用户也可以看到该 Secret 的值。即使 API server 策略不允许用户读取 Secret 对象用户也可以运行暴露 Secret 的 Pod如果运行了多个副本那么这些 Secret 将在它们之间共享。默认情况下etcd 不能保证与 SSL/TLS 的对等通信尽管可以进行配置目前任何节点的 root 用户都可以通过模拟 kubelet 来读取 API server 中的任何 Secret。只有向实际需要它们的节点发送 Secret 才能限制单个节点的 root 漏洞的影响该功能还在计划中。延伸阅读concepts/secret.mdSecret 三种类型与挂载/环境变量用法的快速速查concepts/serviceaccount.mdService Account 与 token Secret 的自动/手动创建guide/configure-pod-service-account.md用 ServiceAccount 的 token Secret 配置 kubeconfig 并配合 RBAC 做权限管理concepts/rbac.md限制 Secret 访问范围的授权模型guide/create-tls-and-secret-key.md集群 TLS 证书/私钥的生成与分发Kubernetes 各组件通信加密的基础practice/using-ceph-for-persistent-storage.mdkubernetes.io/rbd类型 Secret 在存储场景中的实际用法。赞分享教程云原生容器编排【免费下载链接】kubernetes-handbookKubernetes 架构与生态从云原生到 AI 原生基础设施的构建指南项目地址https://gitcode.com/gh_mirrors/ku/kubernetes-handbook点击查看免费下载相关推荐XLeRobot强化学习实战指南从仿真训练到真实机器人的完整方案深度解析XLeRobot强化学习实战指南从仿真训练到真实机器人的完整方案深度解析 XLeRobot项目为机器人强化学习研究提供了从仿真到实物的完整解决方案通过Man具身智能智能硬件终极指南5分钟创建多系统启动U盘Ventoy让你告别重复格式化终极指南5分钟创建多系统启动U盘Ventoy让你告别重复格式化 还在为每个系统镜像都格式化一次U盘而烦恼吗 Ventoy多系统启动工具 是一款革命性的开源操作系统固件开发工具GitHub_Trending/st/starter-workflows敏感信息管理Secrets配置指南GitHub_Trending/st/starter workflows敏感信息管理Secrets配置指南 引言你还在硬编码密钥吗 在持续集成/持续部署示例工程CI/CDDevOps创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/24 19:06:51

epoll高性能底层解析:红黑树与就绪链表如何协作

先聊个我碰过的真实场景:线上有一台 8C16G 的服务器,需要同时维持几十万条 TCP 长连接,业务方希望每条连接都能在第一时间感知到数据可读、可写。最开始用 select 去顶,连接数刚到一万多就肉眼可见地出现延迟,CPU 软中…

2026/9/24 19:06:51

公司官网SEO优化实操:从关键词策略到技术细节全解析

公司官网的SEO优化,说白了就三件事:让搜索引擎看懂你的网站、觉得你的网站值得推荐、愿意把你的网站推给搜索的人。听起来简单,但真正落地的过程中,你会发现关键词、内容和技术这三条线相互纠缠,牵一发而动全身。我这几…

2026/9/24 19:06:51

随机森林实战指南:用sklearn实现花分类并调优模型

简介:这是一份面向机器学习初学者的随机森林花分类实践代码包,聚焦鸢尾花品种预测这一经典案例,帮助读者理解集成学习原理、Bootstrap抽样机制及sklearn建模流程。压缩包体积仅1KB,内含1个Python源文件,可直接运行&…

2026/9/24 19:06:51

STAP仿真实战:ACP与AEP算法对比及MATLAB实现

简介:空时自适应信号处理(STAP)是雷达目标检测与抗干扰中的关键技术,尤其适用于合成孔径雷达(SAR)系统对弱目标、强杂波场景的探测。面向雷达信号处理学习者和工程开发人员,这里提供 ACP&#x…

2026/9/24 19:01:51

IP地址、域名与DNS之间的关系及网络故障排查实战

干网络运维这些年,我发现自己跟人解释最多的问题,不是哪个设备坏了,而是IP地址、域名、DNS这三者到底什么关系。明明每次出故障,最后都能绕回到这三位身上。今天不整虚的,就着这几个基础概念,把原理讲透&am…

2026/9/23 12:07:00

GAMP 5 基于风险的计算机化系统验证:软件分类与审计追踪实践

简介:《A Risk-Based Approach to Compliant GxP Computerized Systems》即业内熟知的GAMP 5指南,面向制药企业质量与IT合规人员、验证工程师及计算机化系统管理者,用于解决GxP法规环境下系统合规性难以科学落地的问题。文档以风险管理为主线…

2026/9/23 12:06:55

安全托管MSSP实战:从静态防御到人机协同的攻防运营与应急响应

简介:这份PPT围绕互联网业务安全托管服务展开,面向企业安全负责人、IT运维人员及关注MSSP/MSS选型的读者,重点回应传统安全过度依赖人工、碎片化静态防御难以对抗产业化攻击等痛点。资源共1个pptx文件,包体约30.63MB,以…

2026/9/24 0:00:21

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:21

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:21

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/22 16:34:32

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/22 20:01:30

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/22 13:25:41

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码