JavaEE 企业级分布式高级架构师(十八)容器虚拟化技术(6)

Kubernetes的存储资源对象

Volume数据卷

为什么要用Volumes

  • k8s中容器中的磁盘的生命周期是短暂的,这就带来了一些列的问题:
    • 当一个容器损坏之后,kubelet会重启这个容器,但是容器中的文件将丢失,容器以干净的状态重新启动。
    • 当很多容器运行在同一个pod中时,很多时候需要数据文件的共享。
    • 在 K8S 中,由于 POD 分布在各个不同的节点之上,并不能实现不同节点之间持久性数据的共享,并且在节点故障时,可能会导致数据的永久性丢失。
  • Volumes就是用来解决以上问题的:Volume 的生命周期独立于容器,Pod 中的容器可能被销毁和重建,但 Volume 会被保留。

Volume数据结构

在这里插入图片描述

  • Volume 是 POD 内部容器共享的数据卷,被 Pause 容器所创建的,当 POD 内部容器宕机、崩溃的时候,Volume 数据卷不会消失,一旦 POD 宕机、崩溃,Volume 数据卷就消失了。
  • 问题:Volume 数据本身是否能够存储数据?
  • 答案:不可以,Volume 本身是 K8S 抽象出来的资源对象,此对象本身不能存储数据,而是用来把数据挂载到容器内部,因此 Volume 数据卷仅仅是进行数据挂载的(从磁盘、网络、文件系统把数据挂载到容器内部)。

数据卷类型

  • kubenetes卷的类型:

在这里插入图片描述

  • 第一种就是本地卷:像 hostPath 类型与 docker 里面的 bind mount 类型,就是直接挂载到宿主机文件的类型;像 emptyDir 是种本地卷,也就是类似于 volume 类型,这两个都是绑定node节点的。
  • 第二种就是网络数据卷:比如 Nfs、ClusterFs、Ceph,这些都是外部的存储都可以挂载到k8s上。
  • 第三种就是云盘:比如AWS、微软(azuredisk)。
  • 第四种就是k8s自身的资源:比如 secret、configmap、downwardAPI。
emptyDir
  • 先来看一下本地卷,像 emptyDir 类似于 docker 的 Volume,而 docker 删除容器,数据卷还会存在,而 emptyDir 删除容器,数据卷也会丢失,一般这个只做临时数据卷来使用。
  • 创建一个空卷,挂载到 Pod 中的容器。Pod 删除,该卷也会被删除。
  • 应用场景:Pod 中容器之间数据共享。
  • 当 Pod 被分配给节点时,首先创建 emptyDir 卷,并且只要该 Pod 在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的,Pod 中的容器可以读取和写入 emptyDir 卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或者不同路径上。当出于任何原因从节点删除 Pod 时,emptyDir 中的数据将被永久删除。
  • 注意:容器崩溃不会从节点中移除 Pod,因此 emptyDir 卷中的数据在容器崩溃时是安全的。
  • emptyDir的用法:
1、暂存空间,例如用于基于磁盘的合并排序
2、用作长时间计算崩溃恢复时候的检查点
3、web服务器容器提供数据时,保存内容管理器容器提取的文件
  • 使用:定义 POD 的 yaml文件
# emptyDir-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-pod1
spec:
  containers:
    - name: test-container
      image: hub.veli.com/library/nginx:latest
      volumeMounts:
        - name: cache-volume
          mountPath: /cache
  volumes:
    - name: cache-volume
      emptyDir: {}

---
apiVersion: v1
kind: Pod
metadata:
  name: test-pod2
spec:
  containers:
  - image: hub.veli.com/library/nginx:latest
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  - name: test-1
    image: hub.veli.com/library/nginx:latest
    command: ["/bin/sh","-c","sleep 3600s"]
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}

在这里插入图片描述

  • 创建执行:
kubectl apply -f emptyDir-pod.yaml

在这里插入图片描述

  • 分别打开两个 Session,进入到这两个容器中:
kubectl exec -it test-pod2 -c test-container
kubectl exec -it test-pod2 -c test-1 -- sh

在这里插入图片描述

Hostpath
  • 挂载 Node文 件系统上的文件或者目录到Pod中的容器。
  • 应用场景:Pod 中容器需要访问宿主机文件。
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - image: hub.veli.com/library/nginx:latest
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    hostPath:
      path: /data
      type: Directory

在这里插入图片描述

  • 除了所需的path属性职位,用户还可以为hostPath卷指定type:

在这里插入图片描述

  • 创建执行:
kubectl apply -f hotspath-pod.yaml

在这里插入图片描述

  • 需要先在 centos110 这个节点创建 /data 目录,创建好目录后,再次查看:已经OK了

在这里插入图片描述

  • 测试一下:

