Skip to content

Commit 60b47c6

Browse files
committed
feat: add gVisor RuntimeClass support for containerd
Add support for running workloads under gVisor (runsc) as a containerd runtime handler, following the existing NVIDIA GPU runtime pattern. gVisor is gated to Debian-family distributions only. The runsc apt package provides both runsc and containerd-shim-runsc-v1. Assisted by Opus 4.6 Signed-off-by: Arnaud Meukam <ameukam@gmail.com>
1 parent d768817 commit 60b47c6

19 files changed

Lines changed: 535 additions & 0 deletions

k8s/crds/kops.k8s.io_clusters.yaml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,40 @@ spec:
954954
description: ConfigOverride is the complete containerd config
955955
file provided by the user.
956956
type: string
957+
gvisor:
958+
description: GVisor configures the gVisor (runsc) sandboxed runtime.
959+
properties:
960+
enabled:
961+
description: Enabled determines if kOps will install the gVisor
962+
runtime.
963+
type: boolean
964+
packages:
965+
description: Packages overrides the URL and hash for the gVisor
966+
packages.
967+
properties:
968+
hashAmd64:
969+
description: HashAmd64 overrides the hash for the AMD64
970+
package.
971+
type: string
972+
hashArm64:
973+
description: HashArm64 overrides the hash for the ARM64
974+
package.
975+
type: string
976+
urlAmd64:
977+
description: UrlAmd64 overrides the URL for the AMD64
978+
package.
979+
type: string
980+
urlArm64:
981+
description: UrlArm64 overrides the URL for the ARM64
982+
package.
983+
type: string
984+
type: object
985+
platform:
986+
description: |-
987+
Platform is the gVisor execution platform: "systrap" (default, works
988+
everywhere including VMs) or "kvm" (bare-metal with KVM support).
989+
type: string
990+
type: object
957991
installCriCtl:
958992
description: InstallCriCtl installs crictl (default "false").
959993
type: boolean

k8s/crds/kops.k8s.io_instancegroups.yaml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,40 @@ spec:
136136
description: ConfigOverride is the complete containerd config
137137
file provided by the user.
138138
type: string
139+
gvisor:
140+
description: GVisor configures the gVisor (runsc) sandboxed runtime.
141+
properties:
142+
enabled:
143+
description: Enabled determines if kOps will install the gVisor
144+
runtime.
145+
type: boolean
146+
packages:
147+
description: Packages overrides the URL and hash for the gVisor
148+
packages.
149+
properties:
150+
hashAmd64:
151+
description: HashAmd64 overrides the hash for the AMD64
152+
package.
153+
type: string
154+
hashArm64:
155+
description: HashArm64 overrides the hash for the ARM64
156+
package.
157+
type: string
158+
urlAmd64:
159+
description: UrlAmd64 overrides the URL for the AMD64
160+
package.
161+
type: string
162+
urlArm64:
163+
description: UrlArm64 overrides the URL for the ARM64
164+
package.
165+
type: string
166+
type: object
167+
platform:
168+
description: |-
169+
Platform is the gVisor execution platform: "systrap" (default, works
170+
everywhere including VMs) or "kvm" (bare-metal with KVM support).
171+
type: string
172+
type: object
139173
installCriCtl:
140174
description: InstallCriCtl installs crictl (default "false").
141175
type: boolean

nodeup/pkg/model/containerd.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ func (b *ContainerdBuilder) Build(c *fi.NodeupModelBuilderContext) error {
9393
return err
9494
}
9595

96+
// If gVisor is enabled, emit the runsc shim config file
97+
if b.InstallGVisorRuntime() {
98+
b.buildGVisorShimConfig(c)
99+
}
100+
96101
if installContainerd {
97102
if err := b.installContainerd(c); err != nil {
98103
return err
@@ -564,6 +569,12 @@ func (b *ContainerdBuilder) buildContainerdConfigV2() (string, error) {
564569
}
565570
}
566571

572+
if b.InstallGVisorRuntime() {
573+
if err := appendGVisorRuntimeConfig(config, []string{"plugins", "io.containerd.grpc.v1.cri", "containerd", "runtimes"}); err != nil {
574+
return "", fmt.Errorf("appending gvisor runtime to v2 containerd config: %w", err)
575+
}
576+
}
577+
567578
if err := applyConfigAdditions(config, containerd.ConfigAdditions); err != nil {
568579
return "", fmt.Errorf("applying ConfigAdditions to v2 containerd config: %w", err)
569580
}
@@ -617,6 +628,12 @@ func (b *ContainerdBuilder) buildContainerdConfigV3() (string, error) {
617628
}
618629
}
619630

