ASP.NET Core 借助 Helm 部署应用至 K8S

前言

玩K8S也有一段时间了,借助云服务提供商的K8S控制台,已经可以很方便的快速部署应用至K8S。通过简单的点击,可以一次性帮忙创建K8S 对象:Deployment、Service、Ingress、ConfigMap等。但是当服务的规模上来后,这种方式就有点捉襟见肘。尤其是需要同时更新多个关联服务时,就需要一个一个的去更改,就有点不太方便。为了解决这个问题,最近上手实操了一下Helm,发现生产力大大提升。

Helm 简介

Helm 是一个为K8S打造的包管理器。通过Helm可以方便管理Kubernetes应用程序。Helm主要有两大核心概念:Charts、Release。

  1. Chart:用来定义,安装和升级K8S 应用。亦可分享及版本化控制。

  2. Release:类似Image之于Container,Release是Chart的运行实例。

目前Helm最新的版本为V3.1,较之前版本,在整体架构上移除服务端Tiller。对于Windows系统而言可借助Choco快速安装:choco install kubernetes-helm,通过执行 helm version确认是否安装成功。

version.BuildInfo{Version:"v3.1.0",GitCommit:"b29d20baf09943e134c2fa5e1e1cab3bf93315fa",GitTreeState:"clean",GoVersion:"go1.13.7"}

在继续往前,请确保已具备基础的K8S基础知识,并且确保本机已安装Docker和K8S。安装教程和K8S简单入门可参考我的这篇文章:ASP.NET Core 借助 K8S 玩转容器编排。

对于第一次接触Helm .NETer 来说我们可以通过VS 2019来快速体验一下。请确保已安装Visual Studio Tools for Kubernetes。

创建 Chart (helm create)

打开VS 创建项目,选择Container Application for Kubernetes,创建一个空的ASP.NET Core Web 项目。创建后,项目结构如下图所示,与平时之间创建的Web项目而言,主要是多了一个 charts目录、 Dockerfile和一个 azds.yaml除了创建项目时通过选择Container Application for Kubernetes类型外,我们也可以通过其他方式创建。我们这里手动删除 charts目录、 Dockerfile和一个 azds.yaml。然后如下图步骤即可重新生成Helm Chart。

当然也可以通过 helm create创建。

安装 Chart (helm install)

在展开之前,先来简要介绍Chart目录:

k8shelmdemo/                         # Chart 目录
├── charts                           # 这个 charts 依赖的其他 charts,始终被安装
├── Chart.yaml                       # 描述这个 Chart 的相关信息、包括名字、描述信息、版本等
├── templates                        # 模板目录
│   ├── deployment.yaml              # deployment 控制器的 Go 模板文件
│   ├── _helpers.tpl                 # 以 _ 开头的文件不会部署到 k8s 上,可用于定制通用信息
│   ├── ingress.yaml                 # ingress 的模板文件
│   ├── NOTES.txt                    # Chart 帮助文本,安装后会显示给用户,例如:如何使用、列出缺省值
│   ├── service.yaml                 # service 的 Go 模板文件
│   ├── secrets.yaml                 # secrets 的 Go 模板文件
│   └── tests
│       └── test-connection.yaml
└── values.yaml                      # 模板的值文件,这些值会在安装时应用到 GO 模板生成部署文件

简单来说,Helm Chart 定义常用的K8S 对象模板,通过values.yaml来填充模板。那我们就来看看填充后的输出结果是怎样的。打开命令提示符,进入到Chart目录,通过 helmtemplate--debug[release name][chart dir]命令就可以测试Chart(亦可通过 helm--dry-run--debug[release name][chart dir]测试)。可以看到输出了Service和Deployment。这里你可能就纳闷了,不是定义了4个K8S对象模板吗,为什么就是输出2个yaml文件呢。这里先按住不表。