在这里插入图片描述

网络卷
准备NFS环境
  • 安装NFS:
yum install nfs-utils -y
  • 暴露目录,让是让其他服务器能挂载这个目录
mkdir /opt/k8s
vim /etc/exports
# 给这个网段加上权限,可读可写
/opt/k8s 192.168.254.0/24(rw,no_root_squash)
  • 启动NFS:
systemctl start nfs
# 关防火墙
systemctl stop firewalld
测试NFS挂载
  • 找个节点去挂载测试一下,只要去共享这个目录就要都去安装这个客户端
yum install nfs-utils -y
mount -t nfs 192.168.254.114:/opt/k8s /mnt
cd mnt
df -h

在这里插入图片描述

远程网络文件挂载
  • NFS服务端 centos114 创建目录:mkdir /opt/k8s/wwwroot
  • 定义 nfs-pod.yaml:
# vim nfs.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nfs
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: hub.veli.com/library/nginx:latest
        volumeMounts:
        - name: wwwroot
          mountPath: /usr/share/nginx/html
        ports:
        - containerPort: 80
      volumes:
      - name: wwwroot
        nfs:
          server: 192.168.254.114
          path: /opt/k8s/wwwroot
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx
  type: NodePort

在这里插入图片描述

  • 将容器中的目录(/usr/share/nginx/html:nginx 的根目录)挂载到远程NFS服务端的目录(/opt/k8s/wwwroot),并且该POD设置了Service的IP类型为NodePort,这样外网可以访问。
  • 执行创建:
kubectl apply -f nfs-pod.yaml

在这里插入图片描述

  • 测试一下
    在这里插入图片描述
  • 外网访问一下:

在这里插入图片描述

存储介质

  • 如下图所示: Volume数据卷直接挂载存储介质,是否存在问题?

在这里插入图片描述

  • Volume 数据卷直接和底层的存储介质直接进行交互的,耦合性较高。
  • Kubernetes 无法控制底层存储介质(存储设备多种多样:高速设备、慢速设备,不同厂商提供的服务存储服务),也就是说底层存储介质是复杂多样的,Volume 进行数据卷挂载的时候,都需要做出适当的适配,要做出调整。
  • 也不能控制需要多大空间,不能自由分配和调度。
  • 访问模式:RMO、RWM ,不能进行自由控制。
  • 一旦 POD 宕机,Volume 数据会丢失,影响数据完整性。

提出你的解决方案:解耦,屏蔽掉对底层复杂操作,让上层操作更简单、高效。

PV与PVC

PV是什么?

  • PV(Persistent Volume) 持久化的数据卷,Kubernetes 为了部署有状态服务(存储持久化的数据,让数据操作更简单高效)而抽象出的一个持久化的数据存储对象。其作用就是屏蔽掉对底层的复杂操作,使得 Kubernetes 更好的管理存储资源。

在这里插入图片描述

  • 说明: PV 屏蔽掉 POD 对底层的存储介质的复杂操作,使得 POD 在数据存储管理将会更加方便。PV 对象生命周期是独立的:POD 宕机了,PV 对象不会消失,数据不会丢失。

PV原理解析

  • PV 资源对象由运维先创建好:按照规划需求,创建多大的空间,访问方式等等。

在这里插入图片描述

  • 可以把 PV 资源对象看做一个个的存储块(对底层物理存储介质抽象),使得 Kubernetes 服务部署的时候使用存储空间就更加自由了,也就是说使用哪个存储块(存储大小自由控制,访问方式)进行自由匹配。
  • PV 对象把底层存储介质(物理存储硬件,不可分割状态)抽象成一个一个虚拟化的存储块,使得 Kubernetes 可以自由的管理存储介质。PV 对象都是根据业务需求事先创建好的,因此 PV 资源对象创建必须经过合理规划、编排。

问题:如何去获取 PV 存储块呢?
创建 POD 对象的时候,需要存储数据,向 PV 对象发出请求,绑定一个合适的 PV 对象即可。
问题:当创建 POD 的时候,需要存储数据(10GB),向 PV 发出请求,匹配一个合适的大小的 PV 对象,但是 PV 对象有成千上万个,如何匹配?
解决方案: 使用 PVC 接受请求,帮助 POD 匹配一个合适的 PV 对象(相当于做了请求转发)。

PVC是什么

  • PVC(Persistent Volume Claim 持久卷声明,简称PVC)是用户的一种存储请求,PVC 代理 POD 发送对存储资源申请的一个请求,且匹配一个合适的 PV 存储块(资源对象)。
  • 它和 POD 类似,POD 消耗 Node 资源,而 PVC 消耗 PV 资源。POD 能够请求特定的资源(如CPU和内存),PVC能够请求指定的大小和访问的模式的PV(可以被映射为一次读写或者多次只读)。

