Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for gVisor #125

Merged
merged 1 commit into from
Feb 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ jobs:
- k3s
- k3s-external
- k3s-rootless
- gvisor
needs: [lint, build]
if: contains(github.event.pull_request.labels.*.name, 'ok-to-test')
steps:
Expand Down
49 changes: 42 additions & 7 deletions modules/common/containerd-rootless.nix
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,29 @@ let
'';
};

runsc-rootless = pkgs.writeShellApplication {
name = "runsc";
runtimeInputs = [
pkgs.gvisor
];
text = ''
exec runsc \
--ignore-cgroups \
"$@"
'';
};

gvisor-rootless = pkgs.buildEnv {
name = "gvisor-rootless";
paths = [
# Specific order matters here, since we want runsc-rootless to win over
# runsc.
runsc-rootless
pkgs.gvisor
];
ignoreCollisions = true;
};

makeProg = args: pkgs.substituteAll (args // {
inherit (pkgs) runtimeShell;
dir = "bin";
Expand Down Expand Up @@ -94,7 +117,7 @@ let
name = "containerd-rootless-child";
src = ./containerd-rootless-child.sh;
inherit mountSources mountPoints;
path = lib.makeBinPath [
path = lib.makeBinPath ([
cfg.package
pkgs.coreutils
pkgs.iptables
Expand All @@ -103,7 +126,7 @@ let
# Mount only works inside user namespaces from "/run/current-system/sw"
# See: https://github.com/NixOS/nixpkgs/issues/42117#issuecomment-872029461
"/run/current-system/sw"
];
] ++ cfg.path);
};

in {
Expand Down Expand Up @@ -160,6 +183,9 @@ in {
options.virtualisation.containerd.rootless = {
inherit (ctrd-lib.options)
nixSnapshotterIntegration
gVisorIntegration
path
defaultRuntime
setAddress
setNamespace
setSnapshotter
Expand Down Expand Up @@ -235,12 +261,15 @@ in {

setAddress = lib.mkDefault "$XDG_RUNTIME_DIR/containerd/containerd.sock";

settings = {
version = 2;
plugins."io.containerd.grpc.v1.cri" = {
cni.bin_dir = lib.mkOptionDefault "${pkgs.cni-plugins}/bin";
settings = lib.recursiveUpdate
(ctrd-lib.mkSettings cfg)
{
plugins."io.containerd.grpc.v1.cri" = {
disable_apparmor = true;
disable_cgroup = true;
restrict_oom_score_adj = true;
};
};
};

bindMounts = {
"$XDG_RUNTIME_DIR/containerd".mountPoint = "/run/containerd";
Expand All @@ -262,5 +291,11 @@ in {
};
};
})
(lib.mkIf cfg.gVisorIntegration {
virtualisation.containerd.rootless = {
path = [ gvisor-rootless ];
settings = ctrd-lib.mkGVisorSettings;
};
})
]);
}
50 changes: 50 additions & 0 deletions modules/common/containerd.nix
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,24 @@ let

nixSnapshotterIntegration = mkEnableOption "Nix snapshotter integration";

gVisorIntegration = mkEnableOption "gVisor integration";

defaultRuntime = mkOption {
type = types.str;
description = lib.mdDoc ''
Configures the default CRI runtime for containerd.
'';
default = "runc";
};

path = mkOption {
type = types.listOf types.path;
description = lib.mdDoc ''
Packages to be included in the PATH for containerd.
'';
default = [];
};

setAddress = mkOption {
type = types.str;
default = "/run/containerd/containerd.sock";
Expand Down Expand Up @@ -60,11 +78,41 @@ let
};
};

mkSettings = cfg: {
version = 2;
plugins."io.containerd.grpc.v1.cri" = {
cni = {
conf_dir = lib.mkOptionDefault "/etc/cni/net.d";
bin_dir = lib.mkOptionDefault "${pkgs.cni-plugins}/bin";
};

containerd = {
default_runtime_name = cfg.defaultRuntime;

runtimes.runc = {
runtime_type = "io.containerd.runc.v2";
options.SystemdCgroup = false;
};
};
};
};

mkGVisorSettings = {
plugins."io.containerd.grpc.v1.cri".containerd = {
runtimes.runsc = {
runtime_type = "io.containerd.runsc.v1";
};
};
};

