k8s 存储练习

练习 1:ConfigMap(明文配置)

1. 核心概念

  • 存储非敏感的配置数据(环境变量、配置文件)
  • 命名空间级别资源,Pod 可以直接挂载使用

2. 编写 YAML 文件

创建 my-configmap.yaml

yaml 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-app-config  # ConfigMap 名称
data:
  # 键值对形式存储配置
  APP_ENV: "test"
  APP_PORT: "8080"
  APP_NAME: "my-test-app"

3. 创建 + 验证

bash 复制代码
# 创建 ConfigMap
kubectl apply -f my-configmap.yaml

# 查看所有 ConfigMap
kubectl get cm

# 查看详细配置(重点)
kubectl describe cm my-app-config

✅ 重点讲解

  • data:存放明文键值对,是 ConfigMap 的核心
  • 用途:给 Pod 注入环境变量、挂载配置文件

练习 2:Secret(敏感数据)

1. 核心概念

  • 存储密码、密钥、token等敏感信息
  • K8s 用 Base64 编码存储(不是加密,仅避免明文)
  • 用法和 ConfigMap 几乎一致,安全性更高

2. 先编码敏感数据(必须做)

bash 复制代码
# 对密码、用户名进行 Base64 编码
echo -n "admin" | base64       # 用户名编码
echo -n "Admin@123456" | base64  # 密码编码

记录输出结果(后面 YAML 要用):

复制代码
用户名编码:YWRtaW4=
密码编码:QWRtaW5AMTIzNDU2

3. 编写 YAML 文件

创建 my-secret.yaml

yaml 复制代码
apiVersion: v1
kind: Secret
metadata:
  name: my-app-secret
type: Opaque  # 通用密钥类型
data:
  # 填写上面编码后的值
  USERNAME: YWRtaW4=
  PASSWORD: QWRtaW5AMTIzNDU2

4. 创建 + 验证

bash 复制代码
# 创建 Secret
kubectl apply -f my-secret.yaml

# 查看 Secret
kubectl get secret

# 查看详情(默认不会显示明文,只会显示数据长度)
kubectl describe secret my-app-secret

# 查看 USERNAME 和 PASSWORD 字段的 明文
kubectl get secret my-app-secret -o jsonpath='{.data.USERNAME}' | base64 -d
kubectl get secret my-app-secret -o jsonpath='{.data.PASSWORD}' | base64 -d

✅ 重点讲解

  • type: Opaque:最常用的自定义密钥类型
  • 绝对不要在 YAML 里写明文,必须用 Base64 编码
  • Secret 数据仅在集群内安全传输,不会暴露到日志

练习 3:PV(持久化存储,管理员创建)

方式一: 自动创建 pv

Kind 集群自带自动存储类 ,你完全不用手动创建PV,直接用PVC就能自动生成PV,100%成功!

步骤1:创建极简PVC(依赖Kind自动创建PV)

新建 pvc.yaml什么都不用改,直接用

yaml 复制代码
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

这个 PVC 能否自动创建并绑定 PV,完全取决于你的集群是否配置了 StorageClass(存储类)

Kind 集群内置了动态存储插件 local-path-provisioner,并默认创建了:

  • 名为 standard 的 默认 StorageClass
  • 该存储类会自动在 Kind 节点的本地临时目录中创建 PV
  • 上面的 PVC 不写 storageClassName 也会自动匹配这个默认 SC → 直接自动创建 PV 并绑定

步骤2:创建PVC + 验证

bash 复制代码
kubectl apply -f pvc.yaml
kubectl get pvc

✅ 此时还是 Pending(正常,因为延迟绑定)

步骤3:本地下载镜像 + 导入 Kind 集群

Kind 集群本身运行在 Docker 容器中,集群内部无法访问外网拉取镜像。

这是 Kind 专用命令,把本地镜像直接塞进 K8s 集群里,永远不用联网拉取

sh 复制代码
# 1. 本地下载小镜像(宿主机执行,肯定成功)
docker pull busybox:1.36

# 2. 把本地镜像导入你的 Kind 集群(名字:my-first-cluster)
kind load docker-image busybox:1.36 --name my-first-cluster

步骤4:启动 pod

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: busybox
    image: busybox:1.36
    command: ["sleep", "3600"]
    volumeMounts:
    - name: my-pvc
      mountPath: /data
  volumes:
  - name: my-pvc
    persistentVolumeClaim:
      claimName: my-pvc
bash 复制代码
kubectl apply -f pod.yaml

步骤5:最终验证

bash 复制代码
kubectl get pvc  # 状态变为 Bound
kubectl get pv   # 自动生成了PV

步骤6: 验证 持久性

  • 写入数据
sh 复制代码
# 1. 进入Pod容器
kubectl exec -it test-pod -- sh