PS \K8S.Helm.Demo\charts> helm template --debug k8s-helm-demo .\k8shelmdemo\
install.go:158: [debug] Original chart version: ""
install.go:175: [debug] CHART PATH: \K8S.Helm.Demo\charts\k8shelmdemo
---
# Source: k8shelmdemo/templates/service.yaml
apiVersion: v1
kind: Service
metadata:name: k8shelmdemolabels:app: k8shelmdemochart: k8shelmdemo-0.1.0release: k8s-helm-demoheritage: Helm
spec:type: ClusterIPports:- port: 80targetPort: httpprotocol: TCPname: httpselector:app: k8shelmdemorelease: k8s-helm-demo
---
# Source: k8shelmdemo/templates/deployment.yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:name: k8shelmdemolabels:app: k8shelmdemochart: k8shelmdemo-0.1.0draft: draft-apprelease: k8s-helm-demoheritage: Helm
spec:replicas: 1selector:matchLabels:app: k8shelmdemorelease: k8s-helm-demotemplate:metadata:labels:app: k8shelmdemodraft: draft-apprelease: k8s-helm-demoannotations:buildID: ""spec:containers:- name: k8shelmdemoimage: "k8shelmdemo:stable"imagePullPolicy: IfNotPresentports:- name: httpcontainerPort: 80protocol: TCPenv:resources:{}

这里目前需要注意一点就是上面输出的Deployment中使用的镜像为 image:"k8shelmdemo:stable"。所以在安装该Chart之前,我们需要构造镜像。镜像构造很简单,在Vs中右键Dockerfile选择构建就好(请确保Docker已启动)。观察VS输出窗口,会有以下输出:

<code class="1 style=" font-size:="" 10px;line-height:="" 12px"="" style="box-sizing: border-box; margin-left: -20px; display: flex; overflow: initial; overflow-wrap: normal; border: 0px; font-family: inherit !important; line-height: 20px !important; white-space: pre !important;">------ Rebuild All started: Project: K8S.Helm.Demo, Configuration: Debug Any CPU ------ language-1>------ Rebuild All started: Project: K8S.Helm.Demo, Configuration: Debug Any CPU ------">1>K8S.Helm.Demo -> D:\Programming\Coding\dotnet\K8S.Ocelot.Demo\src\K8S.Helm.Demo\bin\Debug\netcoreapp3.1\K8S.Helm.Demo.dll
1>docker build -f "d:\programming\coding\dotnet\k8s.ocelot.demo\src\k8s.helm.demo\dockerfile" --force-rm -t k8shelmdemo  --label "com.microsoft.created-by=visual-studio" --label "com.microsoft.visual-studio.project-name=K8S.Helm.Demo" "d:\programming\coding\dotnet\k8s.ocelot.demo\src"
1>
1>Step 2/18 : WORKDIR /app
1> ---> Using cache
1>Step 3/18 : EXPOSE 80
1> ---> bb9dc51530fe
1> ---> 0a4c7c13f9d6
1> ---> Using cache
1>Step 6/18 : COPY ["K8S.Helm.Demo/K8S.Helm.Demo.csproj", "K8S.Helm.Demo/"]
1>Step 7/18 : RUN dotnet restore "K8S.Helm.Demo/K8S.Helm.Demo.csproj"
1>  Restore completed in 7.19 sec for /src/K8S.Helm.Demo/K8S.Helm.Demo.csproj.
1> ---> ba3624442138
1> ---> 43c4f6c4769f
<code class="1 style=" font-size:="" 10px;line-height:="" 12px"="" style="box-sizing: border-box; margin-left: -20px; display: flex; overflow: initial; overflow-wrap: normal; border: 0px; font-family: inherit !important; line-height: 20px !important; white-space: pre !important;">1>Step 9/18 : WORKDIR "/src/K8S.Helm.Demo"
1>Removing intermediate container 145e155d3a5d
<code class="1 style=" font-size:="" 10px;line-height:="" 12px"="" style="box-sizing: border-box; margin-left: -20px; display: flex; overflow: initial; overflow-wrap: normal; border: 0px; font-family: inherit !important; line-height: 20px !important; white-space: pre !important;">1>Step 10/18 : RUN dotnet build "K8S.Helm.Demo.csproj" -c Release -o /app/build
1> ---> Running in 146df981f291
1>Copyright (C) Microsoft Corporation. All rights reserved.
1>  Restore completed in 27.08 ms for /src/K8S.Helm.Demo/K8S.Helm.Demo.csproj.
1>Build succeeded.
1>
1>    0 Error(s)
1>Step 11/18 : FROM build AS publish
1> ---> 94f07ad82c1c
<code class="1 style=" font-size:="" 10px;line-height:="" 12px"="" style="box-sizing: border-box; margin-left: -20px; display: flex; overflow: initial; overflow-wrap: normal; border: 0px; font-family: inherit !important; line-height: 20px !important; white-space: pre !important;">1>Step 12/18 : RUN dotnet publish "K8S.Helm.Demo.csproj" -c Release -o /app/publish
1>Microsoft (R) Build Engine version 16.4.0+e901037fe for .NET Core
1>Copyright (C) Microsoft Corporation. All rights reserved.
1>  K8S.Helm.Demo -> /src/K8S.Helm.Demo/bin/Release/netcoreapp3.1/K8S.Helm.Demo.dll
1>Removing intermediate container 60d63984fe28
1> ---> 85d893dc4a81
1>Step 14/18 : WORKDIR /app
1>Removing intermediate container 69b7fd56c371
1>Step 15/18 : COPY --from=publish /app/publish .
<code class="1 style=" font-size:="" 10px;line-height:="" 12px"="" style="box-sizing: border-box; margin-left: -20px; display: flex; overflow: initial; overflow-wrap: normal; border: 0px; font-family: inherit !important; line-height: 20px !important; white-space: pre !important;">1>Step 16/18 : ENTRYPOINT ["dotnet", "K8S.Helm.Demo.dll"]
1> ---> Running in a43a0516c6dc
1> ---> 36f422c923fd
1> ---> Running in 88d100227ee1
1> ---> 4a71f8e5e761
1> ---> Running in f609881010ad
1> ---> 3301427c0fb8
1>Successfully tagged k8shelmdemo:latest
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

最终构建的镜像名称为 k8shelmdemo:latest。与我们上面Chart中使用的镜像 k8shelmdemo:stable不一致。如果现在安装Chart,那么应用将无法找对应的镜像无法启动。那怎么办呢。查看 deployment.yaml模板文件,我们发现其镜像引用定义为 image:"{{ .Values.image.repository }}:{{ .Values.image.tag }}"。查看 values.yaml发现如下定义:

image:repository: k8shelmdemotag: stablepullPolicy: IfNotPresent

所以改法就很简单了,将 values.yaml的tag更改为 latest即可。更改后在执行 helmtemplate--debug[release name][chart dir] 验证下。接下来通过 helm install来安装Chart。在执行之前,我们先通过 kubectl create ns helmdemo创建一个独立的命名空间以方便确认和清理。再执行 helm install k8shelmdemo.\k8shelmdemo\-n helmdemo 安装(-n 指定我们刚刚创建的命名空间)。具体命令如下:

PS \K8S.Helm.Demo\charts> kubectl create ns helmdemo
namespace/helmdemo created
PS \K8S.Helm.Demo\charts> helm install k8shelmdemo .\k8shelmdemo\ -n helmdemo
NAME: k8shelmdemo
LAST DEPLOYED: Sun Feb 23 17:33:54 2020
NAMESPACE: helmdemo
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get the application URL by running these commands:export POD_NAME=$(kubectl get pods --namespace helmdemo -l "app=k8shelmdemo,release=k8shelmdemo" -o jsonpath="{.items[0].metadat
a.name}")echo "Visit http://127.0.0.1:8080 to use your application"kubectl port-forward $POD_NAME 8080:80
PS \K8S.Helm.Demo\charts>

我们看到同时输出了模板文件夹下的NOTES模板,这时说明helm已经安装了。那怎样确保是否安装成功了呢。继续执行以下命令:

