.NETCore+Kubernetes怎么构建项目

这篇文章主要讲解了“.NET Core+Kubernetes怎么构建项目”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“.NET Core+Kubernetes怎么构建项目”吧!

成都创新互联专业为企业提供交城网站建设、交城做网站、交城网站设计、交城网站制作等企业网站建设、网页设计与制作、交城企业网站模板建站服务,十余年交城做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。

在 Kubernetes 中,Pod 资源的控制器 Deployment、Replicaset、Daemonset 等常用于管理无状态应用,它们所管理的 Pod 对应的 IP、名字,启停顺序等都是随机的,Pod 之间也并不存在任何关联关系。而实际情况下,在应用集群部署时,实例彼此之间可能是需要存在关联关系的(启动顺序、角色),如 MySQL、MongoDB,所以 StatefulSet 就是为了运行有状态服务引入的一种资源类型,StatefulSet 为每个 Pod 维持一个唯一且固定的标识符,必要时还会为其创建专用的存储卷,当 Pod 被重建时,也依然能保持原来的标识符和存储卷。

完整的 StatefulSet 通常由三部分构成:StatefulSetVolumeClaimTemplateHeadless Service

StatefulSet 用于 Pod 资源定义与管控,在 StatefulSet 模式下,Pod 有自己固定的命名规则(StatfulSet 名称 + Pod 创建时所在的索引),假设设置的 StatefulSet 名称为 k8sdemo,replicas 为3,则对应的 Pod 名称将分别是 k8sdemo-0k8sdemo-1k8sdemo-0,同时在进行 Pod 副本伸缩时也能做到按序号进行升降。

VolumeClaimTemplate 用于定义 Pod 所需存储的 PVC 声明 ,PVC 与 PV 进行绑定,提供专有固定的存储卷。

Headless ServiceclusterIP: None)用于为 Pod 生成可解析的 DNS 域名记录,基于 Pod 名称的有序规则,Pod 域名是不会变的(Pod 名称.serviceName),这也保证了 Pod 网络标识的稳定性。

下面继续以 .NET Core  项目构建的 beckjin/k8sdemo:1.2.0 镜像为例,增加了接口访问日志记录的功能。通过集成 log4net 将接口访问日志进行文件记录,日志将输出到 /Data/ 目录,每个 Pod 都会拥有自己的一份日志文件(这只是一个假设的场景,切勿较真,实际情况下日志记录一般都会使用统一的日志采集工具)。 

定义资源

k8sdemo-statefulset.yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
 name: k8sdemo
spec:
 serviceName: "k8sdemo-service"  # 需要与创建的 service name 一致
 replicas: 3
 selector:
   matchLabels:
     name: k8sdemo
 template:
   metadata:
     labels:
       name: k8sdemo
   spec:
     containers:
     - name: k8sdemo
       image: beckjin/k8sdemo:1.2.0
       imagePullPolicy: IfNotPresent
       volumeMounts:
       - name: data
         mountPath: /app/Data  # 将容器内的 Data 目录进行挂载
 volumeClaimTemplates:  # 定义模板,自动创建 PVC
   - metadata:
       name: data
     spec:
       accessModes:
         - ReadOnlyMany
       resources:
         requests:
           storage:  100Mi
       storageClassName: "k8sdemo-sc"  # 将自动与集群内 storageClassName 匹配的 PV 进行绑定
 

k8sdemo-service.yaml

apiVersion: v1
kind: Service
metadata:
 name: k8sdemo-service
spec:
 clusterIP: None
 ports:
 - port: 80
   targetPort: 80
 selector:
   name: k8sdemo
 

StatefulSet 模式下需要设置 serviceName 字段,用来告诉 StatefulSet 控制器具体使用哪个 service 来解析它所管理的 Pod。同时通过 volumeClaimTemplates 字段进行 PVC 定义,StatefulSet 控制器会自动创建与 Pod 对应的 PVC,PVC 的名称为 (volumeClaimTemplateName)-(podName),然后 PVC 会自动与满足要求的 PV 进行绑定,PV 如果不支持自动创建可手动完成。另外当 Pod 被删除时 PVC 与 PV 依然会被保留,Pod 重建时会重新关联之前对应的 PVC 与 PV。

这里还是使用的 NFS 创建 PV 来实现存储,分别创建 3 个(data-k8sdemo-pv-[1~3])满足定义要求的 PV,如下:

apiVersion: v1
kind: PersistentVolume
metadata:
 name: data-k8sdemo-pv-1
spec:
 nfs:
   server: 192.168.124.21
   path: /statefulset/data1
 accessModes:
 - ReadOnlyMany
 capacity:
   storage: 100Mi
 storageClassName: k8sdemo-sc
   

部署与测试

创建 PV 与 StatefulSet:

kubectl apply -f k8sdemo-statefulset-pv1.yaml
kubectl apply -f k8sdemo-statefulset-pv2.yaml
kubectl apply -f k8sdemo-statefulset-pv3.yaml
kubectl apply -f k8sdemo-statefulset.yaml
 
.NET Core+Kubernetes怎么构建项目  
.NET Core+Kubernetes怎么构建项目  

注意::PV 命名顺序并不代表被 PVC 的绑定顺序,这两者没有关系,所以不用对上图的数字编号对应关系有疑问。

创建 Service:

kubectl apply -f k8sdemo-service.yaml
 
.NET Core+Kubernetes怎么构建项目  

因为 Service 定义的是 Headless 模式,所以需要进去 Pod 内进行接口访问测试,如:kubectl exec -it k8sdemo-0 bash 进入 k8sdemo-0 这个 Pod,通过域名 Pod 名称.serviceName来访问,如下:

