Недавно меня спросили, в чем разница между NodePorts, LoadBalancers и Ingress. Все это разные способы получить внешний трафик в кластер. Давайте посмотрим, чем они отличаются, и когда использовать каждый из них.
Примечание: рекомендации рассчитаны на Google Kubernetes Engine. Если вы работаете в другом облаке, на собственном сервере, на миникубе или чем-то еще, будут отличия. Я не углубляюсь в технические детали. Если хотите подробностей, обратитесь к официальной документации.
ClusterIP
ClusterIP — сервис Kubernetes по умолчанию. Он обеспечивает сервис внутри кластера, к которому могут обращаться другие приложения внутри кластера. Внешнего доступа нет.
YAML для сервиса ClusterIP выглядит следующим образом:
apiVersion: v1
kind: Service
metadata:
name: my-internal-service
selector:
app: my-app
spec:
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
С чего я заговорил о сервисе ClusterIP, если к нему нельзя получить доступ из интернета? Способ есть: с помощью прокси-сервера Kubernetes!
Запускаем прокси-сервер Kubernetes:
$ kubectl proxy --port=8080
Теперь можно выполнять навигацию по API Kubernetes для доступа к этому сервису, используя схему:
http://localhost:8080/api/v1/proxy/namespaces//services/<SERVICE-NAME>:<PORT-NAME>/
Используем этот адрес для доступа к вышеуказанному сервису:
http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/
Когда использовать?
Существует несколько сценариев использования прокси-сервера Kubernetes для доступа к сервисам.
Отладка сервисов или подключение к ним напрямую с ноутбука с другими целями
Разрешение внутреннего трафика, отображение внутренних панелей и т. д
Поскольку этот метод требует запуска kubectl в качестве аутентифицированного пользователя, не следует использовать его для предоставления доступа к сервису в интернете или для продакшен-сервисов.
NodePort
Сервис NodePort — самый примитивный способ направить внешний трафик в сервис. NodePort, как следует из названия, открывает указанный порт для всех Nodes (виртуальных машин), и трафик на этот порт перенаправляется сервису.
YAML для службы NodePort выглядит так:
apiVersion: v1
kind: Service
metadata:
name: my-nodeport-service
selector:
app: my-app
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30036
protocol: TCP
По сути, сервис NodePort имеет два отличия от обычного сервиса ClusterIP. Во-первых, тип NodePort. Существует дополнительный порт, называемый nodePort, который указывает, какой порт открыть на узлах. Если мы не укажем этот порт, он выберет случайный. В большинстве случаев дайте Kubernetes самому выбрать порт. Как говорит thockin, с выбором портов все не так просто.
Когда использовать?
Метод имеет множество недостатков:
На порт садится только один сервис
Доступны только порты 30000–32767
Если IP-адрес узла/виртуальной машины изменяется, придется разбираться
По этим причинам я не рекомендую использовать этот метод в продакшн, чтобы напрямую предоставлять доступ к сервису. Но если постоянная доступность сервиса вам безразлична, а уровень затрат — нет, этот метод для вас. Хороший пример такого приложения — демка или временная затычка.
LoadBalancer
Сервис LoadBalancer — стандартный способ предоставления сервиса в интернете. На GKE он развернет Network Load Balancer, который предоставит IP адрес. Этот IP адрес будет направлять весь трафик на сервис.
Когда использовать?
Если вы хотите раскрыть сервис напрямую, это метод по умолчанию. Весь трафик указанного порта будет направлен на сервис. Нет фильтрации, нет маршрутизации и т.д. Это означает, что мы можем направить на сервис такие виды трафика как HTTP, TCP, UDP, Websockets, gRPC и тому подобное.
! Но есть один недостаток. Каждому сервису, который мы раскрываем с помощью LoadBalancer, нужен свой IP-адрес, что может влететь в копеечку.
Ingress
В отличие от приведенных примеров, Ingress сам по себе не сервис. Он стоит перед несколькими сервисами и действует как «интеллектуальный маршрутизатор» или точка вхождения в кластер.
Есть разные типы контроллеров Ingress с богатыми возможностями.
Контроллер GKE по умолчанию запускает HTTP(S) Load Balancer. Вам одновременно будет доступна маршрутизация в бекенд сервисы на основе путей и субдоменов. Например, все на foo.yourdomain.com отправляем в сервис foo, а путь yourdomain.com/bar/ со всеми вложениями — в сервис bar.
YAML для объекта Ingress на GKE с L7 HTTP Load Balancer выглядит следующим образом:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
spec:
backend:
serviceName: other
servicePort: 8080
rules:
- host: foo.mydomain.com
http:
paths:
- backend:
serviceName: foo
servicePort: 8080
- host: mydomain.com
http:
paths:
- path: /bar/*
backend:
serviceName: bar
servicePort: 8080
Когда использовать?
С одной стороны, Ingress — один из лучших способов раскрыть сервисы. С другой стороны — один из самых сложных. Существует множество контроллеров Ingress: Google Cloud Load Balancer, Nginx, Contour, Istio и прочие. Есть и плагины для Ingress-контроллеров, такие как cert-manager, который автоматически предоставляет SSL-сертификаты для сервисов.
Ingress хорош при раскрытии нескольких сервисов на одном IP-адресе, когда все сервисы используют общий протокол L7 (обычно HTTP). Используя встроенную интеграцию GCP, вы платите только за один балансировщик нагрузки. А поскольку Ingress «умный», вы из коробки получаете множество функций (например, SSL, Auth, Routing и т.д.)
За диаграммы спасибо Ahmet Alp Balkan.
Это не самая технически точная диаграмма, но она хорошо иллюстрирует работу NodePort.
Оригинал: Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?.
Комментарии (5)
grigorov
18.05.2018 18:58+1de1m Ну обычно ingress поднимают с node_selector, на машинах в dmz сегменте сети, на него заворачивают трафик с балансера(внешнего nginx), на адреса машин dmz, где крутиться ingress.
Выходит что, основной трафик попадает на nginx отдельный, он имеет доступ только в dmz сегмент, а тот из dmz сегмент уже запрашивает сервисы из сети кубера… Естественно если хочется разделение кубера, на сегменты сети типа dmz, lan, db… ну там без calico не выйдет нормально разрулить…Faight
19.05.2018 13:29Вместо node_selector, рекомендую использовать daemonset + toleration. будет возможность гибче управлять количеством ingress only нод.
eugene-p
18.05.2018 22:09Он обеспечивает сервис внутри кластера, к которому могут обращаться другие приложения внутри кластера. Внешнего доступа нет.
Это зависит от выбранного решения. Сам же по себе, сущность ClusterIP определяет, то что адрес сервиса должен быть выбран из сконфигурированной serviceCidr. В то время как LoadBalancer из сети LoadBalancer'а, выданный адрес которого (IP сервиса) сообщается после его создания.
Иными словами:
ClusterIP — это internal load-balancer
LoadBalancer — это external load-balancer
de1m
Если я правильно понимаю, то NodePort это самый удобный способ, если нету LoadBalancer'a?
Я сейчас про K8S, который не у гугла работает.
Ingress кстати замечательная вещь и если к нему ещё и Kubelego прикрутить, то он вам ещё и сертификаты от Let's Encrypt будет делать.
ISE73
Да, самый простой. Есть еще не упомянутый в статье externalIPs.
С его помощью можно «зачиттерить» проброс внутрь куба.