首页 > 解决方案 > Ocelot api gateway - kubernetes - error: "namespace:serviceservice:managementservice Unable to use , it is invalid. Address must contain only host ...."

问题描述

我面临的问题是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 和端口必须大于 0

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

我怀疑我配置错误。我首先尝试使用有关 kubernetes 的 Ocelot 文档,但该文档已过时。(一个例子是类型 sugest value does not work for more info go this github issue 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>();
                });

标签: kubernetes.net-5ocelot

解决方案


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

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

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

推荐阅读