Как подключиться к дебаггеру в Kubernetes
Что проверяют
Понимаете ли вы, как JDWP работает по сети и как добраться до порта внутри кластера, не открывая его наружу. Следом почти всегда спрашивают, почему под перезапускается, стоит остановиться на брейкпоинте.
Как отвечать
Шаги:
- включить агент:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005. С JDK 9 адрес без*:слушает только localhost. Передавать параметр надёжнее черезJAVA_TOOL_OPTIONS: его читает сама JVM, аJAVA_OPTSработает, только если стартовый скрипт образа его подставляет; - выкатить: под обычно принадлежит Deployment, поэтому правится деплоймент, например
kubectl set env deployment/app JAVA_TOOL_OPTIONS=..., и это запускает rollout. Для отладки лучше оставить одну реплику; - подключиться:
kubectl port-forward pod/my-app 5005:5005и в IntelliJ IDEA конфигурация Remote JVM Debug наlocalhost:5005. IP пода изkubectl get pods -o wideс ноутбука обычно недоступен, а открывать Service типа NodePort ради отладчика нельзя; - не дать kubelet убить под: брейкпоинт, останавливающий все потоки, останавливает и ответ на liveness-пробу, и контейнер перезапускается. Ставьте в IDE политику приостановки Thread или на время отладки ослабьте пробы;
- смотреть без рестарта:
kubectl debugс--targetдобавляет к поду эфемерный контейнер с общим пространством процессов, туда можно принести JDK-утилиты, которых нет в slim-образе.
Для проблем на старте есть suspend=y: JVM ждёт отладчик до запуска main. Альтернатива удалённой отладке: Telepresence или mirrord запускают сервис локально под отладчиком, но с трафиком и окружением кластера.
Где спотыкаются
Оставляют JDWP в продовом образе или открывают порт через Service. Отладочный порт позволяет выполнить произвольный код в JVM, это полноценная дыра.
Кладут параметры в JAVA_OPTS и не понимают, почему агент молчит. Проверяется по логу: JVM пишет Picked up JAVA_TOOL_OPTIONS, а агент печатает Listening for transport dt_socket at address: 5005.
Включают suspend=y и забывают про пробы. JVM ждёт отладчик, приложение не поднимается, и liveness убивает контейнер раньше, чем вы успели подключиться.