From e5a790753dee985d76bbea58686c689ceb47472e Mon Sep 17 00:00:00 2001 From: Jonathan Ballet Date: Fri, 27 Oct 2017 17:45:06 +0200 Subject: [PATCH 1/2] docker: log that a container has been killed by the OOM killer Fix: #2203 (at least for Docker tasks) --- client/driver/docker.go | 7 +++++ client/driver/docker_test.go | 50 ++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/client/driver/docker.go b/client/driver/docker.go index 9bc8554ba536..1597a36b6aec 100644 --- a/client/driver/docker.go +++ b/client/driver/docker.go @@ -1609,6 +1609,13 @@ func (h *DockerHandle) run() { werr = fmt.Errorf("Docker container exited with non-zero exit code: %d", exitCode) } + container, ierr := h.waitClient.InspectContainer(h.containerID) + if ierr != nil { + h.logger.Printf("[ERR] driver.docker: failed to inspect container %s: %v", h.containerID, ierr) + } else if container.State.OOMKilled { + werr = fmt.Errorf("Docker container killed by OOM killer") + } + close(h.doneCh) // Shutdown the syslog collector diff --git a/client/driver/docker_test.go b/client/driver/docker_test.go index 1f2e63223dcf..65a4246e75d3 100644 --- a/client/driver/docker_test.go +++ b/client/driver/docker_test.go @@ -1753,3 +1753,53 @@ func TestDockerDriver_AuthConfiguration(t *testing.T) { } } } + +func TestDockerDriver_OOMKilled(t *testing.T) { + if !tu.IsTravis() { + t.Parallel() + } + if !testutil.DockerIsConnected(t) { + t.Skip("Docker not connected") + } + + task := &structs.Task{ + Name: "oom-killed", + Driver: "docker", + Config: map[string]interface{}{ + "image": "busybox", + "load": "busybox.tar", + "command": "sh", + // Incrementally creates a bigger and bigger variable. + "args": []string{"-c", "x=a; while true; do eval x='$x$x'; done"}, + }, + LogConfig: &structs.LogConfig{ + MaxFiles: 10, + MaxFileSizeMB: 10, + }, + Resources: &structs.Resources{ + CPU: 250, + MemoryMB: 10, + DiskMB: 20, + Networks: []*structs.NetworkResource{}, + }, + } + + _, handle, cleanup := dockerSetup(t, task) + defer cleanup() + + select { + case res := <-handle.WaitCh(): + if res.Successful() { + t.Fatalf("expected error, but container exited successfull") + } + + if !strings.Contains(res.Err.Error(), "killed by OOM killer") { + t.Fatalf("not killed by OOM killer: %s", res.Err) + } + + t.Logf("Successfully killed by OOM killer") + + case <-time.After(time.Duration(tu.TestMultiplier()*5) * time.Second): + t.Fatalf("timeout") + } +} From 15114e448e1048715dcf02c338d34195bf9271db Mon Sep 17 00:00:00 2001 From: Jonathan Ballet Date: Fri, 27 Oct 2017 20:30:52 +0200 Subject: [PATCH 2/2] docker: changed OOM killed error message --- client/driver/docker.go | 2 +- client/driver/docker_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/driver/docker.go b/client/driver/docker.go index 1597a36b6aec..4dc6ae08f62e 100644 --- a/client/driver/docker.go +++ b/client/driver/docker.go @@ -1613,7 +1613,7 @@ func (h *DockerHandle) run() { if ierr != nil { h.logger.Printf("[ERR] driver.docker: failed to inspect container %s: %v", h.containerID, ierr) } else if container.State.OOMKilled { - werr = fmt.Errorf("Docker container killed by OOM killer") + werr = fmt.Errorf("OOM Killed") } close(h.doneCh) diff --git a/client/driver/docker_test.go b/client/driver/docker_test.go index 65a4246e75d3..962c0efdf359 100644 --- a/client/driver/docker_test.go +++ b/client/driver/docker_test.go @@ -1793,7 +1793,7 @@ func TestDockerDriver_OOMKilled(t *testing.T) { t.Fatalf("expected error, but container exited successfull") } - if !strings.Contains(res.Err.Error(), "killed by OOM killer") { + if res.Err.Error() != "OOM Killed" { t.Fatalf("not killed by OOM killer: %s", res.Err) }