# K8s 持久化存储

# 1. Volume

Container(容器)中的磁盘文件是短暂的,当容器崩溃时,kubelet 会重新启动容器,Container 会以最干净的状态启动,最初的文件将丢失。另外,当一个 Pod 运行多个 Container 时,各个容器可能需要共享一些文件。Kubernetes Volume 可以解决这两个问题。

  • 一些需要持久化数据的程序才会用到 Volumes,或者一些需要共享数据的容器需要 volumes。
  • 日志收集的需求需要在应用程序的容器里面加一个 sidecar,这个容器是一个收集日志的容器,比如 filebeat,它通过 volumes 共享应用程序的日志文件目录。
# 1.1 EmptyDir 实现数据共享

和上述 volume 不同的是,如果删除 Pod,emptyDir 卷中的数据也将被删除,一般 emptyDir 卷用于 Pod 中的不同 Container 共享数据。

# cat nginx-deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    app: nginx-deploy
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx-deploy
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx-deploy
    spec:
      restartPolicy: Always
      volumes:
        - name: share-volume
          emptyDir: {}
      containers:
        - name: nginx
          image: nginx:latest
          imagePullPolicy: IfNotPresent
          resources:
            limits:
              memory: 1024Mi
              cpu: 1
            requests:
              memory: 128Mi
              cpu: 100m
          volumeMounts:
            - name: share-volume
              mountPath: /opt
        - name: nginx2
          image: nginx:latest
          imagePullPolicy: IfNotPresent
          resources:
            limits:
              memory: 1024Mi
              cpu: 1
            requests:
              memory: 128Mi
              cpu: 100m
          command:
            - sh
            - '-c'
            - sleep 3600
          volumeMounts:
            - name: share-volume
              mountPath: /mnt
# 1.2 Volumes HostPath 挂载宿主机路径

hostPath 卷可将节点上的文件或目录挂载到 Pod 上,用于 Pod 自定义日志输出或访问 Docker 内部的容器等。

[root@k8s-master01 ~]# cat nginx-deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    app: nginx-deploy
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx-deploy
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx-deploy
    spec:
      restartPolicy: Always
      volumes:
      - name: share-volume
        emptyDir: {}
      - name: tz-config
        hostPath:
          path: /usr/share/zoneinfo/Asia/Shanghai
          type: ""
      - name: timezone
        hostPath:
          path: /etc/timezone
          type: ""
      containers:
        - name: nginx
          image: nginx:latest
          imagePullPolicy: IfNotPresent
          resources:
            limits:
              memory: 1024Mi
              cpu: 1
            requests:
              memory: 128Mi
              cpu: 100m
          volumeMounts:
          - name: share-volume
            mountPath: /opt
          - name: tz-config
            mountPath: /usr/share/zoneinfo/Asia/Shanghai
          - name: tz-config
            mountPath: /etc/localtime
          - name: timezone
            mountPath: /etc/timezone
        - name: nginx2
          image: nginx:latest
          imagePullPolicy: IfNotPresent
          resources:
            limits:
              memory: 1024Mi
              cpu: 1
            requests:
              memory: 128Mi
              cpu: 100m
          command:
            - sh
            - '-c'
            - sleep 3600
          volumeMounts:
          - name: share-volume
            mountPath: /mnt

hostPath 卷常用的 type(类型)如下:

  • type 为空字符串:默认选项,意味着挂载 hostPath 卷之前不会执行任何检查。
  • DirectoryOrCreate:如果给定的 path 不存在任何东西,那么将根据需要创建一个权限为 0755 的空目录,和 Kubelet 具有相同的组和权限。
  • Directory:目录必须存在于给定的路径下。
  • FileOrCreate:如果给定的路径不存储任何内容,则会根据需要创建一个空文件,权限设置为 0644,和 Kubelet 具有相同的组和所有权。
  • File:文件,必须存在于给定路径中。
  • Socket:UNIX 套接字,必须存在于给定路径中。
  • CharDevice:字符设备,必须存在于给定路径中。
  • BlockDevice:块设备,必须存在于给定路径中。
# 1.3 挂载 NFS 至容器
#1.安装nfs
# yum install nfs-utils -y       
# mkdir /data/nfs -p
# vim /etc/exports 
/data 192.168.1.0/24(rw,no_root_squash)
# exportfs -arv   
# systemctl start nfs-server && systemctl enable nfs-server && systemctl status nfs-server 

#2.测试客户端挂载
# showmount -e 192.168.1.75
# mount -t nfs 192.168.1.75:/data/nfs /mnt

#3.Deploy挂载NFS
[root@k8s-master01 ~]# cat nginx-deploy-nfs.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    app: nginx-deploy
  annotations:
    app: nginx-deploy
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx-deploy
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx-deploy
      annotations:
        app: nginx-deploy
    spec:
      restartPolicy: Always
      volumes:
      - name: nfs-volume
        nfs:
          server: 192.168.1.75
          path: /data/nfs
      - name: tz-config
        hostPath:
          path: /usr/share/zoneinfo/Asia/Shanghai
          type: ""
      - name: timezone
        hostPath:
          path: /etc/timezone
          type: ""
      containers:
        - name: nginx-deploy
          image: nginx:latest
          imagePullPolicy: IfNotPresent
          resources:
            limits:
              memory: 1024Mi
              cpu: 1
            requests:
              memory: 128Mi
              cpu: 100m
          volumeMounts:
          - name: nfs-volume
            mountPath: /usr/share/nginx/html
          - name: tz-config
            mountPath: /usr/share/zoneinfo/Asia/Shanghai
          - name: tz-config
            mountPath: /etc/localtime
          - name: timezone
            mountPath: /etc/timezone

# 2. PV、PVC

PersistentVolume:简称 PV,是由 Kubernetes 管理员设置的存储,可以配置 Ceph、NFS、GlusterFS 等常用存储配置,相对于 Volume 配置,提供了更多的功能,比如生命周期的管理、大小的限制。PV 分为静态和动态。

PersistentVolumeClaim:简称 PVC,是对存储 PV 的请求,表示需要什么类型的 PV,需要存储的技术人员只需要配置 PVC 即可使用存储,或者 Volume 配置 PVC 的名称即可。

# 2.1 PV 回收策略
  • Retain:保留,该策略允许手动回收资源,当删除 PVC 时,PV 仍然存在,PV 被视为已释放,管理员可以手动回收卷。
  • Recycle:回收,如果 Volume 插件支持,Recycle 策略会对卷执行 rm -rf 清理该 PV,并使其可用于下一个新的 PVC,但是本策略将来会被弃用,目前只有 NFS 和 HostPath 支持该策略。
  • Delete:删除,如果 Volume 插件支持,删除 PVC 时会同时删除 PV,动态卷默认为 Delete,目前支持 Delete 的存储后端包括 AWS EBS, GCE PD, Azure Disk, or OpenStack Cinder 等。
  • 可以通过 persistentVolumeReclaimPolicy: Recycle 字段配置
# 2.2 PV 访问策略
  • ReadWriteOnce:可以被单节点以读写模式挂载,命令行中可以被缩写为 RWO。
  • ReadOnlyMany:可以被多个节点以只读模式挂载,命令行中可以被缩写为 ROX。
  • ReadWriteMany:可以被多个节点以读写模式挂载,命令行中可以被缩写为 RWX。
  • ReadWriteOncePod :只允许被单个 Pod 访问,需要 K8s 1.22 + 以上版本,并且是 CSI 创建的 PV 才可使用,缩写为 RWOP
Volume PluginReadWriteOnceReadOnlyManyReadWriteManyReadWriteOncePod
AzureFile-
CephFS-
CSIdepends on the driverdepends on the driverdepends on the driverdepends on the driver
FC--
FlexVolumedepends on the driver-
HostPath---
iSCSI--
NFS-
RBD--
VsphereVolume-- (works when Pods are collocated)-
PortworxVolume--
# 2.3 存储分类
  • 文件存储:一些数据可能需要被多个节点使用,比如用户的头像、用户上传的文件等,实现方式:NFS、NAS、FTP、CephFS 等。
  • 块存储:一些数据只能被一个节点使用,或者是需要将一块裸盘整个挂载使用,比如数据库、Redis 等,实现方式:Ceph、GlusterFS、公有云。
  • 对象存储:由程序代码直接实现的一种存储方式,云原生应用无状态化常用的实现方式,实现方式:一般是符合 S3 协议的云存储,比如 AWS 的 S3 存储、Minio、七牛云等。
# 2.4 PV 配置示例 NFS
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv1
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs-slow
  nfs:
    path: /data/pv1
    server: 192.168.1.75

capacity:容量配置

volumeMode:卷的模式,目前支持 Filesystem(文件系统) 和 Block(块),其中 Block 类型需要后端存储支持,默认为文件系统

accessModes:该 PV 的访问模式

storageClassName:PV 的类,一个特定类型的 PV 只能绑定到特定类别的 PVC;

persistentVolumeReclaimPolicy:回收策略

mountOptions:非必须,新版本中已弃用

nfs:NFS 服务配置,包括以下两个选项

  • path:NFS 上的共享目录
  • server:NFS 的 IP 地址
# 2.5 PV 配置示例 HostPath
apiVersion: v1
kind: PersistentVolume
metadata:
  name: hostpath
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: hostpath
  hostPath:
    path: "/mnt/data"

hostPath:hostPath 服务配置

  • path:宿主机路径
# 2.6 PV 的状态
  • Available:可用,没有被 PVC 绑定的空闲资源。
  • Bound:已绑定,已经被 PVC 绑定。
  • Released:已释放,PVC 被删除,但是资源还未被重新使用。
  • Failed:失败,自动回收失败。
# 2.7 PVC 绑定 PV
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  storageClassName: nfs-slow
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi      
  • PVC 的空间申请大小≤PV 的大小
  • PVC 的 StorageClassName 和 PV 的一致
  • PVC 的 accessModes 和 PV 的一致
# 2.8 Depoyment 挂载 PVC
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deploy
  name: nginx-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-deploy
  template:
    metadata:
      labels:
        app: nginx-deploy
    spec:
      volumes:
      - name: nfs-pvc-storage  #volume名称
        persistentVolumeClaim:
          claimName: nfs-pvc   #PVC名称
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
         - name: nfs-pvc-storage
          mountPath: /usr/share/nginx/html

挂载 PVC 的 Pod 一直处于 Pending:

  • PVC 没有创建成功或 PVC 不存在
  • PVC 和 Pod 不在同一个 Namespace

本文出自于:https://edu.51cto.com/course/23845.html

此文章已被阅读次数:正在加载...更新于

请我喝[茶]~( ̄▽ ̄)~*

Xu Yong 微信支付

微信支付

Xu Yong 支付宝

支付宝