Skip to content

Commit d16f999

Browse files
authored
Merge pull request #1 from sapcc/container-id
use container ID instead of pod UID when getting info from docker
2 parents 9a04977 + 4a9f6d7 commit d16f999

File tree

7 files changed

+75
-76
lines changed

7 files changed

+75
-76
lines changed

.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
vendor/

.travis.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
sudo: required
2-
language: go
32
services:
43
- docker
54
install: true
65

7-
script: make container test vet
6+
script: make container

Dockerfile

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
1+
FROM golang:1.11
2+
3+
WORKDIR /go/src/github.com/sapcc/kuberntes-oomkill-exporter
4+
ENV GO111MODULE=on \
5+
CGOENABLED=0
6+
ADD go.mod go.sum ./
7+
RUN go mod download
8+
ADD cache/main.go .
9+
RUN go build -v -o /dev/null
10+
ADD . .
11+
RUN go build -v -o /kubernetes-oomkill-exporter
12+
RUN go test -v
13+
RUN go vet
14+
115
FROM alpine:3.8
216
LABEL maintainer="jan.knipper@sap.com"
317

418
RUN apk --no-cache add ca-certificates
5-
COPY kubernetes-oomkill-exporter /kubernetes-oomkill-exporter
19+
COPY --from=0 /kubernetes-oomkill-exporter /kubernetes-oomkill-exporter
620

721
ENTRYPOINT ["/kubernetes-oomkill-exporter"]
822
CMD ["-logtostderr"]

Makefile

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,19 @@
11
TARGET = kubernetes-oomkill-exporter
22
GOTARGET = github.com/sapcc/$(TARGET)
3-
BUILDMNT = /go/src/$(GOTARGET)
43
REGISTRY ?= sapcc
5-
VERSION ?= 0.2.0
4+
VERSION ?= 0.3.0
65
IMAGE = $(REGISTRY)/$(BIN)
7-
BUILD_IMAGE ?= golang:1.11-alpine3.8
86
DOCKER ?= docker
9-
DIR := ${CURDIR}
10-
11-
ifneq ($(VERBOSE),)
12-
VERBOSE_FLAG = -v
13-
endif
14-
TESTARGS ?= $(VERBOSE_FLAG) -timeout 60s
15-
TEST_PKGS ?= $(GOTARGET)/...
16-
TEST = CGO_ENABLED=0 go test $(TEST_PKGS) $(TESTARGS)
17-
VET_PKGS ?= $(GOTARGET)/...
18-
VET = CGO_ENABLED=0 go vet $(VET_PKGS)
19-
20-
DOCKER_BUILD ?= $(DOCKER) run --rm -v $(DIR):$(BUILDMNT) -w $(BUILDMNT) $(BUILD_IMAGE) /bin/sh -c
217

228
all: container
239

2410
container:
25-
$(DOCKER_BUILD) 'go build'
2611
$(DOCKER) build -t $(REGISTRY)/$(TARGET):latest -t $(REGISTRY)/$(TARGET):$(VERSION) .
2712

2813
push:
2914
$(DOCKER) push $(REGISTRY)/$(TARGET):latest
3015
$(DOCKER) push $(REGISTRY)/$(TARGET):$(VERSION)
3116

32-
test:
33-
$(DOCKER_BUILD) '$(TEST)'
34-
35-
vet:
36-
$(DOCKER_BUILD) '$(VET)'
37-
3817
.PHONY: all local container push
3918

4019
clean:

cache/main.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//This file is only used to speedup the docker build
2+
//We use this to download and compile the go module dependencies before adding our own source code.
3+
//See Dockerfile for more details
4+
5+
package main
6+
7+
import (
8+
_ "flag"
9+
_ "net/http"
10+
_ "regexp"
11+
_ "strings"
12+
13+
_ "docker.io/go-docker"
14+
_ "docker.io/go-docker/api/types"
15+
_ "github.com/golang/glog"
16+
_ "github.com/prometheus/client_golang/prometheus"
17+
_ "github.com/prometheus/client_golang/prometheus/promhttp"
18+
_ "golang.org/x/net/context"
19+
_ "k8s.io/node-problem-detector/pkg/systemlogmonitor/logwatchers/kmsg"
20+
_ "k8s.io/node-problem-detector/pkg/systemlogmonitor/logwatchers/types"
21+
)
22+
23+
func main() {
24+
25+
}

