实验环境
安装好k8s集群
Volume: 数据卷,实现数据本地存储
PV: PersistenVolume持久卷,实现数据网络存储
Volume简介
Volume是kubernetes Pod中多个容器访问的共享目录。
volume被定义在pod上,被这个pod的多个容器挂载到相同或不同的路径下。
volume的生命周期与pod的生命周期相同,pod内的容器停止和重启时一般不会影响volume中的数据(数据存储在宿主机目录)。
volume一般被用于持久化,保存pod产生的数据。
volume类型:
emptyDir(临时)
hostPath(持久)
一、emptyDir
1、emptyDir数据卷的特点
(1)emptyDir的生命周期与所属的pod相同,pod删除时,emptyDir中的数据也会被删除。
(2)emptyDir类型需要在volums字段中定义,用volumsMounts字段挂载使用。
(3)kubernetes会在node上自动创建一个目录,无需提前创建。
(4)emptyDir Volume主要用于某些应用程序无需永久保存数据,多个容器的共享目录等。
2、示例(多个容器共享数据)
vim emptyDir.yaml
添加:
apiVersion: v1
kind: Pod
metadata:
name: auth-vol
spec:
containers:
- name: vol1
image: busybox
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /vol1_dir
name: shared-volume
args:
- /bin/sh
- -c
- echo "hello world" > /vol1_dir/hello.txt ; sleep 30000
- name: vol2
image: busybox
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /vol2_dir
name: shared-volume
args:
- /bin/sh
- -c
- cat /vol2_dir/hello.txt ; sleep 30000
volumes:
- name: shared-volume
emptyDir: {}
容器 vol1 将字符串 "hello world" 写入共享存储卷中的文件 /vol1_dir/hello.txt。
容器 vol2 从共享存储卷中读取文件 /vol2_dir/hello.txt 的内容并输出。
由于两个容器共享同一个存储卷,vol2 可以读取到 vol1 写入的文件内容。
3、验证
(1)创建资源
kubectl apply -f emptyDir.yaml
(2)查看 Pod auth-vol 中容器 vol2 的日志
kubectl logs auth-vol vol2
由于两个容器挂载了同一个 emptyDir 卷,vol1 写入的文件 hello.txt 可以被 vol2 读取
(3)查看Pod运行所在节点
kubectl get pod -o wide
(4)在Pod运行所在节点查看容器Mounts的详细信息
docker ps | grep auth
docker inspect 16159dae4e92 | grep -A 8 Mounts
grep -A 8 Mounts: 查找包含 Mounts 的行,并显示该行及其后 8 行内容
(5)查看 Kubernetes Pod 中 emptyDir 存储卷的文件内容
cat /var/lib/kubelet/pods/e6780b70-28a6-4d6d-9370-efa515460b26/volumes/kubernetes.io~empty-dir/shared-volume/hello.txt
(6)删除Pod
kubectl delete pod auth-vol
查看Pod运行所在节点数据源目录中的文件
cat /var/lib/kubelet/pods/e6780b70-28a6-4d6d-9370-efa515460b26/volumes/kubernetes.io~empty-dir/shared-volume/hello.txt
Pod运行所在节点数据被删除
注:emptyDir的使用场景
如果Pod被删除,那么数据也会被删除,不具备持久化。
Pod内的容器,需要共享数据卷的时候,使用的是临时数据卷。
二、HostPath 数据卷
1、HostPath数据卷的特点
HostPath卷将主机节点中的文件或目录挂载到集群中
HostPath就等于运行容器时使用的命令:
docker run -v /host/path:/container/path
除了path属性之外,用户还可以指定type:
DirectoryOrCreate 如果指定的位置没有目录,将创建,权限755,与kubelet具有相同的所有权
Directory 指定的位置必须存在目录
FileOrCreate 如果指定的位置没有文件,将创建,权限644,与kubelet具有相同的所有权
File 指定的位置必须存在文件
vim hostPath.yaml
添加:
apiVersion: v1
kind: Pod
metadata:
name: auth-vol
spec:
containers:
- name: vol1
image: busybox
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /vol1_dir
name: shared-volume
args:
- /bin/sh
- -c
- echo "hello world" > /vol1_dir/hello.txt ; sleep 30000
- name: vol2
image: busybox
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /vol2_dir
name: shared-volume
args:
- /bin/sh
- -c
- cat /vol2_dir/hello.txt ;sleep 30000
volumes:
- name: shared-volume
hostPath:
path: "/data/hostPath"
type: DirectoryOrCreate
创建资源
kubectl apply -f hostPath.yaml
查看Pod运行所在节点
kubectl get pod -o wide
在Pod运行所在节点查看数据存储位置
ls /data/hostPath/
查看 Pod auth-vol 中容器 vol2 的日志
kubectl logs auth-vol vol2
删除Pod
kubectl delete pod auth-vol
查看数据存储位置
ls /data/hostPath/
三、PV持久卷(PersistentVolume)
1、PV、PVC简介
(1)PV
PersistentVolume( PV )是集群之中的一块网络存储。
跟 Node 一样,也是集群的资源。
(2)PVC
PV 是存储资源,而 PersistentVolumeClaim (PVC) 是对 PV 的请求。
2、实现过程
准备存储设备
创建pv(关联到存储)
创建pvc(向pv申请资源)
创建pod(连接pvc)
(1)准备存储设备,此处使用NFS
所有节点都安装nfs-utils工具包和rpc-bind服务
yum -y install nfs-utils
这里准备将NFS服务部署在master1节点上,需要在master1节点上提前规划好共享的目录,生产环境下网络存储是独立存在的。
mkdir /nfsdata
vim /etc/exports
添加:
/nfsdata *(rw,sync,no_root_squash)
systemctl start nfs-server
systemctl enable nfs-server
showmount -e
(2)创建PV(关联到存储)
vim pv1.yaml
添加:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfsdata
server: 192.168.10.11
创建资源
kubectl apply -f pv1.yaml
查看 Kubernetes 集群中的所有 PersistentVolume(PV)
kubectl get pv
返回字段解析:
NAME:PV 的名称。
CAPACITY:PV 的存储容量(例如 1Gi)。
ACCESS MODES:PV 的访问模式(例如 ReadWriteOnce)。
RECLAIM POLICY:PV 的回收策略(例如 Retain、Delete)。
STATUS:PV 的状态(例如 Available、Bound、Released)。
CLAIM:绑定到该 PV 的 PVC 名称(格式为 <namespace>/<pvc-name>)。
STORAGECLASS:PV 的存储类名称。
REASON:PV 的当前状态的原因(例如 Bound、Available)。
AGE:PV 的创建时间。
PV所支持的访问模式:
ReadWriteOnce:PV能以read-write的模式mount到单个节点。(命令模式:RWO)
ReadOnlyMany: PV能以read-only 的模式mount到多个节点。(命令模式:ROX)
ReadWriteMany: PV能以read-write的模式Mount到多个节点。(命令模式:RWX)
PV状态:
Available(可用):一块空闲资源还没有被任何声明绑定
Bound(绑定):卷已经被声明绑定
Released(已释放):声明被删除,但是资源还未被集群重新声明
Failed(失败):该卷的自动回收失败
PV空间的回收策略:persistentVolumeReclaimPolicy
Recycle: 回收,会清除数据,自动回收(新k8s版本已不支持)。
Retain: 保留,需要手动清理回收。
Delete: 删除,(自动删除pv,网络存储数据仍保留,一般在动态供给中使用)
(3)创建一个PVC(向pv申请资源)
PV与PVC的绑定,通过storageClassName和accessModes这两个字段共同决定。
vim pvc1.yaml
添加:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc1
spec:
accessModes:
- ReadWriteOnce
storageClassName: nfs
resources:
requests:
storage: 1Gi
创建资源
kubectl apply -f pvc1.yaml
查看 Kubernetes 集群中的所有 PersistentVolume(PV)和 PersistentVolumeClaim(PVC)
kubectl get pv,pvc
pvc返回字段解析:
NAME:PVC 的名称。
STATUS:PVC 的状态(例如 Bound、Pending)。
VOLUME:绑定到该 PVC 的 PV 名称。
CAPACITY:PVC 的存储容量(例如 1Gi)。
ACCESS MODES:PVC 的访问模式(例如 ReadWriteOnce)。
STORAGECLASS:PVC 的存储类名称。
AGE:PVC 的创建时间。
再次查看pv,状态status由Available换成了Bound,CLAIM(宣称)换成了default/pvc1占用。
总结:
1、RWO模式:当系统中的pv被绑定之后,就不会被其他的PVC绑定了。
2、如果系统中有多个能够满足pvc要求的pv,那么,系统会自动选择一个符合pvc申请空间大小的PV,进行绑定,尽量不浪费存储空间。
(4)创建Pod(连接pvc)
创建pod1:
vim pod1.yaml
添加:
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: pod1
image: busybox
imagePullPolicy: IfNotPresent
args:
- /bin/sh
- -c
- sleep 30000
volumeMounts:
- mountPath: "/data"
name: mydata
volumes:
- name: mydata
persistentVolumeClaim:
claimName: pvc1
创建资源
kubectl apply -f pod1.yaml
kubectl get pod -o wide
在pod1中,创建一个文件
kubectl exec -it pod1 -- touch /data/auth.txt
查看nfs服务器数据目录中的内容
ls /nfsdata/
创建pod2,连接相同的pvc:
vim pod2.yaml
添加:
apiVersion: v1
kind: Pod
metadata:
name: pod2
spec:
containers:
- name: pod2
image: busybox
imagePullPolicy: IfNotPresent
args:
- /bin/sh
- -c
- sleep 30000
volumeMounts:
- mountPath: "/data"
name: mydata
volumes:
- name: mydata
persistentVolumeClaim:
claimName: pvc1
创建资源
kubectl apply -f pod2.yaml
查看pod2中/data目录中的文件
kubectl exec -it pod2 -- ls /data
内容为nfs共享数据
(5)pv的空间回收
查看pv上存放的数据
ls /nfsdata/
删除Pod,PVC,PV
kubectl delete pod,pv,pvc --all
查看数据
ls /nfsdata/
3、PV,PVC的运用
现在部署一个MySQL服务,并且将MySQL的数据进行持久化存储。
(1)创建PV,PVC
vim mysql-pv.yaml
添加:
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 1Gi
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfsdata/mysql-pv
server: 192.168.10.11
vim mysql-pvc.yaml
添加:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: nfs
resources:
requests:
storage: 1Gi
创建共享目录
mkdir /nfsdata/mysql-pv
创建资源
kubectl apply -f mysql-pv.yaml
kubectl apply -f mysql-pvc.yaml
查看 Kubernetes 集群中的所有 PersistentVolume(PV)和 PersistentVolumeClaim(PVC)
kubectl get pv,pvc
(2)部署MySQL
vim mysql.yaml
添加:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ROOT_PASSWORD
value: 123.com
volumeMounts:
- name: mysql-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-storage
persistentVolumeClaim:
claimName: mysql-pvc
---
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
type: NodePort
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
nodePort: 31306
创建资源
kubectl apply -f mysql.yaml
(3)在MySQL数据库中添加数据
kubectl get pod -o wide
kubectl exec -it mysql-7cd7d7cd69-dh54k -- mysql -uroot -p123.com
create database auth;
use auth;
create table users(user_name char(10),user_passwd char(40));
insert users values('zhangsan','123');
select * from users;
(4)模拟MySQL服务器节点故障
删除Pod,k8s集群会产生一个新的Pod,验证这个Pod内是否有之前数据。
kubectl delete pod mysql-7cd7d7cd69-dh54k
kubectl get pod -o wide
删除后会自动创建mysql Pod
进入mysql新Pod
kubectl exec -it mysql-7cd7d7cd69-42qgq -- mysql -uroot -p123.com
show databases;
use auth;
show tables;
select * from users;
数据还在
查看nfs共享目录文件中的数据
ls /nfsdata/mysql-pv/