Сервисы Kubernetes истекают по времени при доступе к подам на разных рабочих узлах.

Вопрос или проблема

Я пытаюсь настроить пару рабочих узлов Kubernetes на экземплярах EC2 и сталкиваюсь с проблемой, когда служба, похоже, не “видит” все поды, которые должна видеть.

Моя точная среда — это пара AWS Snowballs, Красный и Синий, и мой кластер выглядит как control, worker-red и worker-blue [1]. Я развертываю пустой сервер на Python, который ждет GET-запрос на порту 8080 и отвечает локальным именем хоста. Я настроил его с достаточным количеством реплик, чтобы и worker-red, и worker-blue имели хотя бы по одному поду. Наконец, я создал службу, спецификация которой выглядит так:

spec:
    type: NodePort
    selector:
        app: hello-server
    ports:
        - port: 8080
          targetPort: 8080
          nodePort: 30080

Теперь я могу проверить, что мои поды работают

kubectl get pods -o wide
NAME                                      READY   STATUS    RESTARTS   AGE   IP              NODE          NOMINATED NODE   READINESS GATES
hello-world-deployment-587468bdb7-hf4dq   1/1     Running   0          27m   192.168.1.116   worker.red    <none>           <none>
hello-world-deployment-587468bdb7-mclhm   1/1     Running   0          27m   192.168.1.126   worker.blue   <none>           <none>

Теперь я могу попробовать к ним обратиться с помощью curl

curl worker-red:30080
greetings from hello-world-deployment-587468bdb7-hf4dq
curl worker-blue:30080
greetings from hello-world-deployment-587468bdb7-mclhm

Вот что происходит примерно в половине случаев. В другую половину случаев curl завершает работу с ошибкой timeout. В частности, запрос к worker-red будет ВЫНУЖДЕННО давать ответ только от hf4dq, а запрос к worker-blue будет ВЫНУЖДЕННО давать ответ только от mclhm. Если я изолирую и восстановлю worker-blue, так что оба моих пода работают на worker-red, таймаутов не возникает, и оба пода отвечают.

Похоже, что служба NodePort не достигает подов, которые не находятся на хосте, к которому я обращаюсь. Насколько я понимаю, это не то, как должны работать службы. Что я упускаю?

[1] Если я настраиваю так, что у меня два рабочих узла на Красном, возникает та же проблема, которую я описываю, но это мой основной случай использования, поэтому я сосредотачиваюсь именно на нем.

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

  1. Отладка подов, особенно проверьте, есть ли что-то подозрительное в логах:
  • kubectl logs ${POD_NAME} ${CONTAINER_NAME}

  • kubectl logs --previous ${POD_NAME} ${CONTAINER_NAME}

  1. Отладка служб, например, проверив:
  • Существует ли служба?

  • Работает ли служба по DNS-именам?

  • Работает ли служба по IP?

  • Правильно ли определена служба?

  • Имеет ли служба какие-либо конечные точки?

  • Работает ли kube-proxy?

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

Вы используете службу типа NodePort, в этом случае то, что вы наблюдаете, вполне ожидаемо.

Ваша служба соответствует 2 подам, которые работают на двух разных узлах. Поскольку служба типа NodePort, существует присущая ассоциация пода вашей службы и узла, на котором он работает. Если вы обращаетесь к конечной точке worker-red, вы ТОЛЬКО получите ответ от пода worker-red, потому что другой под привязан к другой конечной точке worker-blue:<node-port> и недоступен из конечной точки worker-red. Да, это одна и та же служба, но она поддерживается 2 конечными точками, каждая из которых имеет разные имена хостов.

Вот так в основном работают службы NodePort.

Когда вы объединяете их на одном узле, оба пода доступны с одного и того же имени хоста узла, так что запросы к ним будут работать. Поскольку сейчас обе конечные точки сопоставляются к разным портам, но к одному и тому же имени хоста.

Чтобы лучше понять это, вы можете попробовать изменить тип вашей службы на LoadBalancer. И вы заметите, что сможете получить доступ к обоим подам, используя одно и то же имя хоста, независимо от того, где они запланированы. И это имя хоста/IP-адрес будет адресом LoadBalancer, который будет общим для всех подов в службе.

Надеюсь, это проясняет вашу путаницу!

Ответ или решение

Проблема с тайм-аутами в Kubernetes для доступа к подам на разных рабочих узлах

Ваша ситуация с тайм-аутами при использовании сервиса типа NodePort в Kubernetes, когда куратор обращается к подам на разных рабочих узлах, действительно представляет собой распространенную проблему. Давайте разберем ее более подробно и определим потенциальные решения.

1. Понимание работы сервиса типа NodePort

Сервис типа NodePort предоставляет доступ к подам на заданном порту (в вашем случае 30080) на каждом узле вашего кластера. Однако, когда вы обращаетесь к NodePort, он направляет ваши запросы на под, который запущен на конкретном узле, откуда был сделан запрос. Это объясняет, почему запросы с узла worker-red всегда возвращают результат только от пода, который находится на этом же узле.

Как работают NodePort и поды:

  • Когда вы вызываете curl worker-red:30080, Kubernetes корректно направляет запрос на под, запущенный на узле worker-red (который, как вы заметили, отвечает только от одного пода– hello-world-deployment-587468bdb7-hf4dq).
  • Аналогично, при обращении к worker-blue:30080 это вернет только ответ от пода hello-world-deployment-587468bdb7-mclhm, поскольку запрос был выполнен с этого узла.

2. Почему возникают тайм-ауты?

Тайм-ауты, которые вы испытываете, могут быть связаны с тем, что запросы к NodePort направляются только на локальные поды, и если заблокирован доступ к другим узлам или через маршрутизацию, то запрашиваемая информация недоступна.

Возможные причины тайм-аутов:

  • Кросс-узловая маршрутизация: Возможна проблема с конфигурацией сетью или правилами брандмауэра между worker-red и worker-blue, из-за чего запросы не могут корректно маршрутизироваться.
  • Настройки kube-proxy: Проблемы с kube-proxy могут мешать корректной маршрутизации трафика к подам на разных узлах.

3. Рекомендуемые шаги для устранения проблемы

Чтобы более глубоко проанализировать вашу настройку и выявить проблему, выполните следующие шаги:

  1. Проверка состояния сервисов и подов:

    • Убедитесь, что сервис действительно настроен правильно и соответствует подам:
      kubectl get services
      kubectl describe service <имя-сервиса>
  2. Проверка конечных точек:

    • Проверьте, что у вашего сервиса есть конечные точки, которые указывают на оба пода:
      kubectl get endpoints <имя-сервиса>
  3. Логи подов:

    • Посмотрите на логи и статус подов, чтобы убедиться, что там нет ошибок:
      kubectl logs <имя-пода>
  4. Поменяйте тип сервиса:

    • Рассмотрите возможность изменения типа сервиса на LoadBalancer. Это обеспечит вам внешний адрес для доступа ко всем подам, сохраняя возможность связаться с любым из них независимо от узла:
      spec:
      type: LoadBalancer
      ...

Заключение

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

Если вам потребуется дополнительная помощь, не стесняйтесь задавать вопросы.

Оцените материал
Добавить комментарий

Капча загружается...