存储卷
存储卷的方式
emptyDir
pod被分配到节点时候,首先创建的就是emptydir卷.
只能在pod内部使用,需要创建目录
- 在节点上建一个空的存储卷,让pod中的容器的数据挂载到存储卷中;
- 容器的读写都挂载到卷中,但pod若从节点上删除,则emptydir会删除
[root@master01 ~]# mkdir /opt/volumes
[root@master01 ~]# cd /opt/volumes/
[root@master01 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: {}
[root@master01 volumes]# kubectl apply -f pod-emptydir.yaml
[root@master01 volumes]# kubectl get pods -0 wide
在上面定义了2个容器,其中一个容器是输入日期到index.html中,然后验证访问nginx的html是否可以获取日期。以验证两个容器之间挂载的emptyDir实现共享。
[root@master01 volumes]# curl 10.244.2.12
hostPath存储卷
将node节点的文件系统中的文件或目录挂载到集群中,挂载到当前节点下
以node节点来进行共享数据(单机限制)
| readOnly:false | 表明可以删除和修改数据 |
|---|---|
| readOnly:true | 表明只能读 |
#在node01和node02节点创建挂载目录
[root@node01 ~]# mkdir -p /data/pod/volume1
[root@node01 ~]# echo 'helloween01' > /data/pod/volume1/index.html
#master节点创建pod资源
[root@master01 volumes]# vim 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
nfs共享存储卷
节点安装nfs,并且配置
可以实现持久化数据,可以跨节点共享存储
小型、中型公司会使用
在node01节点上安装nfs,并且配置nfs
很多的虚拟机上面都会自带NFS,所以不需要安装
[root@localhost ~]# mkdir /data/volumes -p
[root@localhost ~]# chmod 777 /data/volumes/
[root@localhost ~]# vim /etc/exports
/data/volumes 192.168.42.0/24(rw,no_root_squash)
#表示不允许root登录
[root@localhost ~]# systemctl start rpcbind
[root@localhost ~]# systemctl start nfs
[root@localhost ~]# hostnamectl set-hostname stor01
[root@localhost ~]# su
[root@localhost ~]# showmount -e 192.168.42.13
master节点
[root@master01 volumes]# vim pod-nfs-vol.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-vol-nfs
namespace: default
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
nfs:
path: /data/volumes
server: stor01
[root@master01 volumes]# kubectl apply -f pod-nfs-vol.yaml
[root@master01 volumes]# kubectl get pods -o wide
PV和PVC
PV是集群中的资源。 PVC是对这些资源的请求,也是对资源的索引检查。
PV
PV全称Persistent Volume,持久化存储卷。用于定义存储卷
PV是PVC的代理商
PVC
PVC全称Persistent Volume Claim,是持久化存储的请求。用于定义存储大小,定义文件
如果PV想读取磁盘数据时候,需要通过PVC读取
PV由存储空间创建出来的
为什么需要PV和PVC
容器磁盘上文件数据生命周期很短,在运行重要应用文件时候可能会出现问题。
首先,当容器出现问题时候,kubectl会重启容器,但是容器中的文件会丢失,容器会以最初的状态重新启动。
其次,在pod中同时运行多个容器时候,容器通常需要共享文件。Kubernetes 中的Volume抽象就很好的解决了这些问题。Pod中的容器通过Pause容器共享Volume。
PV和PVC相互遵循的生命周期
Provisioning(配置)---> Binding(绑定)---> Using(使用)---> Releasing(释放) ---> Recycling(回收)
| 阶段 | 解释 |
|---|---|
| Provisioning | 可以直接创建PV(静态方式),也可以使用StorageClass动态创建 |
| Binding | 将PV分配给PVC,PVC绑定PV后的状态 |
| Using | Pod通过PVC使用PV时候,是不能删除PV的 |
| Releasing | Pod释放Volume后,就可以删除PVC |
| Reclaiming | 回收PV,可以保留PV以便下次使用,也可以直接从云存储中删除 |
5个阶段的PV的4个状态
| 状态 | 详解 |
|---|---|
| Available(可用) | 表示可用状态,还没有被PVC绑定 |
| Bound(已绑定) | 表示PV已经绑定PVC |
| Released(已释放) | 表示PVC被删除,但是资源还没有被集群回收回来 |
| Failed(失败) | 表示PV的自动回收失败 |
三种回收策略
| 策略 | 详解 |
|---|---|
| retain | 保留数据,不清理(如果清理,需要手动清理数据) |
| delete | 只要定了delete策略,只要资源回收,k8s就会自动删除PV里面的数据 |
| recycle | 被回收后,k8s会删除PV里面的数据,将状态改为available,等待再次被PVC使用 |
三种访问模式
| 模式 | 详解 |
|---|---|
| ReadWriteOnce | (RWO)存储可读可写,但只支持被单个 Pod 挂载 |
| ReadOnlyMany | (ROX)存储可以以只读的方式被多个 Pod 挂载 |
| ReadWriteMany | (RWX)存储可以以读写的方式被多个 Pod 共享 |
一个PV从创建到销毁的具体流程如下:
- 一个PV创建完后状态会变成Available,等待被PVC绑定。
- 一旦被PVC邦定,PV的状态会变成Bound,就可以被定义了相应PVC的Pod使用。
- Pod使用完后会释放PV,PV的状态变成Released。
- 变成Released的PV会根据定义的回收策略做相应的回收工作。有三种回收策略,Retain、Delete和Recycle。Retain就是保留现场,K8S集群什么也不做,等待用户手动去处理PV里的数据,处理完后,再手动删除PV。Delete策略,K8S会自动删除该PV及里面的数据。Recycle方式,K8S会将PV里的数据删除,然后把PV的状态变成Available,又可以被新的PVC绑定使用。
[root@master01 ~]# kubectl explain pv
#查看PV的定义方式
[root@master01 ~]# kubectl explain pv.spec
#查看PV定义的规格
[root@master01 ~]# kubectl explain pvc
#查看定义的方式
静态PV
NFS节点部署
- 所有节点安装NFS
[root@nfs ~]# yum install -y nfs-utils rpcbind
很多虚拟机本身就自带NFS
- 创建共享目录,并且授权
[root@nfs ~]# mkdir /nfsdata01
[root@nfs ~]# mkdir /nfsdata02
[root@nfs ~]# mkdir /nfsdata03
[root@nfs ~]# chmod 777 /nfsdata01
[root@nfs ~]# chmod 777 /nfsdata02
[root@nfs ~]# chmod 777 /nfsdata03
- 配置权限
[root@nfs ~]# vim /etc/exports
/nfsdata01 192.168.42.0/24(rw,no_root_squash,sync)
/nfsdata02 192.168.42.0/24(rw,no_root_squash,sync)
/nfsdata03 192.168.42.0/24(rw,no_root_squash,sync)
[root@nfs ~]# exportfs -rv
所有服务器启动NFS服务
[root@nfs ~]# systemctl start rpcbind && systemctl enable rpcbind
[root@nfs ~]# systemctl start nfs && systemctl enable nfs
#手动加载 NFS 共享服务时,应该先启动 rpcbind,再启动 nfs
[root@nfs ~]# netstat -anpt | grep rpcbind
#查看 rpcbind 端口是否开启,rpcbind 服务默认使用 tcp 端口 111