rfc7231 # section-6.5.1 проблема при доступе к интерфейсу do tnet входного контроллера ядра в Kubernetes - PullRequest
1 голос
/ 18 января 2020

Я развернул простое базовое приложение do tnet в Kubernetes. Предоставляемая услуга выглядит следующим образом:

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

Do tnet базовое приложение, которое имеет простой запуск -

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>

Ниже приведена настройка nginx входного контроллера -

Name:                     nginx-nginx-ingress-controller
Namespace:                default
Labels:                   app=nginx-ingress
                          chart=nginx-ingress-1.29.2
                          component=controller
                          heritage=Helm
                          release=nginx
Annotations:              <none>
Selector:                 app=nginx-ingress,component=controller,release=nginx
Type:                     LoadBalancer
IP:                       10.12.0.107
LoadBalancer Ingress:     34.66.164.70
Port:                     http  80/TCP
TargetPort:               http/TCP
NodePort:                 http  30144/TCP
Endpoints:                10.8.1.6:80
Port:                     https  443/TCP
TargetPort:               https/TCP
NodePort:                 https  30469/TCP
Endpoints:                10.8.1.6:443
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

Проблема в том, что когда я изменяю путь к правилам входа на / и получаю доступ с помощью - curl 34.66.164.70/weatherforecast, он прекрасно работает.

Однако, когда я изменяю входной путь на /expense и пытаюсь получить доступ с помощью - curl 34.66.164.70/expense/weatherforecast. Вывод является ошибкой, так как -

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "|4dec8cf0-4fddb4d168cb9569.",
  "errors": {
    "id": [
      "The value 'weatherforecast' is not valid."
    ]
  }
}

Я не могу понять, что является причиной этого. Появляется ли он со стороны ядра tnet или Кубернетес? Если сделать tnet, какое может быть разрешение, а если на Кубернетес, какое ожидаемое разрешение.

Ответы [ 2 ]

3 голосов
/ 18 января 2020

Обновлено 1

Я не вижу nginx.ingress.kubernetes.io/rewrite-target аннотации в вашем объекте Ingress. Не могу сказать, намеренно ли вы его пропустили.

Если эта аннотация отсутствует, ваше приложение получит "GET: / расход / прогноз погоды". Если это то, что вы хотите, все хорошо. Но если вы хотите, чтобы ваше приложение получало «GET: / weatherforecast», вы должны добавить nginx.ingress.kubernetes.io/rewrite-target: / к вам аннотацию Ingress.

Обновлено 2

Ingress- nginx В документации есть статья о «переписать» аннотацию: https://kubernetes.github.io/ingress-nginx/examples/rewrite/#rewrite -target

Существует довольно лаконичный пример, который помогает понять, как выставить /expense/weatherforecast конечную точку. Но, к сожалению, я также не смог достичь экспозиции /expense. Я попробовал более сложное регулярное выражение, и я попробовал аннотацию "app- root" из этой статьи, но ничего не получалось - Ingress всегда возвращал 404 для /expense endpoinnt.

Я не мог найти полезную информацию о как обрабатывать root и относительные конечные точки, поэтому я начал импровизировать. Я обнаружил, что вы можете использовать два пути с резервной копией, чтобы заставить его работать. Не знаю, если это ошибка или особенность:).

После входа spe c отлично работает в моем тестовом приложении. Он может правильно обрабатывать /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
2 голосов
/ 18 января 2020

ОРИГИНАЛ : Благодаря пониманию @heyzling я нашел решение для него. Я изменил путь к приложению в код 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 и выполняющие tnet основные маршруты ничего не должны знать друг о друге. В идеале они не должны зависеть друг от друга для соблюдения правил маршрутизации. Если у кого-то есть лучшее решение? Пожалуйста, сделайте пост. Вышеуказанное решает мою цель, но я не доволен этим.

----------------------------------------------------------------------------------

ОБНОВЛЕНИЕ 2 : Благодаря @heyzling. Наконец-то я нашел решение - похоже, ему пришлось переписать URL-адрес и переслать реальный URL-адрес API, который выполняет tnet код, ожидающий изображение 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

внутри контейнера. Следовательно, это работает как ожидалось. Таким образом, мы DO NOT требуем app.UsePathBase("/expense") больше и оба tnet core и ingress не должны ничего знать друг о друге.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...