-
-
Save proppy/9597b6ecd1dc39ca6613 to your computer and use it in GitHub Desktop.
This file contains 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 characters
package main | |
import ( | |
"encoding/json" | |
"fmt" | |
"log" | |
"os" | |
"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() | |
log.Println("done") | |
} | |
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 | |
} | |
pod := &Pod{ | |
spec: spec, | |
factory: factory, | |
} | |
for _, c := range spec.Spec.Containers { | |
log.Printf("container: #%v", c) | |
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, 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. | |
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 { | |
log.Printf("%#v", cp.process) | |
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() { | |
log.Println(p.containers) | |
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.Sys().(syscall.WaitStatus))) | |
} | |
} | |
func getTemplate() *configs.Config { | |
const defaultMountFlags = syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV | |
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{ | |
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, | |
}, | |
}, | |
} | |
} |
This file contains 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 characters
{ | |
"spec": { | |
"containers": [{ | |
"name": "foo", | |
"image": "/images/busybox", | |
"command": ["/bin/echo"], | |
"args": ["foo"] | |
},{ | |
"name": "bar", | |
"image": "/images/busybox", | |
"command": ["/bin/echo"], | |
"args": ["bar"] | |
}] | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment