【Kubernetes Secret 安全配置指南:从创建配置到环境变量、数据卷使用及私有镜像仓库实践】

提示:本文原创作品,良心制作,干货为主,简洁清晰,一看就会

文章目录


前言

在 Kubernetes 集群中,敏感配置的安全管理是保障业务稳定与数据安全的关键环节。密码、令牌、密钥等信息若直接暴露在配置文件或镜像中,极易引发泄露风险。Secret 作为 K8s 原生的敏感信息存储对象,专门用于安全托管这类数据,实现加密存储与按需挂载。本文将围绕 Secret 的类型、创建方式、使用场景及安全实践展开介绍,帮助开发者规范管理集群敏感配置

我的实验环境

主机名 IP
k8s-master1 192.168.13.136
k8s-node1 192.168.13.139
k8s-node2 192.168.13.140

一、Secret介绍

Secret 是 Kubernetes 用于 存储密码、令牌、密钥等敏感信息的资源对象 ,避免将机密数据直接写入镜像或配置文件。它默认采用 Base64 编码存储,可通过环境变量或数据卷挂载给 Pod 使用,支持通用密钥、Docker 仓库凭证、TLS 证书等多种类型。配合权限控制与加密方案,能有效降低敏感信息泄露风险,是集群安全配置的核心组件

用户可以创建自己的secret,系统也会有自己的secret

pod需要先引用才能使用某个secret

二、Secret创建

2.1 命令方式创建

yaml 复制代码
root@k8s-master1:~# mkdir -p /k8s-test/secret
root@k8s-master1:~# cd /k8s-test/secret/
root@k8s-master1:/k8s-test/secret# echo -n "root" > username.txt  # 存放用户名
root@k8s-master1:/k8s-test/secret# cat username.txt
rootroot@k8s-master1:/k8s-test/secret# echo -n "Abc@123" > password.txt   # 存放密码
# 命令创建secret,generic是Secret的默认类型,也叫Opaque Secret
root@k8s-master1:/k8s-test/secret# kubectl create secret generic user-pass --from-file=./username.txt --from-file=./password.txt
root@k8s-master1:/k8s-test/secret# kubectl get secrets
NAME        TYPE     DATA   AGE
user-pass   Opaque   2      14s

# describe指令不会展示secret的实际内容,这是出于对数据的保护考虑
root@k8s-master1:/k8s-test/secret# kubectl describe secret user-pass  # 查看secret的详细信息发现不够详细
Name:         user-pass
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password.txt:  7 bytes
username.txt:  4 bytes
root@k8s-master1:/k8s-test/secret# kubectl get secret user-pass -o yaml  # 查看secret详细信息方法二
apiVersion: v1
data:
  password.txt: QWJjQDEyMw==   # 密码被加密
  username.txt: cm9vdA==    # 用户被加密
kind: Secret
metadata:
  creationTimestamp: "2026-04-21T06:29:53Z"
  name: user-pass
  namespace: default
  resourceVersion: "541777"
  uid: d0f0fff1-7609-4734-b464-92e0ede6e57d
type: Opaque

# base64解码就可以查看实际内容
root@k8s-master1:/k8s-test/secret# echo cm9vdA== | base64 --decode
rootroot@k8s-master1:/k8s-test/secret# echo QWJjQDEyMw== | base64 --decode
Abc@123root@k8s-master1:/k8s-test/secret# 

2.2 yaml方式创建

yaml 复制代码
# 1.创建secret.yaml文件,内容可以先用base64编码一下防止明文被人发现
root@k8s-master1:/k8s-test/secret# echo -n "root" | base64
cm9vdA==
root@k8s-master1:/k8s-test/secret# echo -n "Qing@123" | base64
UWluZ0AxMjM=

# 2. 创建yaml文件
root@k8s-master1:/k8s-test/secret# vim secret.yaml
---
apiVersion: v1
kind: Secret
metadata:
        name: mysql-secret
type: Opaque   # 模糊
data:
        username: cm9vdA==
        password: UWluZ0AxMjM= 

# 3. 运行secret并查看状态
root@k8s-master1:/k8s-test/secret# kubectl apply -f secret.yaml 
root@k8s-master1:/k8s-test/secret# kubectl get secret
NAME           TYPE     DATA   AGE
mysql-secret   Opaque   2      7s
user-pass      Opaque   2      12m

