您现在的位置是:首页 > 文章详情

ASP.NET Core on K8S学习初探(2)部署WebAPI到K8S

日期:2019-06-30点击:481

在上一篇《单节点环境搭建》中,通过Docker for Windows在Windows开发机中搭建了一个单节点的K8S环境,接下来就是动人心弦的部署ASP.NET Core API到K8S了。但是,在部署之前,我还是把基本的一些概念快速地简单地不求甚解地过一下,过完这些基本概念就可以体验一下部署一个ASP.NET Core WebAPI到K8S了。

一、K8S集群基本概念

(1)集群

首先,K8S集群也是需要多台服务器组成,作为容器的编排管理平台,只有一个节点在生产环境是不够的。

(2)Node

其次,Node作为K8S集群中的工作节点,一个Node可以是VM或物理机,它运行真正的应用程序。

K8S中的Node又分为Master和Worker,和Hadoop集群中的NameNode和DataNode类似,简而言之就是一个是负责调度(维护集群状态)的,一个是负责干活(运行容器)的。

(3)资源

在K8S每个组件(比如Pod,Service等)开放对外暴露的都是一组RESTful API,所以我们所有对于组件的操作都可以通过RESTful API来完成,因此我们可以将其看作是资源。

(4)Kubectl

Kubectl是一个客户端命令行工具,使用它可以连接K8S集群和进行交互。

如下图所示,我们通过kubectl输入命令与远程的K8S集群连接,而这些命令本质是通过调用API访问Master节点提供的API,通过这些API去操作所谓的集群中的“资源”,对这些资源进行创建(POST),修改(PUT),删除(DELETE)等操作。

二、三大核心组件

(1)Pod

Pod是K8S最基本的操作单元,包含一个或多个紧密相关的容器,一个Pod可以被一个容器化的环境看作是应用层的“逻辑宿主机”;

换句话说,在K8S中创建,调度和管理的最小单位就是Pod,而非容器(Container),多个容器之间的挂载是可以共享的,Pod通过提供更高层次的抽象,提供了更加灵活的部署和管理模式;

(2)Service

Service是一个抽象概念,它定义了逻辑集合下访问Pod组的策略。通过使用Service,我们就可以不用关心这个服务下面的Pod的增加和减少、故障重启等,只需通过Service就能够访问到对应服务的容器,即通过Service来暴露Pod的资源。

这样说可能还是有点难懂,举个例子,假设我们的一个服务Service A下面有3个Pod,我们都知道Pod的IP都不是持久化的,重启之后就会有变化。那么Service B想要访问Service A的Pod,它只需跟绑定了这3个Pod的Service A打交道就可以了,无须关心下面的3个Pod的IP和端口等信息的变化。换句话说,就像一个Service Discovery服务发现的组件,你无须关心具体服务的URL,只需知道它们在服务发现中注册的Key就可以通过类似Consul、Eureka之类的服务发现组件中获取它们的URL一样,还是实现了负载均衡效果的URL。

(3)Deployment

Deployment主要负责Pod的编排,例如我们可以使用下面的yaml文件来创建一个Deployment:

apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.12.2 ports: - containerPort: 80

熟悉Docker-Compose的朋友应该对这个yaml不陌生,可以看到Deployment定义了Pod内容,包括Pod数量、更新方式、使用的镜像,资源限制,容器中的映射端口等等。

三、Service的几种类型

(1)ClusterIP

  ClusterIP 服务是 Kubernetes 的默认服务。它给你一个集群内的服务,集群内的其它应用都可以访问该服务,但是集群外部无法访问它。

因此,这种服务常被用于内部程序互相的访问,且不需要外部访问,那么这个时候用ClusterIP就比较合适,如下面的yaml文件所示:

apiVersion: v1 kind: Service metadata: name: my-internal-service selector: app: my-app spec: type: ClusterIP ports: - name: http port: 80 targetPort: 80 protocol: TCP

那么,如果需要从外部访问呢(比如我们在开发模式下总得调试吧)?可以启用K8S的代理模式:

$ kubectl proxy --port=8080

