缘由

在看statefluset基础教程的时候遇到pod状态为pending

kubectl describe pod web-0

日志内容是

 pod has unbound immediate PersistentVolumeClaims

于是就对PV和PVC进行研究。
有给出完整的 web.yaml查看最下面的完整示例。但是我建议先把PV和PVC的概念弄懂了,还有学会查看pod的描述kubectl describe pod podname或者日志kubectl logs -f podname,自然知晓怎么处理pod的状态为pending的问题了。

PV

PersistentVolume(PV)是集群之中的一块网络存储。跟 Node 一样,也是集群的资源。PV 跟 Volume (卷) 类似,不过会有独立于 Pod 的生命周期。比如一个 NFS 的 PV 可以定义为

apiVersion: v1
kind: PersistentVolume
metadata:
  name: "www-data-pv"
  labels:
    name: www-data-pv
    release: stable
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /nfs/www/data
    server: 192.168.84.75

PV 的访问模式(accessModes)有三种:

  • ReadWriteOnce(RWO):是最基本的方式,可读可写,但只支持被单个节点挂载。- ReadOnlyMany(ROX):可以以只读的方式被多个节点挂载。- ReadWriteMany(RWX):这种存储可以以读写的方式被多个节点共享。不是每一种存储都支持这三种方式,像共享方式,目前支持的还比较少,比较常用的是 NFS。在 PVC 绑定 PV 时通常根据两个条件来绑定,一个是存储的大小,另一个就是访问模式。 PV 的回收策略(persistentVolumeReclaimPolicy,即 PVC 释放卷的时候 PV 该如何操作)也有三种
  • Retain,不清理, 保留 Volume(需要手动清理)- Recycle,删除数据,即rm -rf /thevolume/*(只有 NFS 和 HostPath 支持)- Delete,删除存储资源,比如删除 AWS EBS 卷(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支持)

PVC

PV 是存储资源,而 PersistentVolumeClaim (PVC) 是对 PV 的请求。PVC 跟 Pod 类似:Pod 消费 Node 资源,而 PVC 消费 PV 资源;Pod 能够请求 CPU 和内存资源,而 PVC 请求特定大小和访问模式的数据卷。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: www-data-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  selector:
    matchLabels:
      name: www-data-pv
      release: stable

PVC 可以直接挂载到 Pod/StatefulSet 中:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80
              name: web
          volumeMounts:
            - name: www
              mountPath: /usr/share/nginx/html
      volumes:
        - name: www
          persistentVolumeClaim:
            claimName:  www-data-pvc

完整示例

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
    - port: 80
      name: web
  clusterIP: None
  selector:
    app: nginx

---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: "www-data-pv"
  labels:
    name: www-data-pv
    release: stable
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /nfs/www/data
    server: 192.168.84.75

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: www-data-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  selector:
    matchLabels:
      name: www-data-pv
      release: stable

---

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80
              name: web
          volumeMounts:
            - name: www
              mountPath: /usr/share/nginx/html
      volumes:
        - name: www
          persistentVolumeClaim:
            claimName:  www-data-pvc

nfs是需要另外安装的

sudo apt install nfs-kernel-server

需要手动创建一个NFS Volume,具体细节看这里:nfs的安装和使用

StorageClass

上面通过手动的方式创建了一个 NFS Volume,这在管理很多 Volume 的时候不太方便。Kubernetes 还提供了StorageClass来动态创建 PV,不仅节省了管理员的时间,还可以封装不同类型的存储供 PVC 选用。

StorageClass 包括四个部分

  • provisioner:指定 Volume 插件的类型,包括内置插件(如kubernetes.io/glusterfs)和外部插件(如external-storage提供的ceph.com/cephfs)。- mountOptions:指定挂载选项,当 PV 不支持指定的选项时会直接失败。比如 NFS 支持hardnfsvers=4.1等选项。- parameters:指定 provisioner 的选项,比如kubernetes.io/aws-ebs支持typezoneiopsPerGB等参数。- reclaimPolicy:指定回收策略,同 PV 的回收策略。 在使用 PVC 时,可以通过DefaultStorageClass准入控制设置默认 StorageClass, 即给未设置 storageClassName 的 PVC 自动添加默认的 StorageClass。而默认的 StorageClass 带有 annotationstorageclass.kubernetes.io/is-default-class=true

技巧:Kuberntes 中无法删除 PV 的解决方法

系统内有一个已经不再使用的 PV ,已经删除了与其关联的 Pod 及 PVC ,并对其执行了删除命令,但是无法正常删除,一直出于如下状态:

$ kubectl get pv
NAME          CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS        CLAIM                                    STORAGECLASS          REASON   AGE
pv-nfs-gysl   1Gi        RWO            Recycle          Terminating   default/www-vct-statefulset-pvc-gysl-0   managed-nfs-storage            22h

解决方法

$ kubectl patch pv pv-nfs-gysl -p '{"metadata":{"finalizers":null}}'
persistentvolume/pv-nfs-gysl patched
$ kubectl get pv
No resources found.

通过系统帮助信息,我们可以获取patch的简要使用说明:

patch: 使用 strategic merge patch 更新一个资源的 field(s)

--完--