Information in this document may be out of date

This document has an older update date than the original, so the information it contains may be out of date. If you're able to read English, see the English version for the most up-to-date information: Using a Service to Expose Your App

Создание сервиса для открытия доступа к приложению

Узнайте о сервисах в Kubernetes. Разберитесь, какое отношение к сервисам имеют лейблы и селекторы. Сделайте приложение доступным вне кластера Kubernetes.

Цели

  • Узнать о сервисах в Kubernetes
  • Разобраться, какое отношение к сервисам имеют лейблы и селекторы
  • Сделать приложение доступным вне кластера Kubernetes

Обзор сервисов Kubernetes

Под — это расходный материал в Kubernetes. У них есть свой жизненный цикл. Когда рабочий узел прекращает работу, запущенные поды в узле также уничтожаются. После этого ReplicaSet попытается автоматически вернуть кластер обратно в требуемое состояние, создавая новые поды, чтобы поддержать работоспособность приложения. Другим примером жизни и смерти подов может служить бэкенд для обработки изображений с 3 репликами. Поскольку это взаимозаменяемые реплики, они не влияют на фронтенд-часть, даже если под был уничтожен и пересоздан. Тем не менее, каждый под в кластере Kubernetes имеет уникальный IP-адрес — даже под на одном и том же узле. Поэтому необходим способ автоматической координации изменений между подами, чтобы приложения продолжали функционировать.

Сервис (Service) в Kubernetes — это абстрактный объект, который определяет логический набор подов и политику доступа к ним. Сервисы создают слабую связь между подами, которые от них зависят. Сервис создаётся в формате YAML (рекомендуемый формат) или JSON, как и все остальные объекты в Kubernetes. Как правило, набор подов для сервиса определяется селектором лейблов (label selector) — ниже будет описано, в каких случаях может понадобиться сервис без указания селектора (selector) в его спецификации.

Хотя у каждого пода есть уникальный IP-адрес, эти IP-адреса не доступны за пределами кластера без использования сервиса. Сервисы позволяют приложениям принимать трафик. Сервисы могут быть по-разному открыты, в зависимости от значения поля type, указанного в спецификации сервиса:

  • ClusterIP (по умолчанию) — открывает доступ к сервису по внутреннему IP-адресу в кластере. Этот тип делает сервис доступным только внутри кластера;
  • NodePort — открывает сервис на том же порту каждого выбранного узла в кластере с помощью NAT. Делает сервис доступным вне кластера через <NodeIP>:<NodePort>. Является надмножеством ClusterIP.
  • LoadBalancer — создает внешний балансировщик нагрузки в текущем облаке (если это поддерживается) и назначает фиксированный внешний IP-адрес для сервиса. Является надмножеством NodePort.
  • ExternalName — открывает доступ к сервису по содержимому поля externalName (например, foo.bar.example.com), возвращая запись CNAME с его значением. При этом прокси не используется. Для этого типа требуется версия kube-dns 1.7+ или CoreDNS 0.0.8+.

Более подробно узнать о различных типах сервисах можно в руководстве Использование IP-порта источника. Также изучите Подключение приложений к сервисам.

Кроме этого, обратите внимание, что в некоторых случаях в сервисах не определяется selector в спецификации. Сервис без selector не будет создавать соответствующий эндпоинт (Endpoint). Таким образом, пользователь может вручную определить эндпоинты для сервиса. Ещё один возможный сценарий создания сервиса без селектора — это строгое использование type: ExternalName.

Краткое содержание

  • Открытие внешнего трафика для подов
  • Балансировка нагрузки трафика между подов
  • Использование лейблов

Сервис Kubernetes (Service) — это уровень абстракции, который определяет логический набор подов, перенаправляет внешний трафик, балансирует нагрузку и реализует service discovery для этих подов.


Сервисы и лейблы

Сервис направляет трафик через набор подов. Сервисы — это абстракция, позволяющая взаимозаменять поды Kubernetes без ущерба для работы приложения. Сервисы в Kubernetes находят и маршрутизируют трафик между зависимыми подами (это могут быть фронтенд- и бэкенд-компоненты приложения).

