debugging

Signed-off-by: Jess Frazelle <jess@mesosphere.com>
This commit is contained in:
Jess Frazelle 2016-04-16 16:05:09 -07:00
parent 0ae930df26
commit b92f1bdae4
8 changed files with 51 additions and 14 deletions

View file

@ -49,7 +49,7 @@ image.tar:
docker export $(shell docker create $(DOCKER_ROOTFS_IMAGE) sh) > $@ docker export $(shell docker create $(DOCKER_ROOTFS_IMAGE) sh) > $@
rootfs.go: image.tar rootfs.go: image.tar
go generate GOMAXPROCS=1 go generate
fmt: fmt:
@echo "+ $@" @echo "+ $@"
@ -76,6 +76,7 @@ clean: clean-rootfs
@$(RM) *.tar @$(RM) *.tar
@$(RM) rootfs.go @$(RM) rootfs.go
@$(RM) -r $(BINDIR) @$(RM) -r $(BINDIR)
-@docker rm $(shell docker ps -aq) /dev/null 2>&1
install: install:
@echo "+ $@" @echo "+ $@"

View file

@ -8,13 +8,19 @@ This is based off a crazy idea from [@crosbymichael](https://github.com/crosbymi
**NOTE** **NOTE**
You may have noticed you can't file an issue. That's because this is using a crazy You may have noticed you can't file an issue. That's because this is using a crazy
person's (aka my) fork of libcontainer person's (aka my) fork of libcontainer and until I get the patches into upstream
and until I get the patches into upstream there's no there's no way in hell I'm fielding issues from whoever is crazy enough to try this.
way in hell I'm fielding issues from whoever is crazy
enough to try this.
### Building ### Building
This uses the new Golang vendoring so you need go 1.6 or
`GO15VENDOREXPERIMENT=1` in your env.
You will also need `libapparmor-dev` and `libseccomp-dev`.
Most importantly you need userns in your kernel (`CONFIG_USER_NS=y`)
or else this won't even work.
```console ```console
$ make static $ make static
Static container created at: ./bin/alpine Static container created at: ./bin/alpine
@ -97,12 +103,18 @@ $ ./bin/alpine -h
## Cool things ## Cool things
The binary spawned does NOT need to oversee the container process if you The binary spawned does NOT need to oversee the container process if you
run in detached mode with a PID file. You can have it watched by the user mode run in detached mode with a PID file. You can have it watched by the user mode
systemd so that this binary is really just the launcher :) systemd so that this binary is really just the launcher :)
## Example
Nginx running with my user "jessie".
![nginx.png](nginx.png)
## Caveats ## Caveats
**Caps the binary needs to unpack and set **Caps the binary needs to unpack and set
the right perms on the roofs for the userns user** the right perms on the roofs for the userns user**
- **CAP_CHOWN**: chown the rootfs to the userns user - **CAP_CHOWN**: chown the rootfs to the userns user

13
main.go
View file

