Недавно меня спросили, в чем разница между 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)


  1. de1m
    18.05.2018 13:28

    Если я правильно понимаю, то NodePort это самый удобный способ, если нету LoadBalancer'a?
    Я сейчас про K8S, который не у гугла работает.
    Ingress кстати замечательная вещь и если к нему ещё и Kubelego прикрутить, то он вам ещё и сертификаты от Let's Encrypt будет делать.


    1. ISE73
      18.05.2018 22:09

      Да, самый простой. Есть еще не упомянутый в статье externalIPs.
      С его помощью можно «зачиттерить» проброс внутрь куба.


  1. grigorov
    18.05.2018 18:58
    +1

    de1m Ну обычно ingress поднимают с node_selector, на машинах в dmz сегменте сети, на него заворачивают трафик с балансера(внешнего nginx), на адреса машин dmz, где крутиться ingress.

    Выходит что, основной трафик попадает на nginx отдельный, он имеет доступ только в dmz сегмент, а тот из dmz сегмент уже запрашивает сервисы из сети кубера… Естественно если хочется разделение кубера, на сегменты сети типа dmz, lan, db… ну там без calico не выйдет нормально разрулить…


    1. Faight
      19.05.2018 13:29

      Вместо node_selector, рекомендую использовать daemonset + toleration. будет возможность гибче управлять количеством ingress only нод.


  1. eugene-p
    18.05.2018 22:09

    Он обеспечивает сервис внутри кластера, к которому могут обращаться другие приложения внутри кластера. Внешнего доступа нет.

    Это зависит от выбранного решения. Сам же по себе, сущность ClusterIP определяет, то что адрес сервиса должен быть выбран из сконфигурированной serviceCidr. В то время как LoadBalancer из сети LoadBalancer'а, выданный адрес которого (IP сервиса) сообщается после его создания.
    Иными словами:
    ClusterIP — это internal load-balancer
    LoadBalancer — это external load-balancer