Ошибка загрузки модуля Kubernetes в другой модуль

У меня есть приложение, которое я пытаюсь развернуть в Kubernetes (используя Docker Desktop).

В приложении есть два модуля, каждый из которых состоит из одного компонента:

модуль API

  • Приложение node.js Express с API POST.
  • Слушает порт 8000.

ВЕБ-модуль

  • Приложение node.js Express, которое обслуживает статическую веб-страницу.
  • Слушает порт 8080.
  • На веб-странице есть кнопка, которая получает API-интерфейс веб-компонента.
  • API в веб-приложении, в свою очередь, выполняет выборку компонента API.

Идея состоит в том, что я хочу, чтобы WEB-модуль был доступен внешнему миру, но я не хочу, чтобы другие модули были доступны кому-либо, кроме других модулей в кластере. В конце концов я добавлю базу данных, рабочие компоненты, очередь и Redis, которые должны быть скрыты в кластере от внешнего мира. Ничего особенного в архитектуре.

Веб-страница обслуживается нормально, и вызов API на веб-сервере тоже работает отлично.

Вызов модуля WEB в модуль API вызывает у меня проблемы:

URL-адрес, который я пытаюсь использовать: http://localhost:8000.

Я получаю следующую ошибку:

TypeError: fetch failed
    at node:internal/deps/undici/undici:12618:11
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async /app/server.js:51:17 {
cause: Error: connect ECONNREFUSED 10.107.140.254:8000
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1605:16) {
    errno: -111,
    code: 'ECONNREFUSED',
    syscall: 'connect',
    address: '10.107.140.254',
    port: 8000

В дополнение к localhost я пробовал:

  • 0.0.0.0
  • 127.0.0.1
  • хост.docker.internal
  • k8s-api (имя службы для модуля API, см. yaml ниже)
  • server-cluster-ip-service (имя службы для кластера, который я пробовал)

Я нашел страницу, на которой говорилось, что, возможно, веб-узл.js разрешается в ipv6, поэтому я безуспешно добавил это в верхнюю часть своего веб-приложения nodejs:

var dns = require('node:dns');
dns.setDefaultResultOrder('ipv4first');

Я могу успешно свернуть API (с хоста MacOS) с помощью:

curl -d '{"x": 1}' -H "Content-Type: application/json" -X POST http://localhost:8000

Поэтому я уверен, что API работает.

Вот код в API WEB nodejs, который пытается получить модуль API:

await fetch('http://localhost:8000', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
        body: JSON.stringify({}}) })
        .then(r => Promise.all([r, r.status !== 200 ? r.text() : r.json()]))
        .then(([r, json]) => {
                if (r.status !== 200) {
                        console.info(r); console.info(json);
                        }
                })
        .catch(e => {
                console.info(e);
                }
        );

Вот мои файлы манифеста:

API.deployment.yml:

apiVersion: v1
kind: Service
metadata:
  name: k8s-api
  labels:
    app: k8s-api
spec:
  type: LoadBalancer
  ports:
  - port: 8000
    name: "api"
    targetPort: 8000
  selector:
    app: k8s-api
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8s-api-deployment
spec:
  replicas: 1
  minReadySeconds: 10
  selector:
    matchLabels:
      app: k8s-api
  template:
    metadata:
      labels:
        app: k8s-api
        yada: booyah
    spec:
      containers:
      - image: k8s-sample-api
        name: k8s-api
        imagePullPolicy: Never

веб.развертывание.yml:

apiVersion: v1
kind: Service
metadata:
  name: k8s-web
  labels:
    app: k8s-web
spec:
  type: LoadBalancer
  ports:
  - port: 8080
    name: "web"
    targetPort: 8080
  selector:
    app: k8s-web
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8s-web-deployment
spec:
  replicas: 1
  minReadySeconds: 10
  selector:
    matchLabels:
      app: k8s-web
  template:
    metadata:
      labels:
        app: k8s-web
        yada: booyah
    spec:
      containers:
      - image: k8s-sample-web
        name: k8s-web
        imagePullPolicy: Never

Я также попытался объединить их в службе кластеров (с селектором на основе метки yada: booyah), используя кластер.deployment.yml

apiVersion: v1
kind: Service
metadata:
  name: server-cluster-ip-service
spec:
  type: ClusterIP
  selector:
    yada: booyah
  ports:
    - name: "8000"
      port: 8000
      targetPort: 8000
    - name: "8080"
      port: 8080
      targetPort: 8080

Вот что показывает kubectl get all:

NAME                                      READY   STATUS    RESTARTS   AGE
pod/k8s-api-deployment-8cf4dcd8c-p7gbz    1/1     Running   0          2m38s
pod/k8s-web-deployment-7cdf999d48-mx76j   1/1     Running   0          4s

NAME                                TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
service/k8s-api                     LoadBalancer   10.108.64.186   localhost     8000:30825/TCP      2m38s
service/k8s-web                     LoadBalancer   10.106.86.200   localhost     8080:32391/TCP      4s
service/kubernetes                  ClusterIP      10.96.0.1       <none>        443/TCP             36h
service/server-cluster-ip-service   ClusterIP      10.109.42.57    <none>        8000/TCP,8080/TCP   4s

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/k8s-api-deployment   1/1     1            1           2m38s
deployment.apps/k8s-web-deployment   1/1     1            0           4s

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/k8s-api-deployment-8cf4dcd8c    1         1         1       2m38s
replicaset.apps/k8s-web-deployment-7cdf999d48   1         1         1       4s

Какие-либо предложения?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
400
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы добавили localhost:8000 с внешнего сервера, вместо этого вам следует определить исходные значения службы, которые в вашем случае http://k8s-api:8000, также для внутреннего подключения используйте ClusterIP.

Кроме того, проверьте, дает ли серверная служба ответ 200, открыв хост-порт.

Более того, вы можете создать сервис DNS, который будет статичным навсегда:

serviceName.namespaceName.svc.cluster.local

Спасибо, использование k8s-api сработало! Однако я по-прежнему могу получить доступ к внутреннему API через Curl с моего хост-терминала MacOS. Как мне изменить свои развертывания, чтобы сделать API недоступным для хоста, но все еще доступным для WEB-модуля?

danielc 08.04.2024 13:42

вы можете использовать сетевые политики Kubernetes, чтобы ограничить входящий и исходящий трафик определенными модулями/развертываниями. Вы можете обратиться: kubernetes.io/docs/concepts/services-networking/…

Ravi Kyada 09.04.2024 07:22

Другие вопросы по теме