Skip to content

Commit bf08a52

Browse files
Furistoroboquat
authored andcommitted
Enable fuse device on cgroup v2
1 parent c4aeb8d commit bf08a52

File tree

4 files changed

+96
-14
lines changed

4 files changed

+96
-14
lines changed

components/ws-daemon/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ require (
4747
github.com/beorn7/perks v1.0.1 // indirect
4848
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
4949
github.com/cespare/xxhash/v2 v2.1.2 // indirect
50+
github.com/cilium/ebpf v0.7.0 // indirect
5051
github.com/containerd/continuity v0.2.2 // indirect
5152
github.com/containerd/fifo v1.0.0 // indirect
5253
github.com/containerd/ttrpc v1.1.0 // indirect

components/ws-daemon/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLI
151151
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
152152
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
153153
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
154+
github.com/cilium/ebpf v0.7.0 h1:1k/q3ATgxSXRdrmPfH8d7YK0GfqVsEKZAX9dQZvs56k=
154155
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
155156
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
156157
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
@@ -346,6 +347,7 @@ github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4
346347
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
347348
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
348349
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
350+
github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
349351
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
350352
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
351353
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=

components/ws-daemon/pkg/daemon/cgroup_customizer.go

Lines changed: 89 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,17 @@ package daemon
66

77
import (
88
"context"
9+
"path/filepath"
910

1011
"github.com/containerd/cgroups"
12+
"github.com/gitpod-io/gitpod/ws-daemon/pkg/container"
1113
"github.com/gitpod-io/gitpod/ws-daemon/pkg/dispatch"
14+
"github.com/opencontainers/runc/libcontainer/cgroups/ebpf"
15+
"github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter"
16+
"github.com/opencontainers/runc/libcontainer/devices"
17+
"github.com/opencontainers/runc/libcontainer/specconv"
1218
"github.com/opencontainers/runtime-spec/specs-go"
19+
"golang.org/x/sys/unix"
1320
"golang.org/x/xerrors"
1421
)
1522

@@ -18,24 +25,31 @@ var (
1825
fuseDeviceMinor int64 = 229
1926
)
2027

21-
type CgroupCustomizer struct {
28+
func NewCGroupCustomizer(basePath string, unified bool) dispatch.Listener {
29+
if unified {
30+
return &CgroupCustomizerV2{
31+
cgroupBasePath: basePath,
32+
}
33+
} else {
34+
return &CgroupCustomizerV1{
35+
cgroupBasePath: basePath,
36+
}
37+
}
38+
}
39+
40+
type CgroupCustomizerV1 struct {
2241
cgroupBasePath string
2342
}
2443

25-
func (c *CgroupCustomizer) WithCgroupBasePath(basePath string) {
44+
func (c *CgroupCustomizerV1) WithCgroupBasePath(basePath string) {
2645
c.cgroupBasePath = basePath
2746
}
2847

2948
// WorkspaceAdded will customize the cgroups for every workspace that is started
30-
func (c *CgroupCustomizer) WorkspaceAdded(ctx context.Context, ws *dispatch.Workspace) error {
31-
disp := dispatch.GetFromContext(ctx)
32-
if disp == nil {
33-
return xerrors.Errorf("no dispatch available")
34-
}
35-
36-
cgroupPath, err := disp.Runtime.ContainerCGroupPath(context.Background(), ws.ContainerID)
49+
func (c *CgroupCustomizerV1) WorkspaceAdded(ctx context.Context, ws *dispatch.Workspace) error {
50+
cgroupPath, err := retrieveCGroupPath(ctx, ws.ContainerID)
3751
if err != nil {
38-
return xerrors.Errorf("cannot start governer: %w", err)
52+
return err
3953
}
4054

4155
control, err := cgroups.Load(c.customV1, cgroups.StaticPath(cgroupPath))
@@ -64,8 +78,72 @@ func (c *CgroupCustomizer) WorkspaceAdded(ctx context.Context, ws *dispatch.Work
6478
return nil
6579
}
6680

67-
func (c *CgroupCustomizer) customV1() ([]cgroups.Subsystem, error) {
81+
func (c *CgroupCustomizerV1) customV1() ([]cgroups.Subsystem, error) {
6882
return []cgroups.Subsystem{
6983
cgroups.NewDevices(c.cgroupBasePath),
7084
}, nil
7185
}
86+
87+
type CgroupCustomizerV2 struct {
88+
cgroupBasePath string
89+
}
90+
91+
func (c *CgroupCustomizerV2) WorkspaceAdded(ctx context.Context, ws *dispatch.Workspace) error {
92+
cgroupPath, err := retrieveCGroupPath(ctx, ws.ContainerID)
93+
if err != nil {
94+
return err
95+
}
96+
97+
fullCgroupPath := filepath.Join(c.cgroupBasePath, cgroupPath)
98+
cgroupFD, err := unix.Open(fullCgroupPath, unix.O_DIRECTORY|unix.O_RDONLY, 0o600)
99+
if err != nil {
100+
return xerrors.Errorf("cannot get directory fd for %s", fullCgroupPath)
101+
}
102+
defer unix.Close(cgroupFD)
103+
104+
insts, license, err := devicefilter.DeviceFilter(composeDeviceRules())
105+
if err != nil {
106+
return xerrors.Errorf("failed to generate device filter: %w", err)
107+
}
108+
109+
_, err = ebpf.LoadAttachCgroupDeviceFilter(insts, license, cgroupFD)
110+
return err
111+
}
112+
113+
func retrieveCGroupPath(ctx context.Context, id container.ID) (string, error) {
114+
disp := dispatch.GetFromContext(ctx)
115+
if disp == nil {
116+
return "", xerrors.Errorf("no dispatch available")
117+
}
118+
119+
cgroupPath, err := disp.Runtime.ContainerCGroupPath(context.Background(), id)
120+
if err != nil {
121+
return "", xerrors.Errorf("cannot retrieve cgroup path: %w", err)
122+
}
123+
124+
return cgroupPath, nil
125+
}
126+
127+
func composeDeviceRules() []*devices.Rule {
128+
denyAll := devices.Rule{
129+
Type: 'a',
130+
Permissions: "rwm",
131+
Allow: false,
132+
}
133+
134+
allowFuse := devices.Rule{
135+
Type: 'c',
136+
Major: fuseDeviceMajor,
137+
Minor: fuseDeviceMinor,
138+
Permissions: "rwm",
139+
Allow: true,
140+
}
141+
142+
deviceRules := make([]*devices.Rule, 0)
143+
deviceRules = append(deviceRules, &denyAll, &allowFuse)
144+
for _, device := range specconv.AllowedDevices {
145+
deviceRules = append(deviceRules, &device.Rule)
146+
}
147+
148+
return deviceRules
149+
}

components/ws-daemon/pkg/daemon/daemon.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,24 @@ func NewDaemon(config Config, reg prometheus.Registerer) (*Daemon, error) {
4545
if nodename == "" {
4646
return nil, xerrors.Errorf("NODENAME env var isn't set")
4747
}
48-
cgCustomizer := &CgroupCustomizer{}
49-
cgCustomizer.WithCgroupBasePath(config.Resources.CGroupBasePath)
48+
5049
markUnmountFallback, err := NewMarkUnmountFallback(reg)
5150
if err != nil {
5251
return nil, err
5352
}
5453

5554
listener := []dispatch.Listener{
5655
cpulimit.NewDispatchListener(&config.Resources, reg),
57-
cgCustomizer,
5856
markUnmountFallback,
5957
}
6058

6159
unified, err := cgroups.IsUnifiedCgroupSetup()
6260
if err != nil {
6361
return nil, xerrors.Errorf("could not determine cgroup setup: %w", err)
6462
}
63+
64+
listener = append(listener, NewCGroupCustomizer(config.Resources.CGroupBasePath, unified))
65+
6566
if !unified {
6667
listener = append(listener, CacheReclaim(config.Resources.CGroupBasePath))
6768
}

0 commit comments

Comments
 (0)