631+
if b.InstallGVisorRuntime() {
632+
if err := appendGVisorRuntimeConfig(config, []string{"plugins", "io.containerd.cri.v1.runtime", "containerd", "runtimes"}); err != nil {
633+
return "", fmt.Errorf("appending gvisor runtime to v3 containerd config: %w", err)
634+
}
635+
}
636+
620637
if err := applyConfigAdditions(config, containerd.ConfigAdditions); err != nil {
621638
return "", fmt.Errorf("applying ConfigAdditions to v3 containerd config: %w", err)
622639
}
@@ -691,6 +708,45 @@ func appendNvidiaGPURuntimeConfig(config *toml.Tree, runtimesPath []string) erro
691708
return nil
692709
}
693710

711+
// appendGVisorRuntimeConfig adds the "runsc" runtime entry under runtimesPath.
712+
// runtimesPath is schema-specific so the same helper can serve both v2 and v3 builders.
713+
func appendGVisorRuntimeConfig(config *toml.Tree, runtimesPath []string) error {
714+
gvisorConfig, err := toml.TreeFromMap(
715+
map[string]interface{}{
716+
"runtime_type": "io.containerd.runsc.v1",
717+
},
718+
)
719+
if err != nil {
720+
return err
721+
}
722+
723+
path := make([]string, len(runtimesPath)+1)
724+
copy(path, runtimesPath)
725+
path[len(runtimesPath)] = "runsc"
726+
config.SetPath(path, gvisorConfig)
727+
728+
return nil
729+
}
730+
731+
// buildGVisorShimConfig emits /etc/containerd/runsc.toml, the shim-level
732+
// configuration consumed by containerd-shim-runsc-v1 at container creation.
733+
// See https://gvisor.dev/docs/user_guide/containerd/configuration/
734+
func (b *ContainerdBuilder) buildGVisorShimConfig(c *fi.NodeupModelBuilderContext) {
735+
platform := b.NodeupConfig.GVisor.Platform
736+
if platform == "" {
737+
platform = "systrap"
738+
}
739+
740+
shimConfig, _ := toml.Load("")
741+
shimConfig.SetPath([]string{"runsc_config", "platform"}, platform)
742+
743+
c.AddTask(&nodetasks.File{
744+
Path: "/etc/containerd/runsc.toml",
745+
Contents: fi.NewStringResource(shimConfig.String()),
746+
Type: nodetasks.FileType_File,
747+
})
748+
}
749+
694750
// buildRegistryHosts emits one hosts.toml per RegistryMirrors entry under containerdRegistryDirPath.
695751
// The directory is referenced by registry.config_path in the main containerd config; the
696752
// emit-files-iff-mirrors-non-empty condition here must stay in sync with the registry.config_path

nodeup/pkg/model/context.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,14 @@ func (c *NodeupModelContext) InstallNvidiaRuntime() bool {
563563
c.GPUVendor == architectures.GPUVendorNvidia
564564
}
565565

