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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
数据管理 DMS,安全协同 3个实例 3个月
推荐场景:
学生管理系统数据库
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
简介: 本文探索了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实现持久化。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
14天前
|
Java 物联网 C#
C#/.NET/.NET Core学习路线集合,学习不迷路!
C#/.NET/.NET Core学习路线集合,学习不迷路!
|
2月前
|
存储 开发框架 JSON
ASP.NET Core OData 9 正式发布
【10月更文挑战第8天】Microsoft 在 2024 年 8 月 30 日宣布推出 ASP.NET Core OData 9,此版本与 .NET 8 的 OData 库保持一致,改进了数据编码以符合 OData 规范,并放弃了对旧版 .NET Framework 的支持,仅支持 .NET 8 及更高版本。新版本引入了更快的 JSON 编写器 `System.Text.UTF8JsonWriter`,优化了内存使用和序列化速度。
|
2月前
mcr.microsoft.com/dotnet/core/aspnet:2.1安装libgdiplus
mcr.microsoft.com/dotnet/core/aspnet:2.1安装libgdiplus
30 1
|
3月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
3月前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
100 3
|
2月前
|
开发框架 JavaScript 前端开发
一个适用于 ASP.NET Core 的轻量级插件框架
一个适用于 ASP.NET Core 的轻量级插件框架
|
2月前
|
开发框架 缓存 算法
开源且实用的C#/.NET编程技巧练习宝库(学习,工作,实践干货)
开源且实用的C#/.NET编程技巧练习宝库(学习,工作,实践干货)
|
3月前
|
开发框架 NoSQL .NET
利用分布式锁在ASP.NET Core中实现防抖
【9月更文挑战第5天】在 ASP.NET Core 中,可通过分布式锁实现防抖功能,仅处理连续相同请求中的首个请求,其余请求返回 204 No Content,直至锁释放。具体步骤包括:安装分布式锁库如 `StackExchange.Redis`;创建分布式锁服务接口及其实现;构建防抖中间件;并在 `Startup.cs` 中注册相关服务和中间件。这一机制有效避免了短时间内重复操作的问题。
|
4月前
|
物联网 数据管理 Apache
拥抱IoT浪潮,Apache IoTDB如何成为你的智能数据守护者?解锁物联网新纪元的数据管理秘籍!
【8月更文挑战第22天】随着物联网技术的发展,数据量激增对数据库提出新挑战。Apache IoTDB凭借其面向时间序列数据的设计,在IoT领域脱颖而出。相较于传统数据库,IoTDB采用树形数据模型高效管理实时数据,具备轻量级结构与高并发能力,并集成Hadoop/Spark支持复杂分析。在智能城市等场景下,IoTDB能处理如交通流量等数据,为决策提供支持。IoTDB还提供InfluxDB协议适配器简化迁移过程,并支持细致的权限管理确保数据安全。综上所述,IoTDB在IoT数据管理中展现出巨大潜力与竞争力。
109 1
|
5月前
|
SQL NoSQL 数据管理
数据管理DMS使用问题之如何批量导入MongoDB的数据文件
阿里云数据管理DMS提供了全面的数据管理、数据库运维、数据安全、数据迁移与同步等功能,助力企业高效、安全地进行数据库管理和运维工作。以下是DMS产品使用合集的详细介绍。
下一篇
无影云桌面