如此一来,便可以通过K8S的API来访问了,例如下面这个URL就可以访问在yaml中定义的这个my-internal-service了:

http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/

(2)NodePort

  除了只在内部访问的服务,我们总有很多是需要暴露出来公开访问的服务吧。在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就可以通过:NodePort来访问这些服务。例如,下面这个yaml中定义了服务为NodePort类型:

apiVersion: v1 kind: Service metadata: name: my-nodeport-service selector: app: my-app spec: type: NodePort ports: - name: http port: 80 targetPort: 80 nodePort: 30036 protocol: TCP

PS:这种方式顾名思义需要一个额外的端口来进行暴露,且端口范围只能是 30000-32767,如果节点/VM 的 IP 地址发生变化,你需要能处理这种情况。

(3)LoadBalancer

  LoadBalancer 服务是暴露服务到 internet 的标准方式,它借助Cloud Provider创建一个外部的负载均衡器,并将请求转发到:NodePort(向节点导流)。

例如下面这个yaml中:

kind: Service apiVersion: v1 metadata: name: my-service spec: selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376 clusterIP: 10.0.171.239 loadBalancerIP: 78.11.24.19 type: LoadBalancer status: loadBalancer: ingress: - ip: 146.148.47.155

PS:每一个用 LoadBalancer 暴露的服务都会有它自己的 IP 地址,每个用到的 LoadBalancer 都需要付费,这将是比较昂贵的花费。

四、准备一个ASP.NET Core WebAPI