566+
// InstallGVisorRuntime returns true if the gVisor (runsc) runtime should be installed.
567+
// gVisor is only supported on Debian-family distributions (Debian, Ubuntu).
568+
func (c *NodeupModelContext) InstallGVisorRuntime() bool {
569+
return c.NodeupConfig.GVisor != nil &&
570+
fi.ValueOf(c.NodeupConfig.GVisor.Enabled) &&
571+
c.Distribution.IsDebianFamily()
572+
}
573+
566574
// CloudProvider returns the cloud provider we are running on
567575
func (c *NodeupModelContext) CloudProvider() kops.CloudProviderID {
568576
return c.BootConfig.CloudProvider

nodeup/pkg/model/gvisor.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
Copyright The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package model
18+
19+
import (
20+
"k8s.io/kops/upup/pkg/fi"
21+
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
22+
)
23+
24+
// GVisorBuilder installs the gVisor (runsc) sandboxed runtime.
25+
// Only supported on Debian-family distributions.
26+
type GVisorBuilder struct {
27+
*NodeupModelContext
28+
}
29+
30+
var _ fi.NodeupModelBuilder = &GVisorBuilder{}
31+
32+
// Build installs gVisor packages via the upstream apt repository.
33+
func (b *GVisorBuilder) Build(c *fi.NodeupModelBuilderContext) error {
34+
if !b.InstallGVisorRuntime() {
35+
return nil
36+
}
37+
38+
c.AddTask(&nodetasks.AptSource{
39+
Name: "gvisor",
40+
Keyring: "https://gvisor.dev/archive.key",
41+
Sources: []string{
42+
"deb [arch=$(dpkg --print-architecture)] https://storage.googleapis.com/gvisor/releases release main",
43+
},
44+
})
45+
// The runsc package bundles both runsc and containerd-shim-runsc-v1.
46+
c.AddTask(&nodetasks.Package{Name: "runsc"})
47+
48+
return nil
49+
}

pkg/apis/kops/containerdconfig.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ const (
2626
NvidiaDefaultDriverPackage = "nvidia-driver-535-server"
2727
// NvidiaDevicePluginImage is the Nvidia K8s device plugin container image
2828
NvidiaDevicePluginImage = "nvcr.io/nvidia/k8s-device-plugin:v0.17.3"
29+
// GVisorDefaultPlatform is the default gVisor execution platform.
30+
// systrap uses SECCOMP_RET_TRAP/SIGSYS and works in all environments including VMs.
31+
GVisorDefaultPlatform = "systrap"
2932
)
3033

3134
// ContainerdConfig is the configuration for containerd
@@ -55,6 +58,8 @@ type ContainerdConfig struct {
5558
Version *string `json:"version,omitempty"`
5659
// NvidiaGPU configures the Nvidia GPU runtime.
5760
NvidiaGPU *NvidiaGPUConfig `json:"nvidiaGPU,omitempty"`
61+
// GVisor configures the gVisor (runsc) sandboxed runtime.
62+
GVisor *GVisorConfig `json:"gvisor,omitempty"`
5863
// Runc configures the runc runtime.
5964
Runc *Runc `json:"runc,omitempty"`
6065
// SelinuxEnabled enables SELinux support
@@ -106,3 +111,17 @@ type Runc struct {
106111
// Packages overrides the URL and hash for the packages.
107112
Packages *PackagesConfig `json:"packages,omitempty"`
108113
}
114+
115+
// GVisorConfig configures the gVisor sandboxed container runtime.
116+
// When enabled, kOps installs runsc and containerd-shim-runsc-v1,
117+
// registers the "runsc" runtime handler in containerd, and deploys
118+
// a Kubernetes RuntimeClass named "gvisor".
119+
type GVisorConfig struct {
120+
// Enabled determines if kOps will install the gVisor runtime.
121+
Enabled *bool `json:"enabled,omitempty"`
122+
// Platform is the gVisor execution platform: "systrap" (default, works
123+
// everywhere including VMs) or "kvm" (bare-metal with KVM support).
124+
Platform string `json:"platform,omitempty"`
125+
// Packages overrides the URL and hash for the gVisor packages.
126+
Packages *PackagesConfig `json:"packages,omitempty"`
127+
}

pkg/apis/kops/v1alpha2/containerdconfig.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ type ContainerdConfig struct {
4848
Version *string `json:"version,omitempty"`
4949
// NvidiaGPU configures the Nvidia GPU runtime.
5050
NvidiaGPU *NvidiaGPUConfig `json:"nvidiaGPU,omitempty"`
51+
// GVisor configures the gVisor (runsc) sandboxed runtime.
52+
GVisor *GVisorConfig `json:"gvisor,omitempty"`
5153
// Runc configures the runc runtime.
5254
Runc *Runc `json:"runc,omitempty"`
5355
// SelinuxEnabled enables SELinux support
@@ -99,3 +101,17 @@ type Runc struct {
99101
// Packages overrides the URL and hash for the packages.
100102
Packages *PackagesConfig `json:"packages,omitempty"`
101103
}
104+
105+
// GVisorConfig configures the gVisor sandboxed container runtime.
106+
// When enabled, kOps installs runsc and containerd-shim-runsc-v1,
107+
// registers the "runsc" runtime handler in containerd, and deploys
108+
// a Kubernetes RuntimeClass named "gvisor".
109+
type GVisorConfig struct {
110+
// Enabled determines if kOps will install the gVisor runtime.
111+
Enabled *bool `json:"enabled,omitempty"`
112+
// Platform is the gVisor execution platform: "systrap" (default, works
113+
// everywhere including VMs) or "kvm" (bare-metal with KVM support).
114+
Platform string `json:"platform,omitempty"`
115+
// Packages overrides the URL and hash for the gVisor packages.
116+
Packages *PackagesConfig `json:"packages,omitempty"`
117+
}

pkg/apis/kops/v1alpha2/zz_generated.conversion.go

Lines changed: 68 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)