一、介绍
1、为什么需要存储卷
(1)容器启动时,除了来自于镜像的文件系统外,没有其他文件,如果想加入一些文件,例如配置文件,就需要存储卷加进去
(2)容器重启后,非原镜像中的文件会丢失,例如xx服务的数据文件,如果希望容器重启后数据依然在,需要存储卷保证数据的不丢失
(3)pod内有多个容器,如果希望多个容器间共享一些数据,就需要存储卷来存一份数据,给多个容器用,相当于磁盘
2、生命周期
存储卷被定义为pod的一部分,并和pod共享相同的生命周期
二、容器间共享数据型存储卷
1、emptyDir卷
apiVersion: v1
kind: Pod
metadata:
name: emptydir-example
spec:
containers:
- image: docker.io/library/busybox:latest
name: container1
imagePullPolicy: IfNotPresent
command:
- top
volumeMounts:
- name: html
mountPath: /opt/aaa
- image: docker.io/library/busybox:latest
name: container2
imagePullPolicy: IfNotPresent
command:
- top
volumeMounts:
- name: html
mountPath: /opt/bbb
volumes:
- name: html
emptyDir: {}
容器container1向它的目录/opt/aaa写入一个文件,容器container2即可从它的/opt/bbb目录中读取到这个文件,因为这俩目录挂载的是同一个卷。
emptyDir是在工作节点的实际磁盘上创建的,要想创建在内存上,可以指定volumes的medium
2、gitRepo卷
gitRepo基本就是emptyDir卷,在pod启动后、容器启动前,k8s创建一个空目录并将指定的git仓库克隆到其中,只git pull这一次,pod启动后不会再pull,所以无法拉到新代码
有两种方法同步新代码:
a.pod删了重建(由RC控制重新拉起)
b.用一个sidecar容器共享这个卷,sidecar容器中开进程同步代码
无法拉取私仓的代码,只能拉github,因为gitRepo初衷是简单操作,配置私仓就多了一写SSH的配置了,越来越复杂
volumes:
- name: git
ditRepo:
repository: https://github.com/xxxxx.git
revision: master
directory: . // 拉取代码到.目录,挂载时挂到对应目录
三、共享工作节点文件型存储卷
存储卷的生命周期和pod是相同的,pod删除时,存储卷也没了,但可以把数据存放到pod运行的工作节点上,这样即便pod删了,工作节点上的文件依然在
1、hostpath
apiVersion: v1
kind: Pod
metadata:
name: hostpath-example
spec:
containers:
- image: docker.io/library/busybox:latest
name: container1
imagePullPolicy: IfNotPresent
command:
- top
volumeMounts:
- name: hp
mountPath: /opt/aaa/
volumes:
- name: hp
hostPath:
# 工作节点的路径,不是云桌面的
path: /opt/code/aaa/
四、尽量使用持久化存储
hostpath换个工作节点就没了,pod重启后就可能调度到其他节点上
自有集群上(对应云集群,例如Google),持久化的存储一般就需要用NFS了,包括各种类型:glusterfs、cephfs等等,这些都需要外设,外挂存储空间
五、持久卷PV和持久卷声明PVC
开发人员不应该关注于外挂存储空间的,只需要知道申请空间用于存储即可
1、解耦存储技术与pod
将底层存储技术与pod解耦后,开发人员需要关注的是持久卷声明PersistantVolumeClaims-----PVC,集群管理员要关注的是持久卷PersistantVolume-------PV
PV是集群中独立于pod的一块存储,它的底层存储技术可能是glusterfs,可能是cephfs等等,集群管理员需要事先制备好。它不属于任何命名空间,跟节点一样是集群层面的资源
PVC表达的是用户对存储的请求,当用户需要在pod中使用持久化存储时,首先要创建PVC,指定需要的最低容量和访问模式,并提交给k8s API,k8s会找到可匹配的PV并将其绑定到PVC上
一个PVC只能绑定一个PV,但是一个PV能绑定多个PVC,PVC与pod也是一一对应
2、创建PV
查看创建的PV
kubectl get pvNAME
CAPACITY RECLAIMPOLICY ACCESSMODES STATUS CLAIM
mongodb-pv 1Gi Retain RWO,ROX Available
因为现在还没有创建PVC,所以该PV没有绑定任何PVC,status为available
3、创建PVC
这里讲的是PVC和PV的关系,所以先不使用StorageClass
创建成功后
查看PVC状态:
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mongodb-pvc Bound mongodb-pv 1Gi RWO,ROX 111m
看到该PVC绑定了一个卷,即刚才创建的PV,再回头看刚刚的PV
kubectl get pvNAME
CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM
mongodb-pv 1Gi RWO,ROX Retain Bound default/mongodb-pvc
PV的状态为已绑定绑定的是刚创建的PVC,该PVC是在default命名空间下的
4、在pod中使用PVC
apiVersion: v1
kind: Pod
metadata:
name: pvcpod-example
spec:
containers:
- image: docker.io/library/busybox:latest
name: container1
imagePullPolicy: IfNotPresent
command:
- top
volumeMounts:
- name: pvc
mountPath: /opt/aaa/
volumes:
- name: pvc
persistentVolumeClaim:
claimName: pvc
5、回收PV
kubectl delete po
在用的pvc是删不掉的,只能先删除pod
kubectl delete pvc
删了之后看下PVC的状态.
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mongodb-pvc Pending
再看PV的状态
kubectl get pvNAME
CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM
mongodb-pv 1Gi RWO,ROX Retain Released default/mongodb-pvc
被释放了,但仅仅是被释放了,当有新的PVC绑定到该PV后,新的PVC可以看到之前的数据,也就是说数据没有清理
通过将回收策略由Retain改为Recycle可以自动清理数据,也可以改为delete,随着PVC的删除,PV一并被删除
六、持久卷的动态卷配置
PV是提前创建的,创建多大才能使得绑定PVC后,既不浪费空间,又足够用?只能做成动态的,随着PVC的创建而创建,于是,有了StorageClass来动态配置卷
1、创建一个StorageClass资源
集群管理员可以不创建PV,但是必须创建一个或多个StorageClass,它和PV一样是k8s的一种资源
创建一个名为fast的StorageClass
它指定了当PVC请求此StorageClass时应该使用哪个置备程序来提供持久卷,创建PVC时,StorageClass会将yaml中定义的parameters传递给置备程序,并具体到每个供应器插件
2、创建PVC
如果PVC中配置了一个不存在的StorageClass,会失败
查看一下:
kubectl get pvc mongodb-pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mongodb-pvc Bound pvc-asdf13f 1Gi RWO fast 111m
可以看到绑定的StorageClass是fast
查看PV:
kubectl get pvNAME
CAPACITY ACCESS MODES RECLAIM POLICY STATUS STORAGECLASS
pvc-asdf13f 1Gi RWO Delete Bound fast
发现自动创建了一个PV,并且策略为delete,当PVC删除时,这个PV也删除
3、不指定StorageClass
kubectl get sc
NAME TYPE
fast k8s.io/minikube-hostpath
standard(default) k8s.io/minikube-hostpath
可以看到其实有一个默认的StorageClass的,当PVC的yaml里不指定StorageClassName时,就会用这个默认的
如果想不用动态的PV--StorageClass,只用预先配置的PV,可以在yaml里把StorageClassName这一项显示设置为“”
4、了解动态PV供应的全貌