Сетевые сбои в контейнерных средах - одна из самых частых причин простоев микросервисов. Когда контейнеры теряют связь друг с другом, не могут разрешить DNS-имена или сервисы Kubernetes становятся недоступными, время на диагностику критически важно. Это руководство предлагает системный подход: от проверки хоста до анализа внутренней сети кластера. Вы получите четкий алгоритм действий и готовые команды для копирования, которые помогут локализовать и устранить проблему за минуты, а не часы.
С чего начать: системный подход к диагностике сети в контейнерах
Когда сеть не работает, главная ошибка - хаотично перезапускать сервисы или менять конфигурацию. Это может усугубить проблему. Правильная диагностика следует логике от простого к сложному, от хоста к контейнеру, проверяя каждый слой сетевого стека изолированно.
Ментальная карта поиска неисправности: от хоста к сервису
Представьте сетевой стек как слоеный пирог. Диагностика идет снизу вверх:
- Сеть хоста (Host Networking): Физические интерфейсы, маршрутизация, фаервол (iptables/nftables), состояние сетевых драйверов.
- Docker-демон и сетевые драйверы: Состояние демона Docker, доступные сетевые драйверы (bridge, overlay, macvlan), настройки по умолчанию.
- Docker-сети и контейнеры: Конфигурация конкретной сети, к которой подключен контейнер, его IP-адрес, шлюз, DNS-серверы.
- Kubernetes CNI и Network Policies: Работоспособность CNI-плагина (Calico, Flannel, Cilium), примененные Network Policies, которые могут блокировать трафик.
- DNS и сервисы внутри кластера: Работа CoreDNS/kube-dns, корректность Service и Endpoint объектов в Kubernetes.
Двигаясь по этой схеме, вы на каждом шаге получаете бинарный ответ: слой работает или нет. Это позволяет быстро отбросить исправные компоненты и сфокусироваться на проблемном.
Безопасная диагностика: команды, которые не сломают продакшен
Первая фаза диагностики должна использовать только read-only команды инспекции. Они не изменяют состояние системы и безопасны для продакшена.
docker inspect <container_id>- выводит полную конфигурацию контейнера, включая сетевые настройки.docker network inspect <network_name>- показывает детальную информацию о Docker-сети: подключенные контейнеры, подсеть, шлюз.kubectl describe pod/service <name>- отображает события и текущую конфигурацию объектов Kubernetes.kubectl get endpoints <service_name>- ключевая команда для проверки связи Service и Pod.ip addr show/ip route show- современные аналоги ifconfig и route, показывают состояние интерфейсов и таблиц маршрутизации хоста.ss -tulnp(или устаревшийnetstat -tulnp) - отображает открытые порты и процессы на хосте.nslookupилиdig- проверка разрешения DNS-имен. Для теста внутри контейнеров используйте временные утилитарные образы.
Начните с проверки базовой связности на хосте: ping 8.8.8.8 и ip addr show для проверки наличия IP-адресов на интерфейсах.
Проблема: контейнер Docker не имеет доступа во внешнюю сеть или к другим контейнерам
Контейнер изолирован в своей сети и не пингует внешние адреса (например, 8.8.8.8) или другие контейнеры в той же пользовательской сети. Алгоритм диагностики состоит из трех шагов.
Шаг 1: Проверяем базовую связность и настройки сети хоста
Сначала убедитесь, что проблема не на уровне операционной системы.
# Проверьте, включен ли IP forwarding (обязательно для NAT и bridge)
sysctl net.ipv4.ip_forward
# Должно быть: net.ipv4.ip_forward = 1
# Посмотрите на интерфейс docker0 (или другого bridge-интерфейса по умолчанию)
ip addr show docker0
# Должен быть назначен IP-адрес, например, 172.17.0.1
# Проверьте правила iptables в цепочке NAT, которые создает Docker
iptables -L -n -t nat | grep DOCKER
# Вы должны увидеть правило, перенаправляющее трафик с портов хоста на контейнеры.
Если IP forwarding выключен (0), включите его командой sysctl -w net.ipv4.ip_forward=1. Отсутствие интерфейса docker0 может указывать на проблему с запуском или инициализацией Docker-демона.
Шаг 2: Инспектируем Docker-сеть и контейнер
Убедитесь, что контейнер подключен к нужной сети и получил корректные настройки.
# Узнайте имя сети, к которой подключен контейнер
docker inspect <container_id> --format='{{range .NetworkSettings.Networks}}{{.NetworkID}}{{end}}'
# Инспектируйте эту сеть
docker network inspect <network_name>
# В выводе найдите секцию "Containers" и проверьте IP-адрес вашего контейнера.
# Также проверьте "Gateway" и "Subnet".
# Получите детальную сетевую информацию контейнера
docker inspect <container_id> --format='{{json .NetworkSettings}}' | jq .
# Ищите "IPAddress", "Gateway", "DNS".
Контейнер может быть подключен к сети none (--network=none) или host (--network=host), что меняет модель сетевого доступа. Убедитесь, что он использует bridge или пользовательскую сеть.
Шаг 3: Запускаем диагностику изнутри временного контейнера
Запустите легковесный контейнер в той же сети, чтобы проверить её "изнутри".
# Запустите Alpine Linux в проблемной сети
docker run --rm -it --network <problem_network> alpine sh
# Внутри контейнера выполните:
apk add iputils bind-tools # Установите ping и nslookup (если нет)
ping 8.8.8.8 # Проверка внешнего доступа
ping <gateway_ip> # Проверка доступа к шлюзу сети Docker
nslookup google.com # Проверка DNS
ip route show # Просмотр таблицы маршрутизации контейнера
Если ping до 8.8.8.8 не работает, но ping до шлюза работает - проблема в NAT или фаерволе хоста. Если не работает и ping до шлюза - проблема в конфигурации самой Docker-сети. Если nslookup не работает, переходите к следующему разделу.
Распространенные причины: отключенный IP forwarding, конфликтующие правила firewalld, который может блокировать bridge-трафик, или использование устаревшего сетевого драйвера bridge. Подробнее о тонкостях сетевой настройки и устранении подобных ошибок читайте в нашем практическом руководстве по устранению сетевых проблем Docker.
Проблема: DNS не работает внутри контейнеров Docker
Контейнеры не могут разрешать имена, хотя пинг по IP-адресам работает. Проблема часто связана с конфигурацией DNS-серверов.
Как проверить, что DNS сломан именно в контейнере
Сравните работу DNS на хосте и внутри контейнера.
# Проверка DNS на хосте (должно работать)
nslookup google.com
# Проверка DNS из временного контейнера (может не работать)
docker run --rm alpine nslookup google.com
# Более детальная диагностика с dig (образ busybox или alpine с установленным bind-tools)
docker run --rm --dns 8.8.8.8 alpine sh -c "apk add bind-tools && dig google.com"
Если команда на хосте выполняется успешно, а внутри контейнера - нет, проблема в настройках DNS контейнера.
Анализ файла /etc/resolv.conf и параметров запуска
Docker управляет файлом /etc/resolv.conf контейнера. Его содержимое зависит от флагов запуска и конфигурации хоста.
# Узнайте DNS-серверы, с которыми запущен контейнер
docker inspect <container_id> --format='{{.HostConfig.Dns}}'
# Загляните внутрь контейнера, чтобы увидеть актуальный resolv.conf
docker exec <container_id> cat /etc/resolv.conf
По умолчанию Docker копирует DNS-настройки хоста в контейнер. Если на хосте работает systemd-resolved, который слушает на 127.0.0.53, контейнер получит этот адрес в качестве DNS-сервера. Однако из сетевого пространства контейнера этот loopback-адрес недоступен. Решение - явно указать публичный DNS при запуске: docker run --dns 8.8.8.8 ... или изменить настройки Docker-демона (в /etc/docker/daemon.json добавить {"dns": ["8.8.8.8", "1.1.1.1"]}).
Другие частые причины: использование пользовательской сети без опции --dns, конфликт с настройками сети в docker-compose.yml (параметр dns:) или блокировка DNS-трафика сетевым фаерволом хоста. Для комплексного аудита подобных и других настроек безопасности используйте готовый чек-лист аудита безопасности.
Проблема: сервисы в Kubernetes не могут найти друг друга по имени
Pod'ы в кластере Kubernetes не могут соединиться друг с другом через DNS-имя Service (например, mysql-service.default.svc.cluster.local). Это классическая проблема рассинхронизации Service и Pod.
Ключевая команда: kubectl get endpoints - почему она важнее всего
Service в Kubernetes - это абстракция. Фактическую маршрутизацию трафика выполняют Endpoints. Если Endpoints пустые, Service никуда не направляет трафик.
# Проверьте Endpoints для вашего сервиса
kubectl get endpoints <service_name>
# Пример вывода, если все хорошо:
# NAME ENDPOINTS AGE
# my-service 10.244.1.5:8080,10.244.2.3:8080 5d
# Пример вывода, если проблема:
# NAME ENDPOINTS AGE
# my-service <none> 5d
Пустые (
- Несовпадение селекторов (selectors): Метки (labels) в определении Service не соответствуют меткам ни одного запущенного Pod. Проверьте:
kubectl describe svc <service_name>и сравните селектор с метками Pod:kubectl get pods --show-labels. - Pod не в состоянии Ready: Даже если Pod запущен, если его пробы готовности (readinessProbe) не проходят, он не будет добавлен в Endpoints. Проверьте статус Pod:
kubectl get pods- столбец READY должен показывать все контейнеры готовыми (например, 1/1). - Namespace не совпадает: Service и Pod находятся в разных неймспейсах. По умолчанию Service ищет Pod только в своём неймспейсе. Убедитесь, что вы проверяете объекты в одном неймспейсе или используете полное доменное имя (FQDN), включающее namespace:
<service_name>.<namespace>.svc.cluster.local.
Диагностика DNS внутри кластера Kubernetes
Если Endpoints есть, но резолвинг имен все равно не работает, проблема может быть в CoreDNS (или kube-dns).
# Запустите временный Pod с утилитами для проверки DNS
kubectl run dns-test --image=busybox:1.28 --rm -it --restart=Never -- nslookup kubernetes.default
# Эта команда должна вернуть IP-адрес сервиса kubernetes.default.
# Если не работает, проверьте логи CoreDNS
kubectl logs -l k8s-app=kube-dns -n kube-system -c coredns
# Ищите ошибки или необычные сообщения.
# Проверьте конфигурацию CoreDNS
kubectl get configmap coredns -n kube-system -o yaml
Распространенные проблемы DNS в Kubernetes: Pod'ы не могут достичь DNS-сервера из-за Network Policies, неправильно настроенный CoreDNS (например, проблемы с upstream-серверами) или сбои в работе CNI-плагина, отвечающего за сетевую связность. Для глубокой настройки и оптимизации сетей в контейнерных средах изучите продвинутый гайд по Docker сетям.
Шпаргалка команд для быстрой диагностики
Сводная таблица ключевых команд для копирования. Используйте её как чек-лист при возникновении инцидента.
| Среда / Проблема | Команда для диагностики | На что смотреть в выводе |
|---|---|---|
| Docker: Базовая связность | docker run --rm --network <net> alpine ping -c 3 8.8.8.8 |
Успешный ping (0% packet loss). |
| Docker: Проверка сети | docker network inspect <network_name> |
Наличие контейнера в "Containers", корректные "Subnet", "Gateway". |
| Docker: Проверка DNS | docker exec <container_id> cat /etc/resolv.conf |
Доступные DNS-серверы (не 127.0.0.x). |
| Kubernetes: Сервисы | kubectl get endpoints <service_name> |
Столбец ENDPOINTS не должен быть <none>. |
| Kubernetes: DNS | kubectl run -it --rm --image=busybox:1.28 --restart=Never -- nslookup <service> |
Возвращенный IP-адрес сервиса. |
| Хост: Маршрутизация | ip route show |
Наличие маршрута по умолчанию и к сетям контейнеров. |
| Хост: Фаервол | iptables -L -n -t nat | grep DOCKER |
Наличие правил для цепочек DOCKER. |
Систематическое применение этого алгоритма - от проверки хоста до анализа Endpoints в Kubernetes - позволит быстро локализовать 90% сетевых проблем в контейнерах. Помните, что для комплексного контроля за работоспособностью среды необходим мониторинг. Инструменты для отладки и мониторинга запущенных контейнеров помогут выявлять проблемы до их перерастания в инциденты. Для автоматизации безопасности вашей инфраструктуры, включая проверку образов и конфигураций, используйте сервисы, агрегирующие возможности ИИ, например, AiTunnel, который предоставляет единый доступ к множеству моделей для анализа кода и конфигураций.