48·配置管理进阶

卷挂载

kubernetesvolumestorage

卷挂载

学习目标

  1. 理解 Kubernetes 卷的概念和作用
  2. 掌握卷挂载的基本配置方法
  3. 了解不同卷类型的应用场景

核心概念

为什么需要卷

没有卷的问题:
┌─────────────────────────────────────┐
│           Pod                       │
│  ┌─────────────────────────────┐   │
│  │  Container                   │   │
│  │  - 数据写入容器文件系统      │   │
│  │  - 容器重启数据丢失          │   │
│  │  - 多容器无法共享数据        │   │
│  └─────────────────────────────┘   │
└─────────────────────────────────────┘

使用卷的解决方案:
┌─────────────────────────────────────┐
│           Pod                       │
│  ┌─────────────────────────────┐   │
│  │  Container 1                 │   │
│  │  - 读写卷数据                │   │
│  └─────────────────────────────┘   │
│  ┌─────────────────────────────┐   │
│  │  Container 2                 │   │
│  │  - 共享同一卷                │   │
│  └─────────────────────────────┘   │
│  ┌─────────────────────────────┐   │
│  │  Volume                      │   │
│  │  - 持久化存储                │   │
│  │  - 跨容器共享                │   │
│  └─────────────────────────────┘   │
└─────────────────────────────────────┘

卷的生命周期

Pod 创建 → 卷创建 → 容器挂载 → 容器使用 → Pod 删除 → 卷清理

不同卷类型的生命周期:
- emptyDir: Pod 生命周期
- hostPath: 节点生命周期
- PersistentVolume: 独立生命周期

卷的基本配置

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  containers:
  - name: app
    image: my-app:1.0
    volumeMounts:
    - name: data-volume
      mountPath: /data
      readOnly: false  # 是否只读
  volumes:
  - name: data-volume
    emptyDir: {}  # 卷类型

常用卷类型

卷类型说明生命周期典型用途
emptyDir空目录Pod临时存储、缓存
hostPath主机目录节点访问主机文件
configMap配置数据Pod配置文件
secret敏感数据Pod证书、密钥
persistentVolumeClaim持久化存储独立数据库、文件存储

卷挂载选项

volumeMounts:
- name: data-volume
  mountPath: /data           # 挂载路径
  readOnly: false            # 是否只读
  subPath: config.txt        # 挂载卷中的子路径
  mountPropagation: None     # 挂载传播模式

挂载传播模式

模式说明
None不传播挂载
HostToContainer主机挂载传播到容器
Bidirectional双向传播(危险)

多容器共享卷

apiVersion: v1
kind: Pod
metadata:
  name: shared-volume
spec:
  containers:
  - name: writer
    image: busybox
    command: ["sh", "-c", "echo 'Hello from writer' > /data/message && sleep 3600"]
    volumeMounts:
    - name: shared-data
      mountPath: /data
  - name: reader
    image: busybox
    command: ["sh", "-c", "cat /data/message && sleep 3600"]
    volumeMounts:
    - name: shared-data
      mountPath: /data
      readOnly: true
  volumes:
  - name: shared-data
    emptyDir: {}

子路径挂载

volumes:
- name: config-volume
  configMap:
    name: app-config

volumeMounts:
# 只挂载 ConfigMap 中的特定键
- name: config-volume
  mountPath: /etc/nginx/nginx.conf
  subPath: nginx.conf

只读挂载

volumeMounts:
- name: secret-volume
  mountPath: /etc/secrets
  readOnly: true  # 只读挂载

实践练习

练习 1:基本卷挂载

创建 Pod 使用 emptyDir:

apiVersion: v1
kind: Pod
metadata:
  name: volume-demo
spec:
  containers:
  - name: writer
    image: busybox
    command: ["sh", "-c", "echo 'Hello from Pod' > /data/test.txt && sleep 3600"]
    volumeMounts:
    - name: data-volume
      mountPath: /data
  - name: reader
    image: busybox
    command: ["sh", "-c", "cat /data/test.txt && sleep 3600"]
    volumeMounts:
    - name: data-volume
      mountPath: /data
      readOnly: true
  volumes:
  - name: data-volume
    emptyDir: {}

验证:

kubectl logs volume-demo -c reader
# 输出:Hello from Pod

练习 2:ConfigMap 卷挂载

创建 ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  nginx.conf: |
    server {
        listen 80;
        server_name localhost;
        location / {
            return 200 "Hello from Nginx!";
        }
    }

创建 Pod:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-with-config
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: nginx-config
      mountPath: /etc/nginx/conf.d
  volumes:
  - name: nginx-config
    configMap:
      name: nginx-config

验证:

kubectl exec nginx-with-config -- cat /etc/nginx/conf.d/nginx.conf

练习 3:Secret 卷挂载

创建 Secret:

kubectl create secret generic app-secret \
  --from-literal=api-key=sk-123456789

创建 Pod:

apiVersion: v1
kind: Pod
metadata:
  name: app-with-secret
spec:
  containers:
  - name: app
    image: busybox
    command: ["sh", "-c", "cat /etc/secrets/api-key && sleep 3600"]
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secrets
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: app-secret
      defaultMode: 0400

验证:

kubectl logs app-with-secret
# 输出:sk-123456789

练习 4:子路径挂载

创建 ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: multi-config
data:
  app.conf: |
    [app]
    name=my-app
  db.conf: |
    [database]
    host=mysql.example.com

创建 Pod:

apiVersion: v1
kind: Pod
metadata:
  name: subpath-demo
spec:
  containers:
  - name: app
    image: busybox
    command: ["sh", "-c", "cat /etc/config/app.conf && sleep 3600"]
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config/app.conf
      subPath: app.conf
  volumes:
  - name: config-volume
    configMap:
      name: multi-config

验证:

kubectl exec subpath-demo -- cat /etc/config/app.conf

小结

要点说明
卷概念持久化存储、跨容器共享
emptyDir临时存储,Pod 生命周期
卷挂载volumeMounts 配置
只读挂载readOnly: true
子路径挂载subPath 配置
共享卷多容器访问同一卷

练习编辑器

bash
Loading...

继续学习

完成本课后,建议继续学习下一课「EmptyDir 卷」 以巩固所学知识。