Kubernetes

Kubernetes Volume(持久化卷)

Posted on 2020-10-12,8 min read

Persistent Volume(持久化卷)简称PV, 是一个K8S资源对象,我们可以单独创建一个PV, 它不和Pod直接发生关系, 而是通过Persistent Volume Claim, 简称PVC来实现动态绑定, 我们会在Pod定义里指定创建好的PVC, 然后PVC会根据Pod的要求去自动绑定合适的PV给Pod使用.

持久化卷下PV和PVC概念:

Persistent Volume(PV)是由管理员设置的存储,它是群集的一部分。就像节点是集群中的资源一样,PV 也是集群中的资源。 PV 是 Volume 之类的卷插件,但具有独立于使用 PV 的 Pod 的生命周期。此 API 对象包含存储实现的细节,即 NFS、iSCSI 或特定于云供应商的存储系统

PersistentVolumeClaim(PVC)是用户存储的请求。它与 Pod 相似。Pod 消耗节点资源,PVC 消耗 PV 资源。Pod 可以请求特定级别的资源(CPU 和内存)。PVC声明可以请求特定的大小和访问模式(例如,可以以读/写一次或 只读多次模式挂载)

它和普通Volume的区别是什么呢?

普通Volume和使用它的Pod之间是一种静态绑定关系,在定义Pod的文件里,同时定义了它使用的Volume。Volume是Pod的附属品,我们无法单独创建一个Volume,因为它不是一个独立的K8S资源对象。

如何简单理解持久化卷?

我们需要首先创建一个独立的持久化卷(PV)资源对象, 然后创建一个与PV绑定的PVC存储请求, 这个请求会事先定义accessModes, resources等资源配置, 最终我们会在Pod中挂载定义好的PVC以供我们数据存储使用

一. NFS安装配置

我们这里利用NFS去实现k8s持久化卷的配置

1,安装NFS server

# yum install nfs-utils -y

2.启动NFS服务

# systemctl enable nfs-server
# systemctl start nfs-server

3.配置NFS共享目录

# mkdir /srv/pv-demo
# chown nfsnobody:nfsnobody /srv/pv-demo
# chmod 755 /srv/pv-demo
# echo -e "/srv/pv-demo  kube-master(rw,sync)" > /etc/export

4.生效共享目录

# exportfs -a

因为资源有限, 我们最终在Master上创建一个NFS共享目录/srv/pv-demo, 以供我们后面的持久化卷使用, 有富裕的小伙伴可以创建一台与kube-master同一网段的独立server去充当NFS服务器,

二. Persistent Volume配置

1.创建Persistent Volume

# vi pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-demo
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /srv/pv-demo
    server: kube-master

Tip: 这里的定义卷的大小为5G, 使用的accessmodes为ReadWriteOnce, PVC policy为Recycle, NFS共享目录为我们之前在master创建好的/srv/pv-demo, server为我们定义好的本地host kube-master

# kubectl create -f pv.yaml

  1. 查看PV

# kubectl get pv pv-demo

NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM              STORAGECLASS   REASON    AGE
pv-demo   5Gi        RWO            Recycle          Bound     default/pvc-demo                            1h

3.创建Persistent Volume Claim

Tip: 这里PVC可以理解为在PV请求的资源, 也就是说所有我们的数据都会保存在PVC里, 任何PVC的删除操作都会清除我们存储在这里的数据.

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pvc-demo
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi

# kubectl create -f pvc.yaml

4.查看PVC

# kubectl get pvc pvc-demo

NAME       STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc-demo   Bound     pv-demo   5Gi        RWO                           1h

5.创建一个Pod并使用该PVC

# vi pvpod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: httpd-pod
spec:
  containers:
  - image: httpd
    name: httpd-pod
    imagePullPolicy: Always
    volumeMounts:
    - mountPath: "/usr/local/apache2/htdocs/"
      name: httpd-volume
  volumes:
    - name: httpd-volume
      persistentVolumeClaim:
        claimName: pvc-demo

