暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

k8s之PV、PVC静态供给

云原生小记 2020-03-17
1631

k8s之PV、PVC存储静态供给


注意:定义PV的时候一定不要指明命名空间。和namespace一样,PV也是集群级别的,属于集群,不属于命名空间。所有的命名空间都可以用。但是PVC是属于命名空间级别的。Pod,Service属于命名空间中,所以需要定义。


温馨提示:pvc声明的容量大于PV的容量的话是无法进行绑定的


持久化存储

Volume 共享存储原理:

Kubernetes为了能更好的支持有状态应用的数据存储问题,除了基本的HostPath和EmptyDir提供的数据持久化方案之外,还提供了PV,PVC和StorageClass资源对象来对存储进行管理。

Kubernetes对于有状态的容器应用或者对数据需要持久化的应用,不仅需要将容器内的目录挂载到宿主机的目录或者emptyDir临时存储卷,而且需要更加可靠的存储来保存应用产生的重要数据,以便容器应用在重建之后,仍然可以使用之前的数据。不过,存储资源和计算资源(CPU/内存)的管理方式完全不同。为了能够屏蔽底层存储实现的细节,让用户方便使用,同时能让管理员方便管理,Kubernetes从v1.0版本就引入了PersistentVolume和PersistentVolumeClain两个资源对象来实现对存储的管理子系统

  • PV全称是Persisten Volume (持久化卷):是对底层网络存储的抽象,将共享存储定义为一种“资源”,比如节点(Node)也是一种容器应用可以“消费”的资源。PV由管理员进行创建和配置,它与共享存储的具体实现直接相关,例如GlusterFs、iSCSI、RBD或GCE/AWS公有云提供的共享存储,通过插件式的机制完成与共享存储的对接,以供应用访问和使用
  • PVC全称是PersistentVolumeClaim (持久化卷声明):是用户对于存储资源的一个“申请”。就像Pod “消费” Node的资源是一样的,PVC会消费PV的资源。PVC可以申请特定的存储空间和访问模式。

使用PVC“申请”到一定的存储空间仍然不足以满足应用对于存储设备的各种需求。通常应用程序都会对存储设备的特性和性能有不同的要求,包括读写速度、并发性能、数据冗余
等更高的要求。


PV详解

Volume是定义在Pod上的,属于"计算资源"的一部分,而实际上"网络存储"是相对独立于"计算资源"而存在的一种实体资源

1、PV只是网络存储,不属于任何Node,但可以在每个Node上访问 2、PV并不是定义在Pod上,而是独立于Pod之外的定义

PV作为存储资源,主要包括存储能力、访问模式、存储类型、回收策略、后端存储类型
等关键信息的设置。

PV和PVC的生命周期

image

这里采用NFS作为后端存储进行测试。安装NFS网络文件系统可参考如下文章:NFS网络文件系统介绍及部署


创建一个测试PV:pv1.yaml

apiVersion: v1
kind: PersistentVolume #指定类型为PV
metadata:
name: pv0001 #设置PV名字
spec:
capacity: #存储能力,持久卷资源和容量的描述,存储大小是唯一可设置或请求的资源。
storage: 5Gi #设置存储空间大小
accessModes: # 访问模式
- ReadWriteMany #设置访问模式,读写权限,可以被多个节点挂载
persistentVolumeReclaimPolicy: Recycle #回收策略。类似rm -rf
storageClassName:slow #存储类别,速率快慢
nfs:
path: "/data/disk1" #设置挂载点
server: 192.168.2.201 #指定NFS地址
readOnly: false #是否为只读

字段解释:

  • metadata:name              设置PV的名称
  • spec:capacity:storage      设置存储空间大小
  • spec:accessModes           设置访问模式
  • storageClassName           存储类别
  • persistentVolumeReclaimPolicy  回收策略(Reclaim Policy)
  • nfs                        NFS相关设置