# 2. 在挂载的存储目录创建文件(测试持久化)
echo "k8s 练习成功!" > /data/success.txt

# 3. 查看文件
cat /data/success.txt

# 4. 退出容器
exit
  • 删除 Pod(模拟 Pod 崩溃、重启、重建)
sh 复制代码
kubectl delete pod test-pod
  • 重新创建 Pod(使用同一个 PVC)
sh 复制代码
kubectl apply -f pod-nginx-pvc.yaml
  • 进入新 Pod,查看数据是否还在!
sh 复制代码
# 进入新建的 Pod
kubectl exec -it test-pod -- sh

# 查看文件(重点!!!)
cat /data/test.txt

# 退出
exit

方式二: 手动创建 pv

必须让 PV 和 PVC 的 storageClassName 完全一致(都设为空)

PV YAML

yaml 复制代码
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv
spec:
  storageClassName: ""  # 关键:空字符串
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /tmp/my-pv-data

PVC YAML

yaml 复制代码
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  storageClassName: ""  # 关键:和PV一致
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

✅ 重点讲解

  • PV 是集群级别资源,不属于任何命名空间
  • accessModes
    • ReadWriteOnce:单节点可读写(测试首选)
  • persistentVolumeReclaimPolicyRetain(删除 PVC 后数据保留)

练习 4:PVC(存储申请,用户使用)

1. 核心概念

  • Pod 不直接使用 PV,而是通过 PVC 申请存储
  • K8s 会自动匹配满足条件的 PV 并绑定

2. 编写 PVC YAML

创建 my-pvc.yaml

yaml 复制代码
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteOnce  # 必须和 PV 一致
  resources:
    requests:
      storage: 1Gi  # 申请大小,必须 ≤ PV

3. 创建 + 验证绑定

bash 复制代码
# 创建 PVC
kubectl apply -f my-pvc.yaml

# 查看 PVC(状态:Bound 表示绑定 PV 成功)
kubectl get pvc

# 再次查看 PV(状态变为 Bound)
kubectl get pv

✅ 重点讲解

  • PVC 是命名空间级别资源
  • 绑定规则:存储大小 + 访问模式 必须匹配 PV
  • Bound 状态 = 存储就绪,可以给 Pod 使用

练习 5:环境变量 的形式 使用 ConfigMap & Secret 的数据

目标

创建一个 Nginx Pod,同时使用:

  1. ConfigMap 注入环境变量
  2. Secret 注入账号密码
  3. PVC 挂载持久化存储

编写整合 YAML

创建 my-pod.yaml

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: my-test-pod
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
    # 1. 挂载 ConfigMap 作为环境变量
    env:
    - name: APP_ENV
      valueFrom:
        configMapKeyRef:
          name: my-app-config
          key: APP_ENV
    - name: APP_PORT
      valueFrom:
        configMapKeyRef:
          name: my-app-config
          key: APP_PORT
    # 2. 挂载 Secret 作为环境变量
    - name: USERNAME
      valueFrom:
        secretKeyRef:
          name: my-app-secret
          key: USERNAME
    - name: PASSWORD
      valueFrom:
        secretKeyRef:
          name: my-app-secret
          key: PASSWORD
    # 3. 挂载 PVC 持久化存储
    volumeMounts:
    - name: my-storage
      mountPath: /usr/share/nginx/html  # 容器内挂载目录
  # 声明 PVC 存储卷
  volumes:
  - name: my-storage
    persistentVolumeClaim:
      claimName: my-pvc  # 绑定我们创建的 PVC

创建 + 验证

bash 复制代码
# 创建 Pod
kubectl apply -f my-pod.yaml

# 查看 Pod 状态(Running 为成功)
kubectl get pods

验证所有资源是否生效

1. 进入 Pod 查看 ConfigMap + Secret

bash 复制代码
# 进入容器内部
kubectl exec -it my-test-pod -- sh

# 查看环境变量(能看到配置和密码)
env | grep APP_
env | grep USERNAME
env | grep PASSWORD

# 退出容器
exit

2. 验证持久化存储

bash 复制代码
# 在容器的挂载目录创建文件
kubectl exec my-test-pod -- touch /usr/share/nginx/html/test.txt

# 查看文件(证明存储挂载成功)
kubectl exec my-test-pod -- ls /usr/share/nginx/html

练习 6:配置文件 的形式 使用 ConfigMap & Secret 的数据

ConfigMapSecret 作为文件卷 挂载到容器内的指定目录,容器里的程序直接读取文件获取配置(而非读环境变量),这是生产环境 最常用的 方式。


创建 ConfigMap

yaml 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: wtt-app-config
data:
  # 🔥 一个key = 一个完整配置文件(文件名:app.env)
  app.env: |
    APP_ENV=production
    APP_PORT=8080
    LOG_LEVEL=info
    DEBUG=false

