Публикация Deployment с помощью Service

KubernetesBeginner
Практиковаться сейчас

Введение

Поды (Pods) — это временные объекты. Deployment может заменять поды в процессе развертывания, перезапуска или масштабирования, поэтому клиенты не должны подключаться напрямую к IP-адресам отдельных подов. Сервис (Service) предоставляет клиентам стабильное имя и виртуальный IP-адрес, а затем использует метки (labels) для маршрутизации трафика к актуальным соответствующим подам.

В этой лабораторной работе вы создадите небольшой веб-Deployment, опубликуете его с помощью сервиса ClusterIP, изучите, как сервис выбирает бэкенд-поды, протестируете сервис из клиентского пода и масштабируете Deployment, чтобы увидеть, как обновляются конечные точки сервиса.

Создание веб-Deployment

На этом этапе вы подготовите пространство имен (namespace) и создадите Deployment, который позже можно будет опубликовать с помощью сервиса.

Начните работу в /home/labex/project:

mkdir -p /home/labex/project
cd /home/labex/project

Проверьте доступность API-сервера Kubernetes. Если виртуальная машина только что запустилась и узел еще не готов, подождите несколько секунд и выполните команду снова.

kubectl get nodes --request-timeout=5s

Ожидаемый вывод:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

Дождитесь, пока под сетевого плагина кластера перейдет в состояние Ready. В этой лабораторной работе трафик между подами передается через сервис, поэтому сетевая инфраструктура кластера должна быть исправна перед тестированием доступа.

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

Ожидаемый вывод:

pod/calico-node-... condition met

Создайте пространство имен ckad-prep-service и сделайте его текущим:

kubectl create namespace ckad-prep-service
kubectl config set-context --current --namespace=ckad-prep-service

Создайте Deployment с именем web-front с одним подом NGINX. Флаг --port=80 фиксирует порт контейнера в шаблоне пода. Сам по себе он не создает сервис.

kubectl create deployment web-front --image=nginx:1.25 --port=80

Дождитесь готовности Deployment, затем проверьте метку пода. Метка app=web-front важна, так как сервис будет использовать её для поиска бэкенд-подов.

kubectl rollout status deployment/web-front --timeout=120s
kubectl get pods -l app=web-front --show-labels

Ожидаемый вывод:

deployment "web-front" successfully rolled out
NAME                         READY   STATUS    RESTARTS   AGE   LABELS
web-front-...                1/1     Running   0          ...   app=web-front,...

Публикация Deployment с помощью сервиса ClusterIP

На этом этапе вы создадите сервис для Deployment и изучите поля, которые связывают сервис с подами.

Используйте kubectl expose deployment для создания сервиса типа ClusterIP. Порт сервиса — 80, а --target-port=80 указывает сервису перенаправлять трафик на порт 80 соответствующих подов.

kubectl expose deployment web-front --name=web-front --port=80 --target-port=80

Ожидаемый вывод:

service/web-front exposed

Проверьте созданный сервис:

kubectl get service web-front

Ожидаемый вывод:

NAME        TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
web-front   ClusterIP   ...          <none>        80/TCP    ...

Теперь изучите селектор сервиса и сопоставление портов. Селектор определяет, как сервис находит поды; сопоставление портов определяет, как клиентский трафик достигает контейнера.

kubectl get service web-front -o jsonpath='{.spec.selector.app}{" "}{.spec.ports[0].port}{":"}{.spec.ports[0].targetPort}{"\n"}'

Ожидаемый вывод:

web-front 80:80

Kubernetes хранит адреса выбранных бэкендов в объектах EndpointSlice. Выведите список EndpointSlice, созданных для этого сервиса:

kubectl get endpointslice -l kubernetes.io/service-name=web-front

Ожидаемый вывод:

NAME              ADDRESSTYPE   PORTS   ENDPOINTS   AGE
web-front-...     IPv4          80      ...         ...

Тестирование сервиса изнутри кластера

На этом этапе вы создадите временный клиентский под и отправите HTTP-запрос к сервису. Сервис ClusterIP предназначен для доступа внутри кластера, поэтому тестирование из другого пода — самый прямой способ проверки.

Создайте клиентский под, который будет работать в фоновом режиме:

kubectl run service-client --image=busybox:1.36 --restart=Never --command -- sleep 3600

Дождитесь готовности клиентского пода:

kubectl wait --for=condition=Ready pod/service-client --timeout=120s

Ожидаемый вывод:

pod/service-client condition met

Используйте wget внутри клиентского пода, чтобы отправить запрос к http://web-front. Имя web-front разрешается в IP-адрес сервиса внутри пространства имен.

kubectl exec service-client -- wget -qO- http://web-front | head -n 5

Ожидаемый вывод содержит начало стандартной страницы NGINX:

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

Это подтверждает, что клиент успешно обратился к стабильному имени сервиса, а сервис перенаправил трафик на актуальный бэкенд-под.

Масштабирование бэкенда и повторная проверка конечных точек

На этом этапе вы масштабируете Deployment и убедитесь, что сервис сохраняет тот же стабильный «вход», даже если набор бэкенд-подов меняется.

Масштабируйте Deployment до двух реплик:

kubectl scale deployment web-front --replicas=2
kubectl rollout status deployment/web-front --timeout=120s

Ожидаемый вывод:

deployment.apps/web-front scaled
deployment "web-front" successfully rolled out

Выведите список подов. Теперь должно быть два работающих бэкенд-пода с той же меткой app=web-front.

kubectl get pods -l app=web-front

Ожидаемый вывод включает два пода:

NAME                         READY   STATUS    RESTARTS   AGE
web-front-...                1/1     Running   0          ...
web-front-...                1/1     Running   0          ...

Подсчитайте количество конечных точек за сервисом. Команда выводит по одной строке для каждого адреса конечной точки, а затем подсчитывает количество строк.

kubectl get endpointslice -l kubernetes.io/service-name=web-front -o jsonpath='{range .items[*].endpoints[*]}{.addresses[0]}{"\n"}{end}' | wc -l

Ожидаемый вывод:

2

Снова отправьте запрос к сервису из того же клиентского пода:

kubectl exec service-client -- wget -qO- http://web-front | grep '<title>Welcome to nginx'

Ожидаемый вывод:

<title>Welcome to nginx!</title>

Резюме

Вы опубликовали Deployment с помощью сервиса ClusterIP и проверили полный путь доступа внутри кластера. Вы создали бэкенд-Deployment, настроили сервис с селектором и сопоставлением портов, изучили сгенерированный для сервиса EndpointSlice, протестировали доступ из клиентского пода, а затем масштабировали Deployment и подтвердили, что сервис продолжает корректно маршрутизировать трафик на обновленный набор бэкендов.