Сервисы для выбора набора подов используют лейблы и селекторы. Лейблы — пары ключ-значение, добавленные к объектам; например, они могут использоваться чтобы:

  • идентифицировать объекты для окружений разработки, тестирования и production;
  • встроить теги версии;
  • классифицировать объекты через теги.


Лейблы могут добавляться во время создания объектов или после этого. Они также могут быть изменены в любое время. Теперь давайте откроем доступ к приложению с помощью создания сервиса и добавим лейблы.

Создание нового сервиса

Давайте убедимся, что приложение работает. Воспользуемся командой kubectl get и посмотрим на существующие поды:

kubectl get pods

Если работающих подов нет, объекты из предыдущих разделов руководства была удалены. В таком случае вернитесь и повторно создайте деплоймент по инструкциям из раздела Использование kubectl для развёртывания приложения. После этого подождите несколько секунд и повторно запросите список подов. Как только увидите работающий под, можно следовать инструкциям ниже.

Далее посмотрим на список уже имеющихся сервисов в кластере:

kubectl get services

У нас есть сервис под названием kubernetes. Его по умолчанию создаёт minikube при запуске кластера. Чтобы создать новый сервис и сделать его доступным для внешних пользователей, воспользуемся командой expose с указанием типа сервиса NodePort в качестве параметра.

kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080

Попробуем подкоманду get services ещё раз:

kubectl get services

Теперь у нас есть сервис под названием kubernetes-bootcamp. Мы можем увидеть, что у этого сервиса уникальный cluster-IP, внутренний порт и external-IP (IP соответствующего узла).

Чтобы выяснить, какой порт был открыт для внешнего мира (для сервиса со спецификацией type: NodePort), выполним подкоманду describe service:

kubectl describe services/kubernetes-bootcamp

Объявим переменную окружения NODE_PORT, в которую запишем значение назначенного порта узла:

export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"
echo "NODE_PORT=$NODE_PORT"

Теперь можно проверить, что приложение доступно вне кластера, с помощью curl, IP-адреса узла и порта, проброшенного вовне:

curl http://"$(minikube ip):$NODE_PORT"

Получим ответ от сервера. Сервис доступен внешнему миру.

Шаг 2: использование лейблов

Deployment автоматически создаёт лейбл для пода. Подкоманда describe deployment покажет его название (key):

kubectl describe deployment

Воспользуемся этим лейблом при выводе списка подов. Для этого вызовем команду kubectl get pods с флагом -l и нужными значениями лейблов в качестве параметра:

kubectl get pods -l app=kubernetes-bootcamp

То же самое можно делать при выводе списка сервисов:

kubectl get services -l app=kubernetes-bootcamp

Получим имя пода и запишем его в переменную окружения POD_NAME:

export POD_NAME="$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')"
echo "Name of the Pod: $POD_NAME"

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

kubectl label pods "$POD_NAME" version=v1

Новый лейбл добавится к поду (мы зафиксировали версию приложения для этого пода), а мы сможем убедиться в этом с помощью команды describe pod:

kubectl describe pods "$POD_NAME"

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

kubectl get pods -l version=v1

Наш под будет в этом списке.

Удаление сервиса

Чтобы удалить сервис, воспользуйтесь подкомандой delete service. В ней могут указываться и лейблы:

kubectl delete service -l app=kubernetes-bootcamp

Убедитесь, что сервис удалился:

kubectl get services

Вывод подтвердит, что сервис был удалён. Убедиться в том, что удалился соответствующий маршрут для внешнего трафика, можно через curl к доступному ранее IP и порту:

curl http://"$(minikube ip):$NODE_PORT"

Так можно убедиться, что приложение более недоступно снаружи кластера. Проверить, что приложение всё ещё работает, можно через curl, который будет выполнен внутри пода:

kubectl exec -ti $POD_NAME -- curl http://localhost:8080

Мы увидим, что приложение запущено. Оно функционирует, потому что за его работу отвечает деплоймент (Deployment). Чтобы остановить приложение, потребуется также удалить и его деплоймент.

Когда всё готово, переходите к разделу Запуск нескольких экземпляров приложения.