【云原生 | Kubernetes 实战】13、K8s 常见的存储方案及具体应用场景分析(上)

导读:本篇文章讲解 【云原生 | Kubernetes 实战】13、K8s 常见的存储方案及具体应用场景分析(上),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

目录

K8s 持久化存储

一、k8s 持久化存储:emptyDir

二、k8s 持久化存储:hostPath

三、k8s 持久化存储:nfs

3.1 搭建 nfs 服务

3.2 创建Pod,挂载 NFS 共享出来的目录

3.3 测试 pod 挂载 nfs 是否成功


K8s 持久化存储

        在 k8s 中为什么要做持久化存储?k8s 中部署的应用都是以 pod 容器的形式运行的,假如我们部署 MySQL 、 Redis 等数据库需要对这些数据库产生的数据做备份 。因为 Pod 是有生命周期的,如果 pod 不挂载数据卷,那 pod 被删除或重启后这些数据会随之消失,如果想要长久的保留这些数据就要用到 pod 数据持久化存储。

查看 k8s 支持哪些存储类型:

[root@k8s-master01 ~]# kubectl explain pods.spec.volumes

常用的如下:

  • emptyDir
  • hostPath
  • nfs
  • persistentVolumeClaim
  • glusterfs
  • cephfs
  • configMap
  • secret

我们想要使用存储卷,需要经历如下步骤:

  1. 定义 pod 的 volume ,这个 volume 指明它要关联到哪个存储上的;
  2. 在容器中要使用 volumemounts 挂载对应的存储 。

一、k8s 持久化存储:emptyDir

        emptyDir 类型的 Volume 是在 Pod 分配到 Node 上时被创建, Kubernetes 会在 Node 上自动分配一个目录,因此无需指定宿主机 Node 上对应的目录文件。 这个目录的初始内容为空,当 Pod 从 Node 上移除时, emptyDir 中的数据会被永久删除。 emptyDir Volume 主要用于某些应用程序无需永久保存的临时目录,多个容器的共享目录等 。

emptyDir 的一些用途:

  • 缓存空间,例如基于磁盘的归并排序。
  • 为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。
  • 在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。
# 创建个存放此次实验 yaml 文件的目录
[root@k8s-master01 ~]# mkdir volumes
[root@k8s-master01 ~]# cd volumes/

# 查看帮助命令
[root@k8s-master01 volumes]# kubectl explain pods
[root@k8s-master01 volumes]# kubectl explain pods.metadata
[root@k8s-master01 volumes]# kubectl explain pods.spec
[root@k8s-master01 volumes]# kubectl explain pods.spec.containers
[root@k8s-master01 volumes]# kubectl explain pods.spec.volumes
[root@k8s-master01 volumes]# kubectl explain pods.spec.volumes.emptyDir
[root@k8s-master01 volumes]# kubectl explain pods.spec.containers.volumeMounts

# 创建一个 pod,挂载临时目录 emptyDir
[root@k8s-master01 volumes]# vim 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    # 必须与 emptyDir.name 同名
  volumes:
  - emptyDir: {}
    name: cache-volume


[root@k8s-master01 volumes]# kubectl apply -f emptydir.yaml
pod/pod-empty created

# pod 调度到 node2 节点了
[root@k8s-master01 volumes]# kubectl get pods -o wide 
NAME        READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
pod-empty   1/1     Running   0          17s   10.244.169.157   k8s-node2   <none>           <none>

# 查看 pod 的 uid
[root@k8s-master01 volumes]# kubectl get pods pod-empty -o yaml | grep uid
  uid: b8bf8521-cd8d-4085-8ae0-328fa6241879

# 在 node2 查看临时目录
[root@k8s-node2 ~]# tree /var/lib/kubelet/pods/b8bf8521-cd8d-4085-8ae0-328fa6241879
[root@k8s-node2 ~]# cd /var/lib/kubelet/pods/b8bf8521-cd8d-4085-8ae0-328fa6241879/volumes/kubernetes.io~empty-dir/cache-volume/

# 在 master 节点进入容器内部,在挂载目录创建文件
[root@k8s-master01 volumes]# kubectl exec -it pod-empty -- bash
root@pod-empty:/# cd cache/
root@pod-empty:/cache# touch 1.txt

# 在 node2 本地挂载目录可以同步看到
[root@k8s-node2 cache-volume]# ls
1.txt

# 而在 node2 本地挂载目录下创建文件,也能同步到容器中
[root@k8s-node2 cache-volume]# touch 2.txt
root@pod-empty:/cache# ls
1.txt  2.txt

# 如果删除了 pod,那么 node2 本地挂载目录及数据也会被删除
[root@k8s-master01 volumes]# kubectl delete -f emptydir.yaml 
pod "pod-empty" deleted

[root@k8s-node2 cache-volume]# ls
[root@k8s-node2 cache-volume]# cd ../
cd: 获取当前目录时出错: getcwd: 无法访问父目录: 没有那个文件或目录

        由上可知,临时目录在被调度到的 node2 节点本地的 /var/lib/kubelet/pods/b8bf8521-cd8d-4085-8ae0-328fa6241879/volumes/kubernetes.io~empty-dir/cache-volume/ 下。

