Приложения SPA (Vue, React, Angular) не работают должным образом за контроллером входящего трафика Nginx в Kubernetes

Мы используем AKS (службу Azure Kubernetes) для управляемых кластеров Kubernetes, и по большей части мы довольны преимуществами, которые приносит платформа, но мы также сталкиваемся с некоторыми проблемами.

В AKS, если вы размещаете службу типа LoadBalancer, она автоматически создает новый динамический IP-адрес (ресурс Azure) и назначает его службе. Это не очень оптимально, если вы хотите внести в белый список, и просто не имеет смысла, поэтому мы перешли на контроллер входящего трафика Nginx (нет особых причин выбирать Nginx). У нас есть много приложений - API, SPA, 1 входной контроллер для всего кластера и отдельный кластер для каждой среды - QA / Sta / Prod и т. Д. Таким образом, нам нужно как-то управлять маршрутизацией, и параметр входного пути кажется подходящим . Пример:

http://region.azurecloud.com/students/

http://region.azurecloud.com/courses/

где студенты и курсы - входные пути, а затем вы можете добавить / api / студент, например, чтобы получить доступ к определенному API. Результатом будет http://region.azurecloud.com/students/api/student/1, который не идеален, но пока работает.

Вот как выглядит вход:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: students-api-ingress
  namespace: university
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
    - host: https://region.azurecloud.com
      http:
        paths:
          - backend:
              serviceName: students-api-service
              servicePort: 8001
            path: /students(/|$)(.*)

Однако это не очень хорошо работает с приложениями SPA, такими как React, Vue или Angular. Мы сталкиваемся с одной и той же проблемой независимо от технологии. Они размещаются за Nginx в докере, поэтому файл Dockerfile выглядит так:

# build environment
FROM node:12.2.0-alpine as build
WORKDIR /app
COPY package*.json /app/
RUN npm install --silent
COPY . /app
RUN npm run build

# production environment
FROM nginx:1.16.0-alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

А вот и файл nginx.conf:

server {
  listen 80;

  location / {
    root /usr/share/nginx/html;
    try_files $uri $uri/ /index.html =404;
    index  index.html index.htm;

  error_page 500 502 503 504  /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }

    if ($request_method = 'OPTIONS') {
          add_header 'Access-Control-Allow-Origin: $http_origin');
          add_header 'Access-Control-Allow-Origin: GET, POST, DELETE, PUT, PATCH, OPTIONS');
          add_header 'Access-Control-Allow-Credentials: true');
          add_header 'Vary: Origin');

      }

       add_header 'Access-Control-Allow-Origin' "$http_origin" always;
       add_header 'Access-Control-Allow-Credentials' 'true' always;
       add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, DELETE, OPTIONS' always;
       add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;
  }

  include /etc/nginx/extra-conf.d/*.conf;
}

Проблема возникает, когда приложение обращается к таким ресурсам, как файлы .js или изображения. Он создает URL-адрес в формате ingress.host/asset.name, например http://region.azurecloud.com/2342424ewfwer.js вместо того, чтобы включать также входной путь, который будет выглядеть http://region.azurecloud.com/spa/2342424ewfwer.js., и результатом будет ошибка 404 не найдено для всех ресурсов.

Приложения работают правильно, если входной путь просто установлен на / без каких-либо аннотаций перезаписи, но это проблема, потому что у вас не может быть нескольких приложений, использующих базовый входной хост. Одно из решений - использовать отдельный контроллер входящего трафика для каждого приложения SPA, но это возвращает нас к первоначальной проблеме с балансировщиками нагрузки - отдельный балансировщик нагрузки и IP-адрес для каждого приложения SPA, чего мы здесь хотим избежать.

Думаю, я не единственный, кто размещает SPA-приложения за контроллером входящего трафика nginx на Kubernetes, но все подобные темы, которые мне удалось найти, практически никуда не закончились, поскольку нет четкого решения, что следует делать, или предложения не сработали для нас. Интересно, откуда взялась проблема - веб-сервер nginx или контроллер входящего трафика, которые обычно используются для управления маршрутизацией приложений в Kubernetes. Буду признателен за любую помощь или совет по этому поводу.

Спасибо, R


person Ruslan Filipov    schedule 15.06.2020    source источник


Ответы (1)


Я обычно решаю эту проблему для SPA - это разные имена хостов для каждого SPA. Например, в непроизводственном кластере, имеющем два SPA с именами student-portal и teacher-portal, я бы создал записи DNS для student-portal.mydomain.com, teacher-portal.mydomain.com, указывающие на общедоступный IP-адрес балансировщика нагрузки кластера.

Включите доменное имя в правила входящего ресурса.

Я считаю, что это наиболее эффективный способ, позволяющий избежать необходимости рассматривать каждую структуру SPA индивидуально.

person bpdohall    schedule 15.06.2020
comment
Спасибо за предложение. Похоже, так действительно проще. - person Ruslan Filipov; 19.06.2020