说明:

  • app.env = 配置文件的文件名
  • | = YAML 多行文本标记(保留换行,把下面所有内容当成一整个文件的内容)
  • 整个 data 只有 1 个 Key,对应 1 个完整的配置文件
对比项 旧写法(键值对平铺) 新写法(单配置文件)
ConfigMap 结构 多个独立key 1个key = 1个文件名 + 完整文件内容
挂载到Pod后的效果 生成 3个零散文件 APP_ENV、APP_PORT、APP_NAME 生成 1个完整文件 app.env(包含所有配置)
程序读取方式 读N个零散文件(极不规范) 1个标准配置文件(符合所有软件习惯)
生产实用性 仅适合简单环境变量,不能当配置文件 ✅ 标准用法,适配所有应用
维护成本 加配置就要加key,越用越乱 所有配置写在一个文件里,一目了然

创建 Secret

yaml 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: wtt-app-config
data:
  # 🔥 一个key = 一个完整配置文件(文件名:app.env)
  app.env: |
    APP_ENV=production
    APP_PORT=8080
    LOG_LEVEL=info
    DEBUG=false[root@VM-0-16-opencloudos single_node]# cat secret2.yaml 
apiVersion: v1
kind: Secret
metadata:
  name: wtt-app-secret
type: Opaque

# 🔥 用 stringData,直接写明文!
stringData:
  credentials.env: |
    USERNAME=admin
    PASSWORD=123456

说明:

  • Kubernetes 的 Secret -> data 字段:
    ✅ 只接受 Base64 编码字符串
    ❌ 不接受明文
  • 免编码写法(新手首选): 用 stringData 替代 data,可以直接写明文,K8s 自动帮你转 Base64!

Pod

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: whero-test-pod
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80

    # 挂载:持久化存储 + 配置文件 + 密钥文件
    volumeMounts:
    # 1. 原有 PVC 存储(不动)
    - name: my-storage
      mountPath: /usr/share/nginx/html
    
    # 2. 挂载 ConfigMap → 【单个配置文件】app.env
    - name: config-volume
      mountPath: /etc/app/app.env  # 容器内的文件完整路径
      subPath: app.env             # 核心!只挂载ConfigMap里的这个文件,不覆盖目录
    
    # 3. 挂载 Secret → 【单个密钥文件】credentials.env
    - name: secret-volume
      mountPath: /etc/app/credentials.env
      subPath: credentials.env      # 核心!只挂载Secret里的这个文件

  # 声明卷
  volumes:
  - name: my-storage
    persistentVolumeClaim:
      claimName: my-pvc
  # 关联你创建的 ConfigMap
  - name: config-volume
    configMap:
      name: wtt-app-config
  # 关联你创建的 Secret
  - name: secret-volume
    secret:
      secretName: wtt-app-secret

验证

yaml 复制代码
# 进入容器
kubectl exec -it whero-test-pod -- sh

# 查看配置文件目录(只有 2 个文件!完美)
ls /etc/app/
# 输出:app.env  credentials.env

# 查看完整配置文件
cat /etc/app/app.env
# 输出:所有配置都在这一个文件里
# cat /etc/app/app.env
APP_ENV=production
APP_PORT=8080
LOG_LEVEL=info
DEBUG=false



# 查看完整密钥文件
cat /etc/app/credentials.env
# 输出:所有密钥都在这一个文件里(自动解密明文)
# cat /etc/app/credentials.env
USERNAME=admin
PASSWORD=123456

优势(生产环境推荐)

  1. 配置更规范:程序直接读标准配置文件,兼容绝大多数应用
  2. 安全更高 :Secret 挂载为文件权限默认为 600,仅当前用户可读取
  3. 热更新 :ConfigMap/Secret 修改后,容器内文件自动同步更新(无需重启 Pod)
相关推荐
白日做梦Q12 小时前
Docker部署YOLOv8训练+推理完整教程(含报错解决)
yolo·docker·容器
万里侯12 小时前
云原生监控体系建设:打造全方位的可观测性平台
微服务·容器·k8s
会编程的土豆12 小时前
Docker 里面的镜像(Image)和容器(Container)到底是什么
运维·docker·容器
无级程序员12 小时前
记一次K8S增加新节点
云原生·容器·kubernetes
r-t-H12 小时前
KVM虚拟化与Docker基础实践-第三章
linux·运维·nginx·docker·容器
仙柒41521 小时前
控制平面组件和节点组件
运维·容器·kubernetes
Niliuershangba1 天前
Docker Desktop 部署 ChestnutCMS 全流程:从零搭建企业级 CMS 开发环境
运维·docker·容器
wb1891 天前
Kubernetes服务优化
云原生·容器·kubernetes
码点滴1 天前
Workload 自动化进化论:从手动运维到 AI 驱动的 Kubernetes 智能管控
运维·人工智能·kubernetes·自动化·workload