Как стать автором
Обновить

Удалённая отладка 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

Конфигурация запуска Go remote для Delve
Конфигурация запуска Go remote для Delve

Шаг 5. Ставим breaking point и дебажим

Жмём кнопку Debug, ставим breakpoint и отправляем запрос:

Breaking point
Breaking point
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. Пишите в комментариях пользовались ли вы таким способом раньше!

Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.