后端学运维- k8s之数据存储

简介: 本文主要介绍 K8s中数据存储的使用

kubernetes的最小控制单元,容器都是运行在 pod 中的,一个pod中可以有 1 个或多个容器


这个概念我们早已了解,不难明白容器的生命周期会很短暂,当pod出现问题的时候,pod控制器会频繁的创建和销毁,而每个pod都是独立的,因此存储在容器中的数据也会被清除,这种结果无疑是致命打击。这时,可能就会有小伙伴说了,docker 中存在数据挂载,k8s 肯定也存在,我们可以利用数据挂载来解决该问题~ 那么,恭喜你答对了,k8s 中不仅支持数据挂载,而且支持的功能还相当强大,话不多说,我们接下来就进入数据世界~


数据存储


k8s中有个 Volume 的概念,VolumnPod 中能够被多个容器访问的共享目录,K8sVolume 定义在 pod 上,然后被一个 pod里的多个容器挂载到具体的文件目录下,k8s通过 Volume 实现同一个 pod 中不同容器之间的数据共享以及数据的持久化存储,Volume的生命周期不与pod中单个容器的生命周期相关,当容器终止或重启的时候,Volume中的数据也不会被丢失。


Volume 支持常见的类型如下:


网络异常,图片无法展示
|


除了上面列出来的这些,还有 gcePersistentDisk、awsElasticBlockStore、azureFileVolume、azureDisk 这些存储,但是因为使用较少,所以不做过多了解。下面我们就来详细看看每个存储该如何使用!


一、基本存储


1)EmptyDir


这是个最基础的 Volume类型,一个 EmptyDir 就是 Host 上的一个空目录。


概念:


它是在 Pod 被分配到 Node 节点上时才会被创建,初始内容为空,并且无需指定宿主机上对应的目录文件,它会自动在宿主机上分配一个目录


值得关注的是


Pod 销毁时,EmptyDir 中的数据也会被永久删除!


用处:


  1. 用作临时空间,比如 Web 服务器写日志或者 tmp 文件需要的临时目录。


  1. 用作多容器之间的共享目录(一个容器需要从另一个容器中获取数据的目录)


实战:


我们以nginx为例,准备一份资源清单


apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: cbuc-test
  labels:
    app: nginx-pod
spec:
  containers:
  - name: nginx
    image: nginx:1.14-alpine
    ports:
    - containerPort: 80
    volumeMounts: # 将 nginx-Log 挂载到nginx容器中,容器内目录为/var/log/nginx
    - name: nginx-log
      mountPath: /var/log/nginx
  volumes:  #在此声明volume
  - name: nginx-log
    emptyDir: {}


然后我们创建后可以看看emptyDir存储卷在宿主机的位置。默认情况下宿主机中声明volume的目录位置是在 /var/lib/kubelet/pods/<Pod 的 ID>/volumes/kubernetes.io~<Volume 类型 >/<Volume 名字 > 中。


2)HostPath


概念:


HostPath 就是将 Node 节点上一个实际目录挂载到pod中,供容器使用,这种好处就是在 pod 销毁后,该目录下的数据依然存在!


实战:


我们以 nginx 为例,准备一份资源清单:


apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: cbuc-test
  labels:
    app: nginx-pod
spec:
  containers:
  - name: nginx
    image: nginx:1.14-alpine
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-log
      mountPath: /var/log/nginx
  volumes:
  - name: nginx-log
    hostPath:           # 指定宿主机目录为 /data/nginx/log
      path: /data/nginx/log
      type: DirectoryOrCreate   # 创建类型


spec.volumes.hostPath.type(创建类型):


  • DirectoryOrCreate:目录存在就是用,不存在就先创建后使用
  • Directory: 目录必须存在
  • FileOrCreate: 文件存在就是用,不存在就创建后使用
  • File: 文件必须存在
  • Socket: unix 套接字必须存在
  • CharDevice: 字符设备必须存在
  • BlockDevice: 块设备必须存在


我们根据该资源清单可以创建出一个 pod,然后通过 podIp 访问该pod,再查看 /data/nginx/log 下的日志文件,发现已有日志产生


3)NFS


