Created
May 16, 2015 01:00
Revisions
-
crosbymichael created this gist
May 16, 2015 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,232 @@ package main import ( "encoding/json" "fmt" "log" "os" "path/filepath" "syscall" "github.com/docker/libcontainer" "github.com/docker/libcontainer/cgroups" "github.com/docker/libcontainer/configs" "github.com/docker/libcontainer/utils" ) func main() { var spec PodSpec if err := json.NewDecoder(os.Stdin).Decode(&spec); err != nil { log.Fatal(err) } pod, err := New("/var/run/pods", &spec) if err != nil { log.Fatal(err) } if err := pod.Start(); err != nil { log.Fatal(err) } pod.Wait() } type PodSpec struct { Kind string ApiVersion string `json:"apiVersion"` Metadata struct { Name string } Spec struct { Containers []struct { Name string Image string // path Command []string Args []string Env []struct { Name string Value string } Ports []struct { HostIP string `json:"hostIP"` HostPort string `json:"hostPort"` ContainerPort string `json:"containerPort"` } VolumeMounts []struct { Name string MountPath string `json:"mountPath"` } `json:"volumeMounts"` } Volumes []struct { Name string HostPath struct { Path string } `json:"hostPath"` } } Crap struct { IP string } } func New(root string, spec *PodSpec) (*Pod, error) { factory, err := libcontainer.New(root) if err != nil { return nil, err } var pod Pod for _, c := range spec.Spec.Containers { config := getTemplate() config.Rootfs = c.Image config.Cgroups.Name = c.Name cont, err := factory.Create(c.Name, config) if err != nil { return nil, fmt.Errorf("failed to create container %q: %v", c.Name, err) } var env []string for _, e := range c.Env { env = append(env, e.Name+"="+e.Value) } pod.containers = append(pod.containers, containerProcess{ name: c.Name, process: &libcontainer.Process{ Args: append(c.Command, c.Args...), Env: env, Stdout: os.Stdout, Stderr: os.Stderr, }, container: cont, }) } return &Pod{ spec: spec, factory: factory, }, nil } type containerProcess struct { name string process *libcontainer.Process container libcontainer.Container } type Pod struct { spec *PodSpec factory libcontainer.Factory // namespaces shares all the namespaces except the mount and pid namespace with the pod. cgroups *configs.Cgroup containers []containerProcess } func (p *Pod) Start() error { if err := syscall.Unshare(syscall.CLONE_NEWNET | syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC); err != nil { return fmt.Errorf("failed to unshare namespaces: %v", err) } for _, cp := range p.containers { if err := cp.container.Start(cp.process); err != nil { return fmt.Errorf("failed to start container %q: %v", cp.name, err) } } return nil } func (p *Pod) Wait() { for _, cp := range p.containers { state, err := cp.process.Wait() if err != nil { log.Println(err) continue } log.Printf("container exited with status %d\n", utils.ExitStatus(state)) } } func getTemplate() *configs.Config { cgroupRoot, err := cgroups.GetThisCgroupDir("devices") if err != nil { panic(err) } return &configs.Config{ ParentDeathSignal: int(syscall.SIGKILL), Capabilities: []string{ "CHOWN", "DAC_OVERRIDE", "FSETID", "FOWNER", "MKNOD", "NET_RAW", "SETGID", "SETUID", "SETFCAP", "SETPCAP", "NET_BIND_SERVICE", "SYS_CHROOT", "KILL", "AUDIT_WRITE", }, Namespaces: configs.Namespaces([]configs.Namespace{ {Type: configs.NEWNS}, {Type: configs.NEWPID}, }), Cgroups: &configs.Cgroup{ Name: filepath.Base(cwd), Parent: cgroupRoot, AllowAllDevices: false, AllowedDevices: configs.DefaultAllowedDevices, }, Devices: configs.DefaultAutoCreatedDevices, MaskPaths: []string{ "/proc/kcore", }, ReadonlyPaths: []string{ "/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus", }, Mounts: []*configs.Mount{ { Source: "proc", Destination: "/proc", Device: "proc", Flags: defaultMountFlags, }, { Source: "tmpfs", Destination: "/dev", Device: "tmpfs", Flags: syscall.MS_NOSUID | syscall.MS_STRICTATIME, Data: "mode=755", }, { Source: "devpts", Destination: "/dev/pts", Device: "devpts", Flags: syscall.MS_NOSUID | syscall.MS_NOEXEC, Data: "newinstance,ptmxmode=0666,mode=0620,gid=5", }, { Device: "tmpfs", Source: "shm", Destination: "/dev/shm", Data: "mode=1777,size=65536k", Flags: defaultMountFlags, }, { Source: "mqueue", Destination: "/dev/mqueue", Device: "mqueue", Flags: defaultMountFlags, }, { Source: "sysfs", Destination: "/sys", Device: "sysfs", Flags: defaultMountFlags | syscall.MS_RDONLY, }, }, Rlimits: []configs.Rlimit{ { Type: syscall.RLIMIT_NOFILE, Hard: 1024, Soft: 1024, }, }, } }