Введение
Поды (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 и подтвердили, что сервис продолжает корректно маршрутизировать трафик на обновленный набор бэкендов.


