前言

容器化对现在(0202年)来说,已经不算是什么新东西了,老黄最近也在公司推动这一块的发展,有幸落地了几个项目,有.NET Core的,也有.NET Framework的。

容器化现在主流的就是docker,说到docker,51%的概率是离不开kubernetes的。

当容器数量不多的时候,可以考虑人工+半自动化的方式维护。

当容器数量多了的话,不言而喻是需要引入容器编排的利器。

这也算是一个渐进的过程吧。

下面来看看基于 Serverless Kubernetes 的简单实践(不会介绍kubernetes的相关内容哈)。

为什么选择 Serverless Kubernetes

国内云产商基本都会有提供多个版本的Kubernetes让我们自己选择,有的公司可能能力强,一套打包带走。

老黄这边选择的是 Serverless 版的,Serverless 可以说是比较火的一个概念,也可以说是真正的云原生所应该有的基本形态。

当然老黄做出这个决定还有一个更重要的原因,不用自己维护服务器,可以更加专注自身的业务,只需要交付打包好的镜像即可。

毕竟老黄公司没有运维,已经充当半个运维了,不想让自己累趴。。

相信这个是大部分中小型公司一个比较ok的选择。

准备镜像

这里会写两个简单Web Api项目用来演示,一个.NET Core的,一个.NET Framework的。

其中.NET Core会暴露给集群外部访问,.NET Framework只在集群内部访问,同时.NET Core还会调用.NET Framework的接口。

.NET Framework

代码的话就是一个默认的ValuesController。

public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2", "nfx in k8s" };
}
}

知道.NET Framework可以基于jexus跑在Linux下面的话,应该就知道要怎么打包制作镜像了。

可以直接用 beginor 做好的镜像 beginor/jexus-x64:6.2.1.12。

ps: 老黄这边是因为有不少项目需要用到图片,所以是自己单独弄了一个,加了libgdiplus 等一些必备的东西进去。

先准备一个jexus的配置文件,这里用的是最简单的。

port=80
root=/ /app
hosts=*

然后就是Dockerfile了

# 按需替换
FROM jexus-x64-img:6.1 AS base
# FROM beginor/jexus-x64:6.2.1.12 AS base FROM mono:6.8 AS build
WORKDIR /src
COPY . .
# 还原nuget包
RUN nuget restore ServerlessNetApp.sln -Source https://api.nuget.org/v3/index.json
# 编译
RUN msbuild NfxApi/NfxApi.csproj /t:ReBuild /p:Configuration=Release /p:OutDir=/src/out /p:DeleteExistingFiles=True /p:DeployOnBuild=True /p:DeployDefaultTarget=WebPublish /p:WebPublishMethod=FileSystem FROM base AS final
WORKDIR /app
# 把发布文件复制过来
COPY --from=build /src/out/_PublishedWebsites/NfxApi /app
COPY ./nfxweb /usr/jexus/siteconf/default
# 按需放开
# RUN sed -i 's/TLSv1.2/TLSv1.0/g' /etc/ssl/openssl.cnf
CMD [ "jws", "restart"]

build一下,打包出一个镜像

docker build -t nfxapi:v1 -f ./Dockerfile.nfx .

还有重要的一步是,推送到镜像仓库,这样容器服务那边才可以拉取到。

.NET Core

代码也是很简单的,多了一个用HttpClient调用.NET Framework的接口就是了。

[ApiController]
[Route("")]
public class GwController : ControllerBase
{
private readonly IHttpClientFactory _factory; public GwController(IHttpClientFactory factory)
{
_factory = factory;
} [HttpGet]
public string Get()
{
return $"gw-svc in k8s";
} [HttpGet("svc")]
public async Task<string> GetAsync()
{
var client = _factory.CreateClient(); // 请求上面的.NET Framewore 项目
// 用服务名的方式来处理服务发现
var resp = await client.GetAsync("http://api-nfx-svc/api/values");
resp.EnsureSuccessStatusCode();
var res = await resp.Content.ReadAsStringAsync(); return $"ok - {res}";
}
}

下面这个Dockerfile应该好熟悉的了

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80 FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY . .
RUN dotnet restore "ServerlessNetApp.sln"
WORKDIR /src/GwApi
RUN dotnet build "GwApi.csproj" -c Release -o /app/build FROM build AS publish
RUN dotnet publish "GwApi.csproj" -c Release -o /app/publish FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish . # 按需放开
#RUN sed -i 's/TLSv1.2/TLSv1.0/g' /etc/ssl/openssl.cnf
ENTRYPOINT ["dotnet", "GwApi.dll"]

