赞
踩
目录
四、基于动态 storageclass 创建 PV 与 PVC
K8S存储是通过 卷:Volumn
docker 目录结构:bootfs rootfs 镜像
容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet会重启它,但是容器中的文件将丢供—容器以干净的状态(镜像最初的状态〉重新启动。其次,在Pod中同时运行多个容器时,这些容器之间通常需要共享文件。Kubernetes 中的Volume抽象就很好的解决了这些问题。Pod中的容器通过Pause容器共享Volume。
K8s集群中的存储卷跟Docker的存储卷有些类似,只不过Docker的存储卷作用范围为一个容器,而K8s的存储卷的生命周期和作用范围是一个Pod。每个Pod中声明的存储卷由Pod中的所有容器共享。 K8s支持非常多的存储卷类型,特别的,支持多种公有云平台的存储,包括AWS, Google和Azure云;支持多种分布式存储包括GlusterFS和Ceph;也支持较容易使用的主机本地目录hostPath和NFS。 K8s还支持使用Persistent Volume Claim即PVC这种逻辑存储,使用这种存储,使得存储的使用者可以忽略后台的实际存储技术(例如AWS, Google或GlusterFS和Ceph),而将有关存储实际技术的配置交给存储管理员通过Persistent Volume来配置。
当Pod被分配给节点时,首先创建emptyDir卷,并且只要该Pod在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。Pod中的容器可以读取和写入emptyDir卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径上。当出于任何原因从节点中删除Pod 时,emptyDir中的数据将被永久删除。
随着pod 的诞生而诞生,pod 一被删除重建,emptyDir 存储卷 数据就会丢失。不是持久化存储到磁盘中的。
用处:pod 临时存储数据。
- mkdir /opt/volumes
- cd /opt/volumes
-
- vim pod-emptydir.yaml
-
- apiVersion: v1
- kind: Pod
- metadata:
- name: pod-emptydir
- namespace: default
- labels:
- app: myapp
- tier: frontend
- spec:
- containers:
- - name: myapp
- image: ikubernetes/myapp: v1
- imagePullPolicy: IfNotPresent
- ports:
- - name: http
- containerPort: 80 #定义容器挂载内容
- volumeMounts:
- #使用的存储卷名称,如果跟下面volume字段name值相同,则表示使用volume的这个存储卷
- - name: html
- #挂载至容器中哪个目录
- mountPath: /usr/share/nginx/html/
- - name:busybox
- image: busybox: latest
- imagePullPolicy: IfNotPresent
- volumeMounts:
- - name: html
- #在容器内定义挂载存储名称和挂载路径
- mountPath: /data/
- #每两秒往磁盘写时间信息
- command: [ '/bin/sh' , '-c' , 'while true;do echo $(date) >> /data/index.html;sleep 2;done']
- #定义存储卷
- volumes:
- #定义存储卷名称
- - name: html
- #定义存储卷类型
- emptyDir: {}
-
-
- apiVersion: v1
- kind: Pod
- metadata:
- name: pod-emptydir
- namespace: default
- labels:
- app: myapp
- tier: frontend
- spec:
- containers:
- - name: myapp
- image: ikubernetes/myapp:v1
- imagePullPolicy: IfNotPresent
- ports:
- - name: http
- containerPort: 80
- volumeMounts:
- - name: html
- mountPath: /usr/share/nginx/html/
- - name: busybox
- image: busybox:latest
- imagePullPolicy: IfNotPresent
- volumeMounts:
- - name: html
- mountPath: /data/
- command: ['sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done']
- volumes:
- - name: html
- emptyDir: {}

hostPath卷将 node 节点的文件系统中的文件或目录挂载到集群中。
hostPath可以实现持久存储,但是在node节点故障时,也会导致数据的丢失。
- //在 node01 节点上创建挂载目录
- mkdir -p /data/pod/volume1
- echo 'node01.kgc.com' > /data/pod/volume1/index.html
-
- //在 node02 节点上创建挂载目录
- mkdir -p /data/pod/volume1
- echo 'node02.kgc.com' > /data/pod/volume1/index.html
-
- //创建 Pod 资源
- vim pod-hostpath.yaml
- apiVersion: v1
- kind: Pod
- metadata:
- name: pod-hostpath
- namespace: default
- spec:
- containers:
- - name: myapp
- image: ikubernetes/myapp:v1
- #定义容器挂载内容
- volumeMounts:
- #使用的存储卷名称,如果跟下面volume字段name值相同,则表示使用volume的这个存储卷
- - name: html
- #挂载至容器中哪个目录
- mountPath: /usr/share/nginx/html
- #读写挂载方式,默认为读写模式false
- readOnly: false
- #volumes字段定义了paues容器关联的宿主机或分布式文件系统存储卷
- volumes:
- #存储卷名称
- - name: html
- #路径,为宿主机存储路径
- hostPath:
- #在宿主机上目录的路径
- path: /data/pod/volume1
- #定义类型,这表示如果宿主机没有此目录则会自动创建
- type: DirectoryOrCreate
-
-
- kubectl apply -f pod-hostpath.yaml
-
- //访问测试
- kubectl get pods -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- pod-hostpath 2/2 Running 0 37s 10.244.2.35 node02 <none> <none>
-
- curl 10.244.2.35
- node02.kgc.com
-
- //删除pod,再重建,验证是否依旧可以访问原来的内容
- kubectl delete -f pod-hostpath.yaml
- kubectl apply -f pod-hostpath.yaml
-
- kubectl get pods -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- pod-hostpath 2/2 Running 0 36s 10.244.2.37 node02 <none> <none>
-
- curl 10.244.2.37
- node02.kgc.com

PersistentVolume(持久卷,简称PV) 是集群中由管理员配置的一段网络存储。集群中的资源就像一个节点是一个集群资源,可以从远程的NFS 或分布式对象存储系统中创建得来(PV 存储空间大小、访问方式)。
PV 是诸如卷之类的卷插件,但是只有独立于使用 PV 的任何单个 pod 的生命周期。
该 API 对象捕获存储的实现细节,即 NFS,ISCSI 或云提供商特定的存储系统。
PV 就是从存储设备中的空间创建出一个存储资源。
PersistentVolumeClaim(持久卷声明,简称PVC) 是用户存储的请求。PVC 的使用逻辑:在 pod 中定义一个存储卷(该存储卷类型为PVC),定义的时候直按指定大小,PVC 必须与对应的 PV 建立关系,PVC 会根据定义去 PV 申请,而 PV是由存储空间创建出来的。PV 和 PVC 是 kubernetes 抽象出来的一种存储资源。
虽然 PersistentVolumeClaims 允许用户使用抽象存储资源,但是常见的需求是,用户需要根据不同的需求去创建PV,用于不同的场景。而此时需要集群管理员提供不同需求的 PV,而不仅仅是 PV 的大小和访问模式,但又不需要用户了解这些卷的实现细节。
对于这样的需求,此时可以采用 storageclass 资源。
总结:
PV 全称叫做 Persistent Volume,持久化存储卷。它是用来描述或者说用来定义一个存储卷的,这个通常都是由运维工程师来定义。
PVC 的全称是 Persistent Volume Claim,是持久化存储的请求。它是用来描述希望使用什么样的或者说是满足什么条件的 PV 存储。
PV 是集群中的资源,PVC 是对这些资源的请求,也是对资源的索引检查。
PVC与PV的绑定是一对一的映射 没找到匹配的PV,那么PVC会无限期得处于unbound未绑定状态。
PV 和 PVC 之间的相互作用遵循这个生命周期:
Provisioning(配置) ---> Binding(绑定) ---> Using(使用) ---> Releasing(释放) ---> Recycling(回收)
根据这 5 个阶段,PV 的状态有以下 4 种:
Available(可用):表示可用状态,还未被任何 PVC 绑定
Bound(已绑定):表示 PV 已经绑定到 PVC
Released(已释放):表示 PVC 被删掉,但是资源尚未被集群回收
Failed(失败):表示该 PV 的自动回收失败
模式 | 解释 |
ReadWriteOnce(RWO) | 可读可写,但只支持被单个节点挂载。 |
ReadOnlyMany (ROX) | 只读,可以被多个节点挂载。 |
ReadWriteMany (RWX) | 多路可读可写。这种存储可以以读写的方式被多个节点共享。不是每一种存储都支持这三种方式,像共享方式,目前支持的还比较少,比较常用的是 NFS。在PVC绑定PV时通常根据两个条件来绑定,一个是存储的大小,另一个就是访问模式。 |
有三种回收策略,Retain、Delete和Recycle。
查看pv的定义方式 :kubectl explain pv
- FIELDS:
- apiVersion: v1
- kind: PersistentVolume
- metadata: #由于 PV 是集群级别的资源,即 PV 可以跨 namespace 使用,所以 PV 的 metadata 中不用配置 namespace
- name:
- spec
kubectl explain pv.spec
- spec:
- nfs:(定义存储类型)
- path:(定义挂载卷路径)
- server:(定义服务器名称)
- accessModes:(定义访问模型,有以下三种访问模型,以列表的方式存在,也就是说可以定义多个访问模式)
- - ReadWriteOnce #(RWO)存储可读可写,但只支持被单个 Pod 挂载
- - ReadOnlyMany #(ROX)存储可以以只读的方式被多个 Pod 挂载
- - ReadWriteMany #(RWX)存储可以以读写的方式被多个 Pod 共享
- #nfs 支持全部三种;iSCSI 不支持 ReadWriteMany(iSCSI 就是在 IP 网络上运行 SCSI 协议的一种网络存储技术);HostPath 不支持 ReadOnlyMany 和 ReadWriteMany。
- capacity:(定义存储能力,一般用于设置存储空间)
- storage: 2Gi (指定大小)
- storageClassName: (自定义存储类名称,此配置用于绑定具有相同类别的PVC和PV)
- persistentVolumeReclaimPolicy: Retain #回收策略(Retain/Delete/Recycle)
- #Retain(保留):当删除与之绑定的PVC时候,这个PV被标记为released(PVC与PV解绑但还没有执行回收策略)且之前的数据依然保存在该PV上,但是该PV不可用,需要手动来处理这些数据并删除该PV。
- #Delete(删除):删除与PV相连的后端存储资源(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支持)
- #Recycle(回收):删除数据,效果相当于执行了 rm -rf /thevolume/* (只有 NFS 和 HostPath 支持)

查看PVC的定义方式:kubectl explain pvc
- KIND: PersistentVolumeClaim
- VERSION: v1
- FIELDS:
- apiVersion <string>
- kind <string>
- metadata <Object>
- spec <Object>
PV和PVC中的spec关键字段要匹配,比如存储(storage)大小、访问模式(accessModes)、存储类名称(storageClassName)
- kubectl explain pvc.spec
- spec:
- accessModes: (定义访问模式,必须是PV的访问模式的子集)
- resources:
- requests:
- storage: (定义申请资源的大小)
- storageClassName: (定义存储类名称,此配置用于绑定具有相同类别的PVC和PV)
这里有两种 PV 的提供方式:静态或者动态
静态 —》直接固定存储空间
动态 —》通过存储类进行动态创建存储空间
nfs-server | k8s-master(192.168.111.20) |
---|---|
nfs-client | k8s-node1(192.168.111.30),k8s-node2(192.168.111.40) |
yum install -y nfs-utils rpcbind
- mkdir /nfsdata1
- mkdir /nfsdata2
- mkdir /nfsdata3
- chmod 777 /nfsdata1
- chmod 777 /nfsdata2
- chmod 777 /nfsdata3
- vim /etc/exports
- /nfsdata1 192.168.111.0/24(rw,no_root_squash,sync)
- /nfsdata2 192.168.111.0/24(rw,no_root_squash,sync)
- /nfsdata3 192.168.111.0/24(rw,no_root_squash,sync)
-
- exportfs -rv
- #手动加载 NFS 共享服务时,应该先启动 rpcbind,再启动 nfs
- systemctl start rpcbind && systemctl enable rpcbind
- systemctl start nfs && systemctl enable nfs
-
- #查看 rpcbind 端口是否开启,rpcbind 服务默认使用 tcp 端口 111
- netstat -anpt | grep rpcbind
查看本机发布的共享目录
showmount -e
- echo '11111' > /nfsdata1/index.html
- echo '22222' > /nfsdata2/index.html
- echo '33333' > /nfsdata3/index.html
这里定义 3 个 PV,并且定义挂载的路径以及访问模式,还有 PV 划分的大小。
- vim pv-demo.yaml #注意自己的共享目录和主机名
- ————————————————————————————————————————————
- apiVersion: v1
- kind: PersistentVolume
- metadata:
- name: pv001
- labels:
- name: pv001
- spec:
- nfs:
- path: /nfsdata1
- server: master
- accessModes: ["ReadWriteMany","ReadWriteOnce"]
- capacity:
- storage: 1Gi
- ---
- apiVersion: v1
- kind: PersistentVolume
- metadata:
- name: pv002
- labels:
- name: pv002
- spec:
- nfs:
- path: /nfsdata2
- server: master
- accessModes: ["ReadWriteOnce"]
- capacity:
- storage: 2Gi
- ---
- apiVersion: v1
- kind: PersistentVolume
- metadata:
- name: pv003
- labels:
- name: pv003
- spec:
- nfs:
- path: /nfsdata3
- server: master
- accessModes: ["ReadWriteMany","ReadWriteOnce"]
- capacity:
- storage: 2Gi
-

创建并查看
- kubectl apply -f pv-demo.yaml
- kubectl get pv
- ----------------------------------------
- [root@master ~]# kubectl apply -f pv-demo.yaml
- persistentvolume/pv001 created
- persistentvolume/pv002 created
- persistentvolume/pv003 created
- [root@master ~]# kubectl get pv
- NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
- pv001 1Gi RWO,RWX Retain Available 6s
- pv002 2Gi RWO Retain Available 6s
- pv003 2Gi RWO,RWX Retain Available 6s
这里定义了 PVC 的访问模式为多路读写,该访问模式必须在前面 PV 定义的访问模式之中。定义 PVC 申请的大小为 2Gi,此时 PVC 会自动去匹配多路读写且大小为 2Gi 的 PV ,匹配成功获取 PVC 的状态即为 Bound。
- vim pvc-demo.yaml
- ---------------------------------------
- apiVersion: v1
- kind: PersistentVolumeClaim
- metadata:
- name: mypvc
- spec:
- accessModes: ["ReadWriteMany"]
- resources:
- requests:
- storage: 2Gi
- ---
- apiVersion: v1
- kind: Pod
- metadata:
- name: pv-pvc
- spec:
- containers:
- - name: myapp
- image: nginx
- volumeMounts:
- - name: html
- mountPath: /usr/share/nginx/html
- volumes:
- - name: html
- persistentVolumeClaim:
- claimName: mypv

发布并查看
- kubectl apply -f pvc-demo.yaml
- kubectl get pv
- ------------------------------------
- [root@master ~]# kubectl apply -f pvc-demo.yaml
- persistentvolumeclaim/mypvc created
- pod/pv-pvc created
- [root@master ~]# kubectl get pv
- NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
- pv001 1Gi RWO,RWX Retain Available 4m51s
- pv002 2Gi RWO Retain Available 4m51s
- pv003 2Gi RWO,RWX Retain Bound default/mypvc 4m51s
-
可以看到 pv003 设定的 pvc 请求存储卷是 2Gi 并且多路可读可写。
访问 pv003
- [root@master ~]# kubectl get pod -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- pv-pvc 1/1 Running 0 58s 10.244.1.3 node01 <none> <none>
- [root@master ~]# kubectl get pv
- NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
- pv001 1Gi RWO,RWX Retain Available 84s
- pv002 2Gi RWO Retain Available 84s
- pv003 2Gi RWO,RWX Retain Bound default/mypvc 84s
- [root@master ~]# curl 10.244.1.3
- 33333
pod 创建不成功检查下网络怎么样,delete pv/pvc.yaml 重试。
- 1. 我们通过相同的存储卷,只修改 pod 的名称
- cp pvc-demo.yaml 1.yaml
- cp pvc-demo.yaml 2.yaml
- 2. 修改 pod 的名称后,apply 执行创建
- kubectl apply -f 1.yaml
- kubectl apply -f 2.yaml
- 3. 查看 ip
- kubectl get pod -o wide
- 4. curl 进行测试,查看是否共享存储卷,多路读写
前面的例子中,我们提前创建了 PV,然后通过 PVC 申请 PV 并在 Pod 中使用,这种方式叫做静态供给(Static Provision)。与之对应的是动态供给(Dynamical Provision),即如果没有满足 PVC 条件的 PV,会动态创建 PV。相比静态供给,动态供给有明显的优势:不需要提前创建 PV,减少了管理员的工作量,效率高。
StorageClass的属性
(1)Provisioner(存储分配器): 用来决定使用哪个卷插件分配 PV,该字段必须指定。可以指定内部分配器,也可以指定外部分配器。外部分配器的代码地址为: kubernetes-incubator/external-storage,其中包括NFS和Ceph等。
(2)Reclaim Policy(回收策略): 通过reclaimPolicy字段指定创建的Persistent Volume的回收策略,回收策略包括:Delete 或者 Retain,没有指定默认为Delete。
(3)更多属性: 查看 storage-classes官网
NFS Client Provisioner是一个automatic provisioner,使用NFS作为存储,自动创建PV和对应的PVC,本身不提供NFS存储,需要外部先有一套NFS存储服务。
(1)PV以 $ {namespace}-$ {pvcName}-$ {pvName}的命名格式提供(在NFS服务器上)
(2)PV回收的时候以 archieved-$ {namespace}-$ {pvcName}-$ {pvName} 的命名格式(在NFS服务器上)
(3)nfs-client-provisioner源码地址
在 PV 和 PVC 使用过程中存在的问题,在 PVC 申请存储空间时,未必就有现成的 PV 符合 PVC 申请的需求,上面 nfs 在做 PVC 可以成功的因素是因为我们做了指定的需求处理。当 PVC 申请的存储空间不一定有满足 PVC 要求的 PV 时,Kubernetes 为管理员提供了描述存储 “class(类)” 的方法(StorageClass)。
举个例子,在存储系统中划分一个 1TB 的存储空间提供给 Kubernetes 使用,当用户需要一个 10G 的 PVC 时,会立即通过 restful 发送请求,从而让存储空间创建一个 10G 的 image,之后在我们的集群中定义成 10G 的 PV 供给给当前的 PVC 作为挂载使用。在此之前我们的存储系统必须支持 restful 接口,比如 ceph 分布式存储,而 glusterfs 则需要借助第三方接口完成这样的请求。
- kubectl explain storageclass #storageclass 也是 k8s 上的资源
- KIND: Storageclass
- VERSION: storage.k8s.io/vl
- FIELDS:
- allowVolumeExpansion <boolean>
- allowedTopologies<[]Object>apiversion<string>
- kind <string>
- metadata <object>
- mountOptions <[]string>挂载选项
- parameters <map[string]string #参数,取决于分配器,可以接受不同的参数。例如参数 type 的值 io1 和参数 iopsPerGB 特定于 EBS PV。当参数被省略时,会使用默认值。
- provisioner <string-requred- #存储分配器,用来决定使用哪个卷插件分配 PV。该字段必须指定。
- reclaimPolicy <string> #回收策略,可以是 Delete 或者 Retain。如果 StorageClass 对象被创建时没有指定 reclaimPolicy,它将默认为 Delete。
- volumeBindingMode<string> #卷的绑定模式
- StorageClass 中包含 provisioner、parameters 和 reclaimPolicy 字段,当 class 需要动态分配 PersistentVolume 时会使用到。由于 storageclass 需要一个独立的存储系统,此处就不再演示。从其他资料查看定义 storageclass 的方式如下:
- ==========================================================
- kind: storageClass
- apiversion: storage.k8s.io/v1432
- metadata :
- name : standard
- provisioner: kubernetes.iol aws-ebs435 parameters:
- type: gp2
- reclaimPolicy: Retain
- mountoptions:
- - debug
示例:
StorageClass standard:
StorageClass slow:
这两个 StorageClass 都会动态创建 AWS EBS,不同在于 standard 创建的是 gp2 类型的 EBS,而 slow 创建的是 io1 类型的 EBS。不同类型的 EBS 支持的参数可参考 AWS 官方文档。StorageClass 支持 Delete 和 Retain 两种 reclaimPolicy,默认是 Delete。
与之前一样,PVC 在申请 PV 时,只需要指定 StorageClass 和容量以及访问模式,比如:
除了 AWS EBS,Kubernetes 支持其他多种动态供给 PV 的 Provisioner
下面演示如何为 MySQL 数据库提供持久化存储,步骤为:
- 创建 PV 和 PVC。
- 部署 MySQL。
- 向 MySQL 添加数据。
- 模拟节点宕机故障,Kubernetes 将 MySQL 自动迁移到其他节点。
- 验证数据一致性。
mysql-pv.yml
- vim mysql-pv.yml
- ---------------------------------------
- apiVersion: v1
- kind: PersistentVolume
- metadata:
- name: mysql-pv
- spec:
- accessModes:
- - ReadWriteOnce
- capacity:
- storage: 1Gi
- persistentVolumeReclaimPolicy: Retain
- storageClassName: nfs
- nfs:
- path: /nfsdata1/mysql-pv
- server: master

mysql-pvc.yml
- vim mysql-pvc.yml
- -----------------------------------
- apiVersion: v1
- kind: PersistentVolumeClaim
- metadata:
- name: mysql-pvc
- spec:
- accessModes:
- - ReadWriteOnce
- resources:
- requests:
- storage: 1Gi
- storageClassName: nfs
创建 mysql-pv 和 mysql-pvc
- [root@master ~]# kubectl apply -f mysql-pv.yml
- persistentvolume/mysql-pv created
- [root@master ~]# kubectl apply -f mysql-pvc.yml
- persistentvolumeclaim/mysql-pvc created
- [root@master ~]# kubectl get pv,pvc
- NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
- persistentvolume/mysql-pv 1Gi RWO Retain Bound default/mysql-pvc nfs 24s
-
- NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
- persistentvolumeclaim/mysql-pvc Bound mysql-pv 1Gi RWO nfs 20s
- #将先前实验的配置清除,方便检查
mysql.yml
- vim mysql.yml
- ------------------------------------
- apiVersion: v1
- kind: Service
- metadata:
- name: mysql
- spec:
- ports:
- - port: 3306
- selector:
- app: mysql
- ---
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: mysql
- spec:
- selector:
- matchLabels:
- app: mysql
- template:
- metadata:
- labels:
- app: mysql
- spec:
- containers:
- - image: mysql:5.6
- name: mysql
- env:
- - name: MYSQL_ROOT_PASSWORD
- value: password
- ports:
- - containerPort: 3306
- name: mysql
- volumeMounts:
- - name: mysql-persistent-storage
- mountPath: /var/lib/mysql
- volumes:
- - name: mysql-persistent-storage
- persistentVolumeClaim:
- claimName: mysql-pvc

PVC mysql-pvc Bound 的 PV mysql-pv 将被 mount 到 MySQL 的数据目录 /var/lib/mysql。
- kubectl apply -f mysql.yml
- kubectl get pod -o wide
- [root@k8s pv2]# kubectl get pods
- NAME READY STATUS RESTARTS AGE
- test-pd 1/1 Running 0 14s
- web-0 1/1 Running 0 16m
- web-1 1/1 Running 0 8m16s
- web-2 0/1 Pending 0 16m
- [root@k8s pv2]# kubectl exec -it test-pd -- sh
- / # ping web-0.nginx
- ping: bad address 'web-0.nginx'
- / # ping web-0.nginx
- PING web-0.nginx (10.150.2.120): 56 data bytes
- 64 bytes from 10.150.2.120: seq=0 ttl=64 time=4.891 ms
- 64 bytes from 10.150.2.120: seq=1 ttl=64 time=0.209 ms
- 64 bytes from 10.150.2.120: seq=2 ttl=64 time=0.196 ms
- 64 bytes from 10.150.2.120: seq=3 ttl=64 time=0.131 ms
- 64 bytes from 10.150.2.120: seq=4 ttl=64 time=0.128 ms

- [root@k8s pv2]# kubectl get pods -o wide -n kube-system
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- coredns-f68b4c98f-nkqlm 1/1 Running 2 22d 10.150.0.7 k8s-master-01 <none> <none>
- coredns-f68b4c98f-wzrrq 1/1 Running 2 22d 10.150.0.6 k8s-master-01 <none> <none>
- etcd-k8s-master-01 1/1 Running 3 22d 192.168.223.30 k8s-master-01 <none> <none>
- kube-apiserver-k8s-master-01 1/1 Running 3 22d 192.168.223.30 k8s-master-01 <none> <none>
- kube-controller-manager-k8s-master-01 1/1 Running 4 22d 192.168.223.30 k8s-master-01 <none> <none>
- kube-flannel-ds-8zj9t 1/1 Running 1 11d 192.168.223.30 k8s-node-01 <none> <none>
- kube-flannel-ds-jmq5p 1/1 Running 0 11d 192.168.223.30 k8s-node-02 <none> <none>
- kube-flannel-ds-vjt8b 1/1 Running 4 11d 192.168.223.30 k8s-master-01 <none> <none>
- kube-proxy-kl2qj 1/1 Running 2 22d 192.168.223.30 k8s-master-01 <none> <none>
- kube-proxy-rrlg4 1/1 Running 1 22d 192.168.223.9 k8s-node-01 <none> <none>
- kube-proxy-tc2nd 1/1 Running 0 22d 192.168.223.10 k8s-node-02 <none> <none>
- kube-scheduler-k8s-master-01 1/1 Running 4 22d 192.168.223.30 k8s-master-01 <none> <none>
- [root@k8s-master-01 pv2]# dig -t A nginx.default.svc.cluster.local. @10.150.0.7
-
- ; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.8 <<>> -t A nginx.default.svc.cluster.local. @10.244.0.7
- ;; global options: +cmd
- ;; Got answer:
- ;; WARNING: .local is reserved for Multicast DNS
- ;; You are currently testing what happens when an mDNS query is leaked to DNS
- ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26852
- ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
- ;; WARNING: recursion requested but not available
-
- ;; OPT PSEUDOSECTION:
- ; EDNS: version: 0, flags:; udp: 4096
- ;; QUESTION SECTION:
- ;nginx.default.svc.cluster.local. IN A
-
- ;; ANSWER SECTION:
- nginx.default.svc.cluster.local. 30 IN A 10.111.55.241
-
- ;; Query time: 7 msec
- ;; SERVER: 10.150.0.7#53(10.150.0.7)
- ;; WHEN: 一 08月 06 00:00:38 CST 2021
- ;; MSG SIZE rcvd: 107

删除对应的pod、svc、statefulset、pv、pvc
- [root@k8s pv]# kubectl get pods
- NAME READY STATUS RESTARTS AGE
- test-pd 1/1 Running 0 18m
- web-0 1/1 Running 0 34m
- web-1 1/1 Running 0 26m
- web-2 0/1 Pending 0 34m
-
- [root@k8s pv]# kubectl delete -f pod.yaml
- service "nginx" deleted
- statefulset.apps "web" deleted
-
- [root@k8s pv]# kubectl get pods
- NAME READY STATUS RESTARTS AGE
- test-pd 1/1 Running 0 18m
- web-0 0/1 Terminating 0 35m
- web-1 0/1 Terminating 0 26m
-
- [root@k8s pv]# kubectl get svc
- NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
- kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 22d
-
- [root@k8s pv]# kubectl delete statefulsets.apps --all
- No resources found
- [root@k8s pv]# kubectl get pv
- NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
- pv2 2Gi RWX Retain Bound default/www-web-1 nfs 35m
- pv3 1Gi RWX Retain Bound default/www-web-0 nfs 35m
-
- [root@k8s pv]# kubectl get pvc
- NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
- www-web-0 Bound pv3 1Gi RWX nfs 35m
- www-web-1 Bound pv2 2Gi RWX nfs 35m
- www-web-2 Pending nfs 35m
-
-
-
-
- [root@k8s pv]# kubectl delete pvc --all
- persistentvolumeclaim "www-web-0" deleted
- persistentvolumeclaim "www-web-1" deleted
- persistentvolumeclaim "www-web-2" deleted
-
- #查看pv显示release状态
- [root@k8s pv]# kubectl get pv
- NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
- pv2 2Gi RWX Retain Released default/www-web-1 nfs 36m
- pv3 1Gi RWX Retain Released default/www-web-0 nfs 36m
-
- #编辑pv2的yaml格式、因为 claimRef的显示所以一直显示release的状态,可以通过edit修改pv2的yaml,删除对应的claimRef的那一段
-
- [root@k8s pv]# kubectl edit pv pv2 -o yaml
-
- # Please edit the object below. Lines beginning with a '#' will be ignored,
- # and an empty file will abort the edit. If an error occurs while saving this file will be
- # reopened with the relevant failures.
- #
- apiVersion: v1
- kind: PersistentVolume
- metadata:
- annotations:
- kubectl.kubernetes.io/last-applied-configuration: |
- {"apiVersion":"v1","kind":"PersistentVolume","metadata":{"annotations":{},"name":"pv2"},"spec":{"accessModes":["ReadWriteMany"],"capacity":{"storage":"2Gi"},"nfs":{"path":"/root/data/pv2","server":"192.168.15.31"},"persistentVolumeReclaimPolicy":"Retain","storageClassName":"nfs"}}
- pv.kubernetes.io/bound-by-controller: "yes"
- creationTimestamp: "2021-12-26T15:34:19Z"
- finalizers:
- - kubernetes.io/pv-protection
- name: pv2
- resourceVersion: "501755"
- uid: 7b9f8b31-f111-4064-9ec7-d06e55f6bebd
- spec:
- accessModes:
- - ReadWriteMany
- capacity:
- storage: 2Gi
- claimRef:
- apiVersion: v1
- kind: PersistentVolumeClaim
- name: www-web-1
- namespace: default
- resourceVersion: "498363"
- uid: 7d47eaf8-8bed-40fc-b790-18e93a8a0398
- nfs:
- path: /root/data/pv2
- "/tmp/kubectl-edit-euy6w.yaml" 37L, 1260C

- #这时候发现状态已经为 Available状态
- [root@k8s pv]# kubectl get pv
- NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
- pv2 2Gi RWX Retain Available nfs 44m
- pv3 1Gi RWX Retain Released default/www-web-0 nfs 44m
pv是持久卷
pvc是持久卷消费
pv是全局的
pvc是绑定命名空间的
挂载中的pvc无法删除,除非占用该pvc的pod删除。
PV可以理解成k8s集群找那个的某个网络存储对应的一块存储,与Volume很类似,但有以下区别:
① PV只能提供网络存储,不属于任何Node,但可以在每个Node上访问
② PV并不是定义在Pod之上的,而是独立于Pod之外定义。
③ PV目前只有几种类型: GCE Persistent Disks、 NFS、 RBD、 iSCSI、 AWS ElasticBlockStore、 GlusterFS
PV 就是从存储设备的空间创建出一个存储资源(逻辑上存在)
pod 使用pvc ----请求------> PV资源 ------> 存储设备中
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。