diff --git a/cmd/buildkitd/config/config.go b/cmd/buildkitd/config/config.go index 42b1b4026661..f25ab3e52c8a 100644 --- a/cmd/buildkitd/config/config.go +++ b/cmd/buildkitd/config/config.go @@ -179,6 +179,9 @@ type ContainerdConfig struct { DefaultCgroupParent string `toml:"defaultCgroupParent"` Rootless bool `toml:"rootless"` + + // HyperVIsolation enables Hyper-V isolation for Windows containers. + HyperVIsolation bool `toml:"hypervIsolation"` } type ContainerdRuntime struct { diff --git a/cmd/buildkitd/config/load_test.go b/cmd/buildkitd/config/load_test.go index 5a2768e67b3d..18ca4c6c36e6 100644 --- a/cmd/buildkitd/config/load_test.go +++ b/cmd/buildkitd/config/load_test.go @@ -43,6 +43,7 @@ foo="bar" namespace="non-default" platforms=["linux/amd64"] address="containerd.sock" +hypervIsolation=true [worker.containerd.runtime] name="exotic" path="/usr/bin/exotic" @@ -110,6 +111,7 @@ searchDomains=["example.com"] require.Nil(t, cfg.Workers.Containerd.Enabled) require.Equal(t, 1, len(cfg.Workers.Containerd.Platforms)) require.Equal(t, "containerd.sock", cfg.Workers.Containerd.Address) + require.True(t, cfg.Workers.Containerd.HyperVIsolation) require.Equal(t, 0, len(cfg.Workers.OCI.GCPolicy)) require.Equal(t, "non-default", cfg.Workers.Containerd.Namespace) diff --git a/cmd/buildkitd/main_containerd_worker.go b/cmd/buildkitd/main_containerd_worker.go index b784e65112b2..8f9db8e16d60 100644 --- a/cmd/buildkitd/main_containerd_worker.go +++ b/cmd/buildkitd/main_containerd_worker.go @@ -124,6 +124,11 @@ func init() { Name: "containerd-worker-selinux", Usage: "apply SELinux labels", }, + &cli.BoolFlag{ + Name: "containerd-worker-hyperv-isolation", + Usage: "use Hyper-V isolation for Windows containers", + Value: defaultConf.Workers.Containerd.HyperVIsolation, + }, &cli.IntFlag{ Name: "containerd-max-parallelism", Usage: "limit the number of parallel build steps that can run at the same time", @@ -265,6 +270,9 @@ func applyContainerdFlags(c *cli.Command, cfg *config.Config) error { if c.IsSet("containerd-worker-selinux") { cfg.Workers.Containerd.SELinux = c.Bool("containerd-worker-selinux") } + if c.IsSet("containerd-worker-hyperv-isolation") { + cfg.Workers.Containerd.HyperVIsolation = c.Bool("containerd-worker-hyperv-isolation") + } if c.IsSet("containerd-max-parallelism") { cfg.Workers.Containerd.MaxParallelism = c.Int("containerd-max-parallelism") } @@ -355,6 +363,7 @@ func containerdWorkerInitializer(c *cli.Command, common workerInitializerOpt) ([ TraceSocket: common.traceSocket, Runtime: runtime, CDIManager: cdiManager, + HyperVIsolation: cfg.HyperVIsolation, } opt, err := containerd.NewWorkerOpt(workerOpts, ctd.WithTimeout(60*time.Second)) diff --git a/docs/buildkitd.toml.md b/docs/buildkitd.toml.md index 6f037544a693..09a91bee116a 100644 --- a/docs/buildkitd.toml.md +++ b/docs/buildkitd.toml.md @@ -159,6 +159,8 @@ provenanceEnvDir = "/etc/buildkit/provenance.d" cniPoolSize = 16 # defaultCgroupParent sets the parent cgroup of all containers. defaultCgroupParent = "buildkit" + # hypervIsolation enables Hyper-V isolation for Windows containers. + hypervIsolation = false [worker.containerd.labels] "foo" = "bar" diff --git a/docs/windows.md b/docs/windows.md index 9d8bf91f374d..3179c343f93e 100644 --- a/docs/windows.md +++ b/docs/windows.md @@ -80,6 +80,27 @@ You will be asked to restart your machine, do so, and then continue with the res time="2024-02-26T10:42:16+03:00" level=info msg="running server on //./pipe/buildkitd" ``` + **Running `buildkitd` with Hyper-V isolation:** + + Some Windows hosts cannot run process-isolated containers for a base image + when the container OS version does not match the host OS version. To make + all build containers created by the containerd worker use Hyper-V isolation, + start `buildkitd` with: + + ```powershell + buildkitd --containerd-worker-hyperv-isolation + ``` + + The same setting can be configured in `buildkitd.toml`: + + ```toml + [worker.containerd] + hypervIsolation = true + ``` + + Hyper-V isolation requires the `Microsoft-Hyper-V` and `Containers` + Windows features to be enabled. + **Running `buildkitd` with the CNI:** Note that the above simple run will not have the networking bit setup; diff --git a/worker/containerd/containerd.go b/worker/containerd/containerd.go index 6accceac3235..57ab5db2b688 100644 --- a/worker/containerd/containerd.go +++ b/worker/containerd/containerd.go @@ -45,6 +45,7 @@ type WorkerOptions struct { TraceSocket string Runtime *RuntimeInfo CDIManager *cdidevices.Manager + HyperVIsolation bool } // NewWorkerOpt creates a WorkerOpt. @@ -152,6 +153,7 @@ func newContainerd(client *ctd.Client, workerOpts WorkerOptions) (base.WorkerOpt CDIManager: workerOpts.CDIManager, NetworkProviders: np, ProxyProvider: proxyProvider, + HyperVIsolation: workerOpts.HyperVIsolation, } opt := base.WorkerOpt{