main.go

Lines changed: 17 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@ package main
22

33
import (
44
"flag"
5-
"fmt"
65
"net/http"
76
"regexp"
87
"strings"
98

109
docker_client "docker.io/go-docker"
1110
docker_types "docker.io/go-docker/api/types"
12-
docker_filters "docker.io/go-docker/api/types/filters"
1311
"github.com/golang/glog"
1412
"github.com/prometheus/client_golang/prometheus"
1513
"github.com/prometheus/client_golang/prometheus/promhttp"
@@ -18,10 +16,8 @@ import (
1816
"k8s.io/node-problem-detector/pkg/systemlogmonitor/logwatchers/types"
1917
)
2018

21-
const (
22-
OOMMatchExpression = ".*killed as a result of limit of.*"
23-
PodExtractExpression = "^.+/pod(\\w+\\-\\w+\\-\\w+\\-\\w+\\-\\w+)/.+$"
24-
PodUIDLabel = "io.kubernetes.pod.uid"
19+
var (
20+
kmesgRE = regexp.MustCompile("/pod(\\w+\\-\\w+\\-\\w+\\-\\w+\\-\\w+)/([a-f0-9]+) killed as a result of limit of /kubepods")
2521
)
2622

2723
var (
@@ -74,66 +70,43 @@ func main() {
7470
}
7571

7672
for log := range logCh {
77-
podUID := getPodUIDFromLog(log.Message)
78-
if podUID != "" {
79-
container, err := getContainerFromPod(podUID, dockerClient)
80-
73+
podUID, containerID := getContainerIDFromLog(log.Message)
74+
if containerID != "" {
75+
container, err := getContainer(containerID, dockerClient)
8176
if err != nil {
82-
glog.Warningf("Could not get container for pod UID %s: %v", podUID, err)
77+
glog.Warningf("Could not get container %s for pod %s: %v", containerID, podUID, err)
8378
} else {
84-
prometheusCount(container)
79+
prometheusCount(container.Config.Labels)
8580
}
8681
}
8782
}
8883
}
8984

90-
func getPodUIDFromLog(log string) string {
91-
match, err := regexp.MatchString(OOMMatchExpression, log)
92-
if err != nil {
93-
return ""
94-
}
95-
96-
var ret []string
97-
if match {
98-
re := regexp.MustCompile(PodExtractExpression)
99-
ret = re.FindStringSubmatch(log)
100-
if len(ret) == 2 {
101-
return ret[1]
102-
}
85+
func getContainerIDFromLog(log string) (string, string) {
86+
if matches := kmesgRE.FindStringSubmatch(log); matches != nil {
87+
return matches[1], matches[2]
10388
}
10489

105-
return ""
90+
return "", ""
10691
}
10792

108-
func getContainerFromPod(podUID string, cli *docker_client.Client) (docker_types.Container, error) {
109-
filters := docker_filters.NewArgs()
110-
filters.Add("label", fmt.Sprintf("%s=%s", PodUIDLabel, podUID))
111-
filters.Add("label", fmt.Sprintf("%s=%s", "io.kubernetes.docker.type", "container"))
112-
113-
listOpts := docker_types.ContainerListOptions{
114-
Filters: filters,
115-
}
116-
117-
containers, err := cli.ContainerList(context.Background(), listOpts)
93+
func getContainer(containerID string, cli *docker_client.Client) (docker_types.ContainerJSON, error) {
94+
container, err := cli.ContainerInspect(context.Background(), containerID)
11895
if err != nil {
119-
return docker_types.Container{}, err
120-
}
121-
122-
if len(containers) < 1 {
123-
return docker_types.Container{}, fmt.Errorf("There should be at least one container with UID %s", podUID)
96+
return docker_types.ContainerJSON{}, err
12497
}
98+
return container, nil
12599

126-
return containers[0], nil
127100
}
128101

129-
func prometheusCount(container docker_types.Container) {
102+
func prometheusCount(containerLabels map[string]string) {
130103
var counter prometheus.Counter
131104
var err error
132105

133106
var labels map[string]string
134107
labels = make(map[string]string)
135108
for key, label := range prometheusContainerLabels {
136-
labels[label] = container.Labels[key]
109+
labels[label] = containerLabels[key]
137110
}
138111

139112
glog.V(5).Infof("Labels: %v\n", labels)

main_test.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package main
22

33
import (
44
"fmt"
5-
"reflect"
65
"strings"
76
"testing"
87

@@ -11,17 +10,22 @@ import (
1110
)
1211

1312
func TestGetPodUIDFromLog(t *testing.T) {
14-
klog, podUIDs := getTestData()
15-
var extractedUIDs []string
13+
klog, podUIDs, containerIDs := getTestData()
14+
15+
var extractedContainerIDs []string
16+
var extractedPodUIDs []string
1617

1718
for _, msg := range klog {
1819
parsedMsg, err := parseMessage(msg)
1920
require.NoError(t, err, "There should be no error while parsing kernel log")
20-
uid := getPodUIDFromLog(parsedMsg.Message)
21-
extractedUIDs = append(extractedUIDs, uid)
21+
uid, cid := getContainerIDFromLog(parsedMsg.Message)
22+
fmt.Println(uid)
23+
extractedContainerIDs = append(extractedContainerIDs, cid)
24+
extractedPodUIDs = append(extractedPodUIDs, uid)
2225
}
2326

24-
require.True(t, reflect.DeepEqual(podUIDs, extractedUIDs), "Extracted UIDs do not match the expected result")
27+
require.Equal(t, containerIDs, extractedContainerIDs, "Extracted container ids do not match the expected result")
28+
require.Equal(t, podUIDs, extractedPodUIDs, "Extracted container ids do not match the expected result")
2529
}
2630

2731
func parseMessage(input string) (kmsgparser.Message, error) {
@@ -44,13 +48,17 @@ func parseMessage(input string) (kmsgparser.Message, error) {
4448
}, nil
4549
}
4650

47-
func getTestData() ([]string, []string) {
51+
func getTestData() ([]string, []string, []string) {
4852
return []string{
4953
"6,22743,6115623303887,-;Task in /kubepods/burstable/pode501ca8a-ec23-11e8-b17a-0a586444015a/f24766bce80e0ce4f0ca2887da2be9d0d250448d7ef503d9f85bf5e549c757d5 killed as a result of limit of /kubepods/burstable/pode501ca8a-ec23-11e8-b17a-0a586444015a",
5054
"6,23800,6780904484233,-;Task in /kubepods/burstable/pod0c4e2576-ef09-11e8-b17a-0a586444015a/9df959ad4292532c5d551226063bd840b906cbf118983fffefa0e3ab90331dc2 killed as a result of limit of /kubepods/burstable/pod0c4e2576-ef09-11e8-b17a-0a586444015a/9df959ad4292532c5d551226063bd840b906cbf118983fffefa0e3ab90331dc2",
5155
},
5256
[]string{
5357
"e501ca8a-ec23-11e8-b17a-0a586444015a",
5458
"0c4e2576-ef09-11e8-b17a-0a586444015a",
59+
},
60+
[]string{
61+
"f24766bce80e0ce4f0ca2887da2be9d0d250448d7ef503d9f85bf5e549c757d5",
62+
"9df959ad4292532c5d551226063bd840b906cbf118983fffefa0e3ab90331dc2",
5563
}
5664
}

0 commit comments

Comments
 (0)