这里准备一个空的ASP.NET Core WebAPI项目,使用默认自带的ValuesController控制器,具体代码见[这里](https://github.com/EdisonChou/AspNetCore.On.K8S/tree/master/src/01_hello-k8s/EDC.K8S.Demo.WebApi)。 

Dockerfile如下:

FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base WORKDIR /app EXPOSE 80 FROM microsoft/dotnet:2.1-sdk AS build WORKDIR /src COPY . . RUN dotnet restore RUN dotnet build -c Release -o /app FROM build AS publish RUN dotnet publish -c Release -o /app FROM base AS final WORKDIR /app COPY --from=publish /app . ENTRYPOINT ["dotnet", "EDC.K8S.Demo.WebApi.dll"]

我们可以事先在自己的Docker环境构建这样的一个镜像,看看能否正常使用。

由于后面会使用到这个镜像,因此可以将此镜像push到Docker Hub上。

docker push your-image-name:tagname

当然你也可以直接使用我上传的这个镜像(edisonsaonian/k8s-demo)。

五、部署ASP.NET Core WebAPI到K8S

5.1 准备Deployment YAML

在上一篇中我们知道Deployment主要负责Pod的编排,那么我们这里就通过一个YAML来创建一个Deployment。

apiVersion: apps/v1 kind: Deployment metadata: name: k8s-demo namespace: aspnetcore labels: name: k8s-demo spec: replicas: 2 selector: matchLabels: name: k8s-demo template: metadata: labels: name: k8s-demo spec: containers: - name: k8s-demo image: edisonsaonian/k8s-demo ports: - containerPort: 80 imagePullPolicy: Always --- kind: Service apiVersion: v1 metadata: name: k8s-demo namespace: aspnetcore spec: type: NodePort ports: - port: 80 targetPort: 80 selector: name: k8s-demo

这里这个deploy.yaml就会告诉K8S关于你的API的所有信息,以及通过什么样的方式暴露出来让外部访问。

需要注意的是,这里我们提前为要部署的ASP.NET Core WebAPI项目创建了一个namespace,叫做aspnetcore,因此这里写的namespace : aspnetcore。

K8S中通过标签来区分不同的服务,因此这里统一name写成了k8s-demo。

在多实例的配置上,通过replicas : 2这个设置告诉K8S给我启动2个实例起来,当然你可以写更大的一个数量值。

最后,在spec中告诉K8S我要通过NodePort的方式暴露出来公开访问,因此端口范围从上一篇可以知道,应该是 30000-32767这个范围之内。

5.2 通过kubectl部署到K8S

首先,确保你的Docker for Windows以及Kubernetes都启动起来了。

然后,在Powershell中通过kubectl完成API的部署,只需要下面这一句命令行即可:

kubectl create -f deploy.yaml

看到上面的提示"service created",就可以知道已经创建好了,这里我们再通过下面这个命令来验证一下:

kubectl get svc -n aspnetcore

可以看到,在命名空间aspnetcore下,就有了一个k8s-demo的服务运行起来了,并通过端口号31435向外部提供访问。

5.3 在K8S中验证WebAPI

首先,我们可以通过浏览器来访问一下这个API接口,看看是否能正常访问到。

  • /api/values

  • /api/values/1000

其次,还记得在第一篇中部署的Dashboard吗?我们通过Dashboard来看看我们的k8s-demo的状态:

从Dashboard中可以看到更为详细的信息,包括运行的Deployment、容器组(由于我们设置的replicas=2,因此会有2个容器运行起来)、副本集等等,也可以通过Dashboard实时初步地监控我们的API的运行情况。

六、在K8S中对WebAPI的伸缩

6.1 通过Dashboard伸缩WebAPI

在Dashboard中,我们可以可视化地对我们的Deployment进行容器实例的伸缩,如下图所示:

在弹出的伸缩选项对话框中输入个数,例如我们这里从2个缩减为1个,然后确定。

再次观看Dashboard,可以看到已经从原来的2个容器实例变为1个了。

3.2 通过Kubectl伸缩WebAPI

除了在Dashboard中可视化地操作进行伸缩,也可以通过kubectl来进行,例如下面这句命令,将容器实例扩展到3个。需要注意的是,由于我们的k8s-demo所在的命名空间是在aspnetcore下,因此也需要指明--namespace=aspnetcore。

kubectl scale deployment k8s-demo --replicas=3 --namespace=aspnetcore

再到Dashboard中来验证一下,是否扩展到了3个容器实例:

6.2 自动伸缩WebAPI实例

在K8S中,提供了一个autoscale接口来实现服务的自动伸缩,它会采用默认的自动伸缩策略(例如根据CPU的负载情况)来帮助我们实现弹性伸缩的功能。例如下面这句命令可以实现我们的k8s-demo可以伸缩的范围是1~3个,根据负载情况自己伸缩,在没有多少请求量压力很小时收缩为一个,在压力较大时启动另一个实例来降低负载。

kubectl autoscale deployment k8s-demo --min=1 --max=3 --namespace=aspnetcore

七、补充知识点

7.1 常用Kubectl命令

kubectl get svc -n kube-system //获取指定命名空间的服务 kubectl cluster-info // 获取集群信息 kubectl get nodes // 获取集群节点信息 kubectl delete node 192.168.2.152 //删除节点 192.168.2.152 kubectl get namespaces // 获取所有命名空间 kubectl create namespace aspnetcore // 创建一个命名空间“aspnetcore”

更多kubectl命令参考:

(1)https://jimmysong.io/kubernetes-handbook/guide/kubectl-cheatsheet.html

(2)https://www.jianshu.com/p/fb5c0d115421

7.2 YAML文件解析

  关于YAML文件各个节点的解释,可以通过下面这个命令去了解:

kubectl explain deployment.metadata

更多YAML文件的节点参考:https://www.kubernetes.org.cn/1414.html

7.3 更多K8S基础知识?

推荐阅读《18张插画了解Kubernetes背景与概念

八、小结

本文简单的介绍了一下在Docker for Windows环境下,通过kubectl部署一个ASP.NET Core WebAPI到K8S中,并初步使用了K8S的伸缩特性对Deployment进行实例的伸缩,体验了一下所谓的容器的编排。当然,笔者也是初玩,有很多还没学习,这也只是K8S的冰山一角,后续我会学习在Linux下部署K8S的生产级集群环境,深入学习K8S的各种概念并实践,最后会学习阿里云ACK服务(容器服务Kubernetes版)或腾讯云TKE服务(基于Kubernetes的容器服务)去部署和实践公司的生产环境,相信到时也会有很多的分享的!

参考资料

原文链接:https://yq.aliyun.com/articles/707054
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章