ASP.NET Core on K8S深入学习(8)数据管理

简介: 本文探索了K8S的数据管理方案Volume,其中普通类型的Volume如emptyDir和hostPath虽然使用方便,但是可持久性不强,而外部云存储Volume Provider则提供了更好的持久化存储。

在Docker中我们知道,要想实现数据的持久化(所谓Docker的数据持久化即_数据不随着Container的结束而结束_),需要将数据从宿主机挂载到容器中,常用的手段就是Volume数据卷。在K8S中,也提供了存储模型Volume,支持我们将应用中的数据持久化存储到容器中。

一、Volume

1.1 关于K8S Volume

  为了持久化保存容器的数据,我们可以使用K8S Volume,其本质上也是一个目录,与Docker Volume没有什么区别。

  需要注意的是:K8S Volume的生命周期独立于容器,Pod中的容器可能被销毁和重建,但Volume会被保留。

  当Volume被mount到Pod中,Pod中的的所有容器都可以访问这个Volume。在K8S中,支持多种backend类型,例如emptyDir, hostPath, NFS, Ceph以及一些云服务商提供的存储服务等等。对Pod来说,它不需要关心到底数据会被存储在本地文件系统中还是远程云端硬盘中,它认为所有类型的Volume都只是一个目录而已。

1.2 使用K8S Volume

  (1)emptyDir

  作为K8S最基础的Volume类型,emptyDir提供了最基础的持久化方案,但是这个方案不怎么好。因为,emptyDir对于Pod来说并非持久的(它对于容器来说是持久化的),因为当Pod从节点删除时,Volume的内容也会被删除。但如果只是容器被销毁而Pod还在,则Volume不会受影响。

  换句话说:emptyDir Volume的生命周期与Pod一致。鉴于此特性,不建议在实际中使用此类型Volume。

  (2)hostPath

  相对于emptyDir,hotPath则克服了其生命周期的弱点,如果Pod被销毁,hostPath对应的目录还是会被保留。不过,如果一旦Host崩溃,hostPath也就无法访问了。因为,hostPath是将Docker Host文件系统中已经存在的目录mount给Pod的容器,所以会依赖于Host。

  在K8S中,那些需要访问K8S或Docker内部数据(配置文件和二进制库)的应用需要使用到hostPath,比如kube-apiserver和kube-controller-manager这样的应用。下面的配置就是kube-apiserver的持久化设置,其定义了3个hostPath:ca-certs, etc-pki以及k8s-certs,分别对应Host目录为/etc/ssl/certs, /etc/pki 以及 /etc/kubernetes/pki。

    volumeMounts:
    - mountPath: /etc/ssl/certs
      name: ca-certs
      readOnly: true
    - mountPath: /etc/pki
      name: etc-pki
      readOnly: true
    - mountPath: /etc/kubernetes/pki
      name: k8s-certs
      readOnly: true
  dnsPolicy: ClusterFirst
  enableServiceLinks: true
  hostNetwork: true
  nodeName: k8s-master
  priority: 2000000000
  nodeName: k8s-master
  priority: 2000000000
  priorityClassName: system-cluster-critical
  restartPolicy: Always
  schedulerName: default-scheduler
  securityContext: {}
  terminationGracePeriodSeconds: 30
  tolerations:
  - effect: NoExecute
    operator: Exists
  volumes:
  - hostPath:
      path: /etc/ssl/certs
      type: DirectoryOrCreate
    name: ca-certs
  - hostPath:
      path: /etc/pki
      type: DirectoryOrCreate
    name: etc-pki
  - hostPath:
      path: /etc/kubernetes/pki
      type: DirectoryOrCreate
    name: k8s-certs

  (3)外部Storage Povider

  如果我们的K8S是部署在AWS、GCE、Azure等公有云上,那么可以直接使用云硬盘做为Volume。这里由于我没有使用,所以跳过,有使用的朋友可以直接参考各云服务提供商的参考文档进行配置。

二、PersistentVolume与PersistentVolumeClaim

2.1 关于PersistentVolume与PersistentVolumeClaim

  前面提到的几种方案在可管理性上均有不足,特别是当集群规模较大的时候,效率和安全性均有待提高。因此,K8S提供了一个解决方案:PersistentVolumePersistentVolumeClaim,以下简称PV和PVC。

  PV是外部存储系统中的一块存储空间,由管理员创建和维护。与Volume一样,PV具有持久性,生命周期独立于Pod。

  PVC则是对PV的申请(Claim),PVC通常由普通用户创建和维护。当需要为Pod分配存储资源的时候,用户就可以创建一个PVC,指明存储资源的容量大小和访问方式(比如ReadOnly)等信息,K8S会查找并提供满足条件的PV。

  了解ASP.NET Identity的童鞋应该对Claim这个词不陌生,如果把我们的认证信息看成一个Claims,那么其中的一个一个的键值对就是Claim。我们常用的ClaimTypes如下图所示,我们可以通过Claim定位到认证信息中的Value。

  同理,我们知道了Claim也就可以定位到我们要使用的哪个PV的地址。

  与K8S Volume一样,K8S PersistentVolume也支持多种类型的存储,比如NFS、AWS EBS、Ceph等等。

