diff --git a/pkg/build/nodeimage/buildcontext.go b/pkg/build/nodeimage/buildcontext.go index f0eb09be36..60b048d8fd 100644 --- a/pkg/build/nodeimage/buildcontext.go +++ b/pkg/build/nodeimage/buildcontext.go @@ -284,6 +284,11 @@ func (c *buildContext) prePullImagesAndWriteManifests(bits kube.Bits, parsedVers }) } } + // Wait for containerd socket to be ready, which may take 1s when running under emulation + if err := importer.WaitForReady(); err != nil { + c.logger.Errorf("Image build failed, containerd did not become ready %v", err) + return nil, err + } if err := errors.AggregateConcurrent(fns); err != nil { return nil, err } diff --git a/pkg/build/nodeimage/imageimporter.go b/pkg/build/nodeimage/imageimporter.go index 7839263fe7..c8ab1391c2 100644 --- a/pkg/build/nodeimage/imageimporter.go +++ b/pkg/build/nodeimage/imageimporter.go @@ -19,6 +19,7 @@ package nodeimage import ( "io" + "sigs.k8s.io/kind/pkg/errors" "sigs.k8s.io/kind/pkg/exec" ) @@ -38,7 +39,28 @@ func (c *containerdImporter) Prepare() error { ).Run(); err != nil { return err } - // TODO(bentheelder): some healthcheck? + return nil +} + +func (c *containerdImporter) WaitForReady() error { + // ctr doesn't respect timeouts when the socket doesn't exist + // so we'll look for the socket to exist ourselves, THEN attempt ctr info + // TODO: we are assuming the socket path, and this is kind of hacky + if err := c.containerCmder.Command( + "bash", "-c", `set -e +# wait for socket to exist +for i in {0..5}; do + if [ -S /run/containerd/containerd.sock ]; then + break + fi + sleep "$i" +done +# check healthy +ctr info +`, + ).Run(); err != nil { + return errors.Wrap(err, "failed to wait for containerd to become ready") + } return nil }