.NET Core + Kubernetes:Volume

和 Docker 类似,Kubernetes 中也提供了  Volume 来实现数据卷挂载,但 Kubernetes 中 Volume 是基于 Pod,而不是容器,它可被 Pod 中多个容器共享,另外 Kubernetes 中提供比较丰富的 Volume 类型[1],如:emptyDirhostPathnfspersistentVolumeClaimdownwardAPIsecretconfigMap 等,每种类型都有其特点及使用场景。

下面将介绍几种常用 Volume 类型的使用方式,在这之前先在 k8sdemo .NET Core 服务中添加以下两个接口(镜像版本升级为 1.2.0),以方便后面效果演示。

[HttpGet]
public string GetConfig([FromQuery]string key)
{// ......
}[HttpGet]
public string GetVolumeData()
{// ......
}

GetConfig:通过传入配置文件 appsettings.json 的 key 获取对应值;GetVolumeData:获取容器内 /Data/data.txt 的文件内容;

emptyDir

emptyDir 的初始状态是一个没有任何内容的 Volume,其生命周期与 Pod 一致,当 Pod 中的容器挂掉时,emptyDir Volume 中的内容不会被清除,容器重启后数据依然可见。只有当整个 Pod 从集群中被删除,emptyDir Volume 中的内容才会被清除。如下:emptyDir Volume 位于 Pod 内。

通过以下配置文件创建的 Pod 中将包含 k8sdemo 和 busybox 两个 container,busybox 是一个集成了一些常用 linux 命令的镜像,这里将使用它在 Pod 内进行文件内容修改。k8sdemo 容器的 /app/Data/ 目录文件与 busybox 容器的 /data/ 目录文件将通过 emptyDir Volume 进行共享。

apiVersion: apps/v1
kind: Deployment
metadata:name: emptydir-demo
spec:replicas: 1selector:matchLabels:name: emptydir-demotemplate:metadata:labels:name: emptydir-demospec:containers:- name: k8sdemoimage: beckjin/k8sdemo:1.2.0volumeMounts:- mountPath: /app/Data/name: shareports:- containerPort: 80- name: busyboximage: busyboxcommand:- "/bin/sh"- "-c"- "sleep 3600"volumeMounts:- mountPath: /data/name: sharevolumes:- name: shareemptyDir: {}
---
apiVersion: v1
kind: Service
metadata:name: emptydir-demo-service
spec:selector:name: emptydir-demotype: NodePortports:- port: 80targetPort: 80

执行命令 kubectl exec -it emptydir-demo-746f49b55b-p6pzz -c busybox -- /bin/sh 进入 busybox  容器,然后执行 echo 'emptyDir Volume' > /data/data.txt,最后访问 k8sdemo 服务的 GetVolumeData 接口获取文件内容:

hostPath

hostPath 类型是挂载宿主机上的文件或目录到 Pod 中,与 Pod 所在的 Node 是强关联的,所以当 Pod 因重启被重新调度时,一定要确保所在主机的相关文件或目录的正确性,如下:

如下配置中 replicas 字段设置为 2 ,正常情况下 Pod 将会在 node1 和 node2 上分别被创建,另外 hostPath 字段中的 path 指定了 /data/k8sdemo/ 目录挂载到容器内的 /app/Data/,所以分别在 node1 和 node2 创建 /data/k8sdemo/data.txt ,内容为 node1 hostPath Volumenode2 hostPath Volume

kind: Deployment
metadata:name: hostpath-demo
spec:replicas: 2selector:matchLabels:name: hostpath-demotemplate:metadata:labels:name: hostpath-demospec:containers:- name: k8sdemoimage: beckjin/k8sdemo:1.2.0volumeMounts:- mountPath: /app/Data/name: shareports:- containerPort: 80volumes:- name: sharehostPath:path: /data/k8sdemotype: Directory
---
apiVersion: v1
kind: Service
metadata:name: hostpath-demo-service
spec:selector:name: hostpath-demotype: NodePortports:- port: 81targetPort: 80

访问 k8sdemo 服务的 GetVolumeData 接口获取文件内容,当路由到不同 Pod(即不同的 node) 返回内容将不一样,如下:

nfs

NFS(network file system) 网络文件系统,类似 Windows 中的文件夹共享。首先在 Kubernetes 集群外搭建一个 NFS Server,然后指定文件目录进行共享,最终与  Pod 内的容器关联,实现数据卷挂载,如下:

NFS Server 搭建

  1. 在机器上安装依赖组件(集群外的机器 192.168.1.13,并关闭防火墙

    yum install -y nfs-utils rpcbind
    
  2. 将主机上的 /share 目录作为共享目录,如果多个目录可以添加多行

    [root@localhost ~]# vim /etc/exports
    /share  192.168.1.0/24(insecure,rw,no_root_squash)
    
  3. 启动 NFS

    systemctl start rpcbind.service
    systemctl enable rpcbind.servicesystemctl start nfs.service
    systemctl enable nfs.service
    
  4. Kubernetes 集群内各节点安装 nfs-utils,方便使用 showmount

    yum install -y nfs-utils
    

完成以上步骤后,在 Kubernetes 集群中任意节点执行  showmount -e 192.168.1.13 验证是否正常:

如下配置中 volumes 指定了 nfs 字段配置,即将  NFS Server 中的 /share 目录挂载到容器内的 /app/Data/,与 hostPath Volume 类型的主要区别是依赖单独的 NFS Server,和 node 本身并不耦合。

apiVersion: apps/v1
kind: Deployment
metadata:name: nfs-demo
spec:replicas: 2selector:matchLabels:name: nfs-demotemplate:metadata:labels:name: nfs-demospec:containers:- name: k8sdemoimage: beckjin/k8sdemo:1.2.0volumeMounts:- mountPath: /app/Dataname: shareports:- containerPort: 80volumes:- name: sharenfs:server: 192.168.1.13path: /share
---
apiVersion: v1
kind: Service
metadata:name: nfs-demo-service
spec:selector:name: nfs-demotype: NodePortports:- port: 82targetPort: 80

在 NFS Server 中执行 echo 'nfs Volume' > /share/data.txt,然后访问 k8sdemo 服务的 GetVolumeData 接口获取文件内容,如下:

persistentVolumeClaim

PersistentVolumeClaim(PVC)PersistentVolume(PV) 在使用上是一对密不可分的组合,PV 主要是资源对象定义,PVC 主要是对应资源对象的引用,PV 支持 多种插件类型[2] 进行实现,以下将继续使用 NFS 来作为 PV 插件。

如下图:首先基于 PV 插件在 Kubernetes 集群中创建各种资源规格的 PV,根据 Pod 需要存储卷资源创建 PVC,Kubernetes 将符合资源规格要求且消耗资源最小的 PV 绑定到 PVC,PV 和 PVC 是一对一的关系,如果找不到符合条件的 PV,PVC 会一直处于未绑定状态,PVC 绑定成功后可被 Pod 内的容器引用。

NFS Server 添加 mount 目录

修改 NFS Server /etc/exports 并生效 ,在 Kubernetes 集群中任意节点执行 showmount -e 192.168.1.13 验证是否正常:

创建 PV

以下配置将会创建3个 PV,storage 分别为 500M、1G、2G。

apiVersion: v1
kind: PersistentVolume
metadata:name: pv-share-a
spec:nfs:path: /share_aserver: 192.168.1.13accessModes:- ReadWriteManycapacity:storage: 500Mi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv-share-b
spec:nfs:path: /share_bserver: 192.168.1.13accessModes:- ReadWriteManycapacity:storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:name: pv-share-c
spec:nfs:path: /share_cserver: 192.168.1.13accessModes:- ReadWriteManycapacity:storage: 2Gi

创建 PVC

apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvc-k8sdemo
spec:accessModes:- ReadWriteManyresources:requests:storage: 1Gi

PVC 创建成功后,pv-share-b 的 STATUS 会变为 Bound,同时 CLAIM 属性会显示相关的 PVC,从上图也可以看出使用的是最小符合资源规格的 PV,并不会将 pv-share-c 绑定到当前 PVC。更多关于 PV 和 PVC 属性说明可参考:persistent-volumes[3]

创建 Pod

如下配置中 volumes 指定了 persistentVolumeClaim 字段配置,这里只需要设置 claimName 为前面创建的 PVC 名称 pvc-k8sdemo 即可,使用上比较简单。

apiVersion: apps/v1
kind: Deployment
metadata:name: pvc-demo
spec:replicas: 2selector:matchLabels:name: pvc-demotemplate:metadata:labels:name: pvc-demospec:containers:- name: k8sdemoimage: beckjin/k8sdemo:1.2.0volumeMounts:- mountPath: /app/Dataname: shareports:- containerPort: 80volumes:- name: sharepersistentVolumeClaim:claimName: pvc-k8sdemo
---
apiVersion: v1
kind: Service
metadata:name: pvc-demo-service
spec:selector:name: pvc-demotype: NodePortports:- port: 83targetPort: 80

在 NFS Server 中执行 echo 'pvc Volume share_a' > /share_a/data.txt,share_b、share_c 类似,然后访问 k8sdemo 服务的 GetVolumeData 接口获取文件内容,如下:

configMap

configMap 主要使镜像和配置文件解耦,以便实现镜像的可移植性和可复用性,configMap 是配置信息的集合,可直接注入到 Pod 的容器中使用,扮演着配置中心的角色。configMap 可以以数据卷的形式挂载,也可以基于环境变量的形式注入到 Pod 容器中使用。另外 secret 是一种相对安全的 configMap,它默认会将配置信息进行 base64 编码,使配置不是明文直接存储在 configMap 中,起到一定的保护作用。

下面主要介绍 configMap 以数据卷挂载方式的使用,如下图,在 Kubernetes 集群中创建一个 configMap 资源类型,然后供 Pod 内的容器使用。

如下,创建一个数据卷形式的 ConfigMap,appsettings.json 是 .NET Core 程序内使用的配置文件。

apiVersion: v1
kind: ConfigMap
metadata:name: configmap-k8sdemo
data:appsettings.json: |-{"ServiceName": "k8sdemo"}

如下配置中 volumes 指定了 configMap 资源的名称为以上创建的 configMap 对象:configmap-k8sdemo

apiVersion: apps/v1
kind: Deployment
metadata:name: configmap-demo
spec:replicas: 2selector:matchLabels:name: configmap-demotemplate:metadata:labels:name: configmap-demospec:containers:- name: k8sdemoimage: beckjin/k8sdemo:1.2.0volumeMounts:- name: configfilemountPath: /app/appsettings.jsonsubPath: appsettings.jsonports:- containerPort: 80volumes:- name: configfileconfigMap:name: configmap-k8sdemoitems:- key: appsettings.jsonpath: appsettings.json
---
apiVersion: v1
kind: Service
metadata:name: configmap-demo-service
spec:selector:name: configmap-demotype: NodePortports:- port: 84targetPort: 80

通过访问 k8sdemo 服务的 GetConfig 接口获取指定 key 的值:

参考资料

[1]

Volume 类型: https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes

[2]

多种插件类型: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes

[3]

persistent-volumes: https://kubernetes.io/docs/concepts/storage/persistent-volumes/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/309143.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法-二分搜索-找出最大值和次大值

二分搜索 <2>找出最大值和第二大值 时间复杂度O&#xff08;n) class Program {static void Main(string[] args){List<int> list new List<int> { 10, 3, 6, 4, 7, 1, 9, 2 };var v getMax(list, 0, list.Count - 1);}static (int, int) getMax(List<…

WPF中的Data Binding调试指南

点击蓝字“大白技术控”关注我哟加个“星标★”&#xff0c;每日良时&#xff0c;好文必达&#xff01;WPF中的Data Binding如何Debug?大家平时做WPF开发&#xff0c;相信用Visual studio的小伙伴比较多。XAML代码曾经在某些特殊版本的Visual Studio中是可以加断点进行调试的&…

算法-连续项的最大和问题(最大子数组问题)三种不同解法

连续项的最大和问题 &#xff08;1&#xff09;暴力求解 时间复杂度 O&#xff08;n^2&#xff09; &#xff08;2&#xff09;分治求解 时间复杂度 O&#xff08;nlogn&#xff09; &#xff08;3&#xff09; 线性求解 时间复杂度 O&#xff08;n&#xff09; C#代码 usin…

.NET 5 尝鲜 - 开源项目TerminalMACS WPF管理端支持.NET 5

点击上方“Dotnet9”添加关注哦聊天界面设计TerminalMACS一个使用 Prism 作为模块化框架、基于多个开源控件库作为UI控件选择、集成开源 UI 界面设计的 .NET 5 WPF 客户端项目。项目名称&#xff1a;TerminalMACS WPF管理端项目开源地址&#xff1a;Github&#xff1a;https://…

算法-排序-插入排序

插入排序 特点&#xff1a;原址排序&#xff0c;比较排序&#xff0c;&#xff08;最坏的情况&#xff09;时间复杂度O&#xff08;n^2&#xff09; #include <iostream>void insertion_sort(int *arr,int start,int end) {for (int i start1; i < end1; i) {int k…

MongoDB via Dotnet Core数据映射详解

用好数据映射&#xff0c;MongoDB via Dotnet Core开发变会成一件超级快乐的事。一、前言MongoDB这几年已经成为NoSQL的头部数据库。由于MongoDB free schema的特性&#xff0c;使得它在互联网应用方面优于常规数据库&#xff0c;成为了相当一部分大厂的主数据选择&#xff1b;…

算法-排序-归并排序

归并排序 特点&#xff1a;非原址排序&#xff0c;比较排序&#xff0c;时间复杂度O&#xff08;nlgn&#xff09; 稳定 // // Created by 许加权 on 2021/6/18. //#include <iostream> void merge_sort(int *arr,int start,int end) {if(start < end){int middle …

FreeSql.Generator命令行代码生成器是如何实现的

目录FreeSql介绍FreeSql.GeneratorRazorEngine.NetCore源码解析FreeSql.ToolsFreeSqlFreeSql 是功能强大的对象关系映射技术(O/RM)&#xff0c;支持 .NETCore 2.1 或 .NETFramework 4.0 或 Xamarin。有一个强大的ORM&#xff0c;也方便我们开发一个代码生成器。一般情况下&…

算法-排序-选择排序

选择排序 特点&#xff1a;原址排序&#xff0c;比较排序&#xff0c;时间复杂度O&#xff08;n^2&#xff09; // // Created by 许加权 on 2021/6/19. //#include <iostream>void selection_sort(int *arr,int start,int end) {for (int i start 1; i < end1; i…

.Net Core Configuration Etcd数据源

前言.Net Core为我们提供了一套强大的Configuration配置系统&#xff0c;使用简单扩展性强。通过这套配置系统我们可以将Json、Xml、Ini等数据源加载到程序中,也可以自己扩展其他形式的存储源。今天我们要做的就是通过自定义的方式为其扩展Etcd数据源操作。何为Etdc在使用etcd之…

算法-二分查找

二分查找 特点&#xff1a; T(n) T(n/2 - 1) c 时间复杂度O&#xff08;lgn) 前提&#xff1a;需要已排序的集合 int binary_search(int *arr,int start,int end,int key) {if(start<end){int middle (startend)/2;if(arr[middle] key) return middle;if(key<arr[m…

Java IDEA断点调试

断点调试(debug) 断点调试应用案例 01&#xff1a; package Assign;public class Debug01 {public static void main(String[] args) {int sum 0;for (int i 0;i<5;i){sumi;System.out.println(i);System.out.println(sum);}System.out.println("continue");} …

.NET Core请求控制器Action方法正确匹配,但为何404?

【导读】提前预祝各位端午节快乐。有时候我们会发现方法名称都正确匹配&#xff0c;但就是找不到对应请求接口&#xff0c;所以本文我们来深入了解下何时会出现接口请求404的情况。匹配控制器Action方法&#xff08;404&#xff09;首先我们创建一个web api应用程序&#xff0c…

布斯乘法以及带符号数的运算

乘法理解 对于最熟悉的十进制乘法很最基本的运算原理就是一个乘数乘以另一个乘数的个位、十位、百位数字然后求和。比如 放到二进制来看其实它也是这样的&#xff0c;多位数的乘法就是一个乘数乘上另一个乘数的各位求和。那么&#xff1a; 布斯算法及原理 原理 已经知道两…

算法-排序-冒泡排序

冒泡排序 特点&#xff1a;原址排序&#xff0c;比较排序 时间复杂度O&#xff08;n^2) void bubble_sort(int *arr,int start,int end) {for (int i start; i < end; i) {for (int j end; j >i ; j--) {if(arr[j-1]>arr[j]){int temp arr[j];arr[j] arr[j-1];a…

C++重载输出操作符<<,为什么要返回引用

针对&#xff1a;ostream & operator <<(ostream & os, const ClassType &object) 说明几点&#xff1a; 1.第一个形参为对ostream对象的引用&#xff0c;在该对象上将产生输出&#xff0c;ostream为非const&#xff0c;因为写入到流会改变流的状态&#x…

angular 接入 IdentityServer4

angular 接入 IdentityServer4Intro最近把活动室预约的项目做了一个升级&#xff0c;预约活动室需要登录才能预约&#xff0c;并用 IdentityServer4 做了一个统一的登录注册中心&#xff0c;这样以后就可以把其他的需要用户操作的应用统一到 IdentityServer 这里&#xff0c;这…

算法-计算逆序对个数

求逆序对的个数 特点&#xff1a;利用归并排序中合并的步骤&#xff0c;计算逆序对 时间复杂度O&#xff08;nlgn&#xff09; int merge_inversion(int *arr,int start,int end,int middle); int count_inversion(int *arr,int start,int end) {if(start<end){int middle…

主机Redis服务迁移到现有Docker Overlay网络

“《麻雀虽小&#xff0c;五脏俱全》之主机现有Redis服务迁移到Docker Swarm Overlay网络&#xff0c;并搭建高可用容器集群。hello, 好久不见&#xff0c;之前文章记录了一个实战的2C分布式项目的改造过程&#xff0c;结果如下&#xff1a;其中Redis并未完成容器化改造&#x…

堆排序(包含最大堆和最小堆)

堆排序&#xff08;包含最大堆和最小堆&#xff09; 堆排序 时间复杂度nlgn&#xff0c;原址排序。 通用函数 int parent(int i) {return (i - 1) >> 1; } int left(int i) {return (i << 1) 1; } int right(int i) {return (i << 1) 2; }最大堆排序 v…