Приложение React в Kubernetes неправильно подключается

#node.js #reactjs #docker #nginx #kubernetes

Вопрос:

Я новичок в Kubernetes и пытаюсь развернуть приложение React в своем кластере. Вот основная информация:

  • Рабочий стол Docker, одноузловой кластер Kubernetes
  • Интерфейс разработки React, открывающий порт 3000
  • Серверная часть Node.js/Express, открывающая порт 8080
  • Контроллер входа NGINX, обслуживающий мой интерфейс React на «локальном хосте:3000» и маршрутизирующий мои запросы API выборки (fetch(«локальный хост:3000/api/…», ПАРАМЕТРЫ)) на серверную часть (которая работает)

У меня возникла проблема при открытии приложения React. Контроллер входа правильно направляет в приложение, но 3 пакета (bundle.js, main.chink.js, третий, который я не помню) не загружены. Я получаю следующую ошибку:

 GET http://localhost/static/js/main.chunk.js net::ERR_ABORTED 404 (Not Found) ingress (one example)
 

Я понимаю, почему происходит эта ошибка. Контроллер входа правильно направляет трафик, но загружает только index.html файл. В этом файле есть вызовы 3 сценариев (ссылающихся на пакеты), которые не загружены. Я понимаю ошибку, файлы не отправляются в браузер, поэтому index.html файл не может их загрузить, но не знаю, как это исправить.
У кого-нибудь есть какие-нибудь предложения? де, а затем вытащил из Докер-хаба. Кто-нибудь знает, каким может быть возможное решение? Например, исправляет ли это развертывание сборки/ папки (встроенное приложение React с использованием «npm run build»)? Должен ли я использовать nginx внутри своего файла Dockerfile для создания контейнера?

Вход.yaml

 apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: titanic-ingress
  #labels:
      #name: titanic-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: localhost
    http:
      paths:
      - path: /
        pathType: Exact
        backend:
          service:
            name: titanicfrontendservice
            port:
              number: 3000
      - path: /api
        pathType: Exact
        backend:
          service:
            name: titanicbackendservice
            port:
              number: 8080
 

Ingress controller deployment yaml

 apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ingress
  namespace: nginx-ingress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-ingress
  template:
    metadata:
      labels:
        app: nginx-ingress
     #annotations:
       #prometheus.io/scrape: "true"
       #prometheus.io/port: "9113"
    spec:
      serviceAccountName: nginx-ingress
      containers:
      - image: nginx/nginx-ingress:1.10.0
        imagePullPolicy: IfNotPresent
        name: nginx-ingress
        ports:
        - name: http
          containerPort: 80
        - name: https
          containerPort: 443
        - name: readiness-port
          containerPort: 8081
       #- name: prometheus
         #containerPort: 9113
        readinessProbe:
          httpGet:
            path: /nginx-ready
            port: readiness-port
          periodSeconds: 1
        securityContext:
          allowPrivilegeEscalation: true
          runAsUser: 101 #nginx
          capabilities:
            drop:
            - ALL
            add:
            - NET_BIND_SERVICE
        env:
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        args:
          - -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
          - -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret
          #- -v=3 # Enables extensive logging. Useful for troubleshooting.
          - -report-ingress-status
          - -external-service=nginx-ingress
         #- -enable-prometheus-metrics
         #- -global-configuration=$(POD_NAMESPACE)/nginx-configuration
 

Служба контроллера входа yaml

 apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress
  namespace: nginx-ingress
spec:
  externalTrafficPolicy: Local
  type: LoadBalancer
  ports:
  - port: 3000
    targetPort: 80
    protocol: TCP
    name: http
  - port: 443
    targetPort: 443
    protocol: TCP
    name: https
  selector:
    app: nginx-ingress
 

Комментарии:

1. Здравствуйте, вы уверены, что ваш nginx-ingress-controller прослушивает порт 3000? По умолчанию это 80/443. Кроме того, пожалуйста, включите YAML манифест вашего Ingress ресурса, Service и Deployments . Кроме того, вы пытались открыть и подключиться к своему frontend on a NodePort , чтобы опустить Ingress контроллер?

