部署Dotnet Core应用到Kubernetes(一)

最近闲了点,写个大活:部署Dotnet应用到K8s。

写在前边的话

一直想完成这个主题。但这个主题实在太大了,各种拖延症的小宇宙不时爆发一下,结果就拖到了现在。

这个主题,会是一个系列。在这个系列中,我会讨论将应用部署到K8s时需要的各个内容和知识,以及各种刨过的坑。

为了避免这个系列被扩得过大,我不深入讨论K8s的技术,也不去解释如何建立K8s集群之类的问题。这个主题会侧重在开发人员方面,侧重于如何开发适合K8s的应用,以及在K8s上部署。

另外,这个主题也不会关注Docker。在我看来,Docker是一个附加技术,而不是必要内容。

在项目中,是否需要使用K8s,算是一个问题。从各个方面来看,很多中大型的项目都倾向于往这个方面去做,但我们必须清楚,使用K8s增加了项目的复杂度。如果构建的是一个独立的应用程序,那用K8s实在没有必要。而即便是一个大的系统,其实也没有必要从开头就加入K8s。

本主题中的内容大多来自我自己部署Dotnet Core到K8s集群的经验。如果有任何问题,可以在评论中告诉我。

K8s(Kubernetes)面向开发的组件

前边说了,这个主题我们仅关注部署应用程序相关的部分,而不讨论K8s的全部。

面向开发,面向部署,我们需要了解下面几个概念:

  • 节点(Node)

  • Pod

  • 部署(Deployment)

  • 服务(Service)

  • 入口(Ingress)

这几个概念,是整个内容的基础。

1. 节点(Node)

在K8s中,Node对应的是虚拟机或物理硬件,是K8s实际运行容器的地方。

一般来说,有两类节点:

  • 主节点(Master),用来运行所有的控制级(Control-plane)服务。主节点也可以运行应用程序,但一般来说,主节点只处理控制管理服务,不运行工作负载。

  • 其它节点,用来运行真正的应用程序。一个节点可以运行多个应用程序或应用程序容器。

一个典型的K8s集群会像下面图中的样子:

当然,在实际应用中,看K8s的规模。必要时,也可以做成单机,主节点运行控制服务的同时,也运行应用程序。

在集群中,节点越多,可以运行的应用或容器就越多,节点宕机时的容错能力也就越大。

2. Pod

K8s中最小的管理单元,不是一个个独立的容器,而是Pod。

要在K8s中运行应用程序,需要将其打包到一个容器(通常是Docker容器)中,并让K8s运行它。Pod是可以让K8s运行的最小单元。它包含一个或多个容器。当一个Pod被创建或销毁时,它里面的所有容器也会被创建或销毁。

在网上,很多的文章都介绍说:如果有一个依赖于数据库的应用,那应该把应用容器和数据库容器部署在同一个Pod中,以便同步创建或销毁。

以我的经验来说,这个说法很不准确,而且容易造成对K8s应用的误解。在K8s的实际应用中,只包含单个容器的Pod会更常用,也更好用。就好像“支付API”或“订单API”这样的,每个API都有不同的扩展需求、部署要求和迭代速度,因此单独设置Pod给它们是非常合理的。同样,数据库容器也应该部署在独立的Pod中,因为它与应用/服务/API会有不同的生命周期。

还有一个比较常用的是SideCar模式,就是在一个Pod下的主容器旁边部署“SIdeCar“容器,用来充当代理,为主应用程序进行身份证认处理,或服务发现,以及服务通讯,甚至能充当应用性能监控的接收器来用。

一个典型的节点下的Pod是下面的样子:

再重申一下:一个节点下面可以有多个Pod。一个Pod在K8s中会作为一个整体单元进行调度。一个Pod可能包含一个容器,也可能包含多个容器。容器用于部署应用或API。

3. 部署

在我的概念中,K8s主要做了两件事:

  • 管理容器的生存期

  • 管理容器之间的通讯