@ -12,6 +12,7 @@ import (
aaprofile "github.com/docker/docker/profiles/apparmor" aaprofile "github.com/docker/docker/profiles/apparmor"
"github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runc/libcontainer"
"github.com/opencontainers/runc/libcontainer/apparmor" "github.com/opencontainers/runc/libcontainer/apparmor"
"github.com/opencontainers/runc/libcontainer/user"
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
) )
@ -180,13 +181,21 @@ func main() {
// install the default apparmor profile // install the default apparmor profile
if apparmor.IsEnabled() { if apparmor.IsEnabled() {
if err := aaprofile.InstallDefault(defaultApparmorProfile); err != nil { // check if we have the docker-default apparmor profile loaded
logrus.Warnf("AppArmor is enabled on the the system, but the profile (%s) could not be loaded", defaultApparmorProfile) if err := aaprofile.IsLoaded(defaultApparmorProfile); err != nil {
logrus.Warnf("AppArmor enabled on system but the %s profile is not loaded. apparmor_parser needs root to load a profile so we can't do it for you.", defaultApparmorProfile)
} else { } else {
spec.Process.ApparmorProfile = defaultApparmorProfile spec.Process.ApparmorProfile = defaultApparmorProfile
} }
} }
// set the CgroupsPath as this user
user, err := user.CurrentUser()
if err != nil {
logrus.Fatal(err)
}
spec.Linux.CgroupsPath = sPtr(user.Name)
if err := unpackRootfs(spec); err != nil { if err := unpackRootfs(spec); err != nil {
logrus.Fatal(err) logrus.Fatal(err)
} }

BIN
nginx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 MiB

View file

@ -111,11 +111,14 @@ func (m *Manager) Apply(pid int) (err error) {
var c = m.Cgroups var c = m.Cgroups
logrus.Debugf("pre get cgroups data: %#v", c)
d, err := getCgroupData(m.Cgroups, pid) d, err := getCgroupData(m.Cgroups, pid)
if err != nil { if err != nil {
return err return err
} }
logrus.Debugf("cgroups data: %#v, config: %#v", d, d.config)
if c.Paths != nil { if c.Paths != nil {
paths := make(map[string]string) paths := make(map[string]string)
for name, path := range c.Paths { for name, path := range c.Paths {
@ -129,6 +132,7 @@ func (m *Manager) Apply(pid int) (err error) {
paths[name] = path paths[name] = path
} }
m.Paths = paths m.Paths = paths
logrus.Debugf("cgroups apply paths: %#v", m.Paths)
return cgroups.EnterPid(m.Paths, pid) return cgroups.EnterPid(m.Paths, pid)
} }
@ -136,6 +140,7 @@ func (m *Manager) Apply(pid int) (err error) {
defer m.mu.Unlock() defer m.mu.Unlock()
paths := make(map[string]string) paths := make(map[string]string)
for _, sys := range subsystems { for _, sys := range subsystems {
logrus.Debugf("applying cgroups to subsystem %#v", sys)
if err := sys.Apply(d); err != nil { if err := sys.Apply(d); err != nil {
return err return err
} }
@ -353,23 +358,25 @@ func writeFile(dir, file, data string) error {
if dir == "" { if dir == "" {
return fmt.Errorf("no such directory for %s", file) return fmt.Errorf("no such directory for %s", file)
} }
// get the current user // get the current user
u, err := user.CurrentUser() u, err := user.CurrentUser()
if err != nil { if err != nil {
return err return err
} }
if err := os.Chown(dir, u.Uid, u.Gid); err != nil { if err := os.Lchown(dir, u.Uid, u.Gid); err != nil {
return fmt.Errorf("failed to chown %s to %d:%d -> %v", dir, u.Uid, u.Gid, err) return fmt.Errorf("failed to chown to %d:%d -> %v", u.Uid, u.Gid, err)
} }
logrus.Debugf("chown dir %s to %d:%d", dir, u.Uid, u.Gid)
if err := os.Chown(filepath.Join(dir, "tasks"), u.Uid, u.Gid); err != nil { if err := os.Lchown(filepath.Join(dir, file), u.Uid, u.Gid); err != nil {
return fmt.Errorf("failed to chown %s/tasks to %d:%d -> %v", dir, u.Uid, u.Gid, err) return fmt.Errorf("failed to chown to %d:%d -> %v", u.Uid, u.Gid, err)
} }
logrus.Debugf("chown %s to %d:%d", filepath.Join(dir, file), u.Uid, u.Gid)
if err := ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700); err != nil { if err := ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700); err != nil {
logrus.Debugf("failed to write %v to %v: %v", data, file, err) logrus.Debugf("failed to write %v to %v: %v", data, file, err)
//return err
} }
return nil return nil
} }

View file

@ -10,6 +10,7 @@ import (
"path/filepath" "path/filepath"
"strconv" "strconv"
"github.com/Sirupsen/logrus"
"github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/configs"
libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils" libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils"
@ -27,6 +28,7 @@ func (s *CpusetGroup) Apply(d *cgroupData) error {
if err != nil && !cgroups.IsNotFound(err) { if err != nil && !cgroups.IsNotFound(err) {
return err return err
} }
logrus.Debugf("apply cpuset dir is %s", dir)
return s.ApplyDir(dir, d.config, d.pid) return s.ApplyDir(dir, d.config, d.pid)
} }

View file

@ -171,6 +171,7 @@ func (c *linuxContainer) Set(config configs.Config) error {
c.m.Lock() c.m.Lock()
defer c.m.Unlock() defer c.m.Unlock()
c.config = &config c.config = &config
logrus.Debugf("setting cgroups")
return c.cgroupManager.Set(c.config) return c.cgroupManager.Set(c.config)
} }
@ -741,6 +742,7 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
} }
func (c *linuxContainer) criuApplyCgroups(pid int, req *criurpc.CriuReq) error { func (c *linuxContainer) criuApplyCgroups(pid int, req *criurpc.CriuReq) error {
logrus.Debugf("criu apply cgroups")
if err := c.cgroupManager.Apply(pid); err != nil { if err := c.cgroupManager.Apply(pid); err != nil {
return err return err
} }

View file

@ -13,6 +13,7 @@ import (
"strconv" "strconv"
"syscall" "syscall"
"github.com/Sirupsen/logrus"
"github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/system" "github.com/opencontainers/runc/libcontainer/system"
@ -247,6 +248,9 @@ func (p *initProcess) start() error {
return newSystemError(err) return newSystemError(err)
} }
p.setExternalDescriptors(fds) p.setExternalDescriptors(fds)
logrus.Debugf("starting process apply cgroups")
// Do this before syncing with child so that no children // Do this before syncing with child so that no children
// can escape the cgroup // can escape the cgroup
if err := p.manager.Apply(p.pid()); err != nil { if err := p.manager.Apply(p.pid()); err != nil {