Skip to content

Commit 916124b

Browse files
slim-beanEd
authored and
Ed
committed
Adding make debug support to build debug binaries and debug containers which wrap the binary with delve and allow for remote debugging
1 parent 42e5bf1 commit 916124b

File tree

7 files changed

+180
-3
lines changed

7 files changed

+180
-3
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.uptodate
2+
.uptodate-debug
23
.pkg
34
.cache
45
*.output
@@ -7,6 +8,9 @@ requirements.lock
78
mixin/vendor/
89
cmd/loki/loki
910
cmd/promtail/promtail
11+
cmd/loki/loki-debug
12+
cmd/promtail/promtail-debug
1013
/loki
1114
/promtail
1215
/logcli
16+
dlv

Makefile

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ CHARTS := production/helm/loki production/helm/promtail production/helm/loki-sta
88
IMAGE_PREFIX ?= grafana/
99
IMAGE_TAG := $(shell ./tools/image-tag)
1010
UPTODATE := .uptodate
11+
DEBUG_UPTODATE := .uptodate-debug
1112
GIT_REVISION := $(shell git rev-parse --short HEAD)
1213
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
1314

@@ -21,15 +22,25 @@ GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
2122
$(SUDO) docker tag $(IMAGE_PREFIX)$(shell basename $(@D)) $(IMAGE_PREFIX)$(shell basename $(@D)):$(IMAGE_TAG)
2223
touch $@
2324

25+
%/$(DEBUG_UPTODATE): %/Dockerfile.debug
26+
$(SUDO) docker build -f $(@D)/Dockerfile.debug -t $(IMAGE_PREFIX)$(shell basename $(@D))-debug $(@D)/
27+
$(SUDO) docker tag $(IMAGE_PREFIX)$(shell basename $(@D))-debug $(IMAGE_PREFIX)$(shell basename $(@D))-debug:$(IMAGE_TAG)
28+
touch $@
29+
2430
# We don't want find to scan inside a bunch of directories, to accelerate the
2531
# 'make: Entering directory '/go/src/github.com/grafana/loki' phase.
2632
DONT_FIND := -name tools -prune -o -name vendor -prune -o -name .git -prune -o -name .cache -prune -o -name .pkg -prune -o
2733

2834
# Get a list of directories containing Dockerfiles
2935
DOCKERFILES := $(shell find . $(DONT_FIND) -type f -name 'Dockerfile' -print)
3036
UPTODATE_FILES := $(patsubst %/Dockerfile,%/$(UPTODATE),$(DOCKERFILES))
37+
DEBUG_DOCKERFILES := $(shell find . $(DONT_FIND) -type f -name 'Dockerfile.debug' -print)
38+
DEBUG_UPTODATE_FILES := $(patsubst %/Dockerfile.debug,%/$(DEBUG_UPTODATE),$(DEBUG_DOCKERFILES))
39+
DEBUG_DLV_FILES := $(patsubst %/Dockerfile.debug,%/dlv,$(DEBUG_DOCKERFILES))
3140
DOCKER_IMAGE_DIRS := $(patsubst %/Dockerfile,%,$(DOCKERFILES))
3241
IMAGE_NAMES := $(foreach dir,$(DOCKER_IMAGE_DIRS),$(patsubst %,$(IMAGE_PREFIX)%,$(shell basename $(dir))))
42+
DEBUG_DOCKER_IMAGE_DIRS := $(patsubst %/Dockerfile.debug,%,$(DEBUG_DOCKERFILES))
43+
DEBUG_IMAGE_NAMES := $(foreach dir,$(DEBUG_DOCKER_IMAGE_DIRS),$(patsubst %,$(IMAGE_PREFIX)%,$(shell basename $(dir))-debug))
3344
images:
3445
$(info $(patsubst %,%:$(IMAGE_TAG),$(IMAGE_NAMES)))
3546
@echo > /dev/null
@@ -49,13 +60,29 @@ YACC_GOS := $(patsubst %.y,%.go,$(YACC_DEFS))
4960
# for every directory with main.go in it, in the ./cmd directory.
5061
MAIN_GO := $(shell find . $(DONT_FIND) -type f -name 'main.go' -print)
5162
EXES := $(foreach exe, $(patsubst ./cmd/%/main.go, %, $(MAIN_GO)), ./cmd/$(exe)/$(exe))
63+
DEBUG_EXES := $(foreach exe, $(patsubst ./cmd/%/main.go, %, $(MAIN_GO)), ./cmd/$(exe)/$(exe)-debug)
5264
GO_FILES := $(shell find . $(DONT_FIND) -name cmd -prune -o -type f -name '*.go' -print)
65+
66+
# This is the important part of how `make all` enters this file
67+
# the above EXES finds all the main.go files and for each of them
68+
# it creates the dep_exe targets which look like this:
69+
# cmd/promtail/promtail: loki-build-image/.uptodate cmd/promtail//main.go pkg/loki/loki.go pkg/loki/fake_auth.go ...
70+
# cmd/promtail/.uptodate: cmd/promtail/promtail
71+
# Then when `make all` expands `$(UPTODATE_FILES)` it will call the second generated target and initiate the build process
5372
define dep_exe
5473
$(1): $(dir $(1))/main.go $(GO_FILES) $(PROTO_GOS) $(YACC_GOS)
5574
$(dir $(1))$(UPTODATE): $(1)
5675
endef
5776
$(foreach exe, $(EXES), $(eval $(call dep_exe, $(exe))))
5877

78+
# Everything is basically duplicated for debug builds,
79+
# but with a different set of Dockerfiles and binaries appended with -debug.
80+
define debug_dep_exe
81+
$(1): $(dir $(1))/main.go $(GO_FILES) $(PROTO_GOS) $(YACC_GOS)
82+
$(dir $(1))$(DEBUG_UPTODATE): $(1)
83+
endef
84+
$(foreach exe, $(DEBUG_EXES), $(eval $(call debug_dep_exe, $(exe))))
85+
5986
# Manually declared dependancies and what goes into each exe
6087
pkg/logproto/logproto.pb.go: pkg/logproto/logproto.proto
6188
vendor/github.com/cortexproject/cortex/pkg/ring/ring.pb.go: vendor/github.com/cortexproject/cortex/pkg/ring/ring.proto
@@ -65,6 +92,7 @@ pkg/parser/labels.go: pkg/parser/labels.y
6592
pkg/parser/matchers.go: pkg/parser/matchers.y
6693
all: $(UPTODATE_FILES)
6794
test: $(PROTO_GOS) $(YACC_GOS)
95+
debug: $(DEBUG_UPTODATE_FILES)
6896
yacc: $(YACC_GOS)
6997
protos: $(PROTO_GOS)
7098
yacc: $(YACC_GOS)
@@ -86,6 +114,10 @@ TTY := --tty
86114

87115
VPREFIX := github.com/grafana/loki/vendor/github.com/prometheus/common/version
88116
GO_FLAGS := -ldflags "-extldflags \"-static\" -s -w -X $(VPREFIX).Branch=$(GIT_BRANCH) -X $(VPREFIX).Version=$(IMAGE_TAG) -X $(VPREFIX).Revision=$(GIT_REVISION)" -tags netgo
117+
# Per some websites I've seen to add `-gcflags "all=-N -l"`, the gcflags seem poorly if at all documented
118+
# the best I could dig up is -N disables optimizations and -l disables inlining which should make debugging match source better.
119+
# Also remove the -s and -w flags present in the normal build which strip the symbol table and the DWARF symbol table.
120+
DEBUG_GO_FLAGS := -gcflags "all=-N -l" -ldflags "-extldflags \"-static\" -X $(VPREFIX).Branch=$(GIT_BRANCH) -X $(VPREFIX).Version=$(IMAGE_TAG) -X $(VPREFIX).Revision=$(GIT_REVISION)" -tags netgo
89121

90122
NETGO_CHECK = @strings $@ | grep cgo_stub\\\.go >/dev/null || { \
91123
rm $@; \
@@ -96,9 +128,15 @@ NETGO_CHECK = @strings $@ | grep cgo_stub\\\.go >/dev/null || { \
96128
false; \
97129
}
98130

131+
# If BUILD_IN_CONTAINER is true, the build image is run which launches
132+
# an image that mounts this project as a volume. The image invokes a build.sh script
133+
# which essentially re-enters this file with BUILD_IN_CONTAINER=FALSE
134+
# causing the else block target below to be called and the files to be built.
135+
# If BUILD_IN_CONTAINER were false to begin with, the else block is
136+
# executed and the binaries are built without ever launching the build container.
99137
ifeq ($(BUILD_IN_CONTAINER),true)
100138

101-
$(EXES) $(PROTO_GOS) $(YACC_GOS) lint test shell check-generated-files: loki-build-image/$(UPTODATE)
139+
$(EXES) $(DEBUG_EXES) $(PROTO_GOS) $(YACC_GOS) lint test shell check-generated-files: loki-build-image/$(UPTODATE)
102140
@mkdir -p $(shell pwd)/.pkg
103141
@mkdir -p $(shell pwd)/.cache
104142
$(SUDO) docker run $(RM) $(TTY) -i \
@@ -109,6 +147,12 @@ $(EXES) $(PROTO_GOS) $(YACC_GOS) lint test shell check-generated-files: loki-bui
109147

110148
else
111149

150+
$(DEBUG_EXES): loki-build-image/$(UPTODATE)
151+
CGO_ENABLED=0 go build $(DEBUG_GO_FLAGS) -o $@ ./$(@D)
152+
$(NETGO_CHECK)
153+
# Copy the delve binary to make it easily available to put in the binary's container.
154+
[ -f "/go/bin/dlv" ] && mv "/go/bin/dlv" $(@D)/dlv
155+
112156
$(EXES): loki-build-image/$(UPTODATE)
113157
CGO_ENABLED=0 go build $(GO_FLAGS) -o $@ ./$(@D)
114158
$(NETGO_CHECK)
@@ -200,6 +244,6 @@ helm-publish: helm
200244
git push origin gh-pages
201245

202246
clean:
203-
$(SUDO) docker rmi $(IMAGE_NAMES) >/dev/null 2>&1 || true
204-
rm -rf $(UPTODATE_FILES) $(EXES) .cache
247+
$(SUDO) docker rmi $(IMAGE_NAMES) $(DEBUG_IMAGE_NAMES) >/dev/null 2>&1 || true
248+
rm -rf $(UPTODATE_FILES) $(EXES) $(DEBUG_UPTODATE_FILES) $(DEBUG_EXES) $(DEBUG_DLV_FILES) .cache
205249
go clean ./...

cmd/loki/Dockerfile.debug

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM alpine:3.9
2+
RUN apk add --update --no-cache ca-certificates
3+
COPY loki-debug /bin/loki-debug
4+
ADD dlv /usr/bin
5+
COPY loki-local-config.yaml /etc/loki/local-config.yaml
6+
EXPOSE 80
7+
8+
# Expose 40000 for delve
9+
EXPOSE 40000
10+
11+
# Allow delve to run on Alpine based containers.
12+
RUN apk add --no-cache libc6-compat
13+
14+
# Run delve, ending with -- because we pass params via kubernetes, per the docs:
15+
# Pass flags to the program you are debugging using --, for example:`
16+
# dlv exec ./hello -- server --config conf/config.toml`
17+
ENTRYPOINT ["/usr/bin/dlv", "--listen=:40000", "--headless=true", "--api-version=2", "exec", "/bin/loki-debug", "--"]

cmd/promtail/Dockerfile.debug

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM alpine:3.9
2+
RUN apk add --update --no-cache ca-certificates
3+
ADD promtail-debug /usr/bin
4+
ADD dlv /usr/bin
5+
COPY promtail-local-config.yaml /etc/promtail/local-config.yaml
6+
COPY promtail-docker-config.yaml /etc/promtail/docker-config.yaml
7+
8+
# Expose 40000 for delve
9+
EXPOSE 40000
10+
11+
# Allow delve to run on Alpine based containers.
12+
RUN apk add --no-cache libc6-compat
13+
14+
# Run delve, ending with -- because we pass params via kubernetes, per the docs:
15+
# Pass flags to the program you are debugging using --, for example:`
16+
# dlv exec ./hello -- server --config conf/config.toml`
17+
ENTRYPOINT ["/usr/bin/dlv", "--listen=:40000", "--headless=true", "--api-version=2", "exec", "/usr/bin/promtail-debug", "--"]

debug/README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
## Debug images
2+
3+
To build debug images run
4+
5+
```shell
6+
make debug
7+
```
8+
9+
You can use the `docker-compose.yaml` in this directory to launch the debug versions of the image in docker
10+
11+
12+
## Promtail in kubernetes
13+
14+
If you want to debug promtail in kubernetes, I have done so with the ksonnet setup:
15+
16+
```shell
17+
ks init promtail
18+
cd promtail
19+
ks env add promtail
20+
jb init
21+
jb install github.com/grafana/loki/production/ksonnet/promtail
22+
vi environments/promtail/main.jsonnet
23+
```
24+
25+
Replace the contents with:
26+
27+
```jsonnet
28+
local promtail = import 'promtail/promtail.libsonnet';
29+
30+
31+
promtail + {
32+
_images+:: {
33+
promtail: 'grafana/promtail-debug:latest',
34+
},
35+
_config+:: {
36+
namespace: 'default',
37+
38+
promtail_config+: {
39+
external_labels+: {
40+
cluster: 'some_cluster_name',
41+
},
42+
scheme: 'https',
43+
hostname: 'hostname',
44+
username: 'username',
45+
password: 'password',
46+
},
47+
},
48+
}
49+
```
50+
51+
change the `some_cluster_name` to anything meaningful to help find your logs in loki
52+
53+
also update the `hostname`, `username`, and `password` for your loki instance.
54+
55+
## Loki in kubernetes
56+
57+
Haven't tried this yet, it works from docker-compose so it should run in kubernetes just fine also.

debug/docker-compose.yaml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
version: "3"
2+
3+
networks:
4+
loki:
5+
6+
services:
7+
loki:
8+
# this is required according to https://github.com/Microsoft/vscode-go/wiki/Debugging-Go-code-using-VS-Code#linuxdocker
9+
security_opt:
10+
- seccomp:unconfined
11+
image: grafana/loki-debug:latest
12+
ports:
13+
- "40000:40000"
14+
- "3100:3100"
15+
command: -config.file=/etc/loki/local-config.yaml
16+
networks:
17+
- loki
18+
19+
promtail:
20+
# this is required according to https://github.com/Microsoft/vscode-go/wiki/Debugging-Go-code-using-VS-Code#linuxdocker
21+
security_opt:
22+
- seccomp:unconfined
23+
image: grafana/promtail-debug:latest
24+
ports:
25+
- "40100:40000"
26+
volumes:
27+
- /var/log:/var/log
28+
command: -config.file=/etc/promtail/docker-config.yaml
29+
networks:
30+
- loki
31+
32+
grafana:
33+
image: grafana/grafana:master
34+
ports:
35+
- "3000:3000"
36+
networks:
37+
- loki

loki-build-image/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ RUN go get \
1515
github.com/golang/protobuf/protoc-gen-go \
1616
github.com/gogo/protobuf/protoc-gen-gogoslick \
1717
github.com/gogo/protobuf/gogoproto \
18+
github.com/go-delve/delve/cmd/dlv \
1819
golang.org/x/tools/cmd/goyacc && \
1920
rm -rf /go/pkg /go/src
2021
ENV GOMETALINTER_VER="2.0.11"

0 commit comments

Comments
 (0)