在这里插入图片描述

PVC原理

在这里插入图片描述

  • 创建 POD 服务,申请存储空间,存储数据:
    • 向 PVC 发出请求,让 PVC 绑定一个合适的 PV 存储块对象。
    • PVC 发送申请请求,申请一个合适的 PV 存储块,根据以下方式的进行匹配绑定的
      • 访问方式: RWO、RWM
      • 访问大小 :5GB
  • PVC根据以上2点进行匹配到一个合适的pv资源对象的,首先匹配的是访问模式,然后匹配的是访问大小。

生命周期

  • Volume 和 claim 的生命周期:PV 是集群中的资源,PVC 是对这些资源的请求,同时也是这些资源的“提取证”。PV 和 PVC 的交互遵循以下生命周期:
供给
  • 有两种 PV 提供的方式:静态和动态。
  • 静态:集群管理员创建多个 PV,它们携带着真实存储的详细信息,这些存储对于集群用户是可用的。它们存在于 Kubernetes API 中,并可用于存储使用。
  • 动态:当管理员创建的静态 PV 都不匹配用户的 PVC 时,集群可能会尝试专门地供给 Volume 给 PVC。这种供给基于 StorageClass:PVC 必须请求这样一个等级,而管理员必须已经创建和配置过这样一个等级,以备发生这种动态供给的情况。请求等级配置为“”的 PVC,有效地禁用了它自身的动态供给功能。
绑定
  • 用户创建一个 PVC(或者之前就已经就为动态供给创建了),指定要求存储的大小和访问模式。Master 中有一个控制回路用于监控新的 PVC,查找匹配的 PV(如果有),并把 PVC 和 PV 绑定在一起。如果一个 PV 曾经动态供给到了一个新的 PVC,那么这个回路会一直绑定这个 PV 和 PVC。另外,用户总是至少能得到它们所要求的存储,但是 Volume 可能超过它们的请求。一旦绑定了,PVC 绑定就是专属的,无论它们的绑定模式是什么。
  • 如果没找到匹配的 PV,那么 PVC 会无限期得处于 unbound 未绑定状态,一旦 PV 可用了,PVC 就会又变成绑定状态。比如,如果一个供给了很多 50G 的 PV 集群,不会匹配要求 100G 的 PVC。直到 100G 的 PV 添加到该集群时,PVC 才会被绑定。
使用
  • POD 使用 PVC 就像使用 Volume 一样。集群检查 PVC,查找绑定的 PV,并映射 PV 给 POD。对于支持多种访问模式的 PV,用户可以指定想用的模式。一旦用户拥有了一个 PVC,并且 PVC 被绑定,那么只要用户还需要,PV 就一直属于这个用户。用户调度POD,通过在 POD 的 Volume 块中包含 PVC 来访问 PV。
释放
  • 当用户使用 PV 完毕后,他们可以通过 API 来删除 PVC 对象。当 PVC 被删除后,对应的 PV 就被认为是已经是“released”了,但还不能再给另外一个 PVC 使用。前一个 PVC 的属于还存在于该 PV 中,必须根据策略来处理掉。
回收
  • PV 的回收策略告诉集群,在 PV 被释放之后集群应该如何处理该 PV。当前,PV 可以被 Retained(保留)、 Recycled(再利用)或者Deleted(删除)。保留允许手动地再次声明资源。对于支持删除操作的 PV 卷,删除操作会从 Kubernetes 中移除 PV 对象,还有对应的外部存储(如AWS EBS,GCE PD,Azure Disk,或者Cinder volume)。动态供给的卷总是会被删除。

PVC&PV案例

  • 定义两个 PV:
# vim pv1.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv1
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  nfs:
    path: /opt/k8s/pv-demo1
    server: 192.168.254.114
# vim pv2.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv2
spec:
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteMany
  nfs:
    path: /opt/k8s/pv-demo2
    server: 192.168.254.114
  • 执行创建 PV:
kubectl apply -f pv1.yaml
kubectl apply -f pv2.yaml

在这里插入图片描述

  • 定义一个 POD,并通过 PVC 挂载我们的 PV:
# vim pod-pv.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-pv
spec:
  containers:
  - name: nginx
    image: hub.veli.com/library/nginx:latest
    ports:
    - containerPort: 80
    volumeMounts:
      - name: www
        mountPath: /usr/share/nginx/html
  volumes:
    - name: www
      persistentVolumeClaim:
        claimName: my-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 2Gi

在这里插入图片描述

  • 执行创建 PVC和POD:
kubectl apply -f pv1.yaml
kubectl apply -f pv2.yaml

在这里插入图片描述

  • 测试一下:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

讲文明的喜羊羊拒绝pua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值