Skip to content

Commit

Permalink
implement rootless mode
Browse files Browse the repository at this point in the history
Please refer to docs/rootless.md

Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
  • Loading branch information
AkihiroSuda committed Jan 23, 2018
1 parent ff49ce8 commit 511c7e7
Show file tree
Hide file tree
Showing 37 changed files with 4,321 additions and 10 deletions.
6 changes: 6 additions & 0 deletions cmd/buildkitd/main.go
Expand Up @@ -97,6 +97,12 @@ func main() {
Name: "tlscacert", Name: "tlscacert",
Usage: "ca certificate to verify clients", Usage: "ca certificate to verify clients",
}, },
cli.BoolFlag{
Name: "rootless",
Usage: "execute without root privileges",
// TODO(AkihiroSuda): autodetect rootless mode
// TODO(AkihiroSuda): user-friendly help messages
},
} }


app.Flags = append(app.Flags, appFlags...) app.Flags = append(app.Flags, appFlags...)
Expand Down
3 changes: 3 additions & 0 deletions cmd/buildkitd/main_containerd_worker.go
Expand Up @@ -52,6 +52,9 @@ func containerdWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([
if err != nil { if err != nil {
return nil, err return nil, err
} }
if c.GlobalBool("rootless") {
logrus.Warn("rootless mode is not supported for containerd workers")
}
opt, err := containerd.NewWorkerOpt(common.root, socket, ctd.DefaultSnapshotter, labels) opt, err := containerd.NewWorkerOpt(common.root, socket, ctd.DefaultSnapshotter, labels)
if err != nil { if err != nil {
return nil, err return nil, err
Expand Down
11 changes: 10 additions & 1 deletion cmd/buildkitd/main_oci_worker.go
Expand Up @@ -5,6 +5,7 @@ package main
import ( import (
"os/exec" "os/exec"


"github.com/moby/buildkit/executor/runcexecutor"
"github.com/moby/buildkit/worker" "github.com/moby/buildkit/worker"
"github.com/moby/buildkit/worker/base" "github.com/moby/buildkit/worker/base"
"github.com/moby/buildkit/worker/runc" "github.com/moby/buildkit/worker/runc"
Expand All @@ -27,6 +28,11 @@ func init() {
Name: "oci-worker-labels", Name: "oci-worker-labels",
Usage: "user-specific annotation labels (com.example.foo=bar)", Usage: "user-specific annotation labels (com.example.foo=bar)",
}, },
cli.BoolTFlag{
Name: "oci-worker-overlayfs",
Usage: "enable overlayfs snapshotter", // and differ when implemented
// TODO(AkihiroSuda): autodetect overlayfs availability?
},
) )
// TODO: allow multiple oci runtimes and snapshotters // TODO: allow multiple oci runtimes and snapshotters
} }
Expand All @@ -43,7 +49,10 @@ func ociWorkerInitializer(c *cli.Context, common workerInitializerOpt) ([]worker
if err != nil { if err != nil {
return nil, err return nil, err
} }
opt, err := runc.NewWorkerOpt(common.root, labels) exeOpt := runcexecutor.Opt{
Rootless: c.GlobalBool("rootless"),
}
opt, err := runc.NewWorkerOpt(common.root, labels, c.GlobalBoolT("oci-worker-overlayfs"), &exeOpt)
if err != nil { if err != nil {
return nil, err return nil, err
} }
Expand Down
47 changes: 47 additions & 0 deletions docs/rootless.md
@@ -0,0 +1,47 @@
# Rootless mode (Experimental)

Requirements:
- runc with https://github.com/opencontainers/runc/pull/1688
- Some distros such as Arch Linux require `echo 1 > /proc/sys/kernel/unprivileged_ns_clone`


## Terminal 1:

```
$ unshare -U -m
unshared$ echo $$
3539
```

Unsharing mountns (and userns) is required for mounting filesystems without real root privileges.

## Terminal 2:

```
$ id -u
1001
$ grep $(whoami) /etc/subuid
suda:231072:65536
$ grep $(whoami) /etc/subgid
suda:231072:65536
$ newuidmap 3539 0 1001 1 1 231072 65536
$ newgidmap 3539 0 1001 1 1 231072 65536
```

## Terminal 1:

```
unshared# buildkitd --root /home/suda/.local/share/buildkit --addr unix:///run/user/1001/buildkitd.sock --containerd-worker false --oci-worker-overlayfs=false --root
less
```

- On Ubuntu, no need to specify `--oci-worker-overlayfs` to `false`, as unprivileged overlayfs is supported: http://kernel.ubuntu.com/git/ubuntu/ubuntu-artful.git/commit/fs/overlayfs?h=Ubuntu-4.13.0-25.29&id=0a414bdc3d01f3b61ed86cfe3ce8b63a9240eba7
- containerd worker is not supported ( pending PR: https://github.com/containerd/containerd/pull/2006 )

## Terminal 2:

```
$ go run ./examples/buildkit0 | buildctl --addr unix:///run/user/1001/buildkitd.sock build
```

- `apt` is not supported (pending PRs: https://github.com/opencontainers/runc/pull/1693 https://github.com/opencontainers/runc/pull/1692 )
20 changes: 20 additions & 0 deletions executor/oci/rootless.go
@@ -0,0 +1,20 @@
package oci

import (
"context"

"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/oci"
"github.com/opencontainers/runc/libcontainer/specconv"
specs "github.com/opencontainers/runtime-spec/specs-go"
)

// WithRootless sets the container to be rootless mode.
// This function will be removed when containerd/containerd#2006 gets merged
func WithRootless(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
specconv.ToRootless(s)
// without removing CgroupsPath, runc fails:
// "process_linux.go:279: applying cgroup configuration for process caused \"mkdir /sys/fs/cgroup/cpuset/default: permission denied\""
s.Linux.CgroupsPath = ""
return nil
}
18 changes: 16 additions & 2 deletions executor/runcexecutor/executor.go
Expand Up @@ -21,12 +21,17 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )


type Opt struct {
Rootless bool // execute runc without root privileges
}

type runcExecutor struct { type runcExecutor struct {
Opt
runc *runc.Runc runc *runc.Runc
root string root string
} }


func New(root string) (executor.Executor, error) { func New(root string, opt *Opt) (executor.Executor, error) {
if err := exec.Command("runc", "--version").Run(); err != nil { if err := exec.Command("runc", "--version").Run(); err != nil {
return nil, errors.Wrap(err, "failed to find runc binary") return nil, errors.Wrap(err, "failed to find runc binary")
} }
Expand All @@ -48,7 +53,12 @@ func New(root string) (executor.Executor, error) {
Setpgid: true, Setpgid: true,
} }


var xopt Opt
if opt != nil {
xopt = *opt
}
w := &runcExecutor{ w := &runcExecutor{
Opt: xopt,
runc: runtime, runc: runtime,
root: root, root: root,
} }
Expand Down Expand Up @@ -98,7 +108,11 @@ func (w *runcExecutor) Exec(ctx context.Context, meta executor.Meta, root cache.
return err return err
} }
defer f.Close() defer f.Close()
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, containerdoci.WithUIDGID(uid, gid)) specOpts := []containerdoci.SpecOpts{containerdoci.WithUIDGID(uid, gid)}
if w.Opt.Rootless {
specOpts = append(specOpts, oci.WithRootless)
}
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, specOpts...)
if err != nil { if err != nil {
return err return err
} }
Expand Down
1 change: 1 addition & 0 deletions vendor.conf
Expand Up @@ -26,6 +26,7 @@ github.com/containerd/console 84eeaae905fa414d03e07bcd6c8d3f19e7cf180e
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
github.com/seccomp/libseccomp-golang 84e90a91acea0f4e51e62bc1a75de18b1fc0790f


github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
github.com/docker/go-units v0.3.1 github.com/docker/go-units v0.3.1
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 511c7e7

Please sign in to comment.