Volume常用的几个存储卷

emptyDir: 本地临时卷
hostPath: 本地存储卷
configMap: 配置文件
secret: 敏感配置信息所用的配置
nfs: 网络存储卷
pv/pvc/storageclass

不同类型存储卷yaml文件示例

1、emptyDir临时卷

pod删除,存储卷内的数据也随之删除
emptyDir有两种类型,default(默认不需要指定)和Memory,使用Memory需设置sizeLimit参数限制内存使用大小,以防内存泄漏
默认default类型的emptyDir
示例1:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /cache
          name: cache-volume
      volumes:
      - name: cache-volume
        emptyDir: {}

Memory类型的emptyDir,pod内量容器共享emptyDir存储空间
示例2:

apiVersion: v1
kind: Pod
metadata:
  name: pods-with-emptydir-vol
spec:
  containers:
  - image: ikubernetes/admin-box:v1.2
    name: admin
    command: ["/bin/sh", "-c"]
    args: ["sleep 99999"]
    resources: {}
    volumeMounts:
    - name: data
      mountPath: /data
  - image: ikubernetes/demoapp:v1.0
    name: demoapp
    resources: {}
    volumeMounts:
    - name: data
      mountPath: /var/www/html
  volumes:
  - name: data
    emptyDir:
      medium: Memory
      sizeLimit: 16Mi
  restartPolicy: Always

2、hostPath存储卷

hostPath将主机节点的文件系统中的文件或目录挂载到集群中,pod删除,卷不会被删除
示例1:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /cache
          name: cache-volume
      volumes:
      - name: cache-volume
        hostPath:
          path: /tmp/hostDir

hostPath的类型,如果没目录会自动创建的示例,并绑定了pod可以调度的节点
示例2:

apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  nodeName:k8s-node01
  containers:
  - name: redis
    image: redis:7-alpine
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: redisdata
      mountPath: /data
  volumes:
  - name: redisdata
    hostPath:
      type: DirectoryOrCreate
      path: /data/redis

3、nfs共享存储

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /usr/share/nginx/html/mysite
          name: my-nfs-volume
      volumes:
      - name: my-nfs-volume
        nfs:
          server: 172.31.7.109
          path: /data/nfsdir

4、configMap

命令方式创建ConfigMap

字面量:kubectl create cm <name> --from-literal=key1=value1
从文件加载: kubectl create cm <name> --from-file=[key=]/Path/file
从目录加载: kubectl create cm <name> --from-file=/Path/DIR/

配置文件类型的configmap

# vim  nginx-config-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
 default: |
    server {
       listen       80;
       server_name  www.mysite.com;
       index        index.html index.php index.htm;

       location / {
           root /data/nginx/html;
           if (!-e $request_filename) {
               rewrite ^/(.*) /index.html last;
           }
       }
    }
# vim deploy-cm.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: nginx:1.20.0
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-config
          mountPath:  /etc/nginx/conf.d/mysite
      volumes:
      - name: nginx-config
        configMap:
          name: nginx-config
          items:
             - key: default
               path: mysite.conf

变量类型的configmap,配置值无法动态变更

# vim  nginx-config-env-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  username: "user1"
  password: "12345678"
# vim vim deploy-env-cm.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ng-deploy-80
  template:
    metadata:
      labels:
        app: ng-deploy-80
    spec:
      containers:
      - name: ng-deploy-80
        image: nginx
        env:
        - name: city
          value: hangzhou
        - name: MY_USERNAME
          valueFrom:
            configMapKeyRef:
              name: nginx-config
              key: username
              optional: true # 是否可选
        - name: MY_PASSWORD
          valueFrom:
            configMapKeyRef:
              name: nginx-config
              key: password
        ports:
        - containerPort: 80

5、secret

1、数据需要base64编码的secret

# secret对象定义,数据需要base64转码
# echo admin|base64;echo 123456 |base64
# vim secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret-data
type: Opaque
data:
  user: YWRtaW4K
  password: MTIzNDU2Cg==
# deploy使用sectet
# vim deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myserver-myapp-app1-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myserver-myapp-app1
  template:
    metadata:
      labels:
        app: myserver-myapp-app1
    spec:
      containers:
      - name: myserver-myapp-app1
        image: tomcat:7.0.94-alpine
        ports:
        - containerPort: 8080
        volumeMounts:
        - mountPath: /data/myserver/auth
          name: myserver-auth-secret
      volumes:
      - name: myserver-auth-secret
        secret:
          secretName: mysecret-data

2、数据不需要base64编码的secret

apiVersion: v1
kind: Secret
metadata:
  name: mysecret-stringdata
  namespace: myserver
type: Opaque
stringData:
  user: 'admin'
  password: '123456'

3、docker-register类型的secret

# 创建secret
kubectl create secret docker-registry keyName --docker-server=registry.myserver.com --docker-username=USER --docker-password=PASSWORD
# deploy内使用该证书
...
    spec:
      containers:
      - name: myserver-myapp-frontend
        image: registry.myserver.com/library/nginx:1.28.0
        ports:
          - containerPort: 80
      imagePullSecrets:
        - name: aliyun-registry-image-pull-key