官方参考文档:卷 | Kubernetes 

二、k8s 持久化存储:hostPath

        hostPath Volume 是指 Pod 挂载宿主机上的目录或文件。 hostPath Volume 使得容器可以使用宿主机的文件系统进行存储 hostpath (宿主机路径):节点级别的存储卷,在 pod 被删除,这个存储卷还是存在的,不会被删除,但要同一个 pod 被调度到同一个节点上来,在 pod 被删除重新被调度到这个节点之后,对应的数据依然是存在的。

# 查看 hostPath 存储卷的用法
[root@k8s-master01 volumes]#  kubectl explain pods.spec.volumes.hostPath

# 创建一个 pod ,挂载 hostPath 存储卷
[root@k8s-master01 volumes]# vim hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-hostpath
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: test-nginx
    volumeMounts:
    - mountPath: /test-nginx
      name: test-volume
  - image: billygoo/tomcat8-jdk8
    imagePullPolicy: IfNotPresent
    name: test-tomcat
    volumeMounts:
    - mountPath: /test-tomcat
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      path: /data1
      type: DirectoryOrCreate     # DirectoryOrCreate 表示本地有 data1 目录,就用本地的,本地没有就会在 pod 调度到的节点自动创建一个。
# 更新资源清单文件
[root@k8s-master01 volumes]# kubectl apply -f hostpath.yaml 
pod/test-hostpath created

# 查看 pod 调度 到了哪个物理节点
[root@k8s-master01 volumes]# kubectl get pods -o wide 
NAME            READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
test-hostpath   2/2     Running   0          8s    10.244.169.158   k8s-node2   <none>           <none>

支持的 type 值如下:

【云原生 | Kubernetes 实战】13、K8s 常见的存储方案及具体应用场景分析(上)        由上面可以知道 pod 调度到了node2 上,登录到 node2 机器,查看是否在这台机器创建了存储目录:

# data1 目录权限为 755
[root@k8s-node2 ]# cd /
[root@k8s-node2 /]# ll | grep data1
drwxr-xr-x    2 root root    6 12月 15 21:16 data1

# 在本地挂载目录下创建文件
[root@k8s-node2 /]# cd data1/
[root@k8s-node2 data1]# touch 1.txt

# 测试存储卷是否可以正常使用,登录到 nginx 容器
[root@k8s-master01 volumes]# kubectl exec -it test-hostpath -c test-nginx -- bash               
root@test-hostpath:/# cd test-nginx/
root@test-hostpath:/test-nginx# ls
1.txt
root@test-hostpath:/test-nginx# touch 2.txt

# 登录到 tomcat 容器
[root@k8s-master01 volumes]# kubectl exec -it test-hostpath -c test-tomcat -- bash
root@test-hostpath:/usr/local/tomcat# cd /test-tomcat/
root@test-hostpath:/test-tomcat# ls
1.txt  2.txt

        通过上面测试可以看到, 同一个 pod 里的 test nginx 和 test tomcat 这两个容器是共享存储卷
的 。

# 删除 pod ,并使其调度到 node1
[root@k8s-master01 volumes]# vim hostpath.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: test-hostpath
spec:
  nodeName: k8s-node1    # 调度到 node1
  containers:

[root@k8s-master01 volumes]# kubectl delete -f hostpath.yaml 
pod "test-hostpath" deleted

[root@k8s-master01 volumes]# kubectl apply -f hostpath.yaml 
pod/test-hostpath created

[root@k8s-master01 volumes]# kubectl get pods -o wide 
NAME            READY   STATUS    RESTARTS   AGE     IP             NODE        NOMINATED NODE   READINESS GATES
test-hostpath   2/2     Running   0          2m42s   10.244.36.67   k8s-node1   <none>           <none>

        重新进入两个容器内部,会发现原来的(数据)两个文件没有了,本地 node1 节点挂载目录下也没有数据,只有把 pod 重新调度到 node2 节点数据才能恢复!

        hostpath 存储卷缺点:单节点,pod 删除之后重新创建必须调度到同一个 node 节点,数据才不会丢失。

官方参考文档:卷 | Kubernetes

三、k8s 持久化存储:nfs

        NFS:网络文件系统,英文 Network File System(NFS) NFS),是由 SUN 公司研制的 UNIX 表示层 协议(presentation layer protocol),能使使用者访问网络上别处的文件就像在使用自己的计算机一样。

        在 k8s 中,nfs 卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

3.1 搭建 nfs 服务

#1. 搭建 nfs 服务。所有节点都安装 nfs,以 k8s 的控制节点作为 NFS 服务端,工作节点为客户端
yum install -y nfs-utils

#2. 在宿主机创建 NFS 需要的共享目录
[root@k8s-master01 ~]# mkdir /data/volumes -pv

