Введение
В предыдущей лабораторной работе мы рассмотрели, как сервис (Service) предоставляет подам стабильную точку входа внутри кластера. Kubernetes также присваивает каждому сервису DNS-имя. Под, находящийся в том же пространстве имен, обычно может использовать короткое имя сервиса, однако поду в другом пространстве имен часто требуется более длинное имя, включающее пространство имен сервиса.
В этой лабораторной работе вы создадите веб-сервис, протестируете доступ по DNS в пределах одного пространства имен, воспроизведете ошибку при использовании короткого имени между пространствами имен, исправите запрос с помощью полного доменного имени (FQDN) сервиса, а также изучите объекты, которые помогут вам определить, является ли проблема с DNS на самом деле проблемой сервиса, эндпоинтов или CoreDNS.
Подготовка веб-сервиса
На этом этапе вы создадите целевой сервис, который будет использоваться в последующих тестах DNS. Рабочая нагрузка намеренно сделана простой, так как основная тема — именование DNS, а не развертывание приложений.
Начните в /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...
Дождитесь готовности сетевой инфраструктуры кластера. В этой лабораторной работе трафик передается между подами, поэтому сетевое взаимодействие подов должно быть исправным, прежде чем тесты доступа к DNS будут иметь смысл.
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
Ожидаемый вывод:
pod/calico-node-... condition met
Создайте пространство имен с именем ckad-prep-dns и установите его в качестве текущего:
kubectl create namespace ckad-prep-dns
kubectl config set-context --current --namespace=ckad-prep-dns
Создайте Deployment и откройте его с помощью сервиса с именем dns-web:
kubectl create deployment dns-web --image=nginx:1.25 --port=80
kubectl expose deployment dns-web --port=80 --target-port=80
Дождитесь готовности веб-пода:
kubectl rollout status deployment/dns-web --timeout=120s
Проверьте сервис и его EndpointSlice. Сервис является стабильной DNS-целью; EndpointSlice показывает текущие адреса бэкенд-подов, выбранных сервисом.
kubectl get service dns-web
kubectl get endpointslice -l kubernetes.io/service-name=dns-web
Ожидаемый вывод включает:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dns-web ClusterIP ... <none> 80/TCP ...
NAME ADDRESSTYPE PORTS ENDPOINTS AGE
dns-web-... IPv4 80 ... ...
Разрешение имен сервиса в пределах одного пространства имен
На этом этапе вы создадите клиентский под в том же пространстве имен, что и сервис, и используете короткое имя сервиса. Это самый простой случай DNS сервиса.
Создайте клиентский под, который будет работать постоянно:
kubectl run same-ns-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
Дождитесь готовности клиентского пода:
kubectl wait --for=condition=Ready pod/same-ns-client --timeout=120s
Ожидаемый вывод:
pod/same-ns-client condition met
Используйте nslookup внутри клиентского пода, чтобы разрешить короткое имя сервиса dns-web. Короткое имя здесь работает, потому что клиентский под и сервис находятся в одном пространстве имен. nslookup в BusyBox может выводить дополнительные строки NXDOMAIN для других суффиксов поиска и возвращать ненулевой код выхода после отображения правильного адреса, поэтому команда использует || true, а вам следует обратить внимание на строки Name и Address.
kubectl exec same-ns-client -- sh -c 'nslookup dns-web || true'
Ожидаемый вывод включает:
Name: dns-web.ckad-prep-dns.svc.cluster.local
Address: ...
Теперь отправьте HTTP-запрос на короткое имя сервиса:
kubectl exec same-ns-client -- wget -qO- http://dns-web | grep '<title>Welcome to nginx'
Ожидаемый вывод:
<title>Welcome to nginx!</title>
Диагностика ошибки короткого имени между пространствами имен
На этом этапе вы создадите клиентский под в другом пространстве имен и воспроизведете распространенную ошибку DNS. Короткое имя сервиса разрешается сначала относительно пространства имен клиентского пода, поэтому dns-web не найдет сервис в ckad-prep-dns, когда клиент запущен в другом пространстве имен.
Создайте второе пространство имен и клиентский под в нем:
kubectl create namespace ckad-prep-dns-client
kubectl run remote-client --namespace ckad-prep-dns-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
kubectl wait --namespace ckad-prep-dns-client --for=condition=Ready pod/remote-client --timeout=120s
Ожидаемый вывод включает:
namespace/ckad-prep-dns-client created
pod/remote-client created
pod/remote-client condition met
Попробуйте разрешить короткое имя из удаленного пространства имен. Конструкция || true позволяет продолжить работу, так как эта ошибка ожидаема.
kubectl exec --namespace ckad-prep-dns-client remote-client -- nslookup dns-web || true
Ожидаемый вывод включает ошибку, например:
** server can't find dns-web...
Теперь разрешите полное доменное имя (FQDN) сервиса. Полный шаблон выглядит так: <service>.<namespace>.svc.cluster.local.
kubectl exec --namespace ckad-prep-dns-client remote-client -- nslookup dns-web.ckad-prep-dns.svc.cluster.local
Ожидаемый вывод включает:
Name: dns-web.ckad-prep-dns.svc.cluster.local
Address 1: ...
Используйте то же полное имя для доступа по HTTP:
kubectl exec --namespace ckad-prep-dns-client remote-client -- wget -qO- http://dns-web.ckad-prep-dns.svc.cluster.local | grep '<title>Welcome to nginx'
Ожидаемый вывод:
<title>Welcome to nginx!</title>
Проверка пути устранения неполадок DNS
На этом этапе вы изучите объекты, которые помогают отделить проблему именования DNS от проблемы сервиса или бэкенда. Практический порядок устранения неполадок: подтвердить имя и пространство имен сервиса, подтвердить наличие эндпоинтов, затем подтвердить доступность CoreDNS.
Сначала проверьте сервис в его целевом пространстве имен:
kubectl get service dns-web --namespace ckad-prep-dns
Ожидаемый вывод включает:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
dns-web ClusterIP ... <none> 80/TCP ...
Затем проверьте EndpointSlice. Если DNS разрешается, но HTTP-трафик не проходит, отсутствие эндпоинтов является частой причиной.
kubectl get endpointslice --namespace ckad-prep-dns -l kubernetes.io/service-name=dns-web
Ожидаемый вывод включает как минимум один эндпоинт:
NAME ADDRESSTYPE PORTS ENDPOINTS AGE
dns-web-... IPv4 80 ... ...
Проверьте поды CoreDNS. CoreDNS — это DNS-сервис кластера, который отвечает на DNS-запросы подов.
kubectl get pods --namespace kube-system -l k8s-app=kube-dns
Ожидаемый вывод включает работающие поды CoreDNS:
NAME READY STATUS RESTARTS AGE
coredns-... 1/1 Running ... ...
Наконец, изучите конфигурацию поиска DNS на удаленном клиенте. Строка search объясняет, почему короткое имя dns-web искалось в пространстве имен клиента, прежде чем вы использовали полное имя.
kubectl exec --namespace ckad-prep-dns-client remote-client -- cat /etc/resolv.conf
Ожидаемый вывод включает путь поиска, похожий на этот:
search ckad-prep-dns-client.svc.cluster.local svc.cluster.local cluster.local
nameserver ...
Резюме
Вы попрактиковались в диагностике доступа к DNS сервисов Kubernetes в последовательности, удобной для начинающих. Вы создали сервис, подтвердили, что клиент в том же пространстве имен может использовать короткое имя сервиса, воспроизвели ошибку короткого имени между пространствами имен, исправили её с помощью полного DNS-имени сервиса, а также изучили сервис, EndpointSlice, поды CoreDNS и путь поиска DNS клиента, чтобы понять, откуда возникают проблемы с доступом по DNS.


