Какие виды Service вы знаете в Kubernetes и в каких случаях они применяются?

Ответ

Service в Kubernetes — это абстракция, которая обеспечивает стабильную сетевую точку доступа к набору Pod'ов. В своей работе я применяю разные типы Service в зависимости от задачи.

Основные типы и сценарии их использования:

  1. ClusterIP (тип по умолчанию)

    • Применение: Для внутренней коммуникации между микросервисами внутри кластера. Например, сервису backend нужно обратиться к сервису database.
      apiVersion: v1
      kind: Service
      metadata:
      name: internal-api-service
      spec:
      type: ClusterIP
      selector:
      app: backend-api
      ports:
      - port: 80          # Порт самого Service
        targetPort: 8080  # Порт на Pod'ах
  2. NodePort

    • Применение: Для доступа к сервису снаружи кластера на этапе разработки или демонстрации, либо когда нет облачного LoadBalancer. Открывает статический порт (30000-32767) на каждой ноде.
      spec:
      type: NodePort
      ports:
      - port: 80
        targetPort: 8080
        nodePort: 31000 # (опционально) Можно зафиксировать порт.
  3. LoadBalancer

    • Применение: Стандартный способ вывести сервис в интернет в облачных средах (AWS, GCP, Azure). Провайдер автоматически создает внешний балансировщик нагрузки.
      spec:
      type: LoadBalancer
      # В аннотациях можно задать специфичные для облака настройки
      # metadata:
      #   annotations:
      #     service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
  4. Headless Service (Без ClusterIP)

    • Применение: Когда нужен прямой доступ к каждому Pod'у, минуя балансировку (например, для StatefulSets типа кластера Cassandra или Kafka). DNS-запрос к такому сервису вернет IP-адреса всех Pod'ов.
      spec:
      clusterIP: None # Ключевой параметр
      selector:
      app: stateful-db
  5. ExternalName

    • Применение: Для создания CNAME-алиаса внутри кластера на внешний сервис (например, legacy БД за пределами k8s). Это не прокси, а просто перенаправление DNS.
      spec:
      type: ExternalName
      externalName: legacy-mysql.prod.company.com

Выбор типа — это всегда компромисс между требованиями безопасности, доступности и архитектуры приложения.

Ответ 18+ 🔞

А, Сервисы в кубере! Ну это, блядь, такая штука, которая из кучи разбросанных подов делает одну нормальную, стабильную точку для сети. Без них твои микросервисы друг друга искать будут, как слепые котята в подвале — нихуя не найдут. Я их применяю по-разному, смотря какая задача горит.

Вот основные типы, и где их впендюрить:

  1. ClusterIP (он же дефолтный)

    • Зачем: Чтобы твои сервисы внутри кластера друг с другом болтали, а не по интернету светили. Ну, типа, backend стучится к database, и всё это дело внутри, по-семейному.
      apiVersion: v1
      kind: Service
      metadata:
      name: internal-api-service
      spec:
      type: ClusterIP
      selector:
      app: backend-api
      ports:
      - port: 80          # Порт, на котором Сервис торчит
        targetPort: 8080  # А это порт уже на самих Pod'ах, куда стучать

      Короче, для внутренней кухни. Снаружи него нихуя не видно, и это правильно.

  2. NodePort

    • Зачем: Когда надо быстро что-то наружу вытащить, на коленке потестить или облачного балансировщика нет, как у дурака фантиков. Он, сука, пробивает дырку (порт от 30000 до 32767) на каждой ноде кластера. Захочешь — зайди с любой.
      spec:
      type: NodePort
      ports:
      - port: 80
        targetPort: 8080
        nodePort: 31000 # (не обязательно) Можно и свой порт впихнуть, если не хочешь рандомный.

      Для продакшна так делать — это, конечно, пиздец, но для демо или дебага — вротберунчик, быстро и сердито.

  3. LoadBalancer

    • Зачем: Это когда ты в облаке сидишь (AWS, GCP, Azure) и тебе надо, чтобы сервис в интернет вышел по-взрослому. Ты говоришь куберу "дай балансировщик", а он такой "ёпта, ща" — и провайдер тебе его на блюдечке с голубой каёмочкой приносит.
      spec:
      type: LoadBalancer
      # В аннотациях можно накрутить специфичные для облака прибамбасы
      # metadata:
      #   annotations:
      #     service.beta.kubernetes.io/aws-load-balancer-type: "nlb"

      Удобно, но деньги капают. За каждый такой сервис — отдельный балансировщик, имей в виду.

  4. Headless Service (Безголовый, блядь)

    • Зачем: А вот это хитрая жопа. Когда тебе не нужна балансировка, а надо получить IP-шники всех подов по отдельности. Например, для всяких StatefulSet'ов вроде Кассандры или Кафки, где каждый под должен знать всех соседей в лицо.
      spec:
      clusterIP: None # Вот этот финт ушами делает его безголовым!
      selector:
      app: stateful-db

      Сделаешь DNS-запрос к такому сервису — и он тебе, мудя, список всех айпишников отдаст. Прямой доступ, никаких прокси.

  5. ExternalName

    • Зачем: Это вообще не прокси, а так, DNS-обманка для своих. Создаёшь внутри кластера красивый алиас на какой-нибудь старый, допотопный сервис снаружи (типа базы данных, которая ещё в каменном веке живёт).
      spec:
      type: ExternalName
      externalName: legacy-mysql.prod.company.com

      Твои поды думают, что стучатся на my-cool-service, а на самом деле их тихо-мирно переадресуют на legacy-mysql.prod.company.com. Чистая магия, ёпта.

В общем, выбор типа — это всегда, блядь, такой компромисс: что безопаснее, что доступнее и какую архитектуру ты там понастроил. Главное — не выебнуться и не сделать NodePort для базы данных в продакшне, а то будет вам хиросима и нигерсраки.