#3. 所有节点启动 nfs 并设置开机自启
systemctl enable nfs --now

#4. 配置 nfs 共享服务器上的 /data/volumes 目录
[root@k8s-master01 ~]# vim /etc/exports
/data/volumes *(rw,no_root_squash)

# * :所有客户端都可以访问
# rw:该主机对该共享目录有读写权限
# no_root_squash:登入 NFS 主机使用分享目录的使用者,如果是 root 的话,那么对于这个分享的目录来说,他就具有 root 的权限

#5. 使 NFS 配置生效
[root@k8s-master01 ~]# exportfs -arv
exporting *:/data/volumes

#6. 在 node1 上手动挂载试试
[root@k8s-node1 ~]# mkdir /test 

# 控制节点的宿主机 ip
[root@k8s-node1 ~]# mount 192.168.78.133:/data/volumes /test/

# 说明 nfs 搭建成功
[root@k8s-node1 ~]# df -Th |grep nfs
192.168.78.133:/data/volumes nfs4       27G  7.9G   20G   29% /test

# 卸载目录
[root@k8s-node1 ~]# umount /test 
[root@k8s-node1 ~]# df -Th |grep nfs

3.2 创建Pod,挂载 NFS 共享出来的目录

# 查看帮助命令
[root@k8s-master01 ~]# kubectl explain deployment
[root@k8s-master01 ~]# kubectl explain deployment.spec
[root@k8s-master01 ~]# kubectl explain deployment.spec.selector
[root@k8s-master01 ~]# kubectl explain deployment.spec.template
[root@k8s-master01 ~]# kubectl explain deployment.spec.template.spec
[root@k8s-master01 ~]# kubectl explain deployment.spec.template.spec.containers
[root@k8s-master01 ~]# kubectl explain deployment.spec.template.spec.containers.ports
[root@k8s-master01 ~]# kubectl explain deployment.spec.template.spec.volumes
[root@k8s-master01 ~]# kubectl explain deployment.spec.template.spec.volumes.nfs

[root@k8s-master01 volumes]# vim nfs.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
 name: nfs-test
spec:
  replicas: 3
  selector:
    matchLabels:
      cunchu: nfs
  template:
    metadata:
      labels:
        cunchu: nfs
    spec:
       containers:
       - name: test-nfs
         image: nginx
         imagePullPolicy: IfNotPresent
         ports:
         - containerPort: 80
           protocol: TCP
         volumeMounts:
         - name: nfs-volumes
           mountPath: /usr/share/nginx/html
       volumes:
       - name: nfs-volumes
         nfs:
           path: /data/volumes
           server: 192.168.78.133

# 删除前面创建的 pod
[root@k8s-master01 volumes]# kubectl delete -f hostpath.yaml 
pod "test-hostpath" deleted

# 更新资源清单文件
[root@k8s-master01 volumes]# kubectl apply -f nfs.yaml 
deployment.apps/nfs-test created

# 查看 pod 信息
[root@k8s-master01 volumes]# kubectl get pods -o wide 
NAME                        READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
nfs-test-6bcdf5f5d6-4g7fk   1/1     Running   0          65s   10.244.169.161   k8s-node2   <none>           <none>
nfs-test-6bcdf5f5d6-g5lsj   1/1     Running   0          65s   10.244.169.162   k8s-node2   <none>           <none>
nfs-test-6bcdf5f5d6-hfwqc   1/1     Running   0          65s   10.244.36.74     k8s-node1   <none>           <none>

3.3 测试 pod 挂载 nfs 是否成功

# 登录到 nfs 服务器,在共享目录创建一个 index.html
[root@k8s-master01 volumes]# cd /data/volumes/
[root@k8s-master01 volumes]# vim index.html
hello sky

# 请求任意 pod,查看结果
[root@k8s-master01 ~]# curl 10.244.169.161
hello sky

# 通过上面可以看到,在共享目录创建的 index.html 已经被 pod 挂载了

# 登录到 pod 验证下
[root@k8s-master01 volumes]# kubectl exec -it nfs-test-6bcdf5f5d6-4g7fk -- bash
root@nfs-test-6bcdf5f5d6-4g7fk:/# cat /usr/share/nginx/html/index.html 
hello sky

        上面说明挂载 nfs 存储卷成功了,nfs 支持多个客户端挂载,可以创建多个 pod,挂载同一个nfs 服务器共享出来的目录;但是 nfs 如果宕机了,数据也就丢失了,所以需要使用分布式存储,常见的分布式存储有 glusterfs 和 cephfs(后面会讲到)。

pod 挂载 nfs 官方参考文档:卷 | Kubernetes  

上一篇文章:【云原生 | Kubernetes 实战】12、K8s 四层代理 Service 入门到企业实战应用(下)_Stars.Sky的博客-CSDN博客

下一篇文章:【云原生 | Kubernetes 实战】13、K8s 常见的存储方案及具体应用场景分析(中)_Stars.Sky的博客-CSDN博客

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/74545.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!