# 4. 查看详细信息
root@k8s-master1:/k8s-test/secret# kubectl get secret mysql-secret -o yaml
apiVersion: v1
data:
  password: UWluZ0AxMjM=
  username: cm9vdA==
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"password":"UWluZ0AxMjM=","username":"cm9vdA=="},"kind":"Secret","metadata":{"annotations":{},"name":"mysql-secret","namespace":"default"},"type":"Opaque"}
  creationTimestamp: "2026-04-21T06:42:30Z"
  name: mysql-secret
  namespace: default
  resourceVersion: "543298"
  uid: 9c9dc39c-64e5-45bb-9d49-7f1f8d233bf5
type: Opaque

三、Secret使用

3.1 通过环境变量注入

yaml 复制代码
## 1. 先创建一个secret
root@k8s-master1:/k8s-test/secret# echo -n "root" | base64
cm9vdA==
root@k8s-master1:/k8s-test/secret# echo -n "Qing@2026" | base64
UWluZ0AyMDI2
root@k8s-master1:/k8s-test/secret# vim secret1.yaml
apiVersion: v1
kind: Secret
metadata:
        name: mysql-secret
type: Opaque
data:
        username: cm9vdA==
        password: UWluZ0AyMDI2

## 2. 运行secret并观察状态
root@k8s-master1:/k8s-test/secret# kubectl apply -f secret1.yaml 
root@k8s-master1:/k8s-test/secret# kubectl get secret
NAME           TYPE     DATA   AGE
mysql-secret   Opaque   2      1m30s
root@k8s-master1:/k8s-test/secret# kubectl get secret mysql-secret -o yaml
apiVersion: v1
data:
  password: UWluZ0AyMDI2
  username: cm9vdA==
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"password":"UWluZ0AyMDI2","username":"cm9vdA=="},"kind":"Secret","metadata":{"annotations":{},"name":"mysql-secret","namespace":"default"},"type":"Opaque"}
  creationTimestamp: "2026-04-21T07:10:56Z"
  name: mysql-secret
  namespace: default
  resourceVersion: "546766"
  uid: 6eb0f453-1ba3-4fcc-ab9e-f71695a1497b
type: Opaque
yaml 复制代码
## 3. 创建pod
root@k8s-master1:/k8s-test/secret# vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:
        name: mysql
spec:
        containers:
                - name: mysql
                  image: mysql:5.7
                  env:
                          - name: MYSQL_ROOT_PASSWORD  # 创建新的环境变量名称
                            valueFrom:
                                    secretKeyRef:  # 调用的key是什么
                                            name: mysql-secret  # 变量来自于哪个secret
                                            key: password   # 要用secret里的哪个键

## 4. 运行pod
root@k8s-master1:/k8s-test/secret# kubectl apply -f pod1.yaml 
root@k8s-master1:/k8s-test/secret# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP              NODE        NOMINATED NODE   READINESS GATES
mysql   1/1     Running   0          2m29s   10.244.36.116   k8s-node1   <none>           <none>

## 5. 进入pod,看看能否登录mysql
root@k8s-master1:/k8s-test/secret# kubectl exec -it mysql /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
bash-4.2# mysql -uroot -p'Qing@2026'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.44 MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> exit
Bye
bash-4.2# exit
exit
command terminated with exit code 126
yaml 复制代码
## 6. 修改一下secret看pod中会不会自动更新
root@k8s-master1:/k8s-test/secret# echo -n "Qing@123" | base64
UWluZ0AxMjM=
root@k8s-master1:/k8s-test/secret# vim secret1.yaml
password: UWluZ0AxMjM=   # 把密码改成了Qing@123

## 7. 重新运行secret
root@k8s-master1:/k8s-test/secret# kubectl apply -f secret1.yaml
root@k8s-master1:/k8s-test/secret# kubectl get secret mysql-secret -o yaml
apiVersion: v1
data:
  password: UWluZ0AxMjM=  # 可以看到密码已经更改
  username: cm9vdA==
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"password":"UWluZ0AxMjM=","username":"cm9vdA=="},"kind":"Secret","metadata":{"annotations":{},"name":"mysql-secret","namespace":"default"},"type":"Opaque"}
  creationTimestamp: "2026-04-21T07:10:56Z"
  name: mysql-secret
  namespace: default
  resourceVersion: "549855"
  uid: 6eb0f453-1ba3-4fcc-ab9e-f71695a1497b