HostPath 是我们日常中比较经常使用到的存储方式了,已经可以满足基本的使用场景。目前为止我们小小的总结一下:EmptyDir 是针对 pod,如果 pod 被销毁了,那么改数据就会丢失。针对该问题,HostPath 进行了改进,存储变成是针对 Node ,但是如果 Node 宕机了,那么数据还是会丢失。这个时候就需要准备单独的网络存储系统了,而比较常用的便是 NFS、CIFS


概念:


NFS 是一个网络存储系统,可以搭建一台 NFS 服务器,然后将 Pod 中的存储直接连接到 NFS 系统上,这样的话,无论pod在节点上如何转移,只要 Node 节点和 NFS服务器对接没问题,数据就不会出现问题。


网络异常,图片无法展示
|


实战:


既然需要 NFS 服务器,那肯定需要自己搭建一个。我们选取 master 节点来安装NFS 服务器


# 安装 nfs 服务器
yum install -y nfs-utils
# 准备共享目录
mkdir -p /data/nfs/nginx
# 将共享目录以读写权限暴露给 192.168.108.0/24 网段的所有主机
vim /etc/exports
# 添加以下内容
/data/nfs/nginx    192.168.108.0/24(rw,no_root_squash)
# 启动 nfs 服务器
systemctl start nfs


然后我们在各个节点上同样安装 NFS,以供驱动 NFS 设备


yum install -y nfs-utils


做好以上准备后我们就可以准备资源清单文件了:


apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: cbuc-test
  labels:
    app: nginx
spec:
  containers:
  - name: nginx-pod
    image: nginx:1.14-alpine
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-log
      mountPath: /var/log/nginx
    volumes:
    - name: nginx-log
      nfs:
        server: 192.168.108.100   # NFS服务器地址,也就是master地址
        path: /data/nfs/nginx   # 共享文件路径


创建完pod后,我们可以进入到 /data/nfs 目录下查看到两个日志文件了


网络异常,图片无法展示
|


二、高级存储


管理存储是管理计算的一个明显问题,该部分需要抽象出如何根据消费方式来提供存储的详细信息。而 k8s 也很好的支持了,引入了两个新的 API 资源:PersistenVolumePersistentVolumeClaim


PersistenVolume(PV)是持久化卷的意思,是对底层共享存储的一种抽象,一般情况下PV由 k8s 管理员进行创建和配置,它与底层具体的共享存储技术有关,并通过插件完成与共享存储的对象。


PersistentVolumeClaim(PVC)是持久卷声明的意思,是用户对存储需求的一种声明,换句话说,PVC其实就是用户向 k8s 系统发出的一种资源需求申请。


网络异常,图片无法展示
|


1)PV

PV 是集群中由管理员配置的一段网络存储,它也是集群中的一种资源,资源清单模板如下:


apiVersion: v1
kind: PersistentVolume
meatadata:
  name: pv
spec:
  nfs:          # 存储类型,可以是 CIFS、GlusterFS
  capacity:       # 存储空间的设置
    storage: 2Gi
  accessModes:      # 访问模式
  storageClassName:   # 存储类别
  persistentVolumeReclaimPolicy:    # 回收策略


每个属性真的是又长又难记,我们先来看看每个属性的含义:


  • 存储类型


底层实际存储的类型,k8s 支持多种存储类型,每种存储类型的配置都有所差异


  • 存储能力(capacity)


目前只支持存储空间的设置,未来可能会加入 IOPS、吞吐量等指标的设置


  • 访问模式(accessModes)


用于描述用户应用对存储资源的访问权限,有以下几种访问权限:


  1. ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载


  1. ReadOnlyMany(ROM):只读权限,可以被多个节点挂载


  1. ReadWriteMany(RWM):读写权限,可以被多个节点挂载


  • 存储类别


PV 可以通过storageClassName参数指定一个存储类别


  1. 具有特定类别的PV只能与请求了该类别的PVC进行绑定


  1. 未设定类别的PV则只能与不请求任何类别的PVC进行绑定


  • 回收策略(persistentVolumeReclaimPolicy)