curl k8sdemo-0.k8sdemo-service/weatherforecast
curl k8sdemo-1.k8sdemo-service/weatherforecast
curl k8sdemo-2.k8sdemo-service/weatherforecast
 

在 NFS 挂载目录中查看接口访问日志,以下是 Pod  k8sdemo-1 中的日志:

2020-09-20 06:01:17,451 [17] INFO  [k8sdemo-1] - Request starting HTTP/1.1 GET http://k8sdemo-1.k8sdemo-service/weatherforecast
2020-09-20 06:01:17,455 [17] INFO  [k8sdemo-1] - Executing endpoint 'T.K8SDemo.Controllers.WeatherForecastController.Get (T.K8SDemo)'
2020-09-20 06:01:17,458 [17] INFO  [k8sdemo-1] - Route matched with {action = "Get", controller = "WeatherForecast"}. Executing controller action with signature System.Collections.Generic.IEnumerable`1[T.K8SDemo.WeatherForecast] Get() on controller T.K8SDemo.Controllers.WeatherForecastController (T.K8SDemo).
2020-09-20 06:01:17,459 [17] INFO  [k8sdemo-1] - Executing ObjectResult, writing value of type 'T.K8SDemo.WeatherForecast[]'.
2020-09-20 06:01:17,460 [17] INFO  [k8sdemo-1] - Executed action T.K8SDemo.Controllers.WeatherForecastController.Get (T.K8SDemo) in 2.3627ms
2020-09-20 06:01:17,460 [17] INFO  [k8sdemo-1] - Executed endpoint 'T.K8SDemo.Controllers.WeatherForecastController.Get (T.K8SDemo)'
2020-09-20 06:01:17,461 [17] INFO  [k8sdemo-1] - Request finished in 9.9194ms 200 application/json; charset=utf-8
 

执行 kubectl delete pod k8sdemo-1 删除 Pod k8sdemo-1,等待一会 k8sdemo-1 会自动恢复,然后重新访问 curl k8sdemo-1.k8sdemo-service/weatherforecast,日志依然向原来的文件内追加,也说明保留了原来的状态。

2020-09-20 06:01:17,451 [17] INFO  [k8sdemo-1] - Request starting HTTP/1.1 GET http://k8sdemo-1.k8sdemo-service/weatherforecast
2020-09-20 06:01:17,455 [17] INFO  [k8sdemo-1] - Executing endpoint 'T.K8SDemo.Controllers.WeatherForecastController.Get (T.K8SDemo)'
2020-09-20 06:01:17,458 [17] INFO  [k8sdemo-1] - Route matched with {action = "Get", controller = "WeatherForecast"}. Executing controller action with signature System.Collections.Generic.IEnumerable`1[T.K8SDemo.WeatherForecast] Get() on controller T.K8SDemo.Controllers.WeatherForecastController (T.K8SDemo).
2020-09-20 06:01:17,459 [17] INFO  [k8sdemo-1] - Executing ObjectResult, writing value of type 'T.K8SDemo.WeatherForecast[]'.
2020-09-20 06:01:17,460 [17] INFO  [k8sdemo-1] - Executed action T.K8SDemo.Controllers.WeatherForecastController.Get (T.K8SDemo) in 2.3627ms
2020-09-20 06:01:17,460 [17] INFO  [k8sdemo-1] - Executed endpoint 'T.K8SDemo.Controllers.WeatherForecastController.Get (T.K8SDemo)'
2020-09-20 06:01:17,461 [17] INFO  [k8sdemo-1] - Request finished in 9.9194ms 200 application/json; charset=utf-8
2020-09-20 06:17:06,467 [12] INFO  [k8sdemo-1] - Request starting HTTP/1.1 GET http://k8sdemo-1.k8sdemo-service/weatherforecast
2020-09-20 06:17:06,494 [12] INFO  [k8sdemo-1] - Executing endpoint 'T.K8SDemo.Controllers.WeatherForecastController.Get (T.K8SDemo)'
2020-09-20 06:17:06,527 [12] INFO  [k8sdemo-1] - Route matched with {action = "Get", controller = "WeatherForecast"}. Executing controller action with signature System.Collections.Generic.IEnumerable`1[T.K8SDemo.WeatherForecast] Get() on controller T.K8SDemo.Controllers.WeatherForecastController (T.K8SDemo).
2020-09-20 06:17:06,533 [12] INFO  [k8sdemo-1] - Executing ObjectResult, writing value of type 'T.K8SDemo.WeatherForecast[]'.
2020-09-20 06:17:06,548 [12] INFO  [k8sdemo-1] - Executed action T.K8SDemo.Controllers.WeatherForecastController.Get (T.K8SDemo) in 17.1904ms
2020-09-20 06:17:06,549 [12] INFO  [k8sdemo-1] - Executed endpoint 'T.K8SDemo.Controllers.WeatherForecastController.Get (T.K8SDemo)'
2020-09-20 06:17:06,550 [12] INFO  [k8sdemo-1] - Request finished in 84.3414ms 200 application/json; charset=utf-8

另外对 Pod 副本进行伸缩时效果也是一样的,都会保持 Pod 具有的状态。当然文中的例子和一些组件的集群部署不太一样,比如像 MySQL 这类组件,各实例间还会做数据同步来实现数据的一致性,当然最终也是每个实例关联自己的数据存储卷。

感谢各位的阅读,以上就是“.NET Core+Kubernetes怎么构建项目”的内容了,经过本文的学习后,相信大家对.NET Core+Kubernetes怎么构建项目这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!


名称栏目:.NETCore+Kubernetes怎么构建项目
本文URL:http://pwwzsj.com/article/pejeso.html