type: Opaque
yaml 复制代码
## 8. 进入pod,看新密码能不能登录mysql
root@k8s-master1:/k8s-test/secret# kubectl exec -it mysql /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
bash-4.2# mysql -uroot -p'Qing@123'  # 新密码不能用
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
bash-4.2# mysql -uroot -p'Qing@2026'  # 旧密码可以登录
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.44 MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> exit
Bye
bash-4.2# exit
exit
root@k8s-master1:/k8s-test/secret# 

通过环境变量引用的 Secret,Pod 运行后不会自动更新!

当你把 Secret 以环境变量形式注入 Pod 时:

  • 环境变量的值是容器启动时一次性读取的
  • Secret 后续修改、更新,已经运行的容器不会同步刷新
  • 必须 删除重建 Pod 才能拿到最新的 Secret 值

3.2 数据卷挂载

bash 复制代码
## 1. 创建secret
root@k8s-master1:/k8s-test/secret# echo cm9vdA== | base64 --decode
rootroot@k8s-master1:/k8s-test/secret# echo UWluZ0AxMjM= | base64 --decode
Qing@123root@k8s-master1:/k8s-test/secret# kubectl get secret
No resources found in default namespace.
root@k8s-master1:/k8s-test/secret# cat secret1.yaml 
apiVersion: v1
kind: Secret
metadata:
        name: nginx-secret
type: Opaque
data:
        username: cm9vdA==
        password: UWluZ0AxMjM=
root@k8s-master1:/k8s-test/secret# kubectl apply -f secret1.yaml 
yaml 复制代码
## 2. 创建pod并挂载secret
root@k8s-master1:/k8s-test/secret# vim pod2.yaml 
apiVersion: v1
kind: Pod
metadata:
        name: nginx
spec:
        containers:
                - name: nginx
                  image: nginx:1.24
                  volumeMounts:
                          - name: nginx-volume
                            mountPath: "/etc/secret"
                            readOnly: true
        volumes:
                - name: nginx-volume
                  secret:
                          secretName: nginx-secret
root@k8s-master1:/k8s-test/secret# kubectl apply -f pod2.yaml
root@k8s-master1:/k8s-test/secret# kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
mysql   1/1     Running   0          56m
nginx   1/1     Running   0          6s
root@k8s-master1:/k8s-test/secret# kubectl exec -it nginx /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx:/# ls /etc/secret
password  username
root@nginx:/# cat /etc/secret/username
rootroot@nginx:/# cat /etc/secret/password
Qing@123root@nginx:/# exit
exit
yaml 复制代码
## 3. 更改secret看看pod内部会不会发生变化
root@k8s-master1:/k8s-test/secret# echo -n "qingqing" | base64
cWluZ3Fpbmc=
root@k8s-master1:/k8s-test/secret# vim secret1.yaml 
password: cWluZ3Fpbmc=  # 更改用户名为qingqing
root@k8s-master1:/k8s-test/secret# kubectl apply -f secret1.yaml 
root@k8s-master1:/k8s-test/secret# kubectl get secret nginx-secret -o yaml
apiVersion: v1
data:
  password: UWluZ0AxMjM=
  username: cWluZ3Fpbmc=   # 查看详细信息,可以看到secret已经更改成功
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"password":"UWluZ0AxMjM=","username":"cWluZ3Fpbmc="},"kind":"Secret","metadata":{"annotations":{},"name":"nginx-secret","namespace":"default"},"type":"Opaque"}
  creationTimestamp: "2026-04-21T08:11:23Z"
  name: nginx-secret
  namespace: default
  resourceVersion: "554423"
  uid: 8bdc7fa4-6747-4a7f-acff-318a09427551
type: Opaque

## 4. 进入pod内部,发现文件更改成功
root@k8s-master1:/k8s-test/secret# kubectl exec -it nginx /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx:/# cat /etc/secret/username
qingqingroot@nginx:/# exit
exit
root@k8s-master1:/k8s-test/secret# 

Secret 卷挂载 → 会自动更新!

当你把 Secret 挂载成 Volume

  • K8s 会自动定期同步 Secret 的最新内容,同步时间大约是 1 分钟左右
  • 你修改 Secret 后,不需要重启 Pod,容器里的挂载文件会自动变成新内容
  • 你的程序只要重新读取文件,就能拿到最新值

四、docker私仓secret应用

目前,我有一个harbor仓库,ip地址:192.168.13.137

test-project仓库中里面有三个镜像:nginx:1.22 nginx:1.24 mysql:8.0

yaml 复制代码
# 1. 想让哪台机器拉取harbor仓库的镜像,就在daemon.json中配置harbor的ip
# 我在k8s-node1上配置,待会就让pod运行在k8s-node1上
root@k8s-node1:~# vim /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://a88uijg4.mirror.aliyuncs.com",
    "https://docker.lmirror.top",
    "https://docker.m.daocloud.io",
    "https://hub.uuuadc.top",
    "https://docker.anyhub.us.kg",
    "https://dockerhub.jobcher.com",
    "https://dockerhub.icu",
    "https://docker.ckyl.me",
    "https://docker.awsl9527.cn",
    "https://docker.laoex.link"
  ],
  "insecure-registries": ["192.168.13.137"]
}
root@k8s-node1:~# systemctl daemon-reload
root@k8s-node1:~# systemctl restart docker
yaml 复制代码
# 2. 创建secret存放harbor的账号密码和ip
root@k8s-master1:~# kubectl create secret docker-registry harborsecret --docker-server=192.168.13.137 --docker-username=admin --docker-password=Harbor12345
root@k8s-master1:~# kubectl get secret
NAME           TYPE                             DATA   AGE
harborsecret   kubernetes.io/dockerconfigjson   1      24s

# 3. 创建pod,引用secret
root@k8s-master1:~# vim pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx-harbor
spec:
  nodeName: k8s-node1
  hostNetwork: true    
  imagePullSecrets:
    - name: harborsecret   # 拉取这个镜像时,要使用harborsecret这个账号密码去登录私有仓库
  containers:
    - name: nginx
      image: 192.168.13.137/test-project/nginx:1.22  # 配置harbor镜像的地址
      ports:
        - containerPort: 80  # 暴露端口
root@k8s-master1:~# kubectl apply -f pod.yaml 
root@k8s-master1:~# kubectl get pod -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
nginx-harbor   1/1     Running   0          4s    192.168.13.139   k8s-node1   <none>           <none>

浏览器访问k8s-node1的ip


注:

文中若有疏漏,欢迎大家指正赐教。

本文为100%原创,转载请务必标注原创作者,尊重劳动成果。

求赞、求关注、求评论!你的支持是我更新的最大动力,评论区等你~

相关推荐
xieliyu.2 小时前
Java手搓数据结构:从零模拟实现顺序表增删改查
java·开发语言·数据结构·学习·顺序表
小凡子空白在线学习2 小时前
工作中设计模式内容
java·后端·spring
高林雨露2 小时前
Java开发转kotlin
java·kotlin
Wenzar_2 小时前
# 发散创新:SwiftUI 中状态管理的深度实践与重构艺术 在 SwiftUI 的世界里,**状态驱动 UI 是核心哲学**。但随
java·python·ui·重构·swiftui
不败公爵2 小时前
finsh_thread_entry这个线程是自动启动的
java·linux·服务器
Seven972 小时前
Tomcat的事件监听机制:观察者模式
java
YaBingSec2 小时前
玄机靶场-第三届-长城杯-初赛-SnakeBackdoor WP
java·运维·笔记·tomcat·ssh
ZKNOW甄知科技2 小时前
燕千云ITR深度解析:大型企业如何建立服务价值流?
运维·人工智能·后端·科技·安全·自动化·用户运营
Agent手记2 小时前
等保三级合规:企业级智能体全链路数据安全落地方案 —— 2026年企业级AI Agent安全架构实战
人工智能·安全·ai·安全架构