in {
options.virtualisation.containerd = {
inherit (options)
k3sIntegration
nixSnapshotterIntegration
gVisorIntegration
defaultRuntime
path
setAddress
setNamespace
setSnapshotter
Expand All @@ -76,7 +124,9 @@ in {
default = {
inherit
options
mkGVisorSettings
mkNixSnapshotterSettings
mkSettings
;
};
internal = true;
Expand Down
2 changes: 1 addition & 1 deletion modules/nixos/containerd-rootless.nix
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ in {
../common/containerd-rootless.nix
];

config = lib.mkIf cfg.enable {
config = lib.mkIf cfg.enable {
environment.extraInit = ''
if [ -z "$CONTAINERD_ADDRESS" ]; then
export CONTAINERD_ADDRESS="${cfg.setAddress}"
Expand Down
45 changes: 27 additions & 18 deletions modules/nixos/containerd.nix
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ in {

config = lib.mkIf cfg.enable (lib.mkMerge [
{
virtualisation.containerd = {
settings = cfg.lib.mkSettings cfg;
};

environment.extraInit = ''
if [ -z "$CONTAINERD_ADDRESS" ]; then
export CONTAINERD_ADDRESS="${cfg.setAddress}"
Expand All @@ -33,6 +37,8 @@ in {
export CONTAINERD_SNAPSHOTTER="${cfg.setSnapshotter}"
fi
'');

systemd.services.containerd.path = cfg.path;
}
(lib.mkIf cfg.k3sIntegration {
services.k3s.moreFlags = [
Expand All @@ -42,25 +48,22 @@ in {
virtualisation.containerd = {
setNamespace = lib.mkDefault "k8s.io";

settings.plugins."io.containerd.grpc.v1.cri" = {
stream_server_address = "127.0.0.1";
stream_server_port = "10010";
enable_selinux = false;
enable_unprivileged_ports = true;
enable_unprivileged_icmp = true;
disable_apparmor = true;
disable_cgroup = true;
restrict_oom_score_adj = true;
sandbox_image = "rancher/mirrored-pause:3.6";
settings = {
plugins."io.containerd.grpc.v1.cri" = {
stream_server_address = "127.0.0.1";
stream_server_port = "10010";
enable_selinux = false;
enable_unprivileged_ports = true;
enable_unprivileged_icmp = true;
disable_apparmor = true;
disable_cgroup = true;
restrict_oom_score_adj = true;
sandbox_image = "rancher/mirrored-pause:3.6";

cni = {
conf_dir = "/var/lib/rancher/k3s/agent/etc/cni/net.d/";
bin_dir = "${k3s-cni-plugins}/bin";
};

containerd.runtimes.runc = {
runtime_type = "io.containerd.runc.v2";
options.SystemdCgroup = false;
cni = {
conf_dir = "/var/lib/rancher/k3s/agent/etc/cni/net.d/";
bin_dir = "${k3s-cni-plugins}/bin";
};
};
};
};
Expand All @@ -76,5 +79,11 @@ in {
"--image-service-endpoint unix:///run/nix-snapshotter/nix-snapshotter.sock"
];
})
(lib.mkIf cfg.gVisorIntegration {
virtualisation.containerd = {
path = [ pkgs.gvisor ];
settings = cfg.lib.mkGVisorSettings;
};
})
]);
}
1 change: 1 addition & 0 deletions modules/nixos/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,6 @@ in {
nixosTests.k3s = import ./tests/k3s.nix;
nixosTests.k3s-external = import ./tests/k3s-external.nix;
nixosTests.k3s-rootless = import ./tests/k3s-rootless.nix;
nixosTests.gvisor = import ./tests/gvisor.nix;
};
}
122 changes: 122 additions & 0 deletions modules/nixos/tests/gvisor.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
{ lib, pkgs, ... }:
let
redis = pkgs.nix-snapshotter.buildImage {
name = "ghcr.io/pdtpartners/redis";
tag = "latest";
copyToRoot = [
pkgs.util-linux
];
config = {
Entrypoint = [ "${pkgs.redis}/bin/redis-server" ];
Cmd = [ "--protected-mode" "no" ];
};
};

common = {
environment.systemPackages = [
pkgs.nerdctl
pkgs.redis
];

nix.settings.experimental-features = [ "nix-command" ];
};

in {
nodes = {
rootful = {
imports = [
common
];

virtualisation.containerd = {
enable = true;
nixSnapshotterIntegration = true;
gVisorIntegration = true;
};

services.nix-snapshotter = {
enable = true;
};

services.preload-containerd = {
enable = true;
targets = [{
archives = [ redis ];
}];
};
};

rootless = {
imports = [
common
];

virtualisation.containerd.rootless = {
enable = true;
nixSnapshotterIntegration = true;
gVisorIntegration = true;
};

services.nix-snapshotter.rootless = {
enable = true;
};

services.preload-containerd.rootless = {
enable = true;
targets = [{
archives = [ redis ];
address = "$XDG_RUNTIME_DIR/containerd/containerd.sock";
}];
};

users.users.alice = {
uid = 1000;
isNormalUser = true;
};

environment.variables = {
XDG_RUNTIME_DIR = "/run/user/1000";
};
};
};

testScript = { nodes, ... }:
let
sudo_su = lib.concatStringsSep " " [
"sudo"
"--preserve-env=XDG_RUNTIME_DIR,CONTAINERD_ADDRESS,CONTAINERD_SNAPSHOTTER"
"-u"
"alice"
];

in ''
def test(machine, sudo_su = ""):
if sudo_su == "":
machine.wait_for_unit("nix-snapshotter.service")
machine.wait_for_unit("containerd.service")
machine.wait_for_unit("preload-containerd.service")
else:
machine.succeed("loginctl enable-linger alice")
wait_for_user_unit(machine, "nix-snapshotter.service")
wait_for_user_unit(machine, "containerd.service")
wait_for_user_unit(machine, "preload-containerd.service")

with subtest(f"{machine.name}: Run redis using runtime runsc"):
machine.succeed(f"{sudo_su} nerdctl run -d --name redis --runtime runsc -p 30000:6379 --cap-add syslog ghcr.io/pdtpartners/redis")

with subtest(f"{machine.name}: Ensure that gVisor is active"):
out = machine.succeed(f"{sudo_su} nerdctl exec redis dmesg | grep -i gvisor")
assert "Starting gVisor" in out

with subtest(f"{machine.name}: Ensure that redis is healthy"):
out = machine.wait_until_succeeds(f"{sudo_su} redis-cli -p 30000 ping")
assert "PONG" in out

def wait_for_user_unit(machine, service, user = "alice"):
machine.wait_until_succeeds(f"systemctl --user --machine={user}@ is-active {service}")

start_all()
test(rootful)
test(rootless, "${sudo_su}")
'';
}
Loading