同样的要把它打包成镜像推送到镜像仓库。

docker build -t ncapi:v1 -f ./Dockerfile.nc .

运行起来

运行起来的话就是准备一些yml文件了,这里就贴出部分内容,具体的可以去github看。

先来看看Deployment和Service。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: api-nfx-svc
namespace: test
labels:
app: api-nfx-svc
spec:
replicas: 1
selector:
matchLabels:
app: api-nfx-svc
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: api-nfx-svc
spec:
containers:
image: >-
镜像仓库地址/api-nfx:v1
imagePullPolicy: IfNotPresent
name: api-nfx
resources:
requests:
cpu: 250m
memory: 512Mi
# 省略部分 ...
---
apiVersion: v1
kind: Service
metadata:
name: api-nfx-svc
namespace: test
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: api-nfx-svc
clusterIP: None
sessionAffinity: None

因为要把.NET Core项目暴露出去,让外部访问,所以我们还要有一个Ingress。

这里的话是基于阿里云的负载均衡,没有用ingress-nginx或ingress-traefik,不那么通用。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
# 指定 SLB 的Id
service.beta.kubernetes.io/alicloud-loadbalancer-id: lb-xxxxxxx
name: gw-ingress
namespace: test
spec:
rules:
- host: ncgw.xxx.com
http:
paths:
- backend:
serviceName: api-nc-svc
servicePort: 80
path: /
status:
loadBalancer:
ingress:
- ip: xxx.xxx.xxx.xxxx

依次把服务,路由跑起来。

kubectl apply -f ../k8s/svc-nfx.yml

kubectl apply -f ../k8s/svc-nc.yml

kubectl apply -f ../k8s/ingress.yml

然后就可以看到在控制台的无状态中出现了我们刚才创建的两个应用。

ps: 老黄手抖,把应用名加了个-svc。。。

服务还有路由

最后就是负载均衡

最后通过DNS解析一下域名到这个负载均衡的IP就可以了。

这个时候应用已经跑起来了,现在是只暴露出了.NET Core的项目可以给外面的访问

访问.NET Core项目的这个地址, http://ncgw.domain.com/svc, 就是通过SLB->集群里的.NET Core->集群里面.NET Framework

一些额外细节

阿里云的serverless kubernetes是基于弹性容器实例(ECI)的,所以最终创建的pod是运行在ECI里面的。

下面是ECI的一个列表。

对比一下两者的监控,

先是.NET Core的

再看看.NET Framwork的

.NET Framework的项目确实是占用的资源多一点。

进去容器里面看看吧。

进来容器里面,其实就是进入了集群环境了。

我们同样可以通过服务名去访问到对应的服务了。

最后一个就是服务发现是基于DNS的。

写在最后

serverless kubernetes用起来确实比较方便,省了很多不必要的麻烦,不过也是踩着坑过来的,坑踩多了,也就可以轻车熟路了。

这里也只是演示了最简单的应用,还有水平伸缩(HPA),日志,监控等一系列的内容,这里是没有提及到的。

可能有人会问:

  1. 为什么还有.NET Framework,不直接.NET Core?

很多老业务不是说动就能动的那么干脆,毕竟还有数据库的限制。。。

  1. .NET Framework容器化有什么坑?

只要你代码没问题,可以在linux下面跑,那就没什么坑不坑的,要是用了一些不支持的特性,那谁也救不了的。

  1. serverless kubernetes的其他问题

可以参靠各大云产商的官方文档和提工单咨询。

最后就是这篇文章的代码可以在我的github查阅:

ServerlessNetApp

用Serverless Kubernetes为.NET (Core)应用保驾护航的更多相关文章

  1. 基于Kubernetes 构建.NET Core技术中台

    今天下午在腾讯云+社区社区分享了<基于Kubernetes 构建.NET Core技术中台>,下面是演讲内容的文字实录. 我们为什么需要中台 我们现在处于企业信息化的新时代.为什么这样说呢 ...

  2. Serverless Kubernetes入门:对kubernetes做减法

    背景 Kubernetes作为通用的容器编排系统,承载了广泛的应用和场景,包括CI/CD,数据计算,在线应用,AI等,然而由于其通用性和复杂性,管理一个kubernetes集群对于很多用户而言还是充满 ...

  3. Serverless Kubernetes全面升级2.0架构:支持多命名空间、RBAC、CRD、PV/PVC等功能

    Serverless Kubernetes概述: 阿里云Serverless Kubernetes容器服务最新开放香港.新加坡.悉尼区域,同时全面开放2.0架构,帮助用户更加便捷.轻松地步入“以应用为 ...

  4. Serverless Kubernetes 入门:对 Kubernetes 做减法

    作者 | 贤维  阿里巴巴高级技术专家 导读:Serverless Kubernetes 是阿里云容器服务团队对未来 Kubernetes 演进方向的一种探索,通过对 Kubernetes 做减法,降 ...

  5. 从零入门 Serverless | 一文讲透 Serverless Kubernetes 容器服务

    作者 | 张维(贤维) 阿里云函数计算开发工程师 导读:Serverless Kubernetes 是以容器和 kubernetes 为基础的 Serverless 服务,它提供了一种简单易用.极致弹 ...

  6. 从零入门 Serverless | Serverless Kubernetes 应用部署及扩缩容

    作者 | 邓青琳(轻零) 阿里云技术专家 导读:本文分为三个部分,首先给大家演示 Serverless Kubernetes 集群的创建和业务应用的部署,其次介绍 Serverless Kuberne ...

  7. Serverless Kubernetes 和 Serverless on Kubernetes 的区别

    什么是 Kubernetes? Kubernetes 是一个可移植的.可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化. 什么是 Serverless ? 无服务器是一种云原 ...

  8. 基于Kubernetes 构建.NET Core 的技术体系

    很多公司技术支持岗位的工作,如配置域名,部署环境,修改复位配置,服务重启,扩容缩容,梳理和完善监控,根据开发的需要查找日志等工作,需要和开发进行大量的沟通,如什么是外网域名,什么是内网域名.A nam ...

  9. EDAS Serverless & Kubernetes SLB LVS Nginx

    分布式缓存负载均衡的规则处理:虚拟节点对一致性哈希的改进 - yanghuahui - 博客园https://www.cnblogs.com/yanghuahui/p/3755460.html EDA ...

随机推荐

  1. iOS-Reactive Cocoa的常见用法

    今天是周末,临近年底,工作上遇到不可抗力,会有点一些变动!这多少会让人有一点静不下来,但需克制,Reactive Cocoa是今天的主角! 废话不多说,今天聊聊Reactive Cocoa的常见使用! ...

  2. Servlet Session MVC模式

    一   什么是Session 当首次使用session时,服务器端要创建session,session是保存在服务器端,而给客户端的session的id(一个cookie中保存了sessionId). ...

  3. Flask g 对象

    1.什么是g对象? 在 flask 中,有一个专门用来存储用户信息的 g 对象,g的全称的为global. g 对象在一次请求中的所有的代码的地方,都是可以使用的. 赋值方式 from flask i ...

  4. Thread和Runnable

    继承Thread类不能实现资源共享.(程序启动了三个线程,但是3个线程却分别卖了各自的5张票,并没有达到资源共享的目的) 实现Runnable接口可以资源共享.(程序启动了三个线程,但是3个线程一共才 ...

  5. ScrollView嵌套ConstraintLayout导致最后一项显示不全

    原因:scrollView不受ConstraintLayout的约束布局影响 解决方法: 保持scrollview的宽高为0dp,设置其相对ConstraintLayout相对约束 <andro ...

  6. apache 2.4 httpd 2.4.6 反向代理后端的服务为HTTPS https 基于centos7

    需求场景:通过访问apache的http地址,反向代理访问后端的https服务,而且路径带有只能特定模块才反向代理 配置如下 listen <VirtualHost *:> #管理员邮箱 ...

  7. kafka全部数据清空

    kafka全部数据清空的步骤为: 停止每台机器上的kafka: 删除kafka存储目录(server.properties文件log.dirs配置,默认为“/tmp/kafka-logs”)全部top ...

  8. vc++,MFC,组合框控件设置时0xC0000005: 读取位置 0x00000020 时发生访问冲突

    511.exe 中的 0x78bb5dec (mfc90ud.dll) 处未处理的异常: 0xC0000005: 读取位置 0x00000020 时发生访问冲突 _AFXWIN_INLINE int ...

  9. js的原型和原型链

    总结: 1.每一个函数都有一个prototype属性,默认指向object空对象(原型对象), 每一个原型对象都有一个constructor属性,指向函数对象. eg: Person函数:     P ...

  10. 题解 - 【NOI2015】维修数列

    题面大意: 使用平衡树维护一个数列,支持插入,修改,删除,翻转,求和,求最大和这 \(6\) 个操作. 题意分析: Splay 裸题,几乎各种操作都有了,这个代码就发给大家当个模板吧. 最后求最大和的 ...