PS \K8S.Helm.Demo\charts> helm list -n helmdemo #查看指定命名空间下已安装的chart,也就是运行中的Release
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
k8shelmdemo     helmdemo        1               2020-02-23 17:33:54.2196357 +0800 CST   deployed        k8shelmdemo-0.1.0       1.0
PS \K8S.Helm.Demo\charts> kubectl get all -n helmdemo # 查看指定命名空间下K8S下所有的对象
NAME                               READY   STATUS    RESTARTS   AGE
pod/k8shelmdemo-689bd54677-fcfx7   1/1     Running   0          5m8s
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/k8shelmdemo   ClusterIP   10.97.204.227   <none>        80/TCP    5m8s
NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/k8shelmdemo   1/1     1            1           5m8s
NAME                                     DESIRED   CURRENT   READY   AGE
replicaset.apps/k8shelmdemo-689bd54677   1         1         1       5m8s

至此我们可以确定Chart成功安装。那如何访问刚刚部署的Web应用呢,安装刚刚Chart的安装Notes,通过 kubectl port-forward配置端口转发,来完成。从上面的输出我们已经知道对应的Pod Name 为k8shelmdemo-689bd54677-fcfx7。执行 kubectl port-forward k8shelmdemo-689bd54677-fcfx78090:80

PS \K8S.Helm.Demo\charts> kubectl port-forward k8shelmdemo-689bd54677-fcfx7 8090:80 -n helmdemo
Forwarding from 127.0.0.1:8090 -> 80
Forwarding from [::1]:8090 -> 80

换一个命令行执行 curl-l http://localhost:8090 会看到输出 Helloworld

更新 Chart (helm upgrade)

假设我现在想将输出更新为 HelloHelm,我们来看下怎么办。对于当前应用来说,更新输出,只需要更改Startup的 HelloWorld改为 HelloHelm 就好,然后重新构建镜像。这里思考一下,因为重新构建的镜像Tag还是 k8shelmdemo:latest,所以无需对当前Helm Chart做任何改动,所以也就无需更新。那我们该如何更新应用呢。如果有K8S基础的同学应该很快就能想到,直接删除Pod即可。因为从上面 kubectlgetall-n helmdemo的输出中,我们可以看到Chart为我们的应用自动创建了一个 ReplicaSet实例,ReplicaSet主要用于确保应用始终保持指定数量的实例运行。所以如果删除一个Pod,K8S会按照ReplicaSet的定义,重新启用一个新的Pod。再重新执行 kubectl port-forward,会发现应用已更新。

PS: 因为当前demo使用的是本地镜像,所以删除Pod后,重新运行的pod能够输出更新后的结果。如果镜像来源并非本地,那么对于同一个镜像tag来说,就要考虑更新镜像拉取策略。

PS \K8S.Helm.Demo\charts> kubectl delete pod/k8shelmdemo-689bd54677-fcfx7 -n helmdemo # 删除pod
PS \K8S.Helm.Demo\charts> kubectl get all -n helmdemo
NAME                               READY   STATUS    RESTARTS   AGE
pod/k8shelmdemo-689bd54677-mrr64   1/1     Running   0          29s # 新的Pod创建成功
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/k8shelmdemo   ClusterIP   10.97.204.227   <none>        80/TCP    33m
NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/k8shelmdemo   1/1     1            1           33m
NAME                                     DESIRED   CURRENT   READY   AGE
replicaset.apps/k8shelmdemo-689bd54677   1         1         1       33m

假设现在需要服务部署后直接通过指定端口访问,无需通过 kubeclt port-forward进行端口转发。那么我们就需要对Chart进行相应更新,将生成的Service的类型由默认的 Cluster更改为 LoadBalancer模式。更新 values.yaml中的service节点如下:

service:type: LoadBalancerport: 8093

紧接着通过执行 helm upgrade[release name][chart dir]命令更新应用,如下。