当PV没有再被使用的时候,需要对其处理的方式(不同的存储类型支持的策略也会不同),有以下几种回收策略:


  1. Retain(保留):保留数据。需要管理员手动清理数据


  1. Recycle(回收):清除PV中的数据,效果相当于 rm -rf


  1. Delete(删除):与 PV 相连的后端存储完成 volume 的删除操作,常见于云服务商的存储服务


生命周期:


一个 PV 的生命周期可能会处于4种不同的阶段:


  • Available(可用): 表示可用状态,还未被任何PVC绑定


  • Bound(已绑定): 表示PV已经被PVC绑定


  • Released(已释放): 表示PVC已被删除,但是资源还未被集群重新声明


  • Failed(失败): 表示该PV的自动回收失败


实战:


我们前面已经认识了NFS存储服务器,因此我们这里也依然使用 NFS 服务器做底层存储。首先我们需要创建1个PV,也对应着NFS中1个需要暴露的路径。


# 创建目录
mkdir /data/pv1 -pv
# 向NFS暴露路径
vim /etc/exports
/data/pv1   192.168.108.0/24(rw,no_root_squash)


完成以上步骤后我们就需要创建1个 PV:


apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv01
  namespace: cbuc-test
  labels:
    app: pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /data/pv1
    server: 192.168.108.100


通过创建后我们可以查看到PV:


网络异常,图片无法展示
|


2)PVC


PVC是资源的申请,用来声明对存储空间,访问模式,存储类别的需求信息,资源清单模板如下:


apiVersion: v1
kind: persistentVolumeClaim
metadata:
  name: pvc
  namespace: cbuc-test
  labels:
    app: pvc
spec:
  accessModes:      # 访问模式
  selector:       # 采用标签对PV选择
  storageClassName:   # 存储类别
  resources:        # 请求空间
    request:
      storage: 1Gi


很多属性我们在PV中已经了解到了,这里我们简单过一下~


  • 访问模式(accessModes)


用于描述用户应用对存储资源的访问权限


  • 选择条件(selector)


通过 Labels Selector的设置,对于系统中已经存在的PV进行筛选管理


  • 资源类别(storageClassName)


pvc在定义时可以设定需要的后端存储的类别,只有设置了该class的pv才能被系统选出


  • 资源请求(resources)


描述对存储资源的请求


实战:


准备1份PVC的资源清单模板:


apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc01
  namespace: cbuc-test
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi


创建后我们先查看PVC是否创建成功


网络异常,图片无法展示
|


然后再查看pv是否已经被pvc绑定上


网络异常,图片无法展示
|


3)实际使用


上面我们已经成功创建了 PV 和 PVC,但是还没说明如何使用,接下来我们就准备一份pod清单:


apiVersion: v1
kind: Pod
metadata:
  name: pod-pvc
  namespace: cbuc-test
spec:
  containers:
  - name: nginx01
    image: nginx:1.14-alpine
    volumeMounts:
    - name: test-pv
      mountPath: /var/log/nginx
  volumes:
  - name: test-pv
    persistentVolumeClaim:
      claimName: pvc01
      readOnly: true


4)生命周期


万物皆有生命周期,PV与PVC也不例外,生命周期如下:


  • 资源供应


管理员手动创建底层存储和PV


  • 资源绑定


用户创建PVC,k8s负责根据PVC的声明去寻找PV,并绑定。


  1. 如果找到,则会成功进行绑定,用户的应用就可以使用这个PVC了


  1. 如果找不到,PVC则会无限处于Pending的状态,直到等到系统管理员创建了一个符合其要求的PV


PV一旦绑定到某个PVC上,就会被这个PVC独占,不能再与其他PVC进行绑定了


  • 资源使用


用户可在Pod中想 volume 一样使用pvc


  • 资源释放


用户通过删除PVC来释放PV,当存储资源使用完毕后,用户可以删除PVC,与该PVC绑定的PV将会标记为 已释放,但还不能立刻与其他PVC进行绑定,通过之前PVC写入的数据可能还留在存储设备上,只有在清除之后该PV才能再次使用


  • 资源回收


k8s 会根据pv设置的回收策略进行资源的回收


上面列出了 PV和PVC 的生命周期,与其说是生命周期,但不如是PV和PVC的使用过程!


三、配置存储


