Диагностика доступа к DNS сервисов

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

Введение

В предыдущей лабораторной работе мы рассмотрели, как сервис (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.