形象类比
把K8s集群当成一栋公寓楼
- Pod = 住户房间(用完可销毁,数据默认随房间消失)
- NFS = 楼下公共共享仓库(所有住户共用的外置硬盘)
- PV = 物业提前划分好的固定储物格(实实在在的存储空间)
- PVC = 住户写的储物申请单(只说要多大空间,不用管位置)
- ConfigMap = 普通纸质记事本(存放明文普通配置)
- Secret = 带锁小保险柜(存放密码、密钥等敏感数据)
总结:
- Pod 中 容器应用 产生的 数据 的 目录挂载,通常都放到
pv类型的数据卷中- 而 配置文件 、环境变量等 的挂载处理 在k8s中 推荐 使用
ConfigMap- 用来保存 不方便 明文存储 的 敏感信息 例如 数据库密码、账号、Token、密钥、私钥等 通常用
Secret
一、NFS 网络共享存储(存储底层数据源)
1. 通俗解释
网络文件同步系统,可以实现多台主机在指定目录下进行 资源同步。
k8s借助NFS系统,可以实现 有状态部署 的 硬盘资源的整合管理。
跨服务器共享文件夹,所有K8s节点都能读写同一份文件,是K8s最常用的本地集群持久化存储。
2. 最佳使用场景
- 中小型K8s集群本地持久化数据
- 日志收集、静态文件共享、数据库数据挂载
- 多Pod共享同一份数据文件
3. 实操:搭建NFS服务(腾讯云服务器)
环境
假设 集群服务器有 5 台组成,对应的 IP 地址分别是 1.1.1.1、2.2.2.2、3.3.3.3、4.4.4.4、5.5.5.5
选集群其中一台机器当NFS服务端 :1.1.1.1
其余所有节点:2.2.2.2~5.5.5.5 作为客户端
3.1 服务端安装配置(1.1.1.1执行)
bash
# 安装nfs
yum install -y nfs-utils rpcbind
# 创建共享目录
mkdir -p /data/k8s-nfs
# 配置共享权限
vim /etc/exports
# 写入内容(允许所有集群网段访问)
/data/k8s-nfs *(rw,sync,no_root_squash,no_all_squash)
# 重启开机自启
systemctl start rpcbind && systemctl enable rpcbind
systemctl start nfs && systemctl enable nfs
# 生效配置
exportfs -r
# 查看共享目录
showmount -e localhost
3.2 所有K8s节点客户端安装(全部机器执行)
bash
yum install -y nfs-utils
# 测试挂载连通性
showmount -e 1.1.1.1
4. NFS 增删改查(服务器层面)
- 增:新建共享目录 + 写入exports配置
- 查:
showmount -e 服务端IP - 改:修改
/etc/exports执行exportfs -r - 删:删除目录、清空exports配置,停止nfs服务
5. 说明
K8s 集群运行 不依赖 NFS。
NFS 只是众多存储方案里的其中一种,不是刚需。
对于 ConfigMap 和 Secret 而言数据 存储在 etcd 的,自然没有 任何影响。
对于 PV 而言,不用 nfs 类型, 替换成别的存储后端:云厂商云硬盘(腾讯云 CBS、阿里云云盘)
等 即可。
只有一种情况 必须装 NFS:
业务需要多台节点、多个 Pod 共享同一份数据文件
比如:
- 多实例 Web 共用一份静态资源
- 集群统一日志共享目录
- 多 Pod 读写同一个上传文件
这种场景才需要:
- 一台机器搭 NFS 服务端
- 所有集群节点装 NFS 客户端
除此之外,一辈子不装都没事。
二、PV 持久卷(PersistentVolume)
1. 通俗解释
集群管理员提前建好的存储空间,直接绑定NFS目录,定义好大小、权限、存储类型,等着业务来申请使用。
2. 最佳场景
- 统一规划集群存储资源
- 固定大小数据库、缓存数据持久化
- 统一管控存储权限与读写策略
3. 完整部署步骤
3.1 编写 PV yaml nfs-pv.yaml
yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv-10g
spec:
capacity:
storage: 10Gi # 分配10G空间
accessModes:
- ReadWriteMany # 多Pod同时读写
nfs:
path: /data/k8s-nfs # NFS服务端共享目录
server: 1.1.1.1 # NFS服务端IP
persistentVolumeReclaimPolicy: Retain # 释放后保留数据
3.2 创建PV
bash
kubectl apply -f nfs-pv.yaml
4. PV 全套增删改查命令
bash
# 查所有PV
kubectl get pv
# 查看PV详细信息
kubectl describe pv nfs-pv-10g
# 修改PV(直接编辑)
kubectl edit pv nfs-pv-10g
# 删除PV
kubectl delete pv nfs-pv-10g
5. 业务案例
提前创建20G、50G大小NFS-PV,统一给MySQL、Redis业务预留存储。
6. PV 需要 运维人员 提前创建好吗?
静态 PV 必须运维提前建好,没建就用不了; 但 K8s 有 免手动建 PV 的方案
1. 先说传统模式(你之前学的 NFS+PV+PVC)
规则死规定:
- 运维不手动创建PV → 集群里就没有可用存储空间
- 开发写好PVC去申请存储
- 集群里找不到匹配的PV,PVC状态一直卡在 Pending
- 最终业务Pod挂载失败,无法启动
简单说:
静态卷模式:无提前建好的PV = PVC申请不到存储 = 用不了
2. 不用运维提前建PV的方案(生产最常用)
K8s 提供 StorageClass 存储类
作用:自动创建PV
流程彻底改变:
- 运维只配置一次「存储模板」(比如NFS模板、云盘模板)
- 运维再也不用一个个手动建PV
- 开发直接创建PVC
- K8s自动根据模板实时生成对应PV,自动绑定
- 直接正常使用
通俗比喻
- 老式静态PV:管理员提前把一个个空柜子摆好(建好PV),你才能领
- StorageClass (SC)动态卷:商场有自助存包机,你一扫码申请,机器当场变出柜子,不用管理员提前摆
两种模式对比
| 模式 | 有无SC | 流程 | 优缺点 |
|---|---|---|---|
| 静态存储 | 不用SC | 运维手动建PV → 开发建PVC绑定 | 运维麻烦,必须提前规划 |
| 动态存储 | 配置SC | 运维配置SC规则 → 开发直接建PVC → 自动生成PV | 按需创建,运维零工作量,生产首选 |
StorageClass 常用命令(增删改查)
bash
# 查看所有存储类
kubectl get sc
# 查看详细信息
kubectl describe sc nfs-dynamic-sc
# 修改存储类
kubectl edit sc nfs-dynamic-sc
# 删除存储类
kubectl delete sc nfs-dynamic-sc
适合用 StorageClass
- 生产正式环境 (99%企业在用)
业务量大、项目多,不可能让运维手动一个个建PV - 微服务集群
每个服务独立存储,按需申请5G、10G、20G自动分配 - CI/CD自动发布项目
流水线部署自动创建PVC,自动生成存储 - 云服务器K8s集群
腾讯云/阿里云自带云盘SC,直接用,不用搭NFS - 弹性扩容业务
临时扩容Pod,自动申请存储,用完释放
不适合用 StorageClass
- 极简测试单机集群
自己学习玩一玩,数量少,手动建PV更快 - 需要提前规划固定大容量存储
超大数据库提前划分好固定分区
三、PVC 持久卷声明(PersistentVolumeClaim)
1. 通俗解释
开发人员提交的存储申请单 ,只填写:我需要多大空间、读写权限,K8s自动匹配空闲PV,不用关心存储真实位置。
2. 最佳场景
- 业务项目申请持久化存储
- 部署MySQL、Redis、Nginx日志持久化
- 开发无需接触底层NFS,只申请即可
3. 完整部署步骤
3.1 编写PVC yaml nfs-pvc.yaml
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: app-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi # 申请10G存储
3.2 创建PVC自动绑定PV
bash
kubectl apply -f nfs-pvc.yaml
创建后自动匹配状态为Available 的同规格PV,状态变成Bound绑定成功。
3.3 Pod挂载PVC实现数据持久化
yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: data-volume
mountPath: /usr/share/nginx/html # 容器内挂载目录
volumes:
- name: data-volume
persistentVolumeClaim:
claimName: app-pvc # 引用上面PVC
执行创建:
bash
kubectl apply -f nginx-pod.yaml
效果:删除Pod重建,网页数据依然保留在NFS服务器里。
4. PVC 增删改查命令
bash
# 查看所有PVC
kubectl get pvc
# 查看绑定详情
kubectl describe pvc app-pvc
# 在线修改PVC
kubectl edit pvc app-pvc
# 删除PVC
kubectl delete pvc app-pvc
5. 实战场景
部署MySQL数据库,挂载PVC持久化库文件,集群节点漂移数据不丢失。
四、ConfigMap 明文配置中心
1. 通俗解释
存放明文普通配置的文件仓库,比如端口、域名、超时时间、环境地址,所有人都能看。
2. 最佳使用场景
- 项目配置文件、日志级别、接口地址
- Nginx配置、启动参数、开发环境变量
- 非敏感通用配置统一管理
3. 三种创建方式 + 实操
方式1:命令行快速创建(最简单)
bash
# 键值对创建
kubectl create configmap app-config --from-literal=env=prod,port=8080
# 从本地配置文件创建
kubectl create configmap nginx-conf --from-file=./nginx.conf
方式2:yaml标准创建 configmap.yaml
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: web-config
data:
APP_ENV: production
LOG_LEVEL: info
DB_HOST: 10.0.0.10
创建:
bash
kubectl apply -f configmap.yaml
3种挂载使用方式
- 注入环境变量
- 挂载为配置文件
- 启动命令引用
示例Pod引用ConfigMap:
yaml
apiVersion: v1
kind: Pod
metadata:
name: config-pod
spec:
containers:
- name: app
image: busybox
command: ["sleep","3600"]
env:
- name: ENV
valueFrom:
configMapKeyRef:
name: web-config
key: APP_ENV
这个配置文件的作用:
创建一个 Pod,里面运行一个 busybox 容器,把 ConfigMap(web-config) 里的配置项 APP_ENV,自动注入成容器内部的环境变量 ENV,容器启动后休眠 1 小时方便我们测试。
4. ConfigMap 增删改查
bash
# 查询
kubectl get configmap
kubectl describe configmap web-config
# 修改
kubectl edit configmap web-config
# 删除
kubectl delete configmap web-config
5. 业务案例
统一管理微服务环境变量,测试/生产环境一键切换ConfigMap实现环境切换。
五、Secret 加密私密配置
1. 通俗解释
加密保险箱,专门存放账号密码、数据库密码、Token、密钥,数据默认Base64编码加密,比明文安全。
2. 最佳使用场景
- MySQL、Redis、MQ数据库账号密码
- 接口密钥、JWT令牌、登录凭证
- 集群内部私密授权信息
3. 实操部署
3.1 命令行创建(推荐)
bash
# 创建数据库账号密码secret
kubectl create secret generic db-secret \
--from-literal=db_user=root \
--from-literal=db_pwd=123456
1. kubectl create secret
- 含义:执行创建 Secret 资源
- 作用:告诉 K8s 集群:我要创建一个「加密配置保险箱」
2. generic
- 含义:通用型 Secret
- 作用:最常用的Secret类型,专门存账号、密码、Token、密钥等任意敏感键值对
Secret 一共 3 种官方标准类型:
- generic(通用型 / 万能型)→ 存任意敏感数据(账号、密码、Token、密钥)
- tls(证书专用型)→ 存HTTPS 证书 + 私钥(网站加密用)
- docker-registry(镜像仓库专用型)→ 存私有镜像仓库登录凭证(拉私有镜像用)
3. db-secret
- 含义:给这个 Secret 起的名字
- 作用:后面 Pod 要引用这个密码时,必须写这个名字
4. --from-literal
- 含义:直接用「键=值」的字面量方式创建
- 作用:不用写YAML文件,命令行直接明文写配置,最简单快捷
5. db_user=root
- 键名:
db_user(数据库用户名) - 键值:
root - 作用:存数据库账号
6. db_pwd=123456
- 键名:
db_pwd(数据库密码) - 键值:
123456 - 作用:存数据库密码
3.2 yaml方式创建 secret.yaml
先加密明文:
bash
echo -n "root" | base64 # 输出:cm9vdA==
echo -n "123456" | base64 # 输出:MTIzNDU2
写入yaml:
yaml
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
db_user: cm9vdA==
db_pwd: MTIzNDU2
创建:
bash
kubectl apply -f secret.yaml
3.3 Pod引用Secret(注入密码)
yaml
# 1. 固定API版本:Pod属于K8s核心v1版本API
apiVersion: v1
# 2. 资源类型:我要创建的是【Pod】(K8s最小运行单元)
kind: Pod
# 3. 元数据:给Pod起名字
metadata:
name: mysql-pod # 这个Pod的名字叫 mysql-pod
# 4. Pod规格:定义Pod里装什么、怎么运行
spec:
containers: # 容器列表(一个Pod里可以跑多个容器)
- name: mysql # 给容器起个名字:mysql
image: mysql:5.7 # 用官方MySQL 5.7版本镜像(固定写法)
# 🔥🔥🔥 核心重点:环境变量配置(密码安全核心)
env:
# MySQL 官方镜像强制要求必须设置这个环境变量
# 作用:设置 MySQL 的 root 用户密码
- name: MYSQL_ROOT_PASSWORD
# 值不从YAML写死明文,而是从【Secret】中读取
valueFrom:
# 明确告诉K8s:值来自 Secret 加密配置
secretKeyRef:
name: db-secret # 读取哪个Secret?→ 你创建的 db-secret
key: db_pwd # 读Secret里的哪个键?→ db_pwd(存的是123456)
4. Secret 增删改查命令
bash
# 查看
kubectl get secret
kubectl describe secret db-secret
# 修改
kubectl edit secret db-secret
# 删除
kubectl delete secret db-secret
5. Secret 数据安全性 的保障
Secret 真正的安全来自 K8s 集群的 4 道安全锁:
安全锁 1:RBAC 权限控制(最重要)
- 不是谁都能查看 Secret
- 只有集群管理员、授权账号 才能
kubectl get secret - 普通开发、外部人员根本看不到 Secret 内容
比喻:Secret 是放在带锁保险柜 里的纸条,Base64 只是纸条上的字写歪了,锁才是安全核心
安全锁 2:命名空间隔离
- Secret 只能在同一个 Namespace 内使用
- 跨项目、跨环境完全隔离,无法窃取
安全锁 3:只存内存,不写硬盘
- Pod 挂载的 Secret 不会写入节点磁盘
- 直接放在
tmpfs(内存临时文件)中 - Pod 删除,数据立刻消失,不留痕迹
安全锁 4:传输全程 HTTPS 加密
- K8s 各组件之间传输 Secret,全程 TLS 加密
- 网络传输中不可能被窃听
综上所述:
K8s 超级集群管理员,可以毫无阻碍查看、解码、获取集群内任意所有 Secret 明文敏感数据,没有任何遮挡。
- 超级管理员拥有全局最高 RBAC 权限,不受任何权限限制
- 可以随意执行查看、导出所有 Secret 资源
- Secret 仅靠 Base64 编码,管理员一键就能解码成明文
6. 什么要用 Base64?
不是为了加密!是为了兼容存储:
- Secret 可以存二进制文件(证书、图片、密钥)
- etcd 只能存文本,不能存二进制
- Base64 把二进制 → 纯文本,方便 K8s 存储传输
就是个格式转换工具,和安全无关!
7. 生产环境真正的「高强度安全」怎么做?
如果你的业务是金融、支付等高安全要求:
- 开启 K8s etcd 静态加密(Secret 落盘加密存储)
- 搭配云厂商 KMS 密钥管理服务(腾讯云/阿里云)
- 严格 RBAC 权限,禁止越权查看 Secret
- 敏感密钥使用外部密钥管理系统,不存 K8s