K8s的部署,主要完成的是第一件事,即管理容器的生存周期。所以,部署可以看做是定义K8s如何部署Pod以及如果管理Pod的一组规则。

比方,我们可能这样定义一个部署:

  1. Pod包含支付API应用Docker映像的一个实例;

  2. 我们要运行这个Pod的三个副本

  3. 保证每个容器至少有200Mb的可用内存,并限制它最多不超过400Mb;

  4. 当我们部署Pod新版本时,采用滚动更新策略

定义完后,K8s就会严格执行这个规则。如果应用崩溃了,K8s会删除Pod并安排一个新的Pod,以保证规则规定的副本数量。如果Pod需要更多内存,K8s会选择一个运行容器较少的节点上运行它,或者结束并重新部署它。当应用更新一个新版本时,K8s会创建一个新的部署,来替换旧版本,并将运行转到新的版本。

当然,上面这个例子做了一定的简化。不过,基本上K8s的基本工作就是这么做的。

这里的关键就是:部署定义了规则,K8s在这个部署的整个生命周期中维护并保持这个规则。

4. 服务

前面说过,部署可以用来创建跨多个节点(Node)的Pod的多个副本。这其实就是K8s提高性能及提高可用性的主要原理。

服务是应用对外的部分,供其它API去调用。而在K8s内部,服务可以看作是Pod在集群内的负载均衡器。当我们创建部署时,通常还会创建一个与该应用的Pod关联的服务。

在上面的例子中,当我们创建部署时,也会创建一个“Payment API”的服务,供其它API调用。

而当其它Pod需要与这个支付API的Pod通讯时,实际不会与支付API的一个Pod直接联系,而是将请求发给服务,然后由服务将请求传递给某一个Pod的实例。

这个过程参见下面的图:

服务与网络相关。因此,服务有多种不同的网络模式。这里不详细说了,只拿一个常用的模式举个例子:

K8s将服务分配到一个DNS记录,并通过这个记录将请求从一个Pod转发到另一个Pod。

假设我们有一个支付服务,而我们的购买服务需要调用这个服务。K8s不需要知道Pod的真实IP,我们只需要分配一个DNS记录给服务:

payment-api.xxx.local

通过这个域名,购买服务可以调用支付服务,而不需要知道支付服务对应的Pod的真正IP。

这个工作方式与Dotnet体系完全一样。通过这种方式,可以实现对资源的逻辑分组,这是题外话。

5. 入口

入口与服务很像,但有本质的不同。

服务本质上是K8s集群内部的东西,用来实现Pod之间的内部调用。而入口将HTTP/HTTPS从集群外部路由到内部的服务,这样,外部应用,例如前端、APP或小程序就可以通过这个入口,调用内部服务来处理请求。

同时,入口也可以当成提供外部负载均衡,即跨多个节点平衡对给定服务的请求。

除此之外,入口也可以提供其它一些特性,例如主机名或基于路径的路由。通常,我们可以为每个应用或API配置一个入口。

还有,入口设置也可以用来做应用的反向代理。例如通过一个Nginx实例来配置入口。这都是可以的,而且这样的方式,可以让API隐藏在反向代理之后,而不用直接暴露在外网。这个部分,在后面的文章,我会专门写。

总结一下

这篇文章是这个系列的一个引子。

当我们在K8s中部署一个Dotnet Core的应用时,我们需要配置Pod部署,添加服务来在K8s内部公开这些Pod,并添加一个入口来公开服务。

本系列的后续文章中,我会从开发的各个环节来解释如何使用这些组件来部署Dotnet Core应用到K8s。

敬请关注!!!

(未完待续)

喜欢就来个三连,让更多人因你而受益

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

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

相关文章

java 配置参数_给你的JAVA程序配置参数(Properties的使用)

我们在写JAVA程序时,很多时候运行程序的参数是需要动态改变的测试时一系列参数,运行时一系列参数又或者数据库地址也需要配一套参数,以方便今后的动态部署这些变量的初始化,我们在写小DEMO时完全可以写死在JAVA文件中但程序需要发…

