在k8s中为什么要做持久化存储?
在k8s中部署的应用都是以pod容器的形式运行的,假如我们部署MySQL、Redis等数据库,需要对这些数据库产生的数据做备份。因为Pod是有生命周期的,如果pod不挂载数据卷,那pod被删除或重启后这些数据会随之消失,如果想要长久的保留这些数据就要用到pod数据持久化存储。
k8s持久化存储:emptyDir
查看k8s支持哪些存储
bash
[root@k8s-master](mailto:root@k8s-master) ~]# kubectl explain pods.spec.volumes
FIELDS:
awsElasticBlockStore <Object>
azureDisk <Object>
azureFile <Object>
cephfs <Object>
cinder <Object>
configMap<Object>
csi <Object>
downwardAPI <Object>
emptyDir <Object>
ephemeral <Object>
fc <Object>
flexVolume <Object>
flocker <Object>
gcePersistentDisk <Object>
gitRepo <Object>
glusterfs<Object>
hostPath <Object>
iscsi <Object>
name <string> -required-
nfs <Object>
persistentVolumeClaim<Object>
photonPersistentDisk <Object>
portworxVolume <Object>
projected <Object>
quobyte <Object>
rbd <Object>
scaleIO <Object>
secret <Object>
storageos <Object>
vsphereVolume <Object>
常用的
bash
emptyDir
hostPath
nfs
persistentVolumeClaim
glusterfs
cephfs
configMap
secret
我们想要使用存储卷,需要经历如下步骤
1、定义pod的volume,这个volume指明它要关联到哪个存储上的
2、在容器中要使用volumemounts挂载对应的存储
emptyDir类型的Volume是在Pod分配到Node上时被创建,Kubernetes会在Node上自动分配一个目录,因此无需指定宿主机Node上对应的目录文件。 这个目录的初始内容为空,当Pod从Node上移除时,emptyDir中的数据会被永久删除。emptyDir Volume主要用于某些应用程序无需永久保存的临时目录,多个容器的共享目录等。
创建一个pod,挂载临时目录emptyDir
bash
[[root@k8s-master](mailto:root@k8s-master) ~]# cat emptydir.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-empty
spec:
containers:
- name: container-empty
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /cache
name: cache-volume ##与volumes中的name保持一致
volumes:
- emptyDir: {}
name: cache-volume
更新资源清单文件
bash
[[root@k8s-master](mailto:root@k8s-master) ~]# kubectl apply -f emptydir.yaml
pod/pod-empty created
查看本机临时目录存在的位置,可用如下方法:
查看pod调度到哪个节点
bash
[root@k8s-master ~]# kubectl get pod pod-empty -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-empty 1/1 Running 0 27s 172.16.69.230 k8s-node2 <none> <none>
查看pod的uid
bash
[root@k8s-master ~]# kubectl get pod pod-empty -o yaml | grep uid
uid: 45a10614-495b-4745-be0f-c7492b90e2b7
登录到k8s-node2上
bash
[root@k8s-node2 ~]# tree /var/lib/kubelet/pods/45a10614-495b-4745-be0f-c7492b90e2b7/
/var/lib/kubelet/pods/45a10614-495b-4745-be0f-c7492b90e2b7/
├── containers
│ └── container-empty
│ └── 43f2b9b9
├── etc-hosts
├── plugins
│ └── kubernetes.io~empty-dir
│ ├── cache-volume
│ │ └── ready
│ └── wrapped_kube-api-access-njjrv
│ └── ready
└── volumes
├── kubernetes.io~empty-dir
│ └── cache-volume
└── kubernetes.io~projected
└── kube-api-access-njjrv
├── ca.crt -> ..data/ca.crt
├── namespace -> ..data/namespace
└── token -> ..data/token
11 directories, 7 files
测试
bash
###模拟产生数据测试
root@pod-empty:/cache# touch file{1..10}
root@pod-empty:/cache# ls
10}file{1. aaa file1 file10 file2 file3 file4 file5 file6 file7 file8 file9
root@pod-empty:/cache# exit
exit
###node查看
[root@k8s-node2 ~]# tree /var/lib/kubelet/pods/45a10614-495b-4745-be0f-c7492b90e2b7/
/var/lib/kubelet/pods/45a10614-495b-4745-be0f-c7492b90e2b7/
├── containers
│ └── container-empty
│ └── 43f2b9b9
├── etc-hosts
├── plugins
│ └── kubernetes.io~empty-dir
│ ├── cache-volume
│ │ └── ready
│ └── wrapped_kube-api-access-njjrv
│ └── ready
└── volumes
├── kubernetes.io~empty-dir
│ └── cache-volume
│ ├── 10}file{1.
│ ├── aaa
│ ├── file1
│ ├── file10
│ ├── file2
│ ├── file3
│ ├── file4
│ ├── file5
│ ├── file6
│ ├── file7
│ ├── file8
│ └── file9
└── kubernetes.io~projected
└── kube-api-access-njjrv
├── ca.crt -> ..data/ca.crt
├── namespace -> ..data/namespace
└── token -> ..data/token
12 directories, 18 files
###模拟删除pod测试
[root@k8s-master ~]# kubectl delete pod pod-empty
pod "pod-empty" deleted
[root@k8s-node2 ~]# tree /var/lib/kubelet/pods/45a10614-495b-4745-be0f-c7492b90e2b7/
/var/lib/kubelet/pods/45a10614-495b-4745-be0f-c7492b90e2b7/ [error opening dir]
0 directories, 0 files
k8s持久化存储:hostPath
hostPath Volume是指Pod挂载宿主机上的目录或文件。 hostPath Volume使得容器可以使用宿主机的文件系统进行存储,hostpath(宿主机路径):节点级别的存储卷,在pod被删除,这个存储卷还是存在的,不会被删除,所以只要同一个pod被调度到同一个节点上来,在pod被删除重新被调度到这个节点之后,对应的数据依然是存在的。
查看hostPath存储卷的用法
bash
[[root@k8s-master](mailto:root@k8s-master) ~]# kubectl explain pods.spec.volumes.hostPath
KIND: Pod
VERSION: v1
RESOURCE: hostPath <Object>
DESCRIPTION:
HostPath represents a pre-existing file or directory on the host machine
that is directly exposed to the container. This is generally used for
system agents or other privileged things that are allowed to see the host
machine. Most containers will NOT need this. More info:
[https://kubernetes.io/docs/concepts/storage/volumes#hostpath](https://kubernetes.io/docs/concepts/storage/volumes#hostpath)
Represents a host path mapped into a pod. Host path volumes do not support
ownership management or SELinux relabeling.
FIELDS:
path <string> -required-
type <string>
创建一个pod,挂载hostPath存储卷
bash
[root@k8s-master~]# cat hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-hostpath
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: test-nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /data
type: DirectoryOrCreate
注意:
DirectoryOrCreate表示本地有/data目录,就用本地的,本地没有就会在pod调度到的节点自动创建一个
更新资源清单文件,并查看pod调度到了哪个物理节点
bash
[root@k8s-master ~]# kubectl apply -f test-hostpath.yaml
pod/test-hostpath created
[root@k8s-master ~]# kubectl get pod test-hostpath -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-hostpath 1/1 Running 0 80s 172.16.69.248 k8s-node2 <none> <none>
测试
bash
###没有首页
[root@k8s-master ~]# curl 172.16.69.248
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.25.3</center>
</body>
</html>
###生成首页
[root@k8s-node2 ~]# cd /data/
[root@k8s-node2 data]# ls
[root@k8s-node2 data]# echo 1111 > index.html
[root@k8s-master ~]# curl 172.16.69.248
1111
hostpath存储卷的缺点
单节点,pod删除之后重新创建必须调度到同一个node节点,数据才不会丢失
再yaml文件中进行指定就可以调度到同一个nodeName
bash
apiVersion: v1
kind: Pod
metadata:
name: test-hostpath
spec:
nodeName: k8s-node2
containers:
- image: nginx
name: test-nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /data
type: DirectoryOrCreate
测试
bash
[root@k8s-master ~]# kubectl apply -f test-hostpath.yaml
pod/test-hostpath configured
[root@k8s-master ~]# kubectl delete pod test-hostpath
pod "test-hostpath" deleted
[root@k8s-master ~]# kubectl apply -f test-hostpath.yaml
pod/test-hostpath created
[root@k8s-master ~]# kubectl get pod test-hostpath -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-hostpath 1/1 Running 0 9s 172.16.69.219 k8s-node2 <none> <none>
[root@k8s-master ~]# curl 172.16.69.219
1111