...

pv/pvc存储卷

用于实现pod和后端存储的解耦,与nfs的区别在于,pv和pvc层面实现了对存储服务器的空间分配,存储的访问权限管理

Volume静态存储示例

1、pv资源定义

pv是集群级别的资源,无需定义namespace

apiVersion: v1
kind: PersistentVolume
metadata:
  name: myserver-myapp-static-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    path: /data/k8sdata
    server: 192.168.139.24

2、pvc资源定义

pvc为卷申请,后端需要跟pv绑定,pod通过挂载pvc并将数据存储在pvc关联的pv,pod需要与pvc在同一个namespace

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myserver-myapp-static-pvc
spec:
  volumeName: myserver-myapp-static-pv
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

3、deploy内使用pvc

kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    app: myserver-myapp
  name: myserver-myapp-deployment-name
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myserver-myapp-frontend
  template:
    metadata:
      labels:
        app: myserver-myapp-frontend
    spec:
      containers:
        - name: myserver-myapp-container
          image: nginx:1.20.0
          volumeMounts:
          - mountPath: "/usr/share/nginx/html/statics"
            name: statics-datadir
      volumes:
        - name: statics-datadir
          persistentVolumeClaim:
            claimName: myserver-myapp-static-pvc

Volume动态存储示例

通过storageClass动态创建pv来实现动态储存卷的定义,可参考如下项目(本文示例)
https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner
或者该项目
https://github.com/kubernetes-csi/csi-driver-nfs
部署步骤

1、提前准备好nfs服务
2、创建账号和NFS provisioner
3、创建storageclass
4、创建pvc
5、创建web服务挂载pvc

1、部署nfs服务

apt install nfs-common nfs-kernel-server
vim /etc/exports
/data/nfs *(rw,sync,no_root_squash,no_subtree_check)
exportfs -r
exportfs -v # 查看是否生效
# 可以到其他节点执行挂载命令,看是否可以正常挂载
mount -t nfs  192.168.139.24:/data/nfs /data/nfs
生效即可取消挂载
umount /data/nfs

2、创建rbac权限账号与nfs-provisioner

# 下载权限账号文件
wget https://ghfast.top/https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner/blob/master/deploy/rbac.yaml
# 下载部署nfs
wget https://ghfast.top/https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner/blob/master/deploy/deployment.yaml
# 替换名称空间为nfs
NAMESPACE=nfs
sed -i'' "s/namespace:.*/namespace: $NAMESPACE/g" ./deploy/rbac.yaml ./deploy/deployment.yaml
# 将deployment.yaml文件内的nfs地址修改为真实的地址,示例如下
          env:
            - name: PROVISIONER_NAME
              value: k8s-sigs.io/nfs-subdir-external-provisioner
            - name: NFS_SERVER
              value: 192.168.139.24
            - name: NFS_PATH
              value: /data/nfs
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.139.24
            path: /data/nfs
# 部署rbac以及nfs-provisioner
kubectl create ns nfs
kubectl create -f rbac.yaml
kubectl create -f deployment.yaml

3、创建storageclass

# vim storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # or choose another name, must match deployment's env PROVISIONER_NAME'
reclaimPolicy: Retain #PV的删除策略,默认为delete,删除PV后立即删除NFS server的数据
mountOptions:
  - noresvport #告知NFS客户端在重新建立网络连接时,使用新的传输控制协议源端口
  - noatime #访问文件时不更新文件inode中的时间戳,高并发环境可提高性能
parameters:
  mountOptions: "noresvport,noatime"
  archiveOnDelete: "true"  #删除pod时保留pod数据,默认为false时为不保留数据
# 部署storageclass
kubectl apply -f storageclass.yaml
kubectl get storageclass

4、创建pvc

# vim mypvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: myserver-myapp-dynamic-pvc
spec:
  storageClassName: managed-nfs-storage #调用的storageclass 名称
  accessModes:
    - ReadWriteMany #访问权限
  resources:
    requests:
      storage: 500Mi #空间大小
# 部署pvc
kubectl apply -f mypvc.yaml
kubectl get pvc  # status字段为Bound即为正常状态

5、创建web服务挂载pvc

# vim deploy-nfs.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    app: myserver-myapp
  name: myserver-myapp-deployment-name
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myserver-myapp-frontend
  template:
    metadata:
      labels:
        app: myserver-myapp-frontend
    spec:
      containers:
        - name: myserver-myapp-container
          image: nginx:1.28.0
          volumeMounts:
          - mountPath: "/usr/share/nginx/html/statics"
            name: statics-datadir
      volumes:
        - name: statics-datadir
          persistentVolumeClaim:
            claimName: myserver-myapp-dynamic-pvc
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: myserver-myapp-service
  name: myserver-myapp-service-name
  namespace: myserver
spec:
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30080
  selector:
    app: myserver-myapp-frontend

# 部署应用
Kubectl apply -f deploy-nfs.yaml
# 此时可以将文件上传到容器内的/usr/share/nginx/html/statics/目录下测试是否可以访问了
作者:于浩  创建时间:2025-06-05 14:00
最后编辑:于浩  更新时间:2025-06-10 18:08