JAVA实验报告九异常处理_Java课后练习9(异常处理)

动手动脑1:import javax.swing.*;class AboutException {public static void main(String[] a){int i1, j0, k;ki/j;try{k i/j; // Causes division-by-zero exception//throw new Exception("Hello.Exception!");}catch ( ArithmeticException e){System.out.print…

asp.net core web api之异常

官方建议用app.UseExceptionHandler("/error")来集中处理异常&#xff0c;本例是一个具体的应用。比如项目中有一个ViewModel&#xff0c;要求Name最大长度为5/// <summary>/// 用户模型/// </summary>public class UserModel{/// <summary>/// ID…

java 实现 指派_TAP任务指派问题的汇编实现

近六周的课程设计&#xff0c;编了一个四百行的汇编程序&#xff0c;编的过程很不顺利&#xff0c;遇到种种意想不到的困难&#xff0c;但最终能够实现&#xff0c;可谓欣喜若狂&#xff0c;这期间学到了好多好多&#xff0c;遇到问题怎么精下心来解决&#xff0c;同时对汇编的…

.NET 5.0正式发布,有什么功能特性(翻译)

我们很高兴今天.NET5.0正式发布。这是一个重要的版本—其中也包括了C# 9和F# 5大量新特性和优秀的改进。微软和其他公司的团队已经在生产和性能测试环境中开始使用了。这些团队向我们反馈的结果比较令人满意&#xff0c;它证明了对性能提升及降低Web应用托管成本的机会有积极的…

Java 重写 多态性_java多态性重写overriding和重载overloading的区别

一、概述就Java而言&#xff0c;当有人问&#xff1a;什么是多态&#xff1f;将重载或重写的区别解释为一个可以接受的答案&#xff1f;如果您有一个抽象基类&#xff0c;它定义了一个没有实现的方法&#xff0c;并且您在子类中定义了该方法&#xff0c;那该方法是否仍然覆盖&a…

简单聊聊C#中lock关键字

为了避免多个线程同时操作同一资源&#xff0c;引起数据错误&#xff0c;通常我们会将这个资源加上锁&#xff0c;这样在同一时间只能有一个线程操作资源。在C#中我们使用lock关键字来锁定资源&#xff0c;那lock关键字是如何实现锁定的呢&#xff1f;我们先看一段代码&#xf…

idea如何导入java工程_Eclipse java web项目 ,导入IntelliJ IDEA 完整操作!

或许你用惯了Eclipse&#xff0c;有点排斥其他工具了&#xff0c;你写框架的时候&#xff0c;编译速度是不是特别慢啊&#xff1f;有时候还超过45秒&#xff0c;自动取消运行&#xff01;有时候代码是正常的&#xff0c;却无端端报错&#xff1f;下午吃个饭回来又好了&#xff…

行业思考 | 互联网对传统行业的降维打击

【行业思考】| 作者 / Edison Zhou这是EdisonTalk的第301篇原创内容在周一发布的推文《我在传统行业做数字化转型之预告篇》中&#xff0c;我提到互联网的发展和和竞争对传统行业起到了降维打击的作用&#xff0c;于是就有童鞋私下问我&#xff0c;为何这么说。今天就跟你聊聊这…

java aio复制文件_java复制文件的4种方式及拷贝文件到另一个目录下的实例代码...

尽管Java提供了一个可以处理文件的IO操作类。 但是没有一个复制文件的方法。 复制文件是一个重要的操作,当你的程序必须处理很多文件相关的时候。 然而有几种方法可以进行Java文件复制操作,下面列举出4中最受欢迎的方式。1. 使用FileStreams复制这是最经典的方式将一个文件的内…

BCVP开发者说第一期:Destiny.Core.Flow

沉静岁月&#xff0c;淡忘流年1项目简介Destiny.Core.FlowDestiny.Core.Flow是基于.NetCore平台&#xff0c;轻量级的模块化开发框架&#xff0c;Admin管理应用框架&#xff0c;旨在提升团队的快速开发输出能力&#xff0c;由常用公共操作类&#xff08;工具类、帮助类&#xf…

.NET Core 取消令牌:CancellationToken

在 .NET 开发中&#xff0c;CancellationToken&#xff08;取消令牌&#xff09;是一项比较重要的功能&#xff0c;掌握并合理的使用 CancellationToken 可以提升服务的性能。特别在异步编程中&#xff0c;我常常会以创建 Task 的方式利用多线程执行一些耗时或非核心业务逻辑&a…

java char short区别_java 彻底理解 byte char short int float long double

遇到过很多关于 数值类型范围的问题了&#xff0c;在这做一个总结&#xff0c;我们可以从多方面理解不同数值类型的所能表示的数值范围在这里我们只谈论 java中的数值类型首先说byte&#xff1a;这段是摘自jdk中 Byte.java中的源代码从这里可以看出 byte的取值范围&#xff1a;…

程序员过关斩将--从未停止过的系统架构设计步伐

“首先&#xff0c;这篇文章肯定会得罪一些人“其次&#xff0c;此文只代表我个人的意见&#xff0c;仅供参考从分层说起谈到系统架构的分层和系统领域边界的划分&#xff0c;每个架构师&#xff0c;每个技术经理&#xff0c;甚至每个程序员都有自己的一套想法。无论是怎么样的…

java流上传文档把磁盘撑满_BOOT目录磁盘占用满处理

背景&#xff1a;Ubuntu:16.04查看已安装启动镜像dpkg --get-selections |grep linux-image这里会列出目前已经安装的启动镜像&#xff0c;一般分两种&#xff0c;一种状态为“install”&#xff0c;一种为“deinstall”对于"deinstall"的镜像&#xff0c;一般为镜像…

C# 9.0 正式发布了(C# 9.0 on the record)

翻译自 Mads Torgersen 2020年11月10日的博文《C# 9.0 on the record》 [1]&#xff0c;Mads Torgersen 是微软 C# 语言的首席设计师&#xff0c;也是微软 .NET 团队的项目群经理。C# 9.0 正式发布正式宣布&#xff1a;C# 9.0 发布了&#xff01;早在5月&#xff0c;我就写了一…

磁带最优存储问题java实现_磁带的最优存储问题(贪心选择)

算法设计n个程序的平均读取时间&#xff1a;(贪心策略)在该题目中&#xff0c;要考虑综合因素&#xff1a;长度和读取概率。要求n个程序的平均读取时间最短。按照贪心策略&#xff0c;则每个程序的读取时间都应该最短。故&#xff1a;(1)计算每个程序的长度和读取概率的乘积。(…

BCVP第2期:项目已完成升级.NET5.0

(是时候拿出来这种图了)1开心的锣鼓想必这两天最热闹的几个词语&#xff0c;就是c#9.0、.net5.0还有conf大会了吧&#xff0c;当然还有大一统。其实&#xff0c;早在2019年年中&#xff0c;就已经引入了.NET5.0了&#xff0c;然后从2020-03-16开始&#xff0c;就一直在说.NET5.…

java 1..0 openjdk_java-1.7.0-openjdk-i386和java-7-openjdk-i386有什么区别

两个OpenJDK是一样的.但是OpenJDK与Oracle JDK略有不同.阅读this post了解更多信息.您为OpenJDK获取两个选项的原因是PROBABLY,您有两个安装的OpenJDK副本(或两个不同的引用到系统上的同一目录).为了进一步调查,请尝试使用ls -lh /usr/lib / jvm. /usr/lib / jvm通常是Java安装…

linux java升级版本_为嵌入式Linux设备实现更新/升级系统

我有一个在嵌入式Linux设备上运行的应用程序&#xff0c;并且偶尔会对软件进行更改&#xff0c;有时也会对根文件系统甚至已安装的内核进行更改 .在当前的更新系统中&#xff0c;只删除旧应用程序目录的内容&#xff0c;并在其上复制新文件 . 当对根文件系统进行更改时&#xf…