Ocelot api gateway - kubernetes - error: "namespace:serviceservice:managementservice Unable to use ,it is invalid. Address must contain host only...."

Ocelot api gateway - kubernetes - error: "namespace:serviceservice:managementservice Unable to use ,it is invalid. Address must contain host only...."

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

Ocelot.Provider.Kubernetes.KubernetesServiceDiscoveryProvider[0] requestId: 0HM93C93DL2T0:00000003, previousRequestId: no previous request id, message: namespace:serviceservice:managementservice Unable to use ,it is invalid. Address must contain host only e.g. localhost and port must be greater than 0

warn: Ocelot.Responder.Middleware.ResponderMiddleware[0] requestId: 0HM93C93DL2T0:00000003, previousRequestId: no previous request id, message: Error Code: ServicesAreEmptyError Message: There were no services in NoLoadBalancer errors found in ResponderMiddleware. Setting error response for request path:/api/management/User/3910, request method: GET

我怀疑我配置有误。我首先尝试使用关于 kubernetes 的 Ocelot 文档,但该文档已过时。 (一个例子是 Type the sugest value does not work for more info go this github issue Docs/Kubernetes provider are wrong

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

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

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

我的 ocelot.json 配置文件对于 kubernetes 看起来像这样:

{
  "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>();
                });

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

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

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