Unverified Commit 56fb3de0 authored by Nick Ethier's avatar Nick Ethier Committed by GitHub
Browse files

executor: run exec commands in netns if set (#6405)

executor: run exec commands in netns if set
Showing with 30 additions and 28 deletions
+30 -28
......@@ -309,7 +309,7 @@ func (e *UniversalExecutor) Launch(command *ExecCommand) (*ProcessState, error)
e.childCmd.Env = e.commandCfg.Env
// Start the process
if err = e.start(command); err != nil {
if err = withNetworkIsolation(e.childCmd.Start, command.NetworkIsolation); err != nil {
return nil, fmt.Errorf("failed to start command path=%q --- args=%q: %v", path, e.childCmd.Args, err)
}
......@@ -322,13 +322,14 @@ func (e *UniversalExecutor) Launch(command *ExecCommand) (*ProcessState, error)
func (e *UniversalExecutor) Exec(deadline time.Time, name string, args []string) ([]byte, int, error) {
ctx, cancel := context.WithDeadline(context.Background(), deadline)
defer cancel()
return ExecScript(ctx, e.childCmd.Dir, e.commandCfg.Env, e.childCmd.SysProcAttr, name, args)
return ExecScript(ctx, e.childCmd.Dir, e.commandCfg.Env, e.childCmd.SysProcAttr, e.commandCfg.NetworkIsolation, name, args)
}
// ExecScript executes cmd with args and returns the output, exit code, and
// error. Output is truncated to drivers/shared/structs.CheckBufSize
func ExecScript(ctx context.Context, dir string, env []string, attrs *syscall.SysProcAttr,
name string, args []string) ([]byte, int, error) {
netSpec *drivers.NetworkIsolationSpec, name string, args []string) ([]byte, int, error) {
cmd := exec.CommandContext(ctx, name, args...)
// Copy runtime environment from the main command
......@@ -341,7 +342,7 @@ func ExecScript(ctx context.Context, dir string, env []string, attrs *syscall.Sy
cmd.Stdout = buf
cmd.Stderr = buf
if err := cmd.Run(); err != nil {
if err := withNetworkIsolation(cmd.Run, netSpec); err != nil {
exitErr, ok := err.(*exec.ExitError)
if !ok {
// Non-exit error, return it and let the caller treat
......@@ -399,7 +400,9 @@ func (e *UniversalExecutor) ExecStreaming(ctx context.Context, command []string,
cmd.Stderr = stderr
return nil
},
processStart: cmd.Start,
processStart: func() error {
return withNetworkIsolation(cmd.Start, e.commandCfg.NetworkIsolation)
},
processWait: func() (*os.ProcessState, error) {
err := cmd.Wait()
return cmd.ProcessState, err
......
......@@ -4,6 +4,7 @@ package executor
import (
hclog "github.com/hashicorp/go-hclog"
"github.com/hashicorp/nomad/plugins/drivers"
)
func NewExecutorWithIsolation(logger hclog.Logger) Executor {
......@@ -23,3 +24,7 @@ func (e *UniversalExecutor) getAllPids() (map[int]*nomadPid, error) {
func (e *UniversalExecutor) start(command *ExecCommand) error {
return e.childCmd.Start()
}
func withNetworkIsolation(f func() error, _ *drivers.NetworkIsolationSpec) error {
return f()
}
......@@ -15,7 +15,6 @@ import (
"time"
"github.com/armon/circbuf"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/hashicorp/consul-template/signals"
hclog "github.com/hashicorp/go-hclog"
multierror "github.com/hashicorp/go-multierror"
......@@ -184,23 +183,9 @@ func (l *LibcontainerExecutor) Launch(command *ExecCommand) (*ProcessState, erro
l.systemCpuStats = stats.NewCpuStats()
// Starts the task
if command.NetworkIsolation != nil && command.NetworkIsolation.Path != "" {
netns, err := ns.GetNS(command.NetworkIsolation.Path)
if err != nil {
return nil, fmt.Errorf("failed to get ns %s: %v", command.NetworkIsolation.Path, err)
}
// Start the container in the network namespace
err = netns.Do(func(ns.NetNS) error { return container.Run(process) })
if err != nil {
container.Destroy()
return nil, err
}
} else {
if err := container.Run(process); err != nil {
container.Destroy()
return nil, err
}
if err := container.Run(process); err != nil {
container.Destroy()
return nil, err
}
pid, err := process.Pid()
......@@ -622,6 +607,13 @@ func configureIsolation(cfg *lconfigs.Config, command *ExecCommand) error {
{Type: lconfigs.NEWNS},
}
if command.NetworkIsolation != nil {
cfg.Namespaces = append(cfg.Namespaces, lconfigs.Namespace{
Type: lconfigs.NEWNET,
Path: command.NetworkIsolation.Path,
})
}
// paths to mask using a bind mount to /dev/null to prevent reading
cfg.MaskPaths = []string{
"/proc/kcore",
......
......@@ -10,6 +10,7 @@ import (
"github.com/containernetworking/plugins/pkg/ns"
multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/nomad/helper"
"github.com/hashicorp/nomad/plugins/drivers"
"github.com/opencontainers/runc/libcontainer/cgroups"
cgroupFs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
lconfigs "github.com/opencontainers/runc/libcontainer/configs"
......@@ -173,19 +174,20 @@ func DestroyCgroup(groups *lconfigs.Cgroup, executorPid int) error {
return mErrs.ErrorOrNil()
}
func (e *UniversalExecutor) start(command *ExecCommand) error {
if command.NetworkIsolation != nil && command.NetworkIsolation.Path != "" {
// withNetworkIsolation calls the passed function the network namespace `spec`
func withNetworkIsolation(f func() error, spec *drivers.NetworkIsolationSpec) error {
if spec != nil && spec.Path != "" {
// Get a handle to the target network namespace
netns, err := ns.GetNS(command.NetworkIsolation.Path)
netns, err := ns.GetNS(spec.Path)
if err != nil {
return err
}
// Start the container in the network namespace
return netns.Do(func(ns.NetNS) error {
return e.childCmd.Start()
return f()
})
}
return e.childCmd.Start()
return f()
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment