要实现数据的持久存储,可以通过 PersistentVolumes 和 PersistentVolumeClaims 来保存数据。

PersistentVolume(PV)是一块集群里由管理员手动提供,或 kubernetes 通过 StorageClass 动态创建的存储。 PersistentVolumeClaim(PVC)是一个满足对 PV 存储需要的请求。PersistentVolumes 和 PersistentVolumeClaims 是独立于 Pod 生命周期而在 Pod 重启,重新调度甚至删除过程中保存数据。

img

PV

PV是Kubernetes集群中的一种网络存储实现,跟Node一样,也是属于集群的资源。 PV跟Docker里的Volume(卷)类似,不过会有独立于Pod的生命周期。 使用kubectl get pv查看列表:

$ kubectl get pv
NAME           CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                    STORAGECLASS   REASON   AGE
pvc-c115b166   20Gi       RWO            Delete           Bound    default/mysql-pv-claim   hostpath                14m

PVC

PVC是用户的一个请求,跟Pod类似。Pod消费Node的资源,PVC消费PV的资源

$ kubectl get pvc
NAME             STATUS   VOLUME         CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mysql-pv-claim   Bound    pvc-c115b166   20Gi       RWO            hostpath       18m

示例

apiVersion: v1
kind: Service
metadata:
  name: basic-mysql
  labels:
    app: basic
spec:
  ports:
    - port: 3306
  selector:
    app: basic
    tier: mysql
  type: LoadBalancer
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv-volume
  labels:
    app: basic
spec:
  storageClassName: mysql-storage
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 5Gi
  hostPath:
    path: "/d/dev/k8s/yaml/basic/data/mysql"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  labels:
    app: basic
spec:
  storageClassName: mysql-storage
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: basic-mysql
  labels:
    app: basic
spec:
  selector:
    matchLabels:
      app: basic
      tier: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: basic
        tier: mysql
    spec:
      containers:
      - image: mysql:8.0.26
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: liveapp3306
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: "/var/lib/mysql"
      volumes:
      - name: mysql-persistent-storage
        hostPath:
          path: /run/desktop/mnt/host/d/v/data/mysql
          type: DirectoryOrCreate

注意windows下需要添加/run/desktop/mnt/host为路径前缀,否则找不到地址

hostpath 支持的 type 值如下:

DirectoryOrCreate 如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 Kubelet 相同的组和所有权。 Directory 在给定路径上必须存在的目录。 FileOrCreate 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 Kubelet 相同的组和所有权。 File 在给定路径上必须存在的文件。 Socket 在给定路径上必须存在的 UNIX 套接字。 CharDevice 在给定路径上必须存在的字符设备。 BlockDevice 在给定路径上必须存在的块设备。

kubectl logs basic-mysql-7fc5c87587-5f44z
2022-02-12 09:26:44+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.26-1debian10 started.
find: '/var/lib/mysql/': Operation not permitted
chown: changing ownership of '/var/lib/mysql/': Operation not permitted

出现这个问题是由于 /var/lib/mysql/ 所映射的宿主机文件夹没有写权限

您正在直接在主节点上创建 docker 容器。因此,您可以使用新创建的目录运行 docker 容器。但是当您启动 kubernetes yaml 文件时,它打算在工作节点上运行。由于您在主节点上创建目录,kubelet 无法在工作节点上找到目录并且失败。这就是为什么类型标志上的“DirectoryorCreate”值是一种解决方案