部署Dotnet Core应用到Kubernetes(一)
<div id="output_wrapper_id" class="output_wrapper" style="font-size: 16px; color: rgba(62, 62, 62, 1); line-height: 1.6; word-spacing: 0; letter-spacing: 0; font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif"><blockquote style="line-height: inherit; display: block; padding: 15px 15px 15px 1rem; font-size: 0.9em; margin: 1em 0; color: rgba(129, 145, 152, 1); border-left: 6px solid rgba(220, 230, 240, 1); background-color: rgba(242, 247, 251, 1); overflow: auto; word-wrap: normal; word-break: normal">
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 0">最近闲了点,写个大活:部署Dotnet应用到K8s。</p>
</blockquote>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0"> </p>
<h1 id="h" style="color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0; font-weight: bold; font-size: 1.6em"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">写在前边的话</span></h1>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">一直想完成这个主题。但这个主题实在太大了,各种拖延症的小宇宙不时爆发一下,结果就拖到了现在。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0"> </p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">这个主题,会是一个系列。在这个系列中,我会讨论将应用部署到K8s时需要的各个内容和知识,以及各种刨过的坑。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">为了避免这个系列被扩得过大,我不深入讨论K8s的技术,也不去解释如何建立K8s集群之类的问题。这个主题会侧重在开发人员方面,侧重于如何开发适合K8s的应用,以及在K8s上部署。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">另外,这个主题也不会关注Docker。在我看来,Docker是一个附加技术,而不是必要内容。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0"> </p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">在项目中,是否需要使用K8s,算是一个问题。从各个方面来看,很多中大型的项目都倾向于往这个方面去做,但我们必须清楚,使用K8s增加了项目的复杂度。如果构建的是一个独立的应用程序,那用K8s实在没有必要。而即便是一个大的系统,其实也没有必要从开头就加入K8s。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">本主题中的内容大多来自我自己部署Dotnet Core到K8s集群的经验。如果有任何问题,可以在评论中告诉我。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0"><em style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0; font-style: italic"> <span style="font-size: small; color: inherit; line-height: inherit; margin: 0; padding: 0">为防止非授权转发,这儿给出本文的原文链接:https://www.cnblogs.com/tiger-wang/p/13956098.html</span></em></p>
<h1 id="hk8skubernetes" style="color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0; font-weight: bold; font-size: 1.6em"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">K8s(Kubernetes)面向开发的组件</span></h1>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">前边说了,这个主题我们仅关注部署应用程序相关的部分,而不讨论K8s的全部。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">面向开发,面向部署,我们需要了解下面几个概念:</p>
<ul style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0 0 0 32px; list-style-type: disc">
<li style="font-size: inherit; color: inherit; line-height: inherit; margin: 0 0 0.5em; padding: 0"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">节点(Node)</span></li>
<li style="font-size: inherit; color: inherit; line-height: inherit; margin: 0 0 0.5em; padding: 0"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">Pod</span></li>
<li style="font-size: inherit; color: inherit; line-height: inherit; margin: 0 0 0.5em; padding: 0"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">部署(Deployment)</span></li>
<li style="font-size: inherit; color: inherit; line-height: inherit; margin: 0 0 0.5em; padding: 0"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">服务(Service)</span></li>
<li style="font-size: inherit; color: inherit; line-height: inherit; margin: 0 0 0.5em; padding: 0"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">入口(Ingress)</span></li>
</ul>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">这几个概念,是整个内容的基础。</p>
<h2 id="h1node" style="color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0; font-weight: bold; font-size: 1.4em"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">1. 节点(Node)</span></h2>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">在K8s中,Node对应的是虚拟机或物理硬件,是K8s实际运行容器的地方。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">一般来说,有两类节点:</p>
<ul style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0 0 0 32px; list-style-type: disc">
<li style="font-size: inherit; color: inherit; line-height: inherit; margin: 0 0 0.5em; padding: 0"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">主节点(Master),用来运行所有的控制级(Control-plane)服务。主节点也可以运行应用程序,但一般来说,主节点只处理控制管理服务,不运行工作负载。</span></li>
<li style="font-size: inherit; color: inherit; line-height: inherit; margin: 0 0 0.5em; padding: 0"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">其它节点,用来运行真正的应用程序。一个节点可以运行多个应用程序或应用程序容器。</span></li>
</ul>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">一个典型的K8s集群会像下面图中的样子:</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0"><img src="https://img2020.cnblogs.com/blog/907112/202011/907112-20201110212234732-1821820320.png"></p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">当然,在实际应用中,看K8s的规模。必要时,也可以做成单机,主节点运行控制服务的同时,也运行应用程序。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">在集群中,节点越多,可以运行的应用或容器就越多,节点宕机时的容错能力也就越大。</p>
<h2 id="h2pod" style="color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0; font-weight: bold; font-size: 1.4em"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">2. Pod</span></h2>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">K8s中最小的管理单元,不是一个个独立的容器,而是Pod。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">要在K8s中运行应用程序,需要将其打包到一个容器(通常是Docker容器)中,并让K8s运行它。Pod是可以让K8s运行的最小单元。它包含一个或多个容器。当一个Pod被创建或销毁时,它里面的所有容器也会被创建或销毁。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0"> </p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">在网上,很多的文章都介绍说:如果有一个依赖于数据库的应用,那应该把应用容器和数据库容器部署在同一个Pod中,以便同步创建或销毁。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">以我的经验来说,这个说法很不准确,而且容易造成对K8s应用的误解。在K8s的实际应用中,只包含单个容器的Pod会更常用,也更好用。就好像“支付API”或“订单API”这样的,每个API都有不同的扩展需求、部署要求和迭代速度,因此单独设置Pod给它们是非常合理的。同样,数据库容器也应该部署在独立的Pod中,因为它与应用/服务/API会有不同的生命周期。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">还有一个比较常用的是SideCar模式,就是在一个Pod下的主容器旁边部署“SIdeCar“容器,用来充当代理,为主应用程序进行身份证认处理,或服务发现,以及服务通讯,甚至能充当应用性能监控的接收器来用。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">一个典型的节点下的Pod是下面的样子:</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0"><img src="https://img2020.cnblogs.com/blog/907112/202011/907112-20201110212248318-1045485534.png"></p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">再重申一下:一个节点下面可以有多个Pod。一个Pod在K8s中会作为一个整体单元进行调度。一个Pod可能包含一个容器,也可能包含多个容器。容器用于部署应用或API。</p>
<h2 id="h3" style="color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0; font-weight: bold; font-size: 1.4em"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">3. 部署</span></h2>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">在我的概念中,K8s主要做了两件事:</p>
<ul style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0 0 0 32px; list-style-type: disc">
<li style="font-size: inherit; color: inherit; line-height: inherit; margin: 0 0 0.5em; padding: 0"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">管理容器的生存期</span></li>
<li style="font-size: inherit; color: inherit; line-height: inherit; margin: 0 0 0.5em; padding: 0"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">管理容器之间的通讯</span></li>
</ul>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">K8s的部署,主要完成的是第一件事,即管理容器的生存周期。所以,部署可以看做是定义K8s如何部署Pod以及如果管理Pod的一组规则。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">比方,我们可能这样定义一个部署:</p>
<ol style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0 0 0 32px; list-style-type: decimal">
<li style="font-size: inherit; color: inherit; line-height: inherit; margin: 0 0 0.5em; padding: 0"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">Pod包含支付API应用Docker映像的一个实例;</span></li>
<li style="font-size: inherit; color: inherit; line-height: inherit; margin: 0 0 0.5em; padding: 0"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">我们要运行这个Pod的三个副本</span></li>
<li style="font-size: inherit; color: inherit; line-height: inherit; margin: 0 0 0.5em; padding: 0"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">保证每个容器至少有200Mb的可用内存,并限制它最多不超过400Mb;</span></li>
<li style="font-size: inherit; color: inherit; line-height: inherit; margin: 0 0 0.5em; padding: 0"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">当我们部署Pod新版本时,采用滚动更新策略</span></li>
</ol>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">定义完后,K8s就会严格执行这个规则。如果应用崩溃了,K8s会删除Pod并安排一个新的Pod,以保证规则规定的副本数量。如果Pod需要更多内存,K8s会选择一个运行容器较少的节点上运行它,或者结束并重新部署它。当应用更新一个新版本时,K8s会创建一个新的部署,来替换旧版本,并将运行转到新的版本。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">当然,上面这个例子做了一定的简化。不过,基本上K8s的基本工作就是这么做的。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">这里的关键就是:部署定义了规则,K8s在这个部署的整个生命周期中维护并保持这个规则。</p>
<h1 id="h4" style="color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0; font-weight: bold; font-size: 1.6em"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">4. 服务</span></h1>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">前面说过,部署可以用来创建跨多个节点(Node)的Pod的多个副本。这其实就是K8s提高性能及提高可用性的主要原理。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">服务是应用对外的部分,供其它API去调用。而在K8s内部,服务可以看作是Pod在集群内的负载均衡器。当我们创建部署时,通常还会创建一个与该应用的Pod关联的服务。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">在上面的例子中,当我们创建部署时,也会创建一个“Payment API”的服务,供其它API调用。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">而当其它Pod需要与这个支付API的Pod通讯时,实际不会与支付API的一个Pod直接联系,而是将请求发给服务,然后由服务将请求传递给某一个Pod的实例。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">这个过程参见下面的图:</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0"><img src="https://img2020.cnblogs.com/blog/907112/202011/907112-20201110212329127-320051089.png"></p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">服务与网络相关。因此,服务有多种不同的网络模式。这里不详细说了,只拿一个常用的模式举个例子:</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">K8s将服务分配到一个DNS记录,并通过这个记录将请求从一个Pod转发到另一个Pod。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">假设我们有一个支付服务,而我们的购买服务需要调用这个服务。K8s不需要知道Pod的真实IP,我们只需要分配一个DNS记录给服务:</p>
<pre><code class="bash language-bash hljs" style="margin: 0 2px; line-height: 18px; font-size: 14px; font-weight: normal; word-spacing: 0; letter-spacing: 0; font-family: Consolas, Inconsolata, Courier, monospace; border-radius: 0; overflow-x: auto; background-color: rgba(239, 236, 244, 1); color: rgba(88, 82, 96, 1); padding: 0.5em; white-space: pre !important; word-wrap: normal !important; word-break: normal !important; overflow: auto !important">payment-api.xxx.local<br></code></pre>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">通过这个域名,购买服务可以调用支付服务,而不需要知道支付服务对应的Pod的真正IP。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">这个工作方式与Dotnet体系完全一样。通过这种方式,可以实现对资源的逻辑分组,这是题外话。</p>
<h2 id="h5" style="color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0; font-weight: bold; font-size: 1.4em"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">5. 入口</span></h2>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">入口与服务很像,但有本质的不同。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">服务本质上是K8s集群内部的东西,用来实现Pod之间的内部调用。而入口将HTTP/HTTPS从集群外部路由到内部的服务,这样,外部应用,例如前端、APP或小程序就可以通过这个入口,调用内部服务来处理请求。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">同时,入口也可以当成提供外部负载均衡,即跨多个节点平衡对给定服务的请求。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">除此之外,入口也可以提供其它一些特性,例如主机名或基于路径的路由。通常,我们可以为每个应用或API配置一个入口。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">还有,入口设置也可以用来做应用的反向代理。例如通过一个Nginx实例来配置入口。这都是可以的,而且这样的方式,可以让API隐藏在反向代理之后,而不用直接暴露在外网。这个部分,在后面的文章,我会专门写。</p>
<h1 id="h-1" style="color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0; font-weight: bold; font-size: 1.6em"><span style="font-size: inherit; color: inherit; line-height: inherit; margin: 0; padding: 0">总结一下</span></h1>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">这篇文章是这个系列的一个引子。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">当我们在K8s中部署一个Dotnet Core的应用时,我们需要配置Pod部署,添加服务来在K8s内部公开这些Pod,并添加一个入口来公开服务。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">本系列的后续文章中,我会从开发的各个环节来解释如何使用这些组件来部署Dotnet Core应用到K8s。</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">敬请关注!!!</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0">(未完待续)</p>
<p style="font-size: inherit; color: inherit; line-height: inherit; padding: 0; margin: 1.5em 0"> </p>
<hr>
<p> </p>
<table border="0">
<tbody>
<tr>
<td><img src="https://img2020.cnblogs.com/blog/907112/202005/907112-20200527230728396-985375280.jpg"></td>
<td>
<p>微信公众号:老王Plus</p>
<p>扫描二维码,关注个人公众号,可以第一时间得到最新的个人文章和内容推送</p>
<p>本文版权归作者所有,转载请保留此声明和原文链接</p>
</td>
</tr>
</tbody>
</table>
</div><br><br>
来源:https://www.cnblogs.com/tiger-wang/p/13956098.html
頁:
[1]