k8s .netcore的春天
一直有在关注k8s容器管理平台,不是因为对运维感兴趣,而是它是云原生,云架构的一块基石,我们可以看看bat在云原生架构方面的推动和投入,相信以后软件从已诞生就生长在云上。
K8S,可能有些朋友认为k8s跟微服务没有啥关系,这个的看你站在什么维度和视角去看待这个问题。尤其是.NETCORE平台,没有像JAVASPRINGCLOUD这样的全家桶,更没有SPRINGCLOUDALIBABA这样的最佳实践一站式解决方案,很多技术栈都需要我们自己去踩坑、试错、总结经验,试问有几个公司会去这样投入?回到最初的问题,整套微服务架构体系,我们关注的是啥?服务生命周期管理、服务治理、Devops、容器化、集群网络等等,虽然目前k8s在某些层面做的比较一般,比如服务治理能力,但是我们可以借助k8s的生态,通过sidecar的方式或者其他方式去帮我们完善k8s薄弱的地方,比如服务治理istio。
我这边简单画了一张逻辑架构图,为什么叫简单?架构没有银弹,千变万化,结合自己的业务和成本适合才是最好的。正常情况下外部网络这一层反代是没有的,这里我只是列出几种情况。比如我可以拿掉外部网络的反向代理,把流量直接打到ingress,又或者我把ingress拿掉,gateway通过nodeport方式暴露服务,外部网络还是通过nginx反代,再或者云服务商SLB方案,还是那句话适合才是最好的。可能有朋友会说这个架构就是专业的运维团队都有一定难度,呵呵,确实是挺难的,如果都是基于二进制命令的方式部署,那确实需要玩的很溜,好在容器化技术日新月异,各种辅助工具,从而大大降低了技术门槛。比如以下集群部署,我们可以先通过adm或者二进制或者云服务商部署k8s集群,再通过kubesphere或者云服务商可视化工具部署其他服务,都是界面操作,包括大部分的yaml文件都会帮我们生成,我们只需要简单修改就好,当然前提是对k8s架构有一定的了解。
k8s 集群,这里着重介绍下k8s内部网络集群。整个集群入口通过ingress网关路由接入,ingress其实就是反代,我们把它当传统反向代理看就对了,当然跟传统反代还是有点区别,主要是性能和功能,具体看官网,地址https://www.kubernetes.org.cn/ingress。ingress后面是ocelot网关,关于ocelot网关的功能我就不介绍了,限流、鉴权、路由...,github地址:https://github.com/ThreeMammals/Ocelot,有兴趣的可以自己下载代码看看,在这里集成了ocelot主要是为了业务能更好的控制,最重要的一点ocelot是微软官方团队基于.NETCORE实现的开源产品,怎么也的支持不是么?虽然性能不是那么出色,但是定制性强。再往后就是BFF聚合器和业务服务,BFF聚合器是啥?Backend For Frontend(服务于前端的后端),通常叫用户体验适配器,通俗点说就是以简单统一的方式为终端聚合业务。聚合器没有啥特别的在这里其实就是webapi服务。举个简单列子,添加商品到购物车操作(这里有pc端和app端,多端之间肯定有特定需求),1.获取商品信息,2.获取购物车信息以及购物车里面商品,2.如果包含该商品+1操作,否则添加该商品到购物车。在这个业务场景里面,涉及到了两个独立的服务,商品服务、购物车服务,统一通过聚合服务操作,返回到前端。其他不需要聚合操作的业务,直接通过ocelot请求到service端,比如获取商品列表信息。整个服务请求大概就到这吧,下面介绍下,基础支撑服务。
认证授权,这么多服务不可能每个服务都写一套认证授权代码(当然你也可以统一通过ocelot或者ingress来做,同样支持jwt token机制,但是一般我不会这么去做,尽量提高网关性能吧),而且需要支持多种不同类型的终端,异构平台,所以这里我们使用.NETCORE开源产品IDS4来实现我们的统一认证授权中心,基于jwtbearer token机制实现,并且ids4框架实现了80%以上的OAUTH2&OIDC协议规范,具体介绍可以看看这个文章https://www.cnblogs.com/adair-blog/p/11410183.html。
熔断降级,熔断降级主要分两个层面,网关和代码,网关层面的就不介绍了,通过配置相关策略完成,代码层面基于简单轻量的Polly组件来完成,虽然没有springcloudalibaba的sentinel组件强大(全程可视化),麻雀虽小五脏俱全,有精力的也可以基于它写一个可视化界面包括dashboard(我没去了解现在的最新版有没有这功能)。github地址:https://github.com/App-vNext/Polly,有段时间没关注它了,github上的start9.6k,赞。
服务发现,整个集群里面我没有部署任何服务注册中心组件,consul或者zookeeper,那整个集群是怎么做到服务注册发现调用的呢?这里主要是k8s里面的服务发现机制,我简单介绍一下实现原理,整个集群内部业务服务部署的是clusterip网络模型,Deployment类型的资源,通过kubectl终端,发送创建service命令到kubeapiserver(k8s核心组件之一),kubeapiserver将service信息写入etcd(分布式服务发现组件),此时kubeproxy进程(本地进程)监控到etcd上service和pod信息的变更,然后写入到ipvs/iptables规则里面,最终通过RR或者其他规则轮询转发,当然整个服务发现机制少不了coredns/kube-dns的参与。
配置中心,通过configmap注入的方式实现所有服务的配置管理,虽然目前没有apollo强大,但是原生集成,实时性还好,支持ui配置,灰度发布等等,当然如果不想使用k8s组件configmap,也可以在集群里面部署apollo,zookeep三方组件帮我们实现统一的配置管理。
分布式日志,elk三个开源组件的缩写,具体哪三个就不写了,个人理解它主要应用场景是分布式环境下大数据,高吞吐,近实时,所以非常适合分布式架构下的日志管理中心,.netcore平台的三方日志组件也提供了相关接口,如nlog,serilog等。
缓存redis,如果是大型应用通过k8sStatefulSet资源部署cluster集群,一般规模的应用部署高可用集群即可。redis不仅仅只是给我们做缓存方案,甚至分布式id(这个具体看业务,现在比较受欢迎的是snowflakeid,雪花算法分布式id),分布式锁,统计,布隆过滤器等等这些都会有应用,具体可以看看这个文章:https://www.cnblogs.com/adair-blog/p/14728755.html。
消息中间件:消息中间件目前比较主流的有rabbitmq、kafaka、rocketmq等,各有利弊,.netcore搭配最多的一般是rabmq,可能其他两个是java开发的吧,哈哈。在分布式架构里面它的主要业务场景就是异步、解耦。比较经典的几个场景,支付订单过期、通过三方机构转账操作等等。
服务链路跟踪:在分布式环境下,服务调用链路复杂,排错,监控困难,所以我们需要一款UI丰富的分布式链路监控服务。skywalking是apache基金会下面的一个开源APM项目,为微服务架构和云原生架构系统设计,java平台开发的,支持多语言,并且.NETCORE也有实现代理客户端SkyAPM-dotnet,github地址:https://github.com/SkyAPM/SkyAPM-dotnet,有兴趣的可以看看实现原理,其实它就是一个代理客户端,注入到了.NETCORE中间件里面,实现埋点,然后通过配置实现无侵入请求链路数据采集,实现原理类似淘宝早期的“鹰眼”服务,很久没关注它了,不知道发展的怎么样了。
服务发布,k8s原生支持滚动发布(增量发布),也可以通过手段来实现蓝绿发布(全量,一般不会这么用),还可以通过Isito来实现灰度发布(增量发布),最终集成jenkins来完成自动发布。已gitlab+jenkins+k8s为例:
自动化部署核心是jenkins,它是彻头彻尾的一个插件系统,比如k8s相关操作,都是集成k8s插件完成的,最终通过pipeline流水线脚本按step步骤执行。
到此已经聊的差不多了,也快接近尾声了,其实整套架构想要落地,还需要其他一些技术储备,如Devops,持续交付它们也是基于k8s集群来完成,所以整套体系下来门槛主要就是k8s平台。k8s其实就是一个标准的微服务架构,功能很强大,技术体系也很庞大复杂,上面的架构如果对k8s技术栈生态很熟的话,可以直接通过sidecar的方式集成isito servicemesh服务网格,它是专门用来做服务治理的,只要你能hold住。