Reclaim Policy (回收策略):
目前支持如下三种回收策略:

  • 保留 (Retain) 保留数据,需要手工处理
  • 回收空间 (Recycle) 简单清除文件的操作 (例如执行rm -rf /allenjol/* 命令)
  • 删除 (Delete) 与PV相连的后端存储完成volume的删除操作 (如AWS EBS、GCE PD、Azure Disk、Openstack Cinder等设备的内部volume清理)

AccessModes(访问模式):
只要资源提供者支持,持久卷能够被用任何方式加载到主机上。每种存储都会有不同的能力,每个 PV 的访问模式也会被设置成为该卷所支持的特定模式。例如 NFS 能够支持多个读写客户端,但是某个 NFS PV 可能会在服务器上以只读方式使用。每个 PV 都有自己的一系列的访问模式,这些访问模式取决于 PV 的能力。

PV和PVC是一 一对应的关系。一旦某个PV被PVC占用了他就会显示Bounding状态。就不可能被其他pvc占用。但是PVC相当于存储卷,却可以被多个Pod访问。PVC是否能被多个Pod访问需要定义被访问的模式accessMOde。

三种访问模式:

  • ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载
  • ReadOnlyMany(ROX):只读权限,可以被多个节点挂载
  • ReadWriteMany(RWX):读写权限,可以被多个节点挂载

以上三种访问模式NFS类型都支持。

温馨提示:一个卷不论支持多少种访问模式,同时只能以一种访问模式加载。例如一个 GCEPersistentDisk 既能支持 ReadWriteOnce ,也能支持 ReadOnlyMany。


PV常见状态:

  • Available(可用) :空闲状态
  • Bound(已绑定):已经绑定到某个PVC
  • Released(已释放):对应的PVC已经删除,但资源还没有被集群收回
  • Failed(失败):PV自动回收失败

PVC例子

PersistentVolumeClaim (PVC)
是用户的一个请求。他跟 Pod 类似。Pod 消费 Node 的资源,PVC 消费 PV 的资源。Pod 能够申请特定的资源(CPU 和 内存);Claim 能够请求特定的尺寸和访问模式(例如可以加载一个读写,以及多个只读实例) 如果某个Pod想申请某种类型的PV,则需要定义一个PersistentVolumeClaim(PVC) PVC作为用户对存储资源的需求申请,主要包括存储空间请求、访问模式、PV选择条件和存储类别等信息的设置。帮助文档可以通过命令行kubectl explain pvc来查看。

1. 创建PVC:pvc1.yaml

apiVersion: v1
kind: PersistentVolumeClaim # 指定类型为PVC
metadata:
name: myclaim
spec:
accessModes: # 主要定义卷所应该拥有的访问模式
- ReadWriteOnce # 设置访问模式为单节点读写权限
resources: # 定义卷应该拥有的最小资源
requests:
storage: 10Gi # 申请10Gi的存储空间。带i的是以1024来定义的。不带i的是以1000来定义的

2. 在Pod中引用PVC:pvctest.yaml

kind: Pod
apiVersion: v1
metadata:
name: pvctest-pod
spec:
containers:
- name: my-pvc-frontend
image: nginx:1.12
volumeMounts: #Volume配置
- mountPath: "/var/www/html" # 挂载到容器中的目录
name: pvctest-pod
volumes:
- name: pvctest-pod
persistentVolumeClaim:
claimName: myclaim #引用的名字一定要和上面创建的pvc名字相同

删除PVC

删除PVC之前必须先删除已经使用了该PVC的POD。

  • 创建的顺序:NFS---PV---PVC---POD
  • 删除的顺序:POD---PVC---PV

创建两个测试pv和两个pvc:


[root@k8s-master mainfests]# kubectl get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pv1 1Gi RWO Recycle Bound default/pvc-nfs 90m
persistentvolume/pv2-nfs 2Gi RWO Recycle Bound default/pvc2-nfs 60m

NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/pvc-nfs Bound pv1 1Gi RWO 77m
persistentvolumeclaim/pvc2-nfs Bound pv2-nfs 2Gi RWO


下面describe pvc 以后发现该PVC已经被nfs-pvc的pod挂载使用


[root@k8s-master mainfests]# kubectl describe pvc pvc2-nfs
Name: pvc2-nfs
Namespace: default
StorageClass:
Status: Bound
Volume: pv2-nfs
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"PersistentVolumeClaim","metadata":{"annotations":{},"name":"pvc2-nfs","namespace":"default"},"spec":{"accessMod...
pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 2Gi
Access Modes: RWO
VolumeMode: Filesystem
Mounted By: nfs-pvc-5ffcf8c95-cxzg6
nfs-pvc-5ffcf8c95-ff9mk
nfs-pvc-5ffcf8c95-zptgt
Events: <none>
[root@k8s-master mainfests]# kubectl get po
NAME READY STATUS RESTARTS AGE
nfs-pvc-5ffcf8c95-cxzg6 1/1 Running 0 57m
nfs-pvc-5ffcf8c95-ff9mk 1/1 Running 0 57m
nfs-pvc-5ffcf8c95-zptgt 1/1 Running 0 57m
[root@k8s-master mainfests]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nfs-pvc 3/3 3 3 58m

下面删除pvc2和pv2


# 删除deploy同时会发现pod已经被删除掉
[root@k8s-master mainfests]# kubectl delete deploy nfs-pvc
deployment.extensions "nfs-pvc" deleted

[root@k8s-master mainfests]# kubectl get po
No resources found.

# 接下来删除pvc2-nfs和pv2-nfs
[root@k8s-master mainfests]# kubectl delete pvc pvc2-nfs
persistentvolumeclaim "pvc2-nfs" deleted
[root@k8s-master mainfests]# kubectl delete pv pv2-nfs
persistentvolume "pv2-nfs" deleted

# 查看pv,pvc发现已经被成功删除
[root@k8s-master mainfests]# kubectl get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pv1 1Gi RWO Recycle Bound default/pvc-nfs 95m

NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/pvc-nfs Bound pv1 1Gi RWO 81m

贴出一个deployment测试使用PVC例子

    vim nfs-pvc-deploy.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nfs-pvc
spec:
replicas: 3
template:
metadata:
labels:
app: nfs-pvc
spec:
containers:
- name: nginx
image: nginx:1.12.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumes:
- name: www
persistentVolumeClaim:
claimName: pvc2-nfs

---

apiVersion: v1
kind: Service
metadata:
name: nfs-pvc
labels:
app: nfs-pvc
spec:
type: NodePort
ports:
- port: 80
targetPort: web
selector:
app: nfs-pvc

查看Pod和svc

    [root@k8s-master storageclass]# kubectl get po,svc -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nfs-pvc-955c4c849-7hfwb 1/1 Running 0 4m54s 172.20.2.7 192.168.2.221 <none> <none>
pod/nfs-pvc-955c4c849-8wptd 1/1 Running 0 4m54s 172.20.1.6 192.168.2.220 <none> <none>
pod/nfs-pvc-955c4c849-lxg44 1/1 Running 0 4m54s 172.20.1.5 192.168.2.220 <none> <none>

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.68.0.1 <none> 443/TCP 153d <none>
service/nfs-pvc NodePort 10.68.76.60 <none> 80:27005/TCP 4m54s app=nfs-pvc

我们把容器目录/user/share/nginx/html和挂载到了pvc2-nfs这个 PVC 上面,这个 PVC 就是对应着我们上面的 nfs 的共享数据目录的,该目录下面还没有任何数据,所以现在直接通过node节点的ip:port访问是会出现403的情况。现在我们在/data/k8s这个目录下面新建一个 index.html 的文件。

echo "<h1>Hello Kubernetes~</h1>" >> /data/k8s/index.html

浏览器访问:192.168.2.220:27005

image

但是当前容器中的数据是直接放到共享数据目录根目录下面的,如果以后我们又有一个新的 nginx 容器也做了数据目录的挂载就会出现冲突的情况。这个时候就不太好区分了,这个时候我们可以在 Pod 中使用一个新的属性:subPath,该属性可以来解决这个问题,我们只需要更改上面的 Pod 的 YAML 文件即可:

...
volumeMounts:
- name: www
subPath: nginxpvc-test
mountPath: /usr/share/nginx/html
...

然后将刚才的index.html文件放到/data/k8s/nginxpvc-test/下这时候能正常访问到数据了

    mv /data/k8s/index.html /data/k8s/nginxpvc-test/

# 更新更改过后的deployment文件
kubectl apply -f nfs-pvc-deploy.yaml

测试数据是否会丢失 删除deployment,这时候pod都会被删除,然后查看subpath目录下的数据是否存在。可以看到数据是存在的

    [root@k8s-master storageclass]# kubectl delete deployment nfs-pvc
deployment.extensions "nfs-pvc" deleted
[root@k8s-master storageclass]# ll /data/k8s/nginxpvc-test/
total 4
-rw-r--r-- 1 root root 27 Feb 25 11:05 index.html

这时候如果删除了与改pvc绑定的pod,并且删除pvc这时候pv会被释放

$ kubectl delete -f nfs-pvc-deploy.yaml
deployment.extensions "nfs-pvc" deleted
service "nfs-pvc" deleted
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
...
pvc2-nfs Bound pv2-nfs 2Gi RWO 5m
...
$ kubectl delete pvc pvc2-nfs
persistentvolumeclaim "pvc2-nfs" deleted
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
...
pv2-nfs 2Gi RWO Recycle Released default/pvc2-nfs 6m
...
$ ls /data/k8s/

释放后变成了 Released 状态,表示 PVC 已经被释放了,现在可以被重新绑定了,由于我们设置的 PV 的回收策略是 Recycle,所以我们可以很明显的发现 nfs 的共享数据目录下面已经没有了数据了,这是因为我们把 PVC 给删除掉了,然后回收了数据。

------------------------------------------------------

公众号:竹下侯小姜运维

个人博客:https://www.ayunw.cn

重要的事情认真做,普通的事情规范做!

------------------------------------------------------

不定期更新优质内容,技术干货!如果觉得对你有帮助,请扫描下方二维码关注!

温馨提示

如果你喜欢本文,请分享到朋友圈,想要获得更多信息,请关注我



文章转载自云原生小记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论