zoukankan      html  css  js  c++  java
  • NetCore微服务系列---Ocelot接入K8S

    序言

    准备写这一个系列也挺久了,但一直未动手,一方面自身积累不足,另一方面也不知从何处下手。直到最近稍微得空一些,另一方面也有一些新的体验。

    在此纯粹作为自己个人的一个回顾记录吧。正所谓好记性不如烂笔头么。

    总览

    目前规划的整个微服务体系分为三层。

    最外面一层就是Ocelot,负责路由转发,统一认证、限流熔断等。

    然后第二层是各个应用服务,也可以说是聚合服务,webapi形式对外提供接口能力,支撑PC、H5、APP等。

    最后面一层就是基于领域驱动划分的各个小的服务,grpc形式互相调用。

    但是目前来说其实只做到第一层、第二层。有项目工期很紧的原因,但最主要还是业务场景不够熟悉。这一次才体会到抛开业务场景,谈微服务的话,有点儿耍流氓。

    尤其在做微服务拆分的时候相当痛苦,没有领域专家参与,拆分过程相当痛苦,后来只能做更多的妥协。后续再专门开一篇讲一讲,回归正题了。

    准备工作

    我使用的是Ocelot最新版本,园子里也有关于Ocelot集成K8s的分享,但是最新的Ocelot版本,在集成k8s的过程中,还是存在一些问题的。

    下面简单讲述一下具体的操作步骤了。

    (1)根据Oclelot版本,引入对应的K8s Provider。我这里因为用的是最新版本的Ocelot,所以直接选用最新版的K8s Provider。

      

    (2)在StartUp类的ConfigureService方法中添加以下代码:

    services.AddOcelot()
                .AddPolly()
                .AddKubernetes();

     (3)配置文件中,配置k8s支持。在最新版中,已经不需要配置Host、Port、Token信息。只需配置好k8s服务对应的命名空间即可。

      {
    "ReRoutes": [
      {
        "DownstreamPathTemplate": "/api/values",
        "DownstreamScheme": "http",
        "UpstreamPathTemplate": "/values",
        "ServiceName": "testapiservice",
        "UpstreamHttpMethod": [ "Get" ]
      }
    ],
    "GlobalConfiguration": {
      "ServiceDiscoveryProvider": {
        "Namespace": "dev",
        "Type": "kube"
      }
    }
    

    (4)ocelot中通过k8s服务名转发,具体的实现机制就是通过KubeClient这个K8s的C#语言客户端。具体信息在张队的博客中已经有介绍。因为我们的ocelot网关最终也是运行在pod中的,

    在pod中通过api访问集群服务,是需要经过k8s内部认证的。我们可以通过给serviceaccount进行授权,来解决认证问题。关于k8s中的serviceaccount概念就不多展开了。

    在k8s集群节点中执行以下命令:

    kubectl create clusterrolebinding permissive-binding –clusterrole=cluster-admin –user=admin –user=kubelet –group=system:serviceaccounts

    至此,本来可以开开心心的部署服务,愉快的进行路由转发了。嗯,等会儿,Unable to find service discovery provider for type: kube。嗯哼,这是个什么鬼,心态爆炸有木有!!!

    解决办法

     一开始,我以为是配置问题,然后又觉着是k8s的问题。一通尝试无果,后来,通过在ocelot的issues中寻找到解决方案。原来这是ocelot最新版本的bug,通过以下扩展代码可修复。

    官方也注意到这个问题,应该也会在后续的版本更新中修复掉。

    public static class OcelotBuilderExtensions
        {
            private static readonly ServiceDiscoveryFinderDelegate FixedKubernetesProviderFactoryGet = (provider, config, reroute) =>
            {
                var serviceDiscoveryProvider = KubernetesProviderFactory.Get(provider, config, reroute);
    
                if (serviceDiscoveryProvider is KubernetesServiceDiscoveryProvider)
                {
                    serviceDiscoveryProvider = new Kube(serviceDiscoveryProvider);
                }
                else if (serviceDiscoveryProvider is PollKubernetes)
                {
                    serviceDiscoveryProvider = new PollKube(serviceDiscoveryProvider);
                }
    
                return serviceDiscoveryProvider;
            };
    
            public static IOcelotBuilder AddKubernetesFixed(this IOcelotBuilder builder, bool usePodServiceAccount = true)
            {
                builder.Services.AddSingleton(FixedKubernetesProviderFactoryGet);
                builder.Services.AddKubeClient(usePodServiceAccount);
    
                return builder;
            }
    
            private class Kube : IServiceDiscoveryProvider
            {
                private readonly IServiceDiscoveryProvider serviceDiscoveryProvider;
    
                public Kube(IServiceDiscoveryProvider serviceDiscoveryProvider)
                {
                    this.serviceDiscoveryProvider = serviceDiscoveryProvider;
                }
    
                public Task<List<Service>> Get()
                {
                    return this.serviceDiscoveryProvider.Get();
                }
            }
    
            private class PollKube : IServiceDiscoveryProvider
            {
                private readonly IServiceDiscoveryProvider serviceDiscoveryProvider;
    
                public PollKube(IServiceDiscoveryProvider serviceDiscoveryProvider)
                {
                    this.serviceDiscoveryProvider = serviceDiscoveryProvider;
                }
    
                public Task<List<Service>> Get()
                {
                    return this.serviceDiscoveryProvider.Get();
                }
            }
        }

    添加此扩展代码后,在我们上述步骤中的:AddKubernetes()  需替换成AddKubernetesFixed()

    至此,终于可以在k8s中愉快的使用ocelot了。

    尾声

    ocelot第一阶段的工作可以说是完成了。但在整个体系中,网关还需集成认证。认证我使用的是ids4,在请求到达网关时,直接在网关层进行认证,认证通过后再转发到下游服务。

    所以第二阶段是需配置ocelot集成ids4.

    然后因为我的所有服务都是通过apollo来进行配置的,而且打包成镜像后,在通过修改json文件来修改配置也实在繁琐。

    所以第三阶段就是ocelot使用apollo来进行配置管理。

  • 相关阅读:
    联想笔记本如何开启笔记本的VT-x虚拟化技术功能
    《Python数据分析》环境搭建之安装Jupyter工具(一)
    SQLite文件查看工具DB Browser for SQLite
    《Python操作SQLite3数据库》快速上手教程
    市面上各类网盘(百度网盘、腾讯微云、亿方云、坚果云等)对比 2016年10月
    Selenium安装失败WebDriverException: Message: 'gechodriver' executable needs to be in PATH
    安装Python环境时遇到的问题
    ORA-12541:TNS没有监听器
    PL/SQL连接Oracle数据库,中文乱码,显示问号
    Selenium 简单的例子
  • 原文地址:https://www.cnblogs.com/dandan123/p/13419960.html
Copyright © 2011-2022 走看看