Удалённая отладка Go-приложений в Kubernetes с помощью Delve
В этой статье я расскажу, как отлаживать сервисы, написанные на Go и запущенные в Kubernetes.
Когда система становится достаточно большой, необходимость в отладке — вопрос времени. У сервисов могут быть зависимости, требующие специфичного окружения, или особенности поведения, которые проявляются только на стендах. В таких случаях обычная локальная отладка нас не спасёт.
Что делать? На помощь приходит Delve — отладчик для языка Go. Ниже я покажу, как шаг за шагом настроить удалённую отладку приложения прямо в кластере Kubernetes.
Шаг 1. Простое Go-приложение
Начнём с небольшой программы на Go. Это HTTP-сервер с одним хендлером, принимающим параметр name
.
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
if name == "" {
name = "debugger"
}
fmt.Printf("Received request with name: %s\n", name)
fmt.Fprintf(w, "Hello, %s!\n", name)
})
port := ":8080"
fmt.Println("Server is running on http://localhost" + port)
if err := http.ListenAndServe(port, nil); err != nil {
log.Fatalf("Server failed to start: %v", err)
}
}
Dockerfile для сборки этого сервиса:
FROM golang:1.24.2-alpine3.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o server .
FROM alpine:3.21
WORKDIR /app
COPY --from=builder /app/server .
EXPOSE 8080
CMD ["./server"]
Шаг 2. Отладка внутри Kubernetes
Для примера я использую Minikube — удобный способ развернуть локальный кластер одной командой. Helm-чарты и команды для деплоя вы найдёте на GitHub
Представим, что в нашем приложении баг, и мы хотим его отладить прямо в Kubernetes.
Для этого немного модифицируем Dockerfile: установим Delve и будем запускать бинарь через него. Отладчик будет слушать порт 40000.
FROM golang:1.24.2-alpine3.21 AS builder
WORKDIR /app
# Установка Delve
RUN go install github.com/go-delve/delve/cmd/dlv@v1.24
COPY . .
RUN go build -o server .
FROM alpine:3.21
WORKDIR /app
COPY --from=builder /app/server .
COPY --from=builder /go/bin/dlv ./
EXPOSE 8080
#CMD ["./server"]
# Запуск бинарного файла с помощью Delve
CMD ["./dlv", "--headless=true", "--accept-multiclient", "--continue", "--listen=0.0.0.0:40000", "--api-version=2", "exec", "./server", "--log"]
Перекатим наше приложение. В логах увидим сообщения от Delve
API server listening at: [::]:40000
2025-04-12T16:04:01Z warn layer=rpc Listening for remote connections (connections are not authenticated nor encrypted)
2025-04-12T16:04:01Z info layer=debugger launching process with args: [./server]
2025-04-12T16:04:01Z debug layer=debugger Adding target 17 "/app/server"
2025-04-12T16:04:01Z debug layer=debugger continuing
2025-04-12T16:04:01Z debug layer=debugger ContinueOnce
Шаг 3. Прокидываем порт на локалку
Теперь подключим порт отладчика из пода к локальной машине. Важно: прокидываем не порт сервиса, а порт Delve 40000
.
kubectl port-forward pod/simple-server-69676f6446-sslk9 40000:40000
Шаг 4. Подключаемся из IDE
Открываем GoLand (или VS Code) и добавляем новую конфигурацию запуска:
Run → Edit Configurations → Go Remote
Параметры:
Host: localhost
Port: 40000
On disconnect: Leave it running

Шаг 5. Ставим breaking point и дебажим
Жмём кнопку Debug, ставим breakpoint и отправляем запрос:

curl http://127.0.0.1:62004\?name\=Alice
И — ура! — программа останавливается на breaking point'е прямо в IDE. Можно смотреть переменные, ходить по стеку, делать всё как при локальном дебаге — только теперь приложение живёт в Kubernetes.

Что делать, если у меня несколько реплик приложения?
Ничего сложного. Вам нужно прокинуть порты для каждой реплики, например:
40000 -> 40000 для первой реплики
40000 -> 40001 для второй реплики
40000 -> 40002 для третьей реплики
Затем в IDE создаёте несколько конфигураций запуска Go Remote с разными портами и включаете их одновременно. Включится дебаг той реплики, на которую прийдёт запрос.
Заключение
Теперь вы можете отлаживать Go-приложения, запущенные в Kubernetes, не выходя из своей IDE. Это невероятно удобно при работе с багами, которые не воспроизводятся локально.
⚠️ Важно: не используйте такую отладку в production-среде. Delve не шифрует соединения и не требует авторизации, так что использовать его безопасно только в dev/staging окружениях.
Go-сервис, helm-чарты и инструкцию по запуску в Minikube можно найти на GitHub. Пишите в комментариях пользовались ли вы таким способом раньше!