配置存储,顾名思义就是用来存储配置的,其中包括了两种配置存储,分别是 ConfigMapSecret


1)ConfigMap


ConfigMap 是一种比较特殊的存储卷,它的主要作用是用来存储配置信息的。资源清单模板如下:


apiVersion: v1
kind: ConfigMap
metadata:
  name: cmp
  namespace: cbuc-test
data:
  info:
    username:cbuc
    sex:male


使用方式很简单,少了 spec,多了 data.info,只需在 info 下级以 key: value 的方式存储自己想要配置的配置文件即可


通过kubectl create -f configMap.yaml命令可创建出一个 ConfigMap


网络异常,图片无法展示
|


具体使用如下,我们需要创建一个Pod:


apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  namespace: cbuc-test
spec:
  containers:
  - name: nginx
    image: nginx:1.14-apline
    volumeMounts:   # 将 configMap 挂载到目录中
    - name: config
      mountPath: /var/configMap/config
  volumes:
  - name: config
    configMap:
      name: cmp  # 上面我们创建 configMap 的名称


然后通过命令kubectl create -f pod-cmp.yaml创建出测试Pod,然后可查看pod中的配置文件:


网络异常,图片无法展示
|


2)Secret


在 k8s 中,还存在一种和 ConfigMap 非常类似的对象,称之为 Secret 对象。它主要用于存储敏感信息,例如密码、秘钥、证书等信息。


我们首先对想要配置的数据进行 base64 加密:


# 加密用户名
[root@master test]# echo -n 'cbuc' | base64
Y2J1Yw==
# 加密密码
[root@master test]# echo -n '123456' | base64
MTIzNDU2


然后准备 Secret 资源清单文件


apiVersion: v1
kind: Secret
metadata:
  name: secret
  namespace: cbuc-test
type: Opaque    # 表示base64编码格式的Secret
data:
  username: Y2J1Yw==
  password: MTIzNDU2


通过命令kubectl create -f secret.yaml创建 Secret,然后我们再准备一份Pod资源清单:


apiVersion: v1
kind: Pod
metadata:
  name: pod-secret
  namespace: cbuc-test
spec:
  containers:
  - name: nginx
    image: nginx:1.14-apline
    volumeMounts:
    - name: config
      mountPath: /var/secret/config
  volumes:
  - name: config
    secret:
      secretName: secret


网络异常,图片无法展示
|


创建后我们进入pod查看配置文件,可以发现配置文件的信息已经是解码后的


网络异常,图片无法展示
|


相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
目录
相关文章
|
11天前
|
运维 Kubernetes 监控
揭秘高效运维:如何用kubectl top命令实时监控K8s资源使用情况?
揭秘高效运维:如何用kubectl top命令实时监控K8s资源使用情况?
138 0
|
11天前
|
运维 Kubernetes 监控
构建高效自动化运维体系:基于Docker和Kubernetes的实践指南
【2月更文挑战第30天】 在当今快速发展的云计算时代,传统的IT运维模式已难以满足业务的敏捷性和稳定性需求。本文深入探讨了如何通过Docker容器化技术和Kubernetes集群管理工具构建一个高效、可靠的自动化运维体系。文章首先概述了容器化技术和微服务架构的基本概念,随后详细阐述了基于Docker的应用打包、部署流程,以及Kubernetes在自动化部署、扩展和管理容器化应用中的关键作用。最后,文中通过案例分析,展示了如何在实际场景中利用这些技术优化运维流程,提高系统的整体效率和可靠性。
|
11天前
|
运维 Kubernetes 容器
K8S运维命令必备kubectl命令总结
K8S运维命令必备kubectl命令总结
40 3
|
11天前
|
消息中间件 运维 Kubernetes
构建高效自动化运维体系:Ansible与Kubernetes的融合实践
【5月更文挑战第9天】随着云计算和微服务架构的普及,自动化运维成为确保系统可靠性和效率的关键。本文将深入探讨如何通过Ansible和Kubernetes的集成,构建一个强大的自动化运维体系。我们将分析Ansible的配置管理功能以及Kubernetes容器编排的优势,并展示如何将二者结合,以实现持续部署、快速扩展和高效管理现代云原生应用。文章还将涵盖实际案例,帮助读者理解在真实环境下如何利用这些工具优化运维流程。
|
11天前
|
运维 Kubernetes Cloud Native
构建高效云原生运维体系:Kubernetes最佳实践
【5月更文挑战第9天】 在动态和快速演变的云计算环境中,高效的运维是确保应用稳定性与性能的关键。本文将深入探讨在Kubernetes环境下,如何通过一系列最佳实践来构建一个高效且响应灵敏的云原生运维体系。文章不仅涵盖了容器化技术的选择与优化、自动化部署、持续集成/持续交付(CI/CD)流程的整合,还讨论了监控、日志管理以及灾难恢复策略的重要性。这些实践旨在帮助运维团队有效应对微服务架构下的复杂性,确保系统可靠性及业务的连续性。
|
11天前
|
人工智能 运维 监控
构建高性能微服务架构:现代后端开发的挑战与策略构建高效自动化运维系统的关键策略
【2月更文挑战第30天】 随着企业应用的复杂性增加,传统的单体应用架构已经难以满足快速迭代和高可用性的需求。微服务架构作为解决方案,以其服务的细粒度、独立性和弹性而受到青睐。本文将深入探讨如何构建一个高性能的微服务系统,包括关键的设计原则、常用的技术栈选择以及性能优化的最佳实践。我们将分析微服务在处理分布式事务、数据一致性以及服务发现等方面的挑战,并提出相应的解决策略。通过实例分析和案例研究,我们的目标是为后端开发人员提供一套实用的指南,帮助他们构建出既能快速响应市场变化,又能保持高效率和稳定性的微服务系统。 【2月更文挑战第30天】随着信息技术的飞速发展,企业对于信息系统的稳定性和效率要求
|
11天前
|
存储 运维 Kubernetes
构建高效自动化运维体系:Ansible与Kubernetes的协同实践
【5月更文挑战第2天】随着云计算和微服务架构的兴起,自动化运维成为保障系统稳定性与效率的关键。本文将深入探讨如何利用Ansible作为配置管理工具,结合Kubernetes容器编排能力,共同打造一个高效、可靠的自动化运维体系。通过剖析二者的整合策略及具体操作步骤,为读者提供一套提升运维效率、降低人为错误的实用解决方案。
|
11天前
|
存储 运维 Kubernetes
构建高效自动化运维体系:Ansible与Kubernetes的协同策略
【4月更文挑战第29天】 在当今快速迭代的软件开发环境中,自动化运维成为了确保部署效率和稳定性的关键。本文深入探讨了如何通过Ansible和Kubernetes的集成来实现高效的自动化配置管理与容器编排。文章首先介绍了Ansible与Kubernetes各自的特点及优势,随后详细阐述了它们在自动化运维中的互补作用,并提供了一个实用的集成方案。通过案例分析,验证了该策略在提高部署速度、降低人为错误以及增强系统可靠性方面的有效性。最后,讨论了实施过程中可能遇到的挑战和解决思路。
|
11天前
|
运维 Kubernetes 安全
构建高效自动化运维体系:Ansible与Kubernetes的协同实践
【4月更文挑战第29天】 在当今快速迭代的软件发布周期中,自动化已成为维护大规模服务部署的关键。本文聚焦于将Ansible和Kubernetes结合使用,构建一个灵活、可扩展的自动化运维体系。通过分析两者的技术特性及互补优势,我们将探讨如何优化配置管理流程,实现持续集成和持续部署(CI/CD),并确保系统的稳定性与安全性。此研究不仅为读者提供一套行之有效的运维解决方案,同时也为未来运维技术的发展提供了参考方向。
|
11天前
|
运维 Kubernetes 监控
构建高效自动化运维体系:Ansible与Kubernetes的完美结合
【4月更文挑战第29天】 在当今快速迭代的IT环境中,自动化已成为提高运维效率、减少人为错误的关键。本文将探讨如何通过Ansible和Kubernetes的结合来构建一个高效的自动化运维体系。文章首先分析了Ansible作为配置管理工具的优势,然后讨论了Kubernetes在容器编排领域的领导地位,最后详细阐述了如何将两者融合以实现更灵活、可扩展的自动化策略。