PS \K8S.Helm.Demo\charts> helm upgrade k8shelmdemo .\k8shelmdemo\ -n helmdemo
Release "k8shelmdemo" has been upgraded. Happy Helming!
NAME: k8shelmdemo
LAST DEPLOYED: Sun Feb 23 18:39:30 2020
NAMESPACE: helmdemo
STATUS: deployed
REVISION: 3
TEST SUITE: None
NOTES:
1. Get the application URL by running these commands:NOTE: It may take a few minutes for the LoadBalancer IP to be available.You can watch the status of by running 'kubectl get svc -w k8shelmdemo'export SERVICE_IP=$(kubectl get svc --namespace helmdemo k8shelmdemo -o jsonpath='{.status.loadBalancer.ingress[0].ip}')echo http://$SERVICE_IP:8093
PS \K8S.Helm.Demo\charts> kubectl get all -n helmdemo
NAME                               READY   STATUS    RESTARTS   AGE
pod/k8shelmdemo-689bd54677-pj5pd   1/1     Running   0          22m
NAME                  TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/k8shelmdemo   LoadBalancer   10.97.204.227   localhost     8093:30035/TCP   65m
NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/k8shelmdemo   1/1     1            1           65m
NAME                                     DESIRED   CURRENT   READY   AGE
replicaset.apps/k8shelmdemo-689bd54677   1         1         1       65m
PS \K8S.Ocelot.Demo\src\K8S.Helm.Demo\charts> curl -l localhost:8093
Hello Helm!
PS \K8S.Helm.Demo\charts> helm ls -n helmdemo # 版本已更新
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
k8shelmdemo     helmdemo        2                2020-02-23 18:39:30.2059395 +0800 CST   deployed        k8shelmdemo-0.1.0       1.0

删除 Chart(helm delete)

演示完毕,那如何删除已发布的Release呢,执行 helmdeletek8shelmdemo-n helmdemo

PS \K8S.Helm.Demo\charts> helm delete k8shelmdemo -n helmdemo
release "k8shelmdemo" uninstalled
PS \K8S.Helm.Demo\charts> helm ls -n helmdemo
NAME    NAMESPACE       REVISION        UPDATED STATUS  CHART   APP VERSION
PS \K8S.Helm.Demo\charts> kubectl get all -n helmdemo
No resources found.

执行后,可以发现创建的K8S资源也已清理干净。

最后

以上仅是对 ASP.NET Core 如何使用 Helm 部署到K8S的简单介绍,希望对入门的你有所帮助!对于Helm复杂的应用,主要在于模板填充的复杂应用,大家可以结合官方Helm文档以及eShopOnContainer中Helm示例进行学习。

参考资料:

Get started with Visual Studio Kubernetes Tools

玩K8S不得不会的HELM

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

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

相关文章

.Net Core中IOC容器的使用

本文由江北原创投稿&#xff0c;独家授权技术在于分享&#xff08;公众号ID&#xff1a;sharecore&#xff09;&#xff0c;未经许可&#xff0c;不得转载。作者&#xff1a;江北打代码之前先说一下几个概念,那就是什么是IOC、DI、DIP虽然网上讲这些的已经有很多了,我这里还是要…

qiankun 微前端_qiankun 微前端应用实践与部署(二)

下面是两种方案的简要描述。传统部署方式通过配置 nginx 端口到目录的转发。具体可查看上一篇文章特点需要对外开放子应用对应的端口&#xff0c;将编译好的应用文件放到对应的配置目录。docker 部署方式首先构建主应用与子应用的 docker 镜像&#xff0c;通过 docker run 或者…

在树莓派上使用 PowerShell 调用 Azure 上的 .NET Core API 获取疫情数据

点击上方蓝字关注“汪宇杰博客”导语最近因为疫情被关在家里&#xff0c;做了个无聊成就&#xff1a;我们将在树莓派上用 PowerShell 调用 Azure 上的一个 .NET Core 写的 API 来获取疫情数据。疫情数据API疫情数据来源于腾讯新闻的一个实时更新的页面&#xff0c;原始 API 地址…

