第七章 Kubernetes存储
1、数据卷与数据持久卷
为什么需要数据卷?
容器中的文件在磁盘上是临时存放的,这给容器中运行比较重要的应用程序带来一些问题。
-
问题1:当容器升级或者崩溃时,kubelet会重建容器,容器内文件会丢失;
-
问题2:一个Pod中运行多个容器并需要共享文件;
Kubernetes 卷(Volume) 这一抽象概念能够解决这两个问题。
1. 数据持久化
- 容器的无状态性:Kubernetes 中的容器是无状态的,这意味着它们在重启或重新调度时,容器内的数据会丢失。
- 持久化数据:通过使用数据卷,可以将数据持久化到外部存储系统中,确保数据在容器生命周期外仍然存在。
2. 数据共享
- 多容器共享数据:在某些情况下,同一个 Pod 中的多个容器需要共享数据。数据卷允许这些容器共享同一个存储卷。
- 跨容器协作:例如,一个容器生成日志文件,另一个容器需要读取这些日志文件。
3. 数据隔离
- 独立存储:不同的 Pod 可以使用不同的数据卷,确保数据隔离,避免数据冲突。
- 安全性:通过将敏感数据存储在独立的数据卷中,可以提高安全性。
4. 简化配置
- 统一管理:使用数据卷可以简化应用程序的配置,因为存储配置可以在 Kubernetes 中集中管理。
- 灵活性:可以根据需要选择不同的存储后端(如本地存储、云存储、网络文件系统等),而不需要修改应用程序代码。
5. 生命周期管理
- 数据生命周期:数据卷可以独立于 Pod 的生命周期管理,确保数据在 Pod 重启或删除后仍然可用。
- 自动挂载:Kubernetes 可以自动挂载和卸载数据卷,简化操作。
常用的数据卷:
- 节点本地存储(hostPath,emptyDir)
- 网络存储(NFS,Ceph,GlusterFS)
- 公有云存储(AWS EBS)
- K8S资源存储(configmap,secret)
1.1 临时数据卷:emptyDir
emptyDir卷是一个临时存储卷,与Pod生命周期绑定一起,如果 Pod删除了卷也会被删除。
应用场景:Pod中容器之间数据共享
选项:
-
sizeLimit:500Mi //限制共享空间大小(比较少用)
示例:Pod内容器之间共享数据
apiVersion: v1
kind: Pod
metadata:
name: emptydir-test
spec:
containers:
- name: write-container //程序讲数据写入到文件
image: centos
command: ["bash","-c","for i in {1..100};do echo $i >>
/data/hello;sleep 1;done"]
volumeMounts:
- name: data-volume //通过volume卷名称引用
mountPath: /data
- name: read-container //程序从文件中读取数据
image: centos
command: ["bash","-c","tail -f /data/hello"]
volumeMounts:
- name: data-volume
mountPath: /data
volumes: //定义卷的来源
- name: data-volume
emptyDir: {} //{}中为空值
验证1:验证容器之间是否能够共享数据
[root@k8s-master-1-71 ~]# kubectl apply -f emptydir-test.yaml
[root@k8s-master-1-71 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
emptydir-test 2/2 Running 1 (21s ago) 3m14s
# 进入write-container查看
[root@k8s-master-1-71 ~]# kubectl exec -it emptydir-test -- bash
[root@emptydir-test /]# tail -f /data/hello
...
99
100
command terminated with exit code 137
[root@emptydir-test /]# touch /data/aaa ; ls /data/ //往容器中写入临时文件
aaa hello
## 注:脚本循环结束后退出容器,按照默认的策略Always进行容器重启。
# 进入read-container查看
[root@k8s-master-1-71 ~]# kubectl exec -it emptydir-test -c read-container -- bash
[root@emptydir-test /]# ls /data/
aaa hello
验证2:实际存储位置(基于节点的存储)
补充:Kubelet的工作目录为/var/lib/kubelet/,负载维护Pod数据的
[root@k8s-master-1-71 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
emptydir-test 2/2 Running 2 (45s ago) 5m3s 10.244.114.48 k8s-node2-1-73 <none> <none>
# 根据查看到的Pod所在节点,找到相应的容器ID
[root@k8s-node2-1-73 ~]# docker ps | grep emptydir-test(例如:7c26307b-b290-4bac-9a3b-6f18ffc26776)
6deb6dc27ab2 centos "bash -c 'for i in {…" 44 seconds ago Up 43 seconds k8s_write-container_emptydir-test_default_7c26307b-b290-4bac-9a3b-6f18ffc26776_3
7bb46657087b centos "bash -c 'tail -f /d…" 7 minutes ago Up 7 minutes k8s_read-container_emptydir-test_default_7c26307b-b290-4bac-9a3b-6f18ffc26776_0
fd4c6c671807 registry.aliyuncs.com/google_containers/pause:3.7 "/pause" 7 minutes ago Up 7 minutes k8s_POD_emptydir-test_default_7c26307b-b290-4bac-9a3b-6f18ffc26776_0
# 找到相关Pod关联的empty-dir目录,即可看到挂载的empty-dir目录内容
[root@k8s-node2-1-73 kubernetes.io~empty-dir]# pwd
/var/lib/kubelet/pods/7c26307b-b290-4bac-9a3b-6f18ffc26776/volumes/kubernetes.io~empty-dir
[root@k8s-node2-1-73 kubernetes.io~empty-dir]# ls data-volume/
aaa bbb hello
Pod是节点级别的,Pod中的容器都是捆绑在一个节点上,所以 Pod删除了,卷也会被删除
[root@k8s-master-1-71 ~]# kubectl delete -f emptydir-test.yaml
[root@k8s-node2-1-73 kubernetes.io~empty-dir]# ls data-volume/
ls: 无法访问data-volume/: 没有那个文件或目录
1.2 节点数据卷:hostPath
hostPath卷挂载Node的文件系统(即Pod所在节点)上文件或者目 录到Pod中的容器。
应用场景:Pod中容器需要访问宿主机的文件
选项:
-
path: //将宿主机的目录或文件映射到容器中去
-
type: //指定类型(目录或文件)
示例:将宿主机/tmp目录挂载到容器/data目录
apiVersion: v1
kind: Pod
metadata:
name: hostpath-test
spec:
containers:
- name: busybox
image: busybox
args:
- /bin/sh
- -c
- sleep 36000
volumeMounts:
- name: data-volume
mountPath: /data
volumes:
- name: data-volume
hostPath:
path: /tmp //Pod所在节点的/tmp目录
type: Directory
验证:
[root@k8s-master-1-71 ~]# kubectl apply -f hostpath-test.yaml
[root@k8s-master-1-71 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hostpath-test 1/1 Running 0 86s 10.244.114.49 k8s-node2-1-73 <none> <none>
# 查看Pod所在节点的/tmp目录
[root@k8s-node2-1-73 ~]# ls /tmp/
systemd-private-85c79618aae44d7cbb01bccc046ecb10-chronyd.service-UMOhQf
systemd-private-fdf2b8d40ff841319feb738a463a8f6f-chronyd.service-GJT2Mn
# 进入容器查看/data目录是否有相关映射文件
[root@k8s-master-1-71 ~]# kubectl exec -it hostpath-test -- sh
/ # ls /data/
systemd-private-85c79618aae44d7cbb01bccc046ecb10-chronyd.service-UMOhQf
systemd-private-fdf2b8d40ff841319feb738a463a8f6f-chronyd.service-GJT2Mn
1.3 网络数据卷:NFS
NFS:是一个主流的文件共享服务器(注:每个Node上都要安装nfs-utils包)
# 服务端部署
[root@k8s-node1-1-72 ~]# yum install -y nfs-utils
[root@k8s-node1-1-72 ~]# vi /etc/exports //NFS共享配置目录
/ifs/kubernetes *(rw,no_root_squash)
# 解释:
共享目录 访问来源限制(权限)
[root@k8s-node1-1-72 ~]# mkdir -p /ifs/kubernetes
[root@k8s-node1-1-72 ~]# systemctl enable nfs --now
# 客户端测试
[root@k8s-node2-1-73 ~]# yum install -y nfs-utils
[root@k8s-node2-1-73 ~]# mount -t nfs 192.168.1.72:/ifs/kubernetes /mnt
[root@k8s-node2-1-73 ~]# df -Th | grep /ifs/kubernetes
192.168.1.72:/ifs/kubernetes nfs4 37G 4.3G 33G 12% /mnt
NFS卷:提供对NFS挂载支持,可以自动将NFS共享路径 挂载到Pod中
选项:
-
server: //指定NFS地址
-
path: /指定NFS共享目录
示例:将Nginx网站程序根目录持久化到 NFS存储,为多个Pod提供网站程序文件
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nfs-pod
name: nfs-pod
spec:
selector:
matchLabels:
app: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: web
image: nginx
volumeMounts:
- name: data-volume
mountPath: /usr/share/nginx/html //挂载的目录
volumes:
- name: data-volume //volume卷名称
nfs:
server: 192.168.1.72 //指定NFS地址
path: /ifs/kubernetes //NFS共享目录
验证1:容器之间的数据是否共享
[root@k8s-node2-1-73 ~]# kubectl apply -f nfs-pod.yaml
[root@k8s-master-1-71 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nfs-pod-9b57f886-d8rzx 1/1 Running 0 10m
nfs-pod-9b57f886-tk99z 1/1 Running 0 55s
nfs-pod-9b57f886-wpr9q 1/1 Running 0 10m
# 进入容器1,创建文件测试
[root@k8s-node2-1-73 ~]# kubectl exec -it nfs-pod-9b57f886-d8rzx -- bash
root@nfs-pod-9b57f886-d8rzx:/# df -Th |grep /ifs/kubernetes
192.168.1.72:/ifs/kubernetes nfs4 37G 4.3G 33G 12% /usr/share/nginx/html
root@nfs-pod-9b57f886-d8rzx:~# touch /usr/share/nginx/html/aaaaa
root@nfs-pod-9b57f886-d8rzx:~# ls /usr/share/nginx/html/
aaaaa
# 进入容器2,查看文件
[root@k8s-node2-1-73 ~]# kubectl exec -it nfs-pod-9b57f886-tk99z -- bash
root@nfs-pod-9b57f886-tk99z:/# ls /usr/share/nginx/html/
aaaaa
验证2:增加/删除Pod是否能继续使用共享存储数据
# 删除Pod,查看是否能继续使用共享存储数据
[root@k8s-master-1-71 ~]# kubectl delete pod nfs-pod-9b57f886-tk99z
[root@k8s-master-1-71 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nfs-pod-9b57f886-d8rzx 1/