Вопрос или проблема
Я пытаюсь настроить пару рабочих узлов 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] Если я настраиваю так, что у меня два рабочих узла на Красном, возникает та же проблема, которую я описываю, но это мой основной случай использования, поэтому я сосредотачиваюсь именно на нем.
Сложно однозначно сказать, что может быть не так, но есть несколько шагов, которые вы можете предпринять для устранения вашей проблемы:
- Отладка подов, особенно проверьте, есть ли что-то подозрительное в логах:
-
kubectl logs ${POD_NAME} ${CONTAINER_NAME}
-
kubectl logs --previous ${POD_NAME} ${CONTAINER_NAME}
- Отладка служб, например, проверив:
-
Существует ли служба?
-
Работает ли служба по 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. Рекомендуемые шаги для устранения проблемы
Чтобы более глубоко проанализировать вашу настройку и выявить проблему, выполните следующие шаги:
-
Проверка состояния сервисов и подов:
- Убедитесь, что сервис действительно настроен правильно и соответствует подам:
kubectl get services kubectl describe service <имя-сервиса>
- Убедитесь, что сервис действительно настроен правильно и соответствует подам:
-
Проверка конечных точек:
- Проверьте, что у вашего сервиса есть конечные точки, которые указывают на оба пода:
kubectl get endpoints <имя-сервиса>
- Проверьте, что у вашего сервиса есть конечные точки, которые указывают на оба пода:
-
Логи подов:
- Посмотрите на логи и статус подов, чтобы убедиться, что там нет ошибок:
kubectl logs <имя-пода>
- Посмотрите на логи и статус подов, чтобы убедиться, что там нет ошибок:
-
Поменяйте тип сервиса:
- Рассмотрите возможность изменения типа сервиса на
LoadBalancer
. Это обеспечит вам внешний адрес для доступа ко всем подам, сохраняя возможность связаться с любым из них независимо от узла:spec: type: LoadBalancer ...
- Рассмотрите возможность изменения типа сервиса на
Заключение
Общая картина такова, что NodePort сервис не предназначен для кросс-узлового доступа к подам так, как вы ожидаете. Предлагаемое изменение на LoadBalancer, а также проверка сетевых настроек в вашем окружении, поможет значительно улучшить ситуацию. Понимание принципов работы Kubernetes и деталей маршрутизации обеспечит более надежную и стабильную работу вашего кластера.
Если вам потребуется дополнительная помощь, не стесняйтесь задавать вопросы.