gitlab 删除分支_初识gitlab工作流

git对我来说挺难理解的&#xff0c;平时遇到问题也是绕着走&#xff0c;倒也没啥大问题&#xff0c;但基于git软件的工作流却很重要&#xff0c;尤其对于一个组织来说。git工作流、github工作流、gitlab工作流都属于特性分支(feature branches)的类别&#xff0c;今天主要理解g…

.NET Core开发实战(第7课:用Autofac增强容器能力)--学习笔记(下)

07 | 用Autofac增强容器能力&#xff1a;引入面向切面编程&#xff08;AOP&#xff09;的能力如何获取没有命名的服务呢&#xff1f;// 获取没有命名的服务&#xff0c;把 namd 去掉即可 var servicenamed this.AutofacContainer.Resolve<IMyService>(); servicenamed.S…

hdfs读写流程_一文读懂HDFS分布式存储框架分析

一文读懂HDFS分布式存储框架分析HDFS是一套基于区块链技术的个人的数据存储系统&#xff0c;利用无处不在的私人PC存储空间及便捷的网络为个人提供数据加密存储服务&#xff0c;将闲置的存储空间利用起来&#xff0c;服务于正处于爆发期的个人数据存储市场。HDFS属于什么结构体…

gRPC in ASP.NET Core 3.x - gRPC 简介(1)

gRPC的结构 在我们搭建gRPC通信系统之前&#xff0c;首先需要知道gRPC的结构组成。 首先&#xff0c;需要一个server&#xff08;服务器&#xff09;&#xff0c;它用来接收和处理请求&#xff0c;然后返回响应。 既然有server&#xff0c;那么肯定有client&#xff08;客户端&…

arcgis 获取json经纬度_干货|ArcGIS的矢量化操作——ArcGis中进行地形图的配准

1.1.1方法简介1.1.1.1所有图件扫描后都必须经过扫描纠正&#xff0c;对扫描后的栅格图进行检查&#xff0c;以确保矢量化工作顺利进行。对影像的配准有很多方法&#xff0c;下面介绍一种常用方法。(1)打开 ArcMap&#xff0c;增加 Georeferncing 工具条。(2)把需要进行纠正的影…

使用ASP.NET Core构建RESTful API的技术指南

译者荐语&#xff1a;利用周末的时间&#xff0c;本人拜读了长沙.NET技术社区翻译的技术文章《微软RESTFul API指南》&#xff0c;打算按照步骤写一个完整的教程&#xff0c;后来无意中看到了这篇文章&#xff0c;与我要写的主题有不少相似之处&#xff0c;特意翻译下来。原文来…

查询ecshop网站代码排查方法_提升网站访问速度,提升网站访问速度,提升网站访问速度的个人经验分享...

一、前言网站打开慢这个问题&#xff0c;算是老生常谈了&#xff0c;在实际的生产的环境中&#xff0c;我们会经常遇到这样的问题。作为一个运维工程师&#xff0c;我们该从哪些角度去分析问题&#xff0c;判断问题&#xff0c;并最终解决问题。那么首先我会从几个方面分析这个…

dotnet 手工打一个 dotnet tool 包

现在依靠 dotnet 平台&#xff0c;可以方便分发工具&#xff0c;利用 NuGet 服务进行分发和使用工具。打一个 dotnet tool 包&#xff0c;可以将这个包上传到 NuGet 上&#xff0c;小伙伴通过和安装 NuGet 相同方式就可以将工具安装在本机上。本文将告诉大家如何手工打一个 dot…

漫谈Linux文档属性、拥有者、群组、权限

作者&#xff1a;justmine头条号&#xff1a;大数据与云原生微信公众号&#xff1a;大数据与云原生创作不易&#xff0c;在满足创作共用版权协议的基础上可以转载&#xff0c;但请以超链接形式注明出处。为了方便阅读&#xff0c;微信公众号已按分类排版&#xff0c;后续的文章…