2. @DawidKruk Да, я поменял порты на входном контроллере .yaml, мне не очень нравилось использовать порт 80 (я сохранил 443, хотя и не часто его использую). Я отредактирую вопрос, чтобы включить запрошенные вами yamls. Я уже пробовал открывать интерфейс напрямую с помощью балансировщика нагрузки. Однако я не мог понять, как правильно направлять ПОЧТУ и ПОЛУЧАТЬ запросы. Более конкретно, как я уже спрашивал в StackOverflow, я не могу выбрать подходящий URL-адрес для включения в API выборки.

Ответ №1:

TL;DR

Переключитесь pathType на оба /api и / путь к Prefix .

Я включил некоторые пояснения с фиксированным Ingress ресурсом ниже.


Для целей воспроизведения я использовал titanic декларации, которые вы предоставили в другом вопросе:

Проблема с вашей конфигурацией связана с: pathType .

Используя ваш Ingress ресурс pathType: Exact , вы показали мне пустую страницу.

Изменение вашего Ingress ресурса с pathType: Prefix помощью решенной проблемы.

Боковое примечание!

Появилось сообщение: «Вы бы пережили крушение «Титаника»?».

Точная Ingress конфигурация должна быть следующей:

 apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: titanic-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: localhost
    http:
      paths:
      - path: /
        pathType: Prefix # <-- IMPORTANT
        backend:
          service:
            name: titanicfrontendservice
            port:
              number: 3000
      - path: /api
        pathType: Prefix # <-- IMPORTANT
        backend:
          service:
            name: titanicbackendservice
            port:
              number: 8080
 

Почему я думаю, что это произошло?

Ссылаясь на официальную документацию:

Типы путей

Каждый путь на входе должен иметь соответствующий тип пути. Пути, которые не содержат явного типа пути, не пройдут проверку. Существует три поддерживаемых типа путей:

  • ImplementationSpecific : При этом типе пути соответствие зависит от класса входа. Реализации могут рассматривать это как отдельный тип пути или рассматривать его идентично типам префиксов или точных путей.
  • Exact : Точно соответствует пути URL-адреса и с учетом регистра.
  • Prefix : Совпадения на основе префикса пути URL, разделенного на /. Сопоставление чувствительно к регистру и выполняется по элементам пути. Элемент пути ссылается на список меток в пути, разделенном разделителем/. Запрос соответствует пути p, если каждый p является префиксом p по элементам пути запроса.

Kubernetes.io: Документы: Концепции: Службы сети: Вход: Типы путей (есть несколько примеров того, как обрабатывается сопоставление путей)

Ingress controller вынужден сопоставлять только / путь, оставляя остальные зависимости (кроме index.html ) на других путях, таких как /super.jpg и /folder/awesome.jpg ошибка с 404 кодом.

Боковое примечание!

Вы можете проверить это поведение, создав nginx Pod и поместив в него файлы примеров. После применения Ingress ресурса с / и pathType: Exact вы не сможете запросить его через Ingress контроллер, но вы можете получить доступ к ним в кластере.


Я призываю вас проверить дополнительные ресурсы:

Комментарии:

1. @DavidKruk Большое спасибо! Я уже однажды пытался протестировать исправление, но, похоже, у меня было что-то еще неправильно настроено. Я хочу задать вам один вопрос: у вас есть аккаунт в Твиттере или что-нибудь в этом роде? Вы просто были невероятно вежливы и предупредительны, что я хочу следить за вами для любых будущих обновлений, которые у вас есть, или чего-то в этом роде.

2. @Stroboscopio рад, что вам удалось найти решение. К сожалению, у меня нет аккаунта в твиттере (я подумываю об этом). Не стесняйтесь просматривать ответы в моем профиле, и, возможно, мы еще встретимся на StackOverflow.

Ответ №2:

Проблема с вашим входом.yaml заключается в том, что маршрут для вашего пользовательского интерфейса должен быть /* и располагаться под внутренней маршрутизацией. Кроме того, проверьте свою маршрутизацию на наличие API

 apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: titanic-ingress
  #labels:
      #name: titanic-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: localhost
    http:
      paths:
      - path: /api/*
        pathType: Exact
        backend:
          service:
            name: titanicbackendservice
            port:
              number: 8080
      - path: /*
        pathType: Exact
        backend:
          service:
            name: titanicfrontendservice
            port:
              number: 3000