kubernetes(K8s)学习笔记(第五期):存储与配置管理
本笔记为 Kubernetes 系列第五期,聚焦应用数据持久化与配置管理。涵盖:Volume 概述、emptyDir、hostPath、NFS 存储、PV 与 PVC 持久化存储架构、ConfigMap 配置管理、Secret 敏感信息管理。所有命令和 YAML 示例均已经过整理和注释。全文约 5300 字 ,包含 20 个 YAML 示例 、70+ 命令示例 和 14 张对比表格,是 Kubernetes 应用数据管理的必备指南。
--- Compiled and Authored by Whisky --- June 25th, 2026
目录
- Volume 概述
- emptyDir
- hostPath
- NFS 存储
- PV 与 PVC 持久化存储
- ConfigMap
- Secret
- 总结与知识点一览表
一、Volume 概述
1.1 为什么需要 Volume?
容器天生是无状态的:
- 容器重启后,文件系统会重置
- 容器删除后,所有数据丢失
- 多个容器之间无法共享数据
Volume(存储卷) 解决了以下问题:
- 数据持久化:Pod 重启或删除后数据不丢失
- 数据共享:同一 Pod 中的多个容器可以共享数据
- 数据迁移:Pod 可以在不同节点间迁移,数据保持一致
通俗比喻:容器就像酒店里的临时客房,每次入住都是全新的房间(干净的镜像),退房后所有个人物品(数据)都清空。Volume 就像酒店的储物柜,客人可以把自己的东西存进去,下次入住同一家酒店还能取出来。
1.2 Kubernetes 支持的 Volume 类型
| 类型 | 说明 | 适用场景 |
|---|---|---|
| emptyDir | 临时存储,Pod 删除时清除 | 容器间数据共享 |
| hostPath | 挂载宿主机目录 | 单节点测试、日志收集 |
| nfs | 挂载 NFS 共享目录 | 跨节点共享存储 |
| persistentVolumeClaim | 引用 PVC 持久卷 | 生产环境持久化存储 |
| secret / configMap | 挂载配置数据 | 配置文件、敏感信息 |
| csi | 容器存储接口 | 云存储(AWS EBS、Azure Disk 等) |
1.3 Volume 生命周期
- Volume 的生命周期与 Pod 绑定,而非容器
- Pod 删除时,emptyDir 数据清除,hostPath 和 NFS 数据保留
- PV/PVC 的生命周期独立于 Pod(即使 Pod 删除,PV/PVC 仍然存在)
1.4 Volume 与 Pod 的关系
ini
┌─────────────────────────────────────────────────────────────┐
│ Pod │
│ ┌─────────┐ ┌─────────┐ ┌──────────────────────────┐ │
│ │容器 1 │ │容器 2 │ │ Volume │ │
│ │ │ │ │ │ │ │
│ │ /app │ │ /logs │ │ emptyDir / hostPath / │ │
│ │ │ │ │ │ NFS / PVC │ │
│ └────┬────┘ └────┬────┘ └──────────────────────────┘ │
│ │ │ │ │
│ └────────────┴──────────────────────┘ │
│ 共享 Volume │
└─────────────────────────────────────────────────────────────┘
1.5 环境准备
bash
[root@master30 ~]# kubectl create ns storage
[root@master30 ~]# kubectl config set-context --current --namespace storage
二、emptyDir
2.1 emptyDir 概念
emptyDir 是 Kubernetes 中最简单的 Volume 类型:
- Pod 分配到节点时自动创建
- Pod 运行时一直存在
- Pod 删除时永久删除,数据丢失
- 适合临时数据共享,不适合持久化存储
适用场景:
- 同一 Pod 中多个容器之间共享数据(如日志收集 Sidecar)
- 缓存目录(如 Nginx 缓存)
- 临时工作目录(如数据处理)
2.2 emptyDir 实验
实验目标:在一个 Pod 中创建两个容器,共享 emptyDir 卷,验证数据共享和生命周期。
YAML 文件:
yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox
labels:
app: busybox
spec:
volumes:
- name: datavolume
emptyDir: {} # 定义 emptyDir 卷
containers:
- name: busybox1
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data # 容器内挂载路径
name: datavolume
- name: busybox2
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data
name: datavolume
配置说明:
| 字段 | 作用 |
|---|---|
spec.volumes |
定义卷,此处为 emptyDir |
spec.containers.volumeMounts |
引用卷,指定容器内挂载路径 |
mountPath |
容器内挂载目录 |
name |
必须匹配 volumes 中定义的卷名 |
执行步骤:
bash
# 1. 创建 Pod
[root@master30 ~]# kubectl apply -f pod-with-emptyDir.yaml
pod/busybox created
# 2. 查看容器 ID 和所在节点
[root@master30 ~]# kubectl describe pod busybox | egrep -o 'Container ID.*//.{12}'
Container ID: containerd://07d189383321
Container ID: containerd://bb02c680ca8a
[root@master30 ~]# kubectl describe pod busybox | grep Node:
Node: worker32.whisky.cloud/10.1.8.32
# 3. 登录节点查看挂载情况
root@worker32:~# crictl inspect 07d189383321 | grep datavolume
"hostPath": "/var/lib/kubelet/pods/.../volumes/kubernetes.io~empty-dir/datavolume",
# 4. 在容器1中创建文件
[root@master30 ~]# kubectl exec busybox -c busybox1 -- touch /data/b1-f1
# 5. 在容器2中查看(共享成功)
[root@master30 ~]# kubectl exec busybox -c busybox2 -- ls /data
b1-f1
# 6. 删除 Pod,验证数据丢失
[root@master30 ~]# kubectl delete pod busybox --force
pod "busybox" forced deleted
# 7. 节点上查看(目录已不存在)
root@worker32:~# ls /var/lib/kubelet/pods/.../volumes/kubernetes.io~empty-dir/datavolume
ls: No such file or directory
💡 关键理解 :两个容器通过
mountPath: /data挂载同一个 emptyDir 卷,实现了数据共享。Pod 删除后,emptyDir 数据被清除。emptyDir 非常适合需要数据共享但不需要持久化的场景,比如 Web 服务器 + 日志收集 Sidecar 的组合。
三、hostPath
3.1 hostPath 概念
hostPath 将宿主机节点上的目录挂载到 Pod 中:
- Pod 删除后,宿主机数据保留
- 适合需要访问宿主机文件系统的场景(如日志收集)
- ⚠️ 注意:不同节点上的目录内容可能不同,多节点集群中 Pod 迁移后可能看不到相同数据
适用场景:
- 访问宿主机 Docker/containerd 套接字
- 读取宿主机日志(如
/var/log) - 节点级别的配置文件
- 不适用场景:跨节点数据共享(因为每个节点上的目录独立)
风险警告:hostPath 将宿主机目录暴露给 Pod,存在安全风险。若 Pod 具有写权限,可能覆盖宿主机的关键文件。
3.2 hostPath 实验
实验目标 :将宿主机 /busyboxdir 目录挂载到 Pod 中,验证数据持久性。
YAML 文件:
yaml
apiVersion: v1
kind: Pod
metadata:
name: busybox
labels:
app: busybox
spec:
volumes:
- name: datavolume
hostPath:
path: /busyboxdir # 宿主机路径
containers:
- name: busybox1
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data
name: datavolume
- name: busybox2
image: busybox
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
volumeMounts:
- mountPath: /data
name: datavolume
readOnly: true # 设置为只读
readOnly 说明 :
readOnly: true表示容器对该挂载点只有读权限,默认值为false(可读写)。在多容器 Pod 中,可以让一个容器写入,另一个只读。
执行步骤:
bash
# 1. 在宿主机创建目录
root@worker32:~# mkdir -p /busyboxdir
# 2. 创建 Pod
[root@master30 ~]# kubectl apply -f pod-with-hostPath.yaml
pod/busybox created
# 3. 查看挂载情况
[root@master30 ~]# kubectl describe pod busybox | grep Node:
Node: worker32.whisky.cloud/10.1.8.32
root@worker32:~# crictl inspect 318922d0c666 | grep busyboxdir
"hostPath": "/busyboxdir",
# 4. 在容器中创建文件
[root@master30 ~]# kubectl exec busybox -c busybox1 -- touch /data/b1-f1
[root@master30 ~]# kubectl exec busybox -c busybox2 -- ls /data
b1-f1
# 5. 验证只读限制(busybox2 无法写入)
[root@master30 ~]# kubectl exec busybox -c busybox2 -- touch /data/b2-f2
touch: /data/b2-f2: Read-only file system
command terminated with exit code 1
# 6. 宿主机查看数据
root@worker32:~# ls /busyboxdir/
b1-f1
# 7. 删除 Pod,验证数据保留
[root@master30 ~]# kubectl delete pod busybox --force
root@worker32:~# ls /busyboxdir/
b1-f1 # 数据依然存在
3.3 emptyDir vs hostPath 对比
| 特性 | emptyDir | hostPath |
|---|---|---|
| 数据持久性 | Pod 删除即清除 | 宿主机数据保留 |
| 跨节点数据共享 | ❌ 不共享 | ❌ 不共享(各节点独立) |
| 适用场景 | 临时数据共享 | 访问宿主机文件系统 |
| 生产环境推荐度 | 中等 | 低(仅单节点测试) |
| 安全风险 | 低 | 较高(需控制权限) |
四、NFS 存储
4.1 NFS 概念
NFS(Network File System) 允许 Pod 挂载远程 NFS 共享目录:
- 数据存储在 NFS 服务器上
- Pod 删除后数据保留
- 支持跨节点共享(多个 Pod 可同时访问)
NFS 适用场景:
- 多个 Pod 需要共享同一份数据(如静态文件、配置文件)
- 需要跨节点数据持久化
- 作为 PV/PVC 的后端存储(生产环境常见方案)
NFS 优点:
- 配置简单,兼容性好
- 支持 RWO、ROX、RWX 三种访问模式
- 成本低(无需购买云存储)
NFS 缺点:
- 性能受网络影响
- 单点故障(NFS 服务器宕机则所有挂载失效)
- 不适合高 IOPS 场景
4.2 NFS 服务端部署
在 Master 节点部署 NFS 服务:
bash
# 1. 安装 NFS 服务端
[root@master30 ~]# apt install -y nfs-kernel-server
# 2. 创建共享目录
[root@master30 ~]# mkdir -m 777 /nfsshares
[root@master30 ~]# echo "hello whisky" > /nfsshares/index.html
# 3. 配置共享(允许所有客户端访问)
[root@master30 ~]# cat << EOF > /etc/exports
/nfsshares *(rw)
EOF
# 4. 重启 NFS 服务
[root@master30 ~]# systemctl restart nfs-server.service
在 Worker 节点安装 NFS 客户端:
bash
root@worker31:~# apt install -y nfs-common
root@worker32:~# apt install -y nfs-common
4.3 Pod 挂载 NFS 卷
YAML 文件:
yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: nginx
name: nginx
spec:
volumes:
- name: nfs
nfs:
server: 10.1.8.30 # NFS 服务器 IP
path: "/nfsshares" # NFS 共享路径
containers:
- image: nginx
name: nginx
volumeMounts:
- name: nfs
mountPath: "/usr/share/nginx/html"
执行步骤:
bash
# 1. 创建 Pod
[root@master30 ~]# kubectl apply -f pod-with-nfs.yaml
pod/nginx created
# 2. 查看 Pod IP
[root@master30 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 5m 10.224.51.171 worker32.whisky.cloud
# 3. 访问 Nginx(看到 NFS 中的内容)
[root@master30 ~]# curl 10.224.51.171
hello whisky
# 4. 在容器中创建文件
[root@master30 ~]# kubectl exec nginx -- touch /usr/share/nginx/html/test.html
# 5. 在 NFS 服务端查看
[root@master30 ~]# ls /nfsshares/
index.html test.html
# 6. 删除 Pod,验证数据保留
[root@master30 ~]# kubectl delete pod nginx --force
[root@master30 ~]# ls /nfsshares/
index.html test.html # 数据依然存在
五、PV 与 PVC 持久化存储
5.1 PV / PVC 架构
PV(PersistentVolume,持久卷) 和 PVC(PersistentVolumeClaim,持久卷声明) 是 Kubernetes 提供持久化存储的标准方案。
设计理念:
- 存储管理员:创建 PV,描述后端存储资源
- 应用开发者:创建 PVC,声明存储需求
- Kubernetes 控制器:自动绑定 PV 和 PVC
ini
┌─────────────────────────────────────────────────────────┐
│ Kubernetes 集群 │
│ │
│ ┌─────────────┐ ┌──────────────────────────┐ │
│ │ PV │ ←绑定→ │ PVC │ │
│ │ (资源) │ │ (申请) │ │
│ │ 5Gi / NFS │ │ 请求 5Gi / RWO │ │
│ └─────────────┘ └──────────────────────────┘ │
│ ↑ ↑ │
│ │ │ │
│ 管理员创建 开发者创建 │
│ │
│ ┌──────────────────┐ │
│ │ Pod │ │
│ │ 引用 PVC │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────────┘
PV 与 PVC 的区别:
| 特性 | PV(持久卷) | PVC(持久卷声明) |
|---|---|---|
| 定义者 | 集群管理员 | 应用开发者 / 用户 |
| 资源类型 | 集群级别资源 | Namespace 级别资源 |
| 作用 | 描述存储容量和类型 | 声明存储需求 |
| 生命周期 | 独立于 Pod | 绑定后随 Pod 使用 |
5.2 创建 PV
PV YAML 示例:
yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: web
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
nfs:
path: /nfsshares
server: 10.1.8.30
bash
[root@master30 ~]# kubectl apply -f pv.yaml
[root@master30 ~]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS
web 5Gi RWO Retain Available 3s
5.3 创建 PVC
PVC YAML 示例:
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: webclaim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
bash
[root@master30 ~]# kubectl apply -f pvc.yaml
[root@master30 ~]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES
webclaim Bound web 5Gi RWO
PVC 与 PV 绑定条件:
- 访问模式匹配:PVC 请求的访问模式 PV 必须支持
- 容量满足:PV 容量 ≥ PVC 请求容量
- 存储类匹配:如果指定了 storageClassName,必须一致
5.4 Pod 使用 PVC
YAML 示例:
yaml
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
name: web
spec:
containers:
- image: nginx
name: web
ports:
- containerPort: 80
name: web-port
volumeMounts:
- name: web-persistent-storage
mountPath: /usr/share/nginx/html
volumes:
- name: web-persistent-storage
persistentVolumeClaim:
claimName: webclaim
bash
[root@master30 ~]# kubectl apply -f pod-with-pvc.yaml
[root@master30 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
web 1/1 Running 0 35s 10.224.193.69 worker32.whisky.cloud
# 验证数据
[root@master30 ~]# curl http://10.224.193.69
hello whisky
5.5 PV 访问模式(accessModes)
| 模式 | 缩写 | 含义 | 适用场景 |
|---|---|---|---|
ReadWriteOnce |
RWO | 单个节点以读写方式挂载 | 单实例应用 |
ReadOnlyMany |
ROX | 多个节点以只读方式挂载 | 共享只读数据 |
ReadWriteMany |
RWX | 多个节点以读写方式挂载 | 共享读写数据 |
ReadWriteOncePod |
RWOP | 单个 Pod 以读写方式挂载 | 独占存储 |
不同后端支持的访问模式(以 NFS 为例):
| 卷插件 | RWO | ROX | RWX |
|---|---|---|---|
| NFS | ✅ | ✅ | ✅ |
| hostPath | ✅ | ❌ | ❌ |
| iSCSI | ✅ | ✅ | ❌ |
| CSI | 取决于驱动 | 取决于驱动 | 取决于驱动 |
| GCE Persistent Disk | ✅ | ✅ | ❌ |
⚠️ 重要:每个卷同一时刻只能以一种访问模式挂载。例如,一个 NFS 卷可以支持 RWO、ROX、RWX,但不能同时以多种模式挂载。
5.6 PV 回收策略(Reclaim Policy)
| 策略 | 行为 | 适用场景 |
|---|---|---|
| Retain(默认) | PVC 删除后,PV 保留数据,状态变为 Released | 需要手动清理数据 |
| Recycle(已废弃) | PVC 删除后,自动清理数据 | --- |
| Delete | PVC 删除后,自动删除 PV 和后端存储 | 动态存储场景 |
Retain 策略实验:
bash
# 1. 创建 PV 和 PVC(默认 Retain)
[root@master30 ~]# kubectl apply -f pv-pvc-Retain.yaml
# 2. 删除 PVC
[root@master30 ~]# kubectl delete pvc webclaim
# 3. PV 状态变为 Released
[root@master30 ~]# kubectl get pv
NAME CAPACITY RECLAIM POLICY STATUS CLAIM
web 5Gi Retain Released default/webclaim
# 4. 创建新 PVC,无法绑定(PV 仍保留旧 claimRef)
[root@master30 ~]# kubectl apply -f pvc-db.yaml
[root@master30 ~]# kubectl get pvc dbclaim
NAME STATUS VOLUME CAPACITY
dbclaim Pending
# 5. 手动清理 PV 中的 claimRef 信息
[root@master30 ~]# kubectl edit pv web
# 删除 claimRef 部分
# 删除后 PV 状态变为 Available
# 6. PVC 自动绑定成功
[root@master30 ~]# kubectl get pvc dbclaim
NAME STATUS VOLUME CAPACITY
dbclaim Bound web 5Gi
💡 关键理解:Retain 策略需要管理员手动清理 claimRef 信息,PV 才能重新使用。这是"保留"策略的设计目的------让管理员决定何时释放数据。
5.7 PV 卷类型
| 类型 | 状态 | 说明 |
|---|---|---|
| csi | ✅ 稳定 | 容器存储接口,推荐使用 |
| nfs | ✅ 稳定 | 网络文件系统 |
| hostPath | ✅ 稳定 | 单节点测试 |
| local | ✅ 稳定 | 本地存储设备 |
| fc / iscsi | ✅ 稳定 | 光纤通道 / iSCSI |
| gcePersistentDisk | ❌ 已弃用 | GCE 持久盘 |
| awsElasticBlockStore | ❌ 已弃用 | AWS EBS |
| azureDisk / azureFile | ❌ 已弃用 | Azure 存储 |
5.8 StorageClass 与动态制备(补充)
PV 有两种制备方式:
| 方式 | 说明 | 适用场景 |
|---|---|---|
| 静态制备 | 管理员预先创建 PV | 小规模、固定存储 |
| 动态制备 | 通过 StorageClass 自动创建 PV | 大规模、自动化 |
StorageClass 示例(供参考,非本实验内容):
yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-standard
六、ConfigMap
6.1 ConfigMap 介绍
ConfigMap 是 Kubernetes 中用于存储非敏感配置数据的 API 对象。
| 特性 | 说明 |
|---|---|
| 用途 | 存储配置数据(键值对) |
| 数据大小 | 上限 1 MiB |
| 编码 | 明文(不编码) |
| 更新 | 支持动态更新(Volume 挂载方式) |
| 适用场景 | 配置文件、环境变量、命令行参数 |
使用建议:
- ✅ 存储配置数据(如 nginx.conf、app.properties)
- ✅ 存储环境变量(如 LOG_LEVEL=debug)
- ❌ 不要存储大量数据(>1MiB)
- ❌ 不要存储敏感信息(使用 Secret)
ConfigMap 设计的本质:将配置从容器镜像中分离出来,实现"配置即代码",无需重新构建镜像即可修改配置。
6.2 ConfigMap 创建
方式一:键值对方式
bash
[root@master30 ~]# kubectl create configmap mysql --from-literal=password=redhat
[root@master30 ~]# kubectl get configmaps mysql -o yaml | grep ^data -A1
data:
password: redhat
方式二:文件方式
bash
[root@master30 ~]# echo "Hello World" > index.html
[root@master30 ~]# kubectl create configmap web1 --from-file=./index.html
[root@master30 ~]# kubectl get configmaps web1 -o yaml | grep ^data -A2
data:
index.html: |
Hello World
方式三:目录方式
bash
[root@master30 ~]# echo "error" > error.html
[root@master30 ~]# mkdir web2 && mv index.html error.html web2/
[root@master30 ~]# kubectl create configmap web2 --from-file=./web2
[root@master30 ~]# kubectl get configmaps web2 -o yaml | grep ^data -A4
data:
error.html: |
error
index.html: |
Hello World
方式四:YAML 文件方式
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: web3
data:
index.html: |
Hello World
error.html: |
error
6.3 ConfigMap 引用
方式一:环境变量引用
yaml
apiVersion: v1
kind: Pod
metadata:
name: mysql
spec:
containers:
- image: mysql:latest
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
configMapKeyRef:
name: mysql
key: password
bash
[root@master30 ~]# kubectl apply -f pod-cm-env.yaml
[root@master30 ~]# kubectl exec -it mysql -- bash -c 'echo $MYSQL_ROOT_PASSWORD'
redhat
方式二:Volume 挂载(整体)
yaml
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- image: nginx
name: web
volumeMounts:
- name: webcontent
mountPath: "/usr/share/nginx/html"
volumes:
- name: webcontent
configMap:
name: web2
bash
[root@master30 ~]# kubectl exec web -- ls /usr/share/nginx/html
error.html index.html
[root@master30 ~]# curl http://10.224.193.69
Hello World
[root@master30 ~]# curl http://10.224.193.69/error.html
error
方式三:Volume 挂载(特定 key)
yaml
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- image: nginx
name: web
volumeMounts:
- name: webcontent
mountPath: "/usr/share/nginx/html"
volumes:
- name: webcontent
configMap:
name: web2
items:
- key: index.html
path: index.html
6.4 ConfigMap 动态更新
被挂载的 ConfigMap 内容会自动更新(Volume 挂载方式):
bash
# 1. 更新 ConfigMap
[root@master30 ~]# kubectl edit configmap web1
# 修改 index.html 内容
# 2. 等待约 30 秒,Pod 内的文件自动更新
[root@master30 ~]# curl http://10.224.51.136
Updated content
注意:环境变量方式引用的 ConfigMap 不会动态更新,需要重启 Pod。Volume 挂载方式的支持了动态更新,但 kubelet 的同步周期默认约 1 分钟。
七、Secret
7.1 Secret 介绍
Secret 是 Kubernetes 中用于存储敏感数据的 API 对象。
Secret vs ConfigMap:
| 对比项 | ConfigMap | Secret |
|---|---|---|
| 数据编码 | 明文 | Base64 编码 |
| 适用数据 | 非敏感配置 | 密码、密钥、证书 |
| 数据大小 | 1 MiB | 1 MiB |
| 安全性 | 低 | 中等(可启用加密) |
| 用途 | 配置数据 | 敏感数据 |
Secret 数据编码 :Secret 使用 Base64 编码,但 Base64 不是加密,只是编码。启用 etcd 加密(--encryption-provider-config)可真正保护 Secret 数据。
7.2 Secret 类型
| 类型 | 用途 | 示例 |
|---|---|---|
Opaque(generic) |
通用键值对 | 密码、API Key |
kubernetes.io/dockerconfigjson |
Docker 仓库认证 | 拉取私有镜像 |
kubernetes.io/tls |
TLS 证书 | HTTPS 证书 |
7.3 Secret 创建
generic 类型
键值对方式:
bash
[root@master30 ~]# kubectl create secret generic mysecret1 \
--from-literal=user=tom \
--from-literal=password1=redhat
[root@master30 ~]# kubectl get secrets mysecret1 -o yaml
apiVersion: v1
data:
password1: cmVkaGF0 # redhat 的 base64 编码
user: dG9t # tom 的 base64 编码
type: Opaque
Base64 编解码:
bash
# 编码
[root@master30 ~]# echo -n redhat | base64
cmVkaGF0
[root@master30 ~]# echo -n tom | base64
dG9t
# 解码
[root@master30 ~]# echo -n cmVkaGF0 | base64 -d
redhat
文件方式:
bash
[root@master30 ~]# echo -n tom > user
[root@master30 ~]# echo -n redhat > password1
[root@master30 ~]# kubectl create secret generic mysecret2 --from-file=./user --from-file=./password1
# 文件名作为 key,文件内容作为 value
目录方式:
bash
[root@master30 ~]# mkdir config
[root@master30 ~]# mv user password1 config/
[root@master30 ~]# kubectl create secret generic mysecret5 --from-file=./config
YAML 文件方式:
yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret6
type: Opaque
data:
user: dG9t
password1: cmVkaGF0
docker-registry 类型
bash
[root@master30 ~]# kubectl create secret docker-registry registry \
--docker-username=whisky \
--docker-password=redhat \
--docker-email=whisky@whisky.cloud \
--docker-server=registry.whisky.cloud
tls 类型
bash
# 1. 生成私钥和证书
[root@master30 ~]# openssl genrsa -out www.key 2048
[root@master30 ~]# openssl req -new -key www.key -out www.csr \
-subj "/CN=www.whisky.cloud"
[root@master30 ~]# openssl x509 -req -days 3650 -in www.csr \
-signkey www.key -out www.crt
# 2. 创建 Secret
[root@master30 ~]# kubectl create secret tls www-tls \
--cert=./www.crt --key=./www.key
7.4 Secret 引用
环境变量引用
yaml
apiVersion: v1
kind: Pod
metadata:
name: mysql
spec:
containers:
- image: mysql:latest
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret1
key: password1
Volume 挂载(整体)
yaml
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- image: nginx
name: web
volumeMounts:
- name: webcontent
mountPath: "/usr/share/nginx/html"
volumes:
- name: webcontent
secret:
secretName: web
Volume 挂载(特定 key + subPath)
yaml
apiVersion: v1
kind: Pod
metadata:
name: web
spec:
containers:
- image: nginx
name: web
volumeMounts:
- name: webcontent
mountPath: "/usr/share/nginx/html/index.html"
subPath: index.html
volumes:
- name: webcontent
secret:
secretName: web
Secret 动态更新
Secret 也支持动态更新(Volume 挂载方式):
bash
# 1. 更新 Secret 中的值(需 base64 编码)
[root@master30 ~]# echo -n "Hello Nginx" | base64
SGVsbG8gbmdpbng=
# 2. 编辑 Secret
[root@master30 ~]# kubectl edit secrets web
# 3. 等待约 30 秒,Pod 内文件自动更新
[root@master30 ~]# curl 10.224.51.137/index.html
Hello Nginx
7.5 文件权限设置
设置所有文件权限(defaultMode):
yaml
volumes:
- name: foo
secret:
secretName: mysecret1
defaultMode: 256 # 10进制 256 → 8进制 400(只读)
设置单个文件权限(mode):
yaml
volumes:
- name: foo
secret:
secretName: mysecret1
items:
- key: user
path: user
mode: 511 # 10进制 511 → 8进制 777(所有权限)
八、总结与知识点一览表
8.1 核心知识点汇总
| 模块 | 核心概念 | 关键配置 |
|---|---|---|
| Volume | 存储卷抽象 | spec.volumes, spec.containers.volumeMounts |
| emptyDir | 临时存储,随 Pod 删除 | emptyDir: {} |
| hostPath | 宿主机目录挂载 | hostPath: {path: /xxx} |
| NFS | 网络文件系统 | nfs: {server: IP, path: /xxx} |
| PV | 集群级存储资源 | capacity, accessModes, nfs |
| PVC | 命名空间级存储申请 | resources.requests.storage, accessModes |
| ConfigMap | 非敏感配置存储 | --from-literal, --from-file |
| Secret | 敏感信息存储 | Base64 编码,三种类型 |
8.2 Volume 类型对比
| 类型 | 持久性 | 跨节点 | 适用场景 |
|---|---|---|---|
| emptyDir | ❌ Pod 删除即失 | ❌ | 临时共享 |
| hostPath | ✅ 宿主机保留 | ❌ | 单节点测试 |
| NFS | ✅ 服务端保留 | ✅ | 共享存储 |
| PV/PVC | ✅ 服务端保留 | ✅ | 生产持久化 |
8.3 ConfigMap vs Secret 对比
| 特性 | ConfigMap | Secret |
|---|---|---|
| 数据编码 | 明文 | Base64 |
| 用途 | 配置数据 | 敏感数据 |
| 类型 | 一种 | 三种(generic/docker-registry/tls) |
| 动态更新 | ✅(Volume 方式) | ✅(Volume 方式) |
| etcd 加密 | 不需要 | 推荐启用 |
8.4 常见错误排查
| 错误 | 原因 | 解决方法 |
|---|---|---|
PVC pending |
没有匹配的 PV | 检查 PV 状态和 PVC 请求参数 |
MountVolume.SetUp failed |
宿主机路径不存在 | 创建对应的宿主机目录 |
secret not found |
Secret 未创建或在其他 Namespace | 确认 Secret 名称和 Namespace |
ConfigMap not found |
ConfigMap 未创建 | 确认 ConfigMap 名称 |
Permission denied |
文件权限不足 | 调整 defaultMode 或宿主机权限 |
| NFS 挂载超时 | NFS 服务未启动或网络不通 | systemctl status nfs-server |
8.5 生产环境建议
- 存储选型 :
- 临时数据 → emptyDir
- 测试环境 → hostPath
- 生产环境 → PV/PVC(NFS、CSI 云存储)
- ConfigMap 使用建议 :
- 配置数据大小 < 1 MiB
- 使用 Volume 挂载方式可实现动态更新
- 敏感数据使用 Secret
- Secret 使用建议 :
- 启用 etcd 加密(生产环境)
- 使用 RBAC 限制 Secret 访问权限
- 考虑使用外部 Secret 管理工具(如 HashiCorp Vault)
- PV/PVC 使用建议 :
- 使用 Retain 策略保护重要数据
- 定期备份 PV 中的数据
- 合理规划存储类(StorageClass)
下一期预告:Kubernetes 控制器管理------Deployment 无状态应用部署、ReplicaSet 副本控制、DaemonSet 节点守护、Job/CronJob 任务管理。掌握 Kubernetes 工作负载控制器的核心机制。
--- Compiled and Authored by Whisky --- June 25th, 2026