rfc7231#关于Kubernetes上的dotnet core入口控制器api访问的第6.5.1节问题
我在Kubernetes中部署了一个简单的dotnet核心应用程序。公开的服务如下所示rfc7231#关于Kubernetes上的dotnet core入口控制器api访问的第6.5.1节问题,kubernetes,.net-core,google-kubernetes-engine,asp.net-core-routing,Kubernetes,.net Core,Google Kubernetes Engine,Asp.net Core Routing,我在Kubernetes中部署了一个简单的dotnet核心应用程序。公开的服务如下所示 apiVersion: v1 kind: Service metadata: creationTimestamp: "2020-01-17T18:07:23Z" labels: app.kubernetes.io/instance: expo-api app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: expo-
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2020-01-17T18:07:23Z"
labels:
app.kubernetes.io/instance: expo-api
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: expo-api
app.kubernetes.io/version: 0.0.4
helm.sh/chart: expo-api-0.0.4
name: expo-api-service
namespace: default
resourceVersion: "997971"
selfLink: /api/v1/namespaces/default/services/expo-api-service
uid: 144b9d1d-87d2-4096-9851-9563266b2099
spec:
clusterIP: 10.12.0.122
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
selector:
app.kubernetes.io/instance: expo-api
app.kubernetes.io/name: expo-api
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
我使用的入口控制器是nginx入口控制器,简单入口规则设置如下-
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
creationTimestamp: "2020-01-17T18:07:24Z"
generation: 3
labels:
app.kubernetes.io/instance: expo-api
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: expo-api
app.kubernetes.io/version: 0.0.4
helm.sh/chart: expo-api-0.0.4
name: expo-api
namespace: default
resourceVersion: "1004650"
selfLink: /apis/extensions/v1beta1/namespaces/default/ingresses/expo-api
uid: efef4e15-ed0a-417f-8b34-4e0f46cb1e70
spec:
rules:
- http:
paths:
- backend:
serviceName: expo-api-service
servicePort: 80
path: /expense
status:
loadBalancer:
ingress:
- ip: 34.70.45.62
dotnet核心应用程序具有简单的启动功能-
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
这是入口输出-
Name: expo-api
Namespace: default
Address: 34.70.45.62
Default backend: default-http-backend:80 (10.8.0.9:8080)
Rules:
Host Path Backends
---- ---- --------
*
/expense expo-api-service:80 (10.8.0.26:80,10.8.0.27:80,10.8.1.14:80)
Annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: true
Events: <none>
我无法理解这背后的问题是什么。它是从dotnet核心端还是从Kubernetes端出现的?如果是dotnet,可能的解决方案是什么;如果是Kubernetes,预期的解决方案是什么 更新1 我看不到ingress对象中的
nginx.ingres.kubernetes.io/rewrite target
注释。不能说你是不是故意跳过了
如果此注释不存在,则您的应用程序将收到“GET:/expense/weatherforecast”。如果这是你想要的,一切都好。但如果你想让你的应用程序收到“GET:/weatherforecast”,你应该在ingress注释中添加nginx.ingres.kubernetes.io/rewrite-target://
更新2
Ingress nginx文档中有一篇关于“重写”注释的文章:
这里有一个非常简洁的示例,有助于理解如何公开/expense/weatherforecast
端点。但不幸的是,我也无法实现公开。我尝试了更复杂的正则表达式,并尝试了那篇文章中的“app root”注释,但没有任何效果-对于/expense
endpoinnt,Ingress总是返回404
我找不到任何关于如何处理根端点和相对端点的有用信息,所以我开始即兴创作。我发现可以使用两个备份路径使其工作。不知道这是一个bug还是一个功能:)
以下入口规范在我的测试应用程序上非常有效。它可以正确处理/expense
和/expense/weatherforecast
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: "nginx"
# nginx.ingress.kubernetes.io/use-regex: "true" # can be true or false, no matter
nginx.ingress.kubernetes.io/rewrite-target: "/$1"
name: app
spec:
rules:
- http:
paths:
- backend:
serviceName: app
servicePort: 80
path: "/expense/(.+)" # handle relative path
- backend:
serviceName: app
servicePort: 80
path: "/expense" # handle root
更新1 我看不到ingress对象中的
nginx.ingres.kubernetes.io/rewrite target
注释。不能说你是不是故意跳过了
如果此注释不存在,则您的应用程序将收到“GET:/expense/weatherforecast”。如果这是你想要的,一切都好。但如果你想让你的应用程序收到“GET:/weatherforecast”,你应该在ingress注释中添加nginx.ingres.kubernetes.io/rewrite-target://
更新2
Ingress nginx文档中有一篇关于“重写”注释的文章:
这里有一个非常简洁的示例,有助于理解如何公开/expense/weatherforecast
端点。但不幸的是,我也无法实现公开。我尝试了更复杂的正则表达式,并尝试了那篇文章中的“app root”注释,但没有任何效果-对于/expense
endpoinnt,Ingress总是返回404
我找不到任何关于如何处理根端点和相对端点的有用信息,所以我开始即兴创作。我发现可以使用两个备份路径使其工作。不知道这是一个bug还是一个功能:)
以下入口规范在我的测试应用程序上非常有效。它可以正确处理/expense
和/expense/weatherforecast
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: "nginx"
# nginx.ingress.kubernetes.io/use-regex: "true" # can be true or false, no matter
nginx.ingress.kubernetes.io/rewrite-target: "/$1"
name: app
spec:
rules:
- http:
paths:
- backend:
serviceName: app
servicePort: 80
path: "/expense/(.+)" # handle relative path
- backend:
serviceName: app
servicePort: 80
path: "/expense" # handle root
原创:感谢@heyzling insight,我找到了解决方案。我将应用程序路径更改为code
startup.cs
。问题是Api最初不希望所有控制器都有路由前缀。因此,它给出了错误。因此,我不得不在startup.cs
中做一些细微的更改,以添加app.UsePathBase(“/expense”)
。以下是我添加的配置-
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UsePathBase("/expense"); // this is the added configuration which identifies the ingress path rule individually.
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
理想情况下,我觉得这不是一个好的设计,因为kubernetes入口和dotnet核心路由应该互不了解。理想情况下,它们不应相互依赖以遵守路由规则。如果有人有更好的解决方案?请不要邮寄。上面的一个解决了我的目的,但我不满意
----------------------------------------------------------------------------------
更新2:感谢@heyzling。我终于找到了解决办法-
看起来它必须重写url并将dotnet代码期望的实际API url转发给正在运行的docker映像
下面是代码示例-
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/use-regex: "true"
labels:
app.kubernetes.io/name: expo-api
name: expo-api
namespace: default
spec:
rules:
- http:
paths:
- backend:
serviceName: expo-api-service
servicePort: 80
path: /expense(/|$)(.*)
所以现在你可以两者兼得了-
curl 35.192.198.231/expense/weatherforecast
curl 35.192.198.231/expense/fakeapi
它将重写并转发url,如下所示:
localhost:80/weatherforecast
localhost:80/fakeapi
在容器内。因此,它可以按预期工作。这样,我们就不再需要
app.UsePathBase(“/expense”)
,而dotnet core和ingress也不必相互了解 原创:多亏@heyzling insight,我找到了解决方案。我将应用程序路径更改为codestartup.cs
。问题是Api最初不希望所有控制器都有路由前缀。因此,它给出了错误。因此,我不得不在startup.cs
中做一些细微的更改,以添加app.UsePathBase(“/expense”)
。以下是我添加的配置-
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UsePathBase("/expense"); // this is the added configuration which identifies the ingress path rule individually.
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
理想情况下,我觉得这不是一个好的设计,因为kubernetes入口和dotnet核心路由应该互不了解。理想情况下,它们不应相互依赖以遵守路由规则。如果有人有更好的解决方案?请不要邮寄。上面的一个解决了我的目的,但我不满意
----------------------------------------------------------------------------------
更新2:感谢@heyzling。我终于找到了解决办法-
看起来它必须重写url并将dotnet代码期望的实际API url转发给正在运行的docker映像
下面是代码示例-
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/use-regex: "true"
labels:
app.kubernetes.io/name: expo-api
name: expo-api
namespace: default
spec:
rules:
- http:
paths:
- backend:
serviceName: expo-api-service
servicePort: 80
path: /expense(/|$)(.*)
所以现在你可以两者兼得了-
curl 35.192.198.231/expense/weatherforecast
curl 35.192.198.231/expense/fakeapi
它将重写并转发url,如下所示:
localhost:80/weatherforecast
localhost:80/fakeapi
在容器内。因此,它可以按预期工作。这样,我们就不再需要app.UsePathBase(“/expense”)
,而dotnet core和ingress也不必相互了解 那里