-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mount task_local and alloc dir to docker containers #290
Changes from 4 commits
db88c38
5bf2ad0
f66abc0
87ae6c6
70f4fc5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,12 +4,15 @@ import ( | |
"encoding/json" | ||
"fmt" | ||
"log" | ||
"path/filepath" | ||
"strconv" | ||
"strings" | ||
|
||
docker "github.com/fsouza/go-dockerclient" | ||
|
||
"github.com/hashicorp/nomad/client/allocdir" | ||
"github.com/hashicorp/nomad/client/config" | ||
"github.com/hashicorp/nomad/client/driver/args" | ||
"github.com/hashicorp/nomad/nomad/structs" | ||
) | ||
|
||
|
@@ -97,12 +100,33 @@ func (d *DockerDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool | |
return true, nil | ||
} | ||
|
||
// We have to call this when we create the container AND when we start it so | ||
// we'll make a function. | ||
func createHostConfig(task *structs.Task) *docker.HostConfig { | ||
// hostConfig holds options for the docker container that are unique to this | ||
// machine, such as resource limits and port mappings | ||
return &docker.HostConfig{ | ||
func containerBinds(alloc *allocdir.AllocDir, task *structs.Task) ([]string, error) { | ||
shared := alloc.SharedDir | ||
local, ok := alloc.TaskDirs[task.Name] | ||
if !ok { | ||
return nil, fmt.Errorf("Failed to find task local directory: %v", task.Name) | ||
} | ||
|
||
return []string{ | ||
fmt.Sprintf("%s:%s", shared, allocdir.SharedAllocName), | ||
fmt.Sprintf("%s:%s", local, allocdir.TaskLocal), | ||
}, nil | ||
} | ||
|
||
// createContainer initializes a struct needed to call docker.client.CreateContainer() | ||
func createContainer(ctx *ExecContext, task *structs.Task, logger *log.Logger) (docker.CreateContainerOptions, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly, would this ever be shared? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I can update these. Just an artifact of how it was written. |
||
var c docker.CreateContainerOptions | ||
if task.Resources == nil { | ||
logger.Printf("[ERR] driver.docker: task.Resources is empty") | ||
return c, fmt.Errorf("task.Resources is nil and we can't constrain resource usage. We shouldn't have been able to schedule this in the first place.") | ||
} | ||
|
||
binds, err := containerBinds(ctx.AllocDir, task) | ||
if err != nil { | ||
return c, err | ||
} | ||
|
||
hostConfig := &docker.HostConfig{ | ||
// Convert MB to bytes. This is an absolute value. | ||
// | ||
// This value represents the total amount of memory a process can use. | ||
|
@@ -131,20 +155,16 @@ func createHostConfig(task *structs.Task) *docker.HostConfig { | |
// - https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt | ||
// - https://www.kernel.org/doc/Documentation/scheduler/sched-design-CFS.txt | ||
CPUShares: int64(task.Resources.CPU), | ||
} | ||
} | ||
|
||
// createContainer initializes a struct needed to call docker.client.CreateContainer() | ||
func createContainer(ctx *ExecContext, task *structs.Task, logger *log.Logger) (docker.CreateContainerOptions, error) { | ||
var c docker.CreateContainerOptions | ||
if task.Resources == nil { | ||
logger.Printf("[ERR] driver.docker: task.Resources is empty") | ||
return c, fmt.Errorf("task.Resources is nil and we can't constrain resource usage. We shouldn't have been able to schedule this in the first place.") | ||
// Binds are used to mount a host volume into the container. We mount a | ||
// local directory for storage and a shared alloc directory that can be | ||
// used to share data between different tasks in the same task group. | ||
Binds: binds, | ||
} | ||
|
||
hostConfig := createHostConfig(task) | ||
logger.Printf("[DEBUG] driver.docker: using %d bytes memory for %s", hostConfig.Memory, task.Config["image"]) | ||
logger.Printf("[DEBUG] driver.docker: using %d cpu shares for %s", hostConfig.CPUShares, task.Config["image"]) | ||
logger.Printf("[DEBUG] driver.docker: binding directories %#v for %s", hostConfig.Binds, task.Config["image"]) | ||
|
||
mode, ok := task.Config["network_mode"] | ||
if !ok || mode == "" { | ||
|
@@ -198,14 +218,31 @@ func createContainer(ctx *ExecContext, task *structs.Task, logger *log.Logger) ( | |
hostConfig.PortBindings = dockerPorts | ||
} | ||
|
||
// Create environment variables. | ||
env := TaskEnvironmentVariables(ctx, task) | ||
env.SetAllocDir(filepath.Join("/", allocdir.SharedAllocName)) | ||
env.SetTaskLocalDir(filepath.Join("/", allocdir.TaskLocal)) | ||
|
||
config := &docker.Config{ | ||
Env: TaskEnvironmentVariables(ctx, task).List(), | ||
Env: env.List(), | ||
Image: task.Config["image"], | ||
} | ||
|
||
rawArgs, hasArgs := task.Config["args"] | ||
parsedArgs, err := args.ParseAndReplace(rawArgs, env.Map()) | ||
if err != nil { | ||
return c, err | ||
} | ||
|
||
// If the user specified a custom command to run, we'll inject it here. | ||
if command, ok := task.Config["command"]; ok { | ||
config.Cmd = strings.Split(command, " ") | ||
cmd := []string{command} | ||
if hasArgs { | ||
cmd = append(cmd, parsedArgs...) | ||
} | ||
config.Cmd = cmd | ||
} else if hasArgs { | ||
logger.Println("[DEBUG] driver.docker: ignoring args because command not specified") | ||
} | ||
|
||
return docker.CreateContainerOptions{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,6 +44,7 @@ gox \ | |
-arch="${XC_ARCH}" \ | ||
-osarch="!linux/arm !darwin/386" \ | ||
-ldflags "-X main.GitCommit ${GIT_COMMIT}${GIT_DIRTY}" \ | ||
-cgo \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought we specifically were avoiding cgo? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It can't be. user.Lookup which is part of the stdlib uses cgo. |
||
-output "pkg/{{.OS}}_{{.Arch}}/nomad" \ | ||
. | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason this isn't a method of the Docker Driver? It seems unlikely to be shared