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
- 查看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/", 用来最终测试效果.
- 查看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根目录下
- 向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
- 删除并重新创建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返回内容.