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來進行配置管理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM