Сбой соединения Websocket для внутренней связи внутри контейнера Kubernetes

#node.js #reactjs #docker #kubernetes #websocket

#node.js #reactjs #docker #kubernetes #websocket

Вопрос:

Я использую Kubernetes для развертывания моего приложения React. Из-за базы данных, которую я использую (RethinkDB). Я должен инициировать соединение WebSocket между моим приложением React и Node.js сервер, который подключается через прокси к экземпляру базы данных. Соединение работает так, как задумано, когда я развертываю экземпляр базы данных, сервер внутреннего узла и приложение react на своем локальном компьютере. Однако при развертывании приложения в Kubernetes я получаю сообщение об ошибке

 WebSocket connection to 'ws://localhost:8015/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
  

в моем приложении react.

Для дальнейшей отладки я запустил терминал внутри контейнера и запустил команду curl для службы, которая подключается к базе данных, и не получил никаких ошибок. Я также запустил сервер внутреннего узла, чтобы проверить, подключается ли он к удаленной базе данных, и не увидел там никаких проблем. Наконец, я проверил, инициирует ли внутренний сервер WebSocket, как предполагалось, с помощью wscat, и работает ли соединение с WebSocket. И из-за того, что приложение хорошо работает на моем локальном компьютере, это наводит меня на мысль, что проблема в приложении React, подключающемся к WebSocket, может быть вызвана тем, как Kubernetes обрабатывает соединения с Websocket. Любые разъяснения по этому вопросу приветствуются.

P.S

Я добавил код внутреннего сервера, код в приложении React, который подключается к WebSocket, и файлы YAML моего развертывания React Backend. Если требуются дополнительные файлы, пожалуйста, не стесняйтесь комментировать

сервер внутреннего узла

 const http = require('http');
var rethinkdbWebsocketServer = require('rethinkdb-websocket-server');

const httpServer = http.createServer();
rethinkdbWebsocketServer.listen({
    httpServer: httpServer,
    httpPath: '/',
    dbHost: remoteDB_IP,
    dbPort: 28015,
    unsafelyAllowAnyQuery: true
});

httpServer.listen(8015);
  

Реагирующий код, который подключается к Websocket

 ReactRethinkdb.DefaultSession.connect({
  host: 'localhost',          // the websocket server
  port: process.env.REACT_APP_WEBSOCKET_PORT,
  path: '/',
  secure: false,
  autoReconnectDelayMs: 2000, // when disconnected, millis to wait before reconnect
});
  

deployment.yaml

 apiVersion: apps/v1
kind: Deployment
metadata:
  name: dashboard
  labels:
    app: dashboard
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dashboard
  template:
    metadata:
      labels:
        app: dashboard
    spec:
      containers:
      - name: dashboard
        image: myrepor/dashbaord
        imagePullPolicy: Always
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        ports:
        - containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
  name: dashboard
spec:
  selector:
    app: dashboard
  ports:
    - port: 3000
      targetPort: 3000
  type: LoadBalancer
  

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

1. где в kubernetes развернута база данных? не в том же модуле?

2. Он развертывается как другой модуль kubernetes и предоставляется с помощью балансировщика нагрузки

3.но тогда адрес базы данных не localhost

Ответ №1:

итак, идеи kubernetes сводятся к запуску каждого приложения в отдельном модуле.

И подключение их через службы.

Таким образом, вы можете развертывать каждый уровень отдельно без простоев — маршруты обслуживания к старым pod (ам), пока новые не будут запущены и запущены. (и что еще более важно, масштабируйте отдельно) Kubernetes выполняет какое-то разрешение имен внутри каждого кластера k8s. Не совсем уверен, является ли это полным dns или нет

поэтому я бы рекомендовал

  • разделите ваш сервер узла на один модуль. и разверните для него службу с помощью вашего ws-порта (8015).
  • ваше приложение react выделяет отдельный модуль со своей собственной службой и определяет имя службы сервера узла в качестве конечной точки для WS.

Причина проста — даже не уверен, что localhost будет правильно разрешен с помощью модуля in.

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

1. Я реализовал ваше решение, развернув приложения и серверную часть на своих собственных модулях, но безрезультатно. Однако в моей первой попытке я сделал это, представив WebSocket как ClusterIP. Со второй попытки я использовал тот же подход, но предоставил свой WebSocket внешнему трафику с использованием балансировщика нагрузки, и этот подход сработал. Я не совсем понимаю, почему это сработало, поэтому я пока оставлю вопрос без ответа, чтобы кто-то с лучшим пониманием мог ответить на вопрос