Tip: 这里需要保证claimName的值与我们之前创建的PVC name一致.

# kubectl create -f pvpod.yaml

Tip: 这里我们将PVC挂载到Pod的Apache根目录"/usr/local/apache2/htdocs/", 用来最终测试效果.

  1. 查看Pod是否挂载PVC

# kubectl describe pv

Name:            pv-demo
Labels:          <none>
Annotations:     pv.kubernetes.io/bound-by-controller=yes
StorageClass:
Status:          Bound
Claim:           default/pvc-demo
Reclaim Policy:  Recycle
Access Modes:    RWO
Capacity:        5Gi
Message:
Source:
    Type:      NFS (an NFS mount that lasts the lifetime of a pod)
    Server:    kube-master
    Path:      /srv/pv-demo
    ReadOnly:  false
Events:        <none>

# kubectl describe pods

Name:         httpd-pod
Namespace:    default
Node:         kube-master/172.17.2.153
Start Time:   Fri, 23 Feb 2018 15:38:55 +0800
Labels:       <none>
Annotations:  <none>
Status:       Running
IP:           10.244.0.46
Containers:
  httpd-pod:
    Container ID:   docker://b7e5fd2732864934b732fdbd4bb24b3ccc8949c2e9d8832a36e271f2ee350b2b
    Image:          httpd
    Image ID:       docker-pullable://httpd@sha256:6e61d60e4142ea44e8e69b22f1e739d89e1dc8a2764182d7eecc83a5bb31181e
    Port:           <none>
    State:          Running
      Started:      Fri, 23 Feb 2018 15:38:59 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /usr/local/apache2/htdocs from httpd-volume (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-bnkxx (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  httpd-volume:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  pvc-demo
    ReadOnly:   false
  default-token-bnkxx:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-bnkxx
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From                  Message
  ----    ------                 ----  ----                  -------
  Normal  Scheduled              58m   default-scheduler     Successfully assigned httpd-pod to kube-master
  Normal  SuccessfulMountVolume  58m   kubelet, kube-master  MountVolume.SetUp succeeded for volume "default-token-bnkxx"
  Normal  SuccessfulMountVolume  58m   kubelet, kube-master  MountVolume.SetUp succeeded for volume "pv-demo"
  Normal  Pulling                58m   kubelet, kube-master  pulling image "httpd"
  Normal  Pulled                 58m   kubelet, kube-master  Successfully pulled image "httpd"
  Normal  Created                58m   kubelet, kube-master  Created container
  Normal  Started                58m   kubelet, kube-master  Started container

通过返回打印的信息我们可以看到PVC已经成功mount到我们定义好的Pod的apache根目录下

  1. 向Pod下apache根目录写入index.html

# kubectl exec -ti httpd-pod -- /bin/sh -c "echo 'This is a persistent volume from httpd-pod' > /usr/local/apache2/htdocs/index.html"

8.确认文件写入

# kubectl exec -ti httpd-pod -- cat /usr/local/apache2/htdocs/index.html

This is a persistent volume from httpd-pod
  1. 删除并重新创建Pod来验证数据是否会随Pod销毁而丢失.

# kubectl delete pod httpd-pod
# kubectl create -f pvpod.yaml
# kubectl exec -ti httpd-pod -- cat /usr/local/apache2/htdocs/index.html

This is a persistent volume from httpd-pod

可以看到我们之前写入的index.html仍旧存储在PVC中, 证明其不会随Pod销毁而丢失.

10.查看Pod内网IP

# kubectl get pods -o wide

NAME        READY     STATUS    RESTARTS   AGE       IP            NODE
httpd-pod   1/1       Running   0          1m        10.244.0.46   kube-master

11.利用curl验证写入的index.html

# curl 10.244.0.46

This is a persistent volume from httpd-pod

这里我们成功在Pod下将PVC挂载到apache的家目录, 并返回HTML返回内容.

下一篇: 基于kubekey部署kubernetes生产级集群→