2.2 NFS PV的使用

  NFS是网络文件系统 (Network File System), 它允许系统将本地目录和文件共享给网络上的其他系统。通过 NFS,用户和应用程序可以访问远程系统上的文件,就象它们是本地文件一样。

  关于如何为CentOS配置NFS,请参考这一篇文章《CentOS7安装NFS服务》。

  这里假设已经为我们的k8s-master节点搭建了一个NFS服务器,目录为/edc/k8s/nfsdata,如下图所示:

  (1)创建一个PV

   接下来我们就来创建一个PV,其yaml配置文件如下:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: edc-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /edc/k8s/nfsdata/edc-pv
    server: 192.168.2.100

  其中:

  • capacity指定了PV的容量为1GB
  • accessModes指定访问模式为ReadWriteOnce,表示PV能够以Read-Write模式mount到单个节点。此外,还支持ReadOnlyMany和ReadWriteMany,分别代表PV能以Read-Only模式或者Read-Write模式mount到多个节点。这里ReadWriteOnce只mount到单个节点,即k8s-master(192.168.2.100)。
  • persistentVolumeReclaimPolicy指定了此PV的回收策略为Recycle,表示清除PV中的数据。此外,还支持Retain和Delete,Retain表示需要管理员手动回收,类似于你用C/C++还需要手动写free代码释放空间。而Delete呢,表示删除Storage Provider中的对应存储资源,如果你使用的是外部云服务提供商的存储空间的话。
  • storageClassName指定了PV的class为nfs。
  • nfs配置项指定了PV在NFS服务器上对应的目录,如果没有可以事先创建一下。

  理解了其中的配置项,我们创建该PV,可以看到其状态Status变为了Available,表示可以被PVC申请啦。

   (2)创建一个PVC

   与创建PV不同,创建PVC只需指定PV容量、访问模式以及class即可:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: edc-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs

  有了配置文件,就可以创建PVC了:

   可以看到,edc-pvc已经Bound到edc-pv了,申请PV成功。

   申请成功之后,我们就可以在Pod中使用了,下面是一个示例Pod的配置文件:

apiVersion: v1
kind: Pod
metadata:
  name: edc-pv-pod
spec:
  containers:
  - name: edc-pv-pod
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 30000
    volumeMounts:
    - mountPath: "/mydata"
      name: mydata
  volumes:
    - name: mydata
      persistentVolumeClaim:
        claimName: edc-pvc

  通过kubectl创建该pod,如下所示:

   接下来验证一下PV是否可用:

   可以看到,在Pod中创建的文件/mydata/hello已经保存到了NFS服务器目录的edc-pv目录下了。

2.2 NFS PV的回收

  当我们不再需要某个PV时,也可以使用PVC来回收PV,如下所示:

kubectl delete pvc edc-pvc

  当edc-pvc被删除后,我们会发现K8S启动了一个新Pod,这个Pod就是用来清除edc-pv的数据的。数据的清理需要一个过程,完成后edc-pv的状态会重新恢复为Available,此时可以被新的PVC申请。

   此外,由于我们设置的回收策略为Recycle,所以Pod中的数据也被清除了:

   如果希望能够保留这些数据,那么我们需要将回收策略改为Retain:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: edc-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs
  nfs:
    path: /edc/k8s/nfsdata/edc-pv
    server: 192.168.2.100

  这里就不再验证Retain的效果了。

三、MySQL持久化存储案例

3.1 准备工作

  这里我们来演示一个MySQL持久化存储的案例:

  (1)创建PV和PVC

  准备PV和PVC的yaml:

-- mysql-pv
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs
  nfs:
    path: /edc/k8s/nfsdata/mysql-pv
    server: k8s-master

-- mysql-pvc
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs

  通过kubectl apply创建PV和PVC:

kubectl apply -f mysql-pv.yaml
kubectl apply -f mysql-pvc.yaml

   可以看到,mysql-pvc已经申请到了mysql-pv。

  (2)部署MySQL

  准备yaml配置文件:

apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  ports:
  - port: 3306
  selector:
    app: mysql

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: password
        ports:
        - containerPort: 3306
          name: mysql-container
        volumeMounts:
        - name: mysql-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-storage
        persistentVolumeClaim:
          claimName: mysql-pvc

  重点关注其中的volumeMounts和volumes配置,其中mysql-pvc申请Bound的mysql-pv将会被mount到MySQL的数据目录/var/lib/mysql下。

  通过kubectl创建MySQL:  

kubectl apply -f mysql-service.yaml
kubectl get pod -o wide

  可以看到,MySQL被部署到了k8s-node1节点上。

  (3)客户端访问MySQL

  下面我们在k8s-master上通过客户端访问MySQL Service:

kubectl run -it --rm --image=mysql:5.6 --restart=Never mysql-client -- mysql -h mysql-service -ppassword

  如下图所示,进入了MySQL数据库:

  接下来我们更新一下数据库,如下图所示:

   新建了一张表edc_test,插入了一行数据1110.

3.2 快速验证

  (1)模拟k8s-node1故障

  接下来我们模拟一下k8s-node1宕机,这样在k8s-node1上运行的MySQL服务就会受到影响,不过根据之前的了解,K8S会帮我们将MySQL迁移到k8s-node2上从而保证服务可用。

  首先,关闭k8s-node1:

shutdown now

  其次,验证K8S迁移MySQL:

  (2)验证数据一致性

  虽然k8s-node1挂了,但是K8S帮我们迁移了MySQL到k8s-node2,而且数据也是完好无损,如下图所示:

  (3)验证数据持久性

  如果我们将部署的Service和Deployment删掉,那么其Pod也会停止被删除,但是由于我们的PV的回收策略是Retain,因此其数据不会被清除:

四、小结

  本文探索了K8S的数据管理方案Volume,其中普通类型的Volume如emptyDir和hostPath虽然使用方便,但是可持久性不强,而外部云存储Volume Provider则提供了更好的持久化存储。PV和PVC的模式,更加适合于我们使用在实际环境中,最后还通过了一个MySQL持久化案例演示了如何应用PV和PVC实现持久化。

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
9月前
|
开发框架 .NET C#
ASP.NET Core Blazor 路由配置和导航
大家好,我是码农刚子。本文系统介绍Blazor单页应用的路由机制,涵盖基础配置、路由参数、编程式导航及高级功能。通过@page指令定义路由,支持参数约束、可选参数与通配符捕获,结合NavigationManager实现页面跳转与参数传递,并演示用户管理、产品展示等典型场景,全面掌握Blazor路由从入门到实战的完整方案。
674 6
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:<https://github.com/khellang/Scrutor>
790 5
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
525 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
开发框架 算法 中间件
ASP.NET Core 中的速率限制中间件
在ASP.NET Core中,速率限制中间件用于控制客户端请求速率,防止服务器过载并提高安全性。通过`AddRateLimiter`注册服务,并配置不同策略如固定窗口、滑动窗口、令牌桶和并发限制。这些策略可在全局、控制器或动作级别应用,支持自定义响应处理。使用中间件`UseRateLimiter`启用限流功能,并可通过属性禁用特定控制器或动作的限流。这有助于有效保护API免受滥用和过载。 欢迎关注我的公众号:Net分享 (239字符)
489 1
|
开发框架 缓存 .NET
GraphQL 与 ASP.NET Core 集成:从入门到精通
本文详细介绍了如何在ASP.NET Core中集成GraphQL,包括安装必要的NuGet包、创建GraphQL Schema、配置GraphQL服务等步骤。同时,文章还探讨了常见问题及其解决方法,如处理复杂查询、错误处理、性能优化和实现认证授权等,旨在帮助开发者构建灵活且高效的API。
531 3
|
10月前
|
数据采集 存储 安全
数据治理≠数据管理!90%的企业都搞错了重点!
在数字化转型中,数据不一致、质量差、安全隐患等问题困扰企业。许多组织跳过基础的数据管理,直接进行数据治理,导致方案难以落地。数据管理涵盖数据生命周期中的采集、存储、处理等关键环节,决定了数据是否可用、可靠。本文详解数据管理的四大核心模块——数据质量、元数据、主数据与数据安全,并提供构建数据管理体系的四个阶段:评估现状、确定优先级、建立基础能力与持续改进,助力企业夯实数据基础,推动治理落地。
|
存储 数据管理 数据格式
数据治理 vs. 数据管理:别再傻傻分不清!
数据治理 vs. 数据管理:别再傻傻分不清!
664 10
|
10月前
|
数据采集 存储 SQL
数据管理四部曲:元数据管理、数据整合、数据治理、数据质量管控
老张带你搞定企业数据管理难题!数据找不到、看不懂、用不好?关键在于打好元数据管理、数据整合、数据治理和数据质量管控四大基础。四部曲环环相扣,助你打通数据孤岛,提升数据价值,实现精准决策与业务增长。
数据管理四部曲:元数据管理、数据整合、数据治理、数据质量管控
|
人工智能 关系型数据库 分布式数据库
拥抱Data+AI|“全球第一”雅迪如何实现智能营销?DMS+PolarDB注入数据新活力
针对雅迪“云销通App”的需求与痛点,本文将介绍阿里云瑶池数据库DMS+PolarDB for AI提供的一站式Data+AI解决方案,助力销售人员高效用数,全面提升销售管理效率。

推荐镜像

更多