Ocelot api gateway - kubernetes - error: "namespace:serviceservice:managementservice Unable to

Posted

技术标签:

【中文标题】Ocelot api gateway - kubernetes - error: "namespace:serviceservice:managementservice Unable to use , it is invalid. Address must contain only host ...."【英文标题】:Ocelot api gateway - kubernetes - error: "namespace:serviceservice:managementservice Unable to use ,it is invalid. Address must contain host only...." 【发布时间】:2021-08-18 00:34:30 【问题描述】:

我面临的问题是ocelot kubernetservicediscorverProvider似乎没有在kubernetes的命名空间上找到其他服务。我的目标是使用api网关调用同一命名空间中其他服务中的api。我目前收到 http 404 Not Found 错误。 api 网关 pod 记录以下内容:

Ocelot.Provider.Kubernetes.KubernetesServiceDiscoveryProvider[0] requestId: 0HM93C93DL2T0:00000003, previousRequestId: no previous request id, message: namespace:serviceservice:managementservice 无法使用,无效。地址必须仅包含主机,例如localhost 和 port 必须大于 0

警告:Ocelot.Responder.Middleware.ResponderMiddleware[0] requestId:0HM93C93DL2T0:00000003,previousRequestId:没有以前的请求 id,消息:错误代码:ServicesAreEmptyError 消息:在 ResponderMiddleware 中发现 NoLoadBalancer 错误中没有服务。请求路径设置错误响应:/api/management/User/3910,请求方法:GET

我怀疑我配置错误。我首先尝试使用有关 kubernetes 的 Ocelot 文档,但该文档已过时。 (一个例子是类型的 sugest 值不起作用更多信息去这个 github 问题Docs/Kubernetes provider are wrong)

然后我继续在线搜索 github 问题、堆栈溢出帖子甚至源代码。但我没有看到我的配置中缺少什么。

我目前使用 minikube 在本地运行 kubernetes。我在网上看到的唯一的事情是其他人错误配置了ocelot.json。但我没有看到我在配置中做错了什么。

(在 kubernetes 上尝试 ocelot 之前,我首先在本地主机上尝试它,以尝试它是否有效并看看它缺少什么。它显然缺乏可以控制具有不同角色的 jwt 的中间件,这些角色有权访问端点. 我现在已经自己编写了中间件,它适用于 ocelot 的本地主机配置)

对于 kubernetes,我的 ocelot.json 配置文件如下所示:


  "Routes": [
    
      "UpstreamPathTemplate": "/api/management/User/everything",
      "UpstreamHttpMethod": [ "POST", "PUT", "GET" ],
      "DownstreamPathTemplate": "/api/management/User/everything",
      "DownstreamScheme": "http",
      "ServiceName": "managementservice",
      "AuthenticationOptions": 
        "AuthenticationProviderKey": "Bearer",
        "AllowedScopes": [ "CompanyId", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" ]
      ,
      "RouteClaimsRequirement":  "role": "1,2,3" ,
      "AddHeadersToRequest": 
        "CompanyId": "Claims[CompanyId] > value",
        "UserId": "Claims[http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier] > value"
      
    
  ],
  "GlobalConfiguration": 
    "ServiceDiscoveryProvider": 
      "Host": "127.0.0.1",
      "Port": 8083,
      "Namespace": "service",
      "Type": "KubernetesServiceDiscoveryProvider"
    
  

我的 startup.cs ConfigureServices 方法如下所示

public void ConfigureServices(IServiceCollection services)
        
            services.AddCors(c =>
            
                c.AddPolicy("AllowOrigin", options => options.WithOrigins(Configuration["Cors:AllowOrigins"])
                    .AllowAnyHeader()
                    .AllowAnyMethod().AllowCredentials());
            );

            #region Authication settings

            TokenValidationParameters tokenValidationParameters = new TokenValidationParameters
            
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration["Jwt:Key"])),
                ValidateIssuer = false,
                ValidateAudience = false,
                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero
            ;

            services.AddSingleton(tokenValidationParameters);
            services.AddAuthentication(
                    x =>
                    
                        x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                        x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                    
                )
                .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, x =>
                

                    x.RequireHttpsMetadata = false;
                    x.SaveToken = true;
                    x.TokenValidationParameters = tokenValidationParameters;
                );

            #endregion

       //Some more code

       services.AddOcelot().AddKubernetes();
       

我的 startup.cs 配置方法如下所示

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        
            // some more code

            app.UseOcelot(configuration);
        

我的 program.cs CreateHostBuilder 方法如下所示

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
               .ConfigureAppConfiguration((hostingContext, config) =>
               
                   config.AddJsonFile("secrets/appsettings.kubernetes.json", optional: true)
                         .AddJsonFile("ocelot.json");
               )
                .ConfigureWebHostDefaults(webBuilder =>
                
                    webBuilder.UseStartup<Startup>();
                );

【问题讨论】:

【参考方案1】:

事实证明,我遇到的真正问题在于 kubernetes 的权限。 ocelot 文档也提到了这一点。但是文档中的命令不正确(很可能已过时)。

这是我使用的命令。请注意,kubernetes 文档强烈反对使用此命令permissive-rbac-permissions。但至少是你在本地ocelot中测试你的api网关的一种方式。

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

【讨论】:

以上是关于Ocelot api gateway - kubernetes - error: "namespace:serviceservice:managementservice Unable to 的主要内容,如果未能解决你的问题,请参考以下文章

Ocelot api gateway - kubernetes - error: "namespace:serviceservice:managementservice Unable to

在 Ocelot API Gateway 中的特定路由中添加 Authorization Header(Authorization: Bearer access_token)

Ocelot实现API网关服务

微服务-网关GateWay

微服务之:从零搭建ocelot网关和consul集群

微服务--Ocelot+Consul整合使用,网关+服务注册发现