diff --git a/cmd/minikube/cmd/docker-env.go b/cmd/minikube/cmd/docker-env.go index 06e5ff7ac7f7..d47d51ae8e2e 100644 --- a/cmd/minikube/cmd/docker-env.go +++ b/cmd/minikube/cmd/docker-env.go @@ -25,6 +25,7 @@ import ( "net/url" "os" "os/exec" + "runtime" "strconv" "strings" "time" @@ -47,6 +48,7 @@ import ( "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/reason" "k8s.io/minikube/pkg/minikube/shell" + "k8s.io/minikube/pkg/minikube/sshagent" "k8s.io/minikube/pkg/minikube/sysinit" pkgnetwork "k8s.io/minikube/pkg/network" kconst "k8s.io/minikube/third_party/kubeadm/app/constants" @@ -295,6 +297,7 @@ docker-cli install instructions: https://minikube.sigs.k8s.io/docs/tutorials/doc } cname := ClusterFlagValue() + co := mustload.Running(cname) driverName := co.CP.Host.DriverName @@ -306,14 +309,42 @@ docker-cli install instructions: https://minikube.sigs.k8s.io/docs/tutorials/doc if len(co.Config.Nodes) > 1 { exit.Message(reason.EnvMultiConflict, `The docker-env command is incompatible with multi-node clusters. Use the 'registry' add-on: https://minikube.sigs.k8s.io/docs/handbook/registry/`) } + cr := co.Config.KubernetesConfig.ContainerRuntime + // nerdctld supports amd64 and arm64 + if err := dockerEnvSupported(cr, driverName); err != nil { + exit.Message(reason.Usage, err.Error()) + } + + // for the sake of docker-env command, start nerdctl and nerdctld + if cr == constants.Containerd { + out.WarningT("Using the docker-env command with the containerd runtime is a highly experimental feature, please provide feedback or contribute to make it better") + + startNerdctld() + + // docker-env on containerd depends on nerdctld (https://github.com/afbjorklund/nerdctld) as "docker" daeomn + // and nerdctld daemon must be used with ssh connection (it is set in kicbase image's Dockerfile) + // so directly set --ssh-host --ssh-add to true, even user didn't specify them + sshAdd = true + sshHost = true - if co.Config.KubernetesConfig.ContainerRuntime != constants.Docker { - exit.Message(reason.Usage, `The docker-env command is only compatible with the "docker" runtime, but this cluster was configured to use the "{{.runtime}}" runtime.`, - out.V{"runtime": co.Config.KubernetesConfig.ContainerRuntime}) + // start the ssh-agent + if err := sshagent.Start(cname); err != nil { + exit.Message(reason.SSHAgentStart, err.Error()) + } + // cluster config must be reloaded + // otherwise we won't be able to get SSH_AUTH_SOCK and SSH_AGENT_PID from cluster config. + co = mustload.Running(cname) + + // set the ssh-agent envs for current process + os.Setenv("SSH_AUTH_SOCK", co.Config.SSHAuthSock) + os.Setenv("SSH_AGENT_PID", strconv.Itoa(co.Config.SSHAgentPID)) } r := co.CP.Runner - ensureDockerd(cname, r) + + if cr == constants.Docker { + ensureDockerd(cname, r) + } d := co.CP.Host.Driver port := constants.DockerDaemonPort @@ -381,14 +412,18 @@ docker-cli install instructions: https://minikube.sigs.k8s.io/docs/tutorials/doc if err != nil { exit.Error(reason.IfSSHClient, "Error with ssh-add", err) } - cmd := exec.Command(path, d.GetSSHKeyPath()) cmd.Stderr = os.Stderr + cmd.Env = append(cmd.Env, fmt.Sprintf("SSH_AUTH_SOCK=%s", co.Config.SSHAuthSock)) + cmd.Env = append(cmd.Env, fmt.Sprintf("SSH_AGENT_PID=%d", co.Config.SSHAgentPID)) err = cmd.Run() if err != nil { exit.Error(reason.IfSSHClient, "Error with ssh-add", err) } } + + // eventually, run something similar to ssh --append-known + appendKnownHelper(nodeName, true) }, } @@ -539,6 +574,8 @@ func dockerEnvVars(ec DockerEnvConfig) map[string]string { envSSH := map[string]string{ constants.DockerHostEnv: sshURL(ec.username, ec.hostname, ec.sshport), constants.MinikubeActiveDockerdEnv: ec.profile, + constants.SSHAuthSock: ec.sshAuthSock, + constants.SSHAgentPID: agentPID, } var rt map[string]string @@ -630,6 +667,20 @@ func tryDockerConnectivity(bin string, ec DockerEnvConfig) ([]byte, error) { return c.CombinedOutput() } +func dockerEnvSupported(containerRuntime, driverName string) error { + if runtime.GOARCH != "amd64" && runtime.GOARCH != "arm64" { + return fmt.Errorf("the docker-env command only supports amd64 & arm64 architectures") + } + if containerRuntime != constants.Docker && containerRuntime != constants.Containerd { + return fmt.Errorf("the docker-env command only supports the docker and containerd runtimes") + } + // we only support containerd-env on the Docker driver + if containerRuntime == constants.Containerd && driverName != driver.Docker { + return fmt.Errorf("the docker-env command only supports the containerd runtime with the docker driver") + } + return nil +} + func init() { defaultNoProxyGetter = &EnvNoProxyGetter{} dockerEnvCmd.Flags().BoolVar(&noProxy, "no-proxy", false, "Add machine IP to NO_PROXY environment variable") diff --git a/cmd/minikube/cmd/ssh-host.go b/cmd/minikube/cmd/ssh-host.go index 1755c30ea77a..44b91e3d9f58 100644 --- a/cmd/minikube/cmd/ssh-host.go +++ b/cmd/minikube/cmd/ssh-host.go @@ -45,69 +45,76 @@ var sshHostCmd = &cobra.Command{ Short: "Retrieve the ssh host key of the specified node", Long: "Retrieve the ssh host key of the specified node.", Run: func(cmd *cobra.Command, args []string) { - cname := ClusterFlagValue() - co := mustload.Running(cname) - if co.CP.Host.DriverName == driver.None { - exit.Message(reason.Usage, "'none' driver does not support 'minikube ssh-host' command") - } + appendKnownHelper(nodeName, appendKnown) + }, +} - var err error - var n *config.Node - if nodeName == "" { - n = co.CP.Node - } else { - n, _, err = node.Retrieve(*co.Config, nodeName) - if err != nil { - exit.Message(reason.GuestNodeRetrieve, "Node {{.nodeName}} does not exist.", out.V{"nodeName": nodeName}) - } +func appendKnownHelper(nodeName string, appendKnown bool) { + cname := ClusterFlagValue() + co := mustload.Running(cname) + if co.CP.Host.DriverName == driver.None { + exit.Message(reason.Usage, "'none' driver does not support 'minikube ssh-host' command") + } + + var err error + var n *config.Node + if nodeName == "" { + n = co.CP.Node + } else { + n, _, err = node.Retrieve(*co.Config, nodeName) + if err != nil { + exit.Message(reason.GuestNodeRetrieve, "Node {{.nodeName}} does not exist.", out.V{"nodeName": nodeName}) } + } + + scanArgs := []string{"-t", "rsa"} - scanArgs := []string{"-t", "rsa"} + keys, err := machine.RunSSHHostCommand(co.API, *co.Config, *n, "ssh-keyscan", scanArgs) + if err != nil { + // This is typically due to a non-zero exit code, so no need for flourish. + out.ErrLn("ssh-keyscan: %v", err) + // It'd be nice if we could pass up the correct error code here :( + os.Exit(1) + } - keys, err := machine.RunSSHHostCommand(co.API, *co.Config, *n, "ssh-keyscan", scanArgs) + if appendKnown { + addr, port, err := machine.GetSSHHostAddrPort(co.API, *co.Config, *n) if err != nil { - // This is typically due to a non-zero exit code, so no need for flourish. - out.ErrLn("ssh-keyscan: %v", err) - // It'd be nice if we could pass up the correct error code here :( + out.ErrLn("GetSSHHostAddrPort: %v", err) os.Exit(1) } - if appendKnown { - addr, port, err := machine.GetSSHHostAddrPort(co.API, *co.Config, *n) - if err != nil { - out.ErrLn("GetSSHHostAddrPort: %v", err) - os.Exit(1) - } - - host := addr - if port != 22 { - host = fmt.Sprintf("[%s]:%d", addr, port) - } - knownHosts := filepath.Join(homedir.HomeDir(), ".ssh", "known_hosts") - - fmt.Fprintf(os.Stderr, "Host added: %s (%s)\n", knownHosts, host) - if sshutil.KnownHost(host, knownHosts) { - return - } - - f, err := os.OpenFile(knownHosts, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600) - if err != nil { - out.ErrLn("OpenFile: %v", err) - os.Exit(1) - } - defer f.Close() - - _, err = f.WriteString(keys) - if err != nil { - out.ErrLn("WriteString: %v", err) - os.Exit(1) - } + host := addr + if port != 22 { + host = fmt.Sprintf("[%s]:%d", addr, port) + } + knownHosts := filepath.Join(homedir.HomeDir(), ".ssh", "known_hosts") + fmt.Fprintf(os.Stderr, "Host added: %s (%s)\n", knownHosts, host) + if sshutil.KnownHost(host, knownHosts) { return } - fmt.Printf("%s", keys) - }, + f, err := os.OpenFile(knownHosts, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600) + if err != nil { + out.ErrLn("OpenFile: %v", err) + os.Exit(1) + } + + _, err = f.WriteString(keys) + if err != nil { + out.ErrLn("WriteString: %v", err) + f.Close() + os.Exit(1) + } + + if err := f.Close(); err != nil { + out.ErrLn("Close: %v", err) + os.Exit(1) + } + + return + } } func init() { diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index a248c95135ae..116336d0f9ed 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -2007,3 +2007,33 @@ func isTwoDigitSemver(ver string) bool { majorMinorOnly := regexp.MustCompile(`^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)$`) return majorMinorOnly.MatchString(ver) } + +func startNerdctld() { + // for containerd runtime using ssh, we have installed nerdctld and nerdctl into kicbase + // These things will be included in the ISO/Base image in the future versions + + // copy these binaries to the path of the containerd node + co := mustload.Running(ClusterFlagValue()) + runner := co.CP.Runner + + // and set 777 to these files + if out, err := runner.RunCmd(exec.Command("sudo", "chmod", "777", "/usr/local/bin/nerdctl", "/usr/local/bin/nerdctld")); err != nil { + exit.Error(reason.StartNerdctld, fmt.Sprintf("Failed setting permission for nerdctl: %s", out.Output()), err) + } + + // sudo systemctl start nerdctld.socket + if out, err := runner.RunCmd(exec.Command("sudo", "systemctl", "start", "nerdctld.socket")); err != nil { + exit.Error(reason.StartNerdctld, fmt.Sprintf("Failed to enable nerdctld.socket: %s", out.Output()), err) + } + // sudo systemctl start nerdctld.service + if out, err := runner.RunCmd(exec.Command("sudo", "systemctl", "start", "nerdctld.service")); err != nil { + exit.Error(reason.StartNerdctld, fmt.Sprintf("Failed to enable nerdctld.service: %s", out.Output()), err) + } + + // set up environment variable on remote machine. docker client uses 'non-login & non-interactive shell' therefore the only way is to modify .bashrc file of user 'docker' + // insert this at 4th line + envSetupCommand := exec.Command("/bin/bash", "-c", "sed -i '4i export DOCKER_HOST=unix:///run/nerdctld.sock' .bashrc") + if out, err := runner.RunCmd(envSetupCommand); err != nil { + exit.Error(reason.StartNerdctld, fmt.Sprintf("Failed to set up DOCKER_HOST: %s", out.Output()), err) + } +} diff --git a/deploy/kicbase/Dockerfile b/deploy/kicbase/Dockerfile index 4bbe9a7497aa..4e310cf5b175 100644 --- a/deploy/kicbase/Dockerfile +++ b/deploy/kicbase/Dockerfile @@ -49,6 +49,8 @@ ARG CRI_DOCKERD_VERSION="v0.3.3" ARG CRI_DOCKERD_COMMIT="b58acf8f78f9d7bce1241d1cddb0932e7101f278" ARG CNI_PLUGINS_VERSION="v1.3.0" ARG TARGETARCH +ARG NERDCTL_VERSION="1.0.0" +ARG NERDCTLD_VERSION="0.2.0" # copy in static files (configs, scripts) COPY deploy/kicbase/10-network-security.conf /etc/sysctl.d/10-network-security.conf @@ -59,6 +61,8 @@ COPY deploy/kicbase/containerd_docker_io_hosts.toml /etc/containerd/certs.d/dock COPY deploy/kicbase/clean-install /usr/local/bin/clean-install COPY deploy/kicbase/entrypoint /usr/local/bin/entrypoint COPY deploy/kicbase/CHANGELOG ./CHANGELOG +COPY deploy/kicbase/nerdctld/nerdctld.socket /etc/systemd/system/nerdctld.socket +COPY deploy/kicbase/nerdctld/nerdctld.service /etc/systemd/system/nerdctld.service COPY --from=auto-pause /src/cmd/auto-pause/auto-pause-${TARGETARCH} /bin/auto-pause # Install dependencies, first from apt, then from release tarballs. @@ -136,6 +140,18 @@ RUN clean-install \ # libglib2.0-0 is required for conmon, which is required for podman libglib2.0-0 +# Install nerdctl and nerdctld +RUN export ARCH=$(dpkg --print-architecture) \ + && if [ "$ARCH" = 'amd64' ] || [ "$ARCH" = 'arm64' ]; then \ + echo "Installing nerdctl and nerdctld ..." && \ + curl -L --retry 5 --output /tmp/nerdctl.tgz "https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION}/nerdctl-${NERDCTL_VERSION}-linux-$ARCH.tar.gz" &&\ + tar -C /usr/local/bin -xzvf /tmp/nerdctl.tgz &&\ + curl -L --retry 5 --output /tmp/nerdctld.tgz "https://github.com/afbjorklund/nerdctld/releases/download/v${NERDCTLD_VERSION}/nerdctld-${NERDCTLD_VERSION}-linux-$ARCH.tar.gz" &&\ + tar -C /usr/local/bin -xzvf /tmp/nerdctld.tgz &&\ + chmod 777 /usr/local/bin/nerdctl &&\ + chmod 777 /usr/local/bin/nerdctld; \ + fi + # install docker RUN sh -c "echo 'deb https://download.docker.com/linux/ubuntu jammy stable' > /etc/apt/sources.list.d/docker.list" && \ curl -L https://download.docker.com/linux/ubuntu/gpg -o docker.key && \ diff --git a/deploy/kicbase/nerdctld/nerdctld.service b/deploy/kicbase/nerdctld/nerdctld.service new file mode 100644 index 000000000000..16781e740400 --- /dev/null +++ b/deploy/kicbase/nerdctld/nerdctld.service @@ -0,0 +1,11 @@ +[Unit] +Description=nerdctld +Requires=nerdctld.socket containerd.service +After=nerdctld.socket containerd.service + +[Service] +Type=notify +Environment=CONTAINERD_NAMESPACE=k8s.io +ExecStart=nerdctld --addr fd:// +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/deploy/kicbase/nerdctld/nerdctld.socket b/deploy/kicbase/nerdctld/nerdctld.socket new file mode 100644 index 000000000000..52d5772038ac --- /dev/null +++ b/deploy/kicbase/nerdctld/nerdctld.socket @@ -0,0 +1,9 @@ +[Unit] +Description=nerdctld + +[Socket] +ListenStream=/var/run/nerdctld.sock +SocketMode=0666 + +[Install] +WantedBy=sockets.target \ No newline at end of file diff --git a/pkg/drivers/kic/types.go b/pkg/drivers/kic/types.go index 0a602b9086d5..0753a3543386 100644 --- a/pkg/drivers/kic/types.go +++ b/pkg/drivers/kic/types.go @@ -24,10 +24,10 @@ import ( const ( // Version is the current version of kic - Version = "v0.0.39-1688681246-16834" + Version = "v0.0.39-1689032083-15452" // SHA of the kic base image - baseImageSHA = "849205234efc46da016f3a964268d7c76363fc521532c280d0e8a6bf1cc393b5" + baseImageSHA = "41e03f55414b4bc4a9169ee03de8460ddd2a95f539efd83fce689159a4e20667" // The name of the GCR kicbase repository gcrRepo = "gcr.io/k8s-minikube/kicbase-builds" // The name of the Dockerhub kicbase repository diff --git a/pkg/minikube/reason/reason.go b/pkg/minikube/reason/reason.go index 9cdf4c454562..e7f6b76fe376 100644 --- a/pkg/minikube/reason/reason.go +++ b/pkg/minikube/reason/reason.go @@ -95,6 +95,8 @@ var ( InternalCacheLoad = Kind{ID: "MK_CACHE_LOAD", ExitCode: ExProgramError} // minikube failed to load a Docker Machine CommandRunner InternalCommandRunner = Kind{ID: "MK_COMMAND_RUNNER", ExitCode: ExProgramError} + // minikube failed to start nerdctld + StartNerdctld = Kind{ID: "MK_START_NERDCTLD", ExitCode: ExProgramError} // minikube failed to generate shell command completion for a supported shell InternalCompletion = Kind{ID: "MK_COMPLETION", ExitCode: ExProgramError} // minikube failed to set an internal config value @@ -426,6 +428,8 @@ var ( RuntimeEnable = Kind{ID: "RUNTIME_ENABLE", ExitCode: ExRuntimeError} // minikube failed to cache images for the current container runtime RuntimeCache = Kind{ID: "RUNTIME_CACHE", ExitCode: ExRuntimeError} + // minikube failed to start an ssh-agent when executing docker-env + SSHAgentStart = Kind{ID: "SSH_AGENT_START", ExitCode: ExRuntimeError} // service check timed out while starting minikube dashboard SvcCheckTimeout = Kind{ID: "SVC_CHECK_TIMEOUT", ExitCode: ExSvcTimeout} diff --git a/site/content/en/docs/commands/start.md b/site/content/en/docs/commands/start.md index a824eecf220d..43f373ec83bf 100644 --- a/site/content/en/docs/commands/start.md +++ b/site/content/en/docs/commands/start.md @@ -26,7 +26,7 @@ minikube start [flags] --apiserver-names strings A set of apiserver names which are used in the generated certificate for kubernetes. This can be used if you want to make the apiserver available from outside the machine --apiserver-port int The apiserver listening port (default 8443) --auto-update-drivers If set, automatically updates drivers to the latest version. Defaults to true. (default true) - --base-image string The base image to use for docker/podman drivers. Intended for local development. (default "gcr.io/k8s-minikube/kicbase-builds:v0.0.39-1688681246-16834@sha256:849205234efc46da016f3a964268d7c76363fc521532c280d0e8a6bf1cc393b5") + --base-image string The base image to use for docker/podman drivers. Intended for local development. (default "gcr.io/k8s-minikube/kicbase-builds:v0.0.39-1689032083-15452@sha256:41e03f55414b4bc4a9169ee03de8460ddd2a95f539efd83fce689159a4e20667") --binary-mirror string Location to fetch kubectl, kubelet, & kubeadm binaries from. --cache-images If true, cache docker images for the current bootstrapper and load them into the machine. Always false with --driver=none. (default true) --cert-expiration duration Duration until minikube certificate expiration, defaults to three years (26280h). (default 26280h0m0s) diff --git a/site/content/en/docs/contrib/errorcodes.en.md b/site/content/en/docs/contrib/errorcodes.en.md index 5085c3133ea3..dc256eff5ce1 100644 --- a/site/content/en/docs/contrib/errorcodes.en.md +++ b/site/content/en/docs/contrib/errorcodes.en.md @@ -49,6 +49,9 @@ minkube failed to cache and load cached images "MK_COMMAND_RUNNER" (Exit code ExProgramError) minikube failed to load a Docker Machine CommandRunner +"MK_START_NERDCTLD" (Exit code ExProgramError) +minikube failed to start nerdctld + "MK_COMPLETION" (Exit code ExProgramError) minikube failed to generate shell command completion for a supported shell @@ -403,6 +406,9 @@ minikube failed to enable the current container runtime "RUNTIME_CACHE" (Exit code ExRuntimeError) minikube failed to cache images for the current container runtime +"SSH_AGENT_START" (Exit code ExRuntimeError) +minikube failed to start an ssh-agent when executing docker-env + "SVC_CHECK_TIMEOUT" (Exit code ExSvcTimeout) service check timed out while starting minikube dashboard diff --git a/site/content/en/docs/contrib/tests.en.md b/site/content/en/docs/contrib/tests.en.md index 5c6c113e76be..1b54b2bfadd1 100644 --- a/site/content/en/docs/contrib/tests.en.md +++ b/site/content/en/docs/contrib/tests.en.md @@ -79,6 +79,9 @@ makes sure the --force-systemd flag worked with the cri-o container runtime ## TestForceSystemdEnv makes sure the MINIKUBE_FORCE_SYSTEMD environment variable works just as well as the --force-systemd flag +## TestDockerEnvContainerd +makes sure that minikube docker-env command works when the runtime is containerd + ## TestKVMDriverInstallOrUpdate makes sure our docker-machine-driver-kvm2 binary can be installed properly diff --git a/test/integration/docker_test.go b/test/integration/docker_test.go index 0d1ebea891ee..71a44c587d12 100644 --- a/test/integration/docker_test.go +++ b/test/integration/docker_test.go @@ -20,10 +20,16 @@ package integration import ( "context" + "fmt" "os" "os/exec" + "regexp" + "runtime" "strings" "testing" + "time" + + "k8s.io/minikube/pkg/minikube/constants" ) // TestDockerFlags makes sure the --docker-env and --docker-opt parameters are respected @@ -158,3 +164,94 @@ func TestForceSystemdEnv(t *testing.T) { validateContainerdSystemd(ctx, t, profile) } } + +// TestDockerEnvContainerd makes sure that minikube docker-env command works when the runtime is containerd +func TestDockerEnvContainerd(t *testing.T) { + t.Log("running with", ContainerRuntime(), DockerDriver(), runtime.GOOS, runtime.GOARCH) + if ContainerRuntime() != constants.Containerd || !DockerDriver() || runtime.GOOS != "linux" { + t.Skip("skipping: TestDockerEnvContainerd can only be run with the containerd runtime on Docker driver") + } + profile := UniqueProfileName("dockerenv") + ctx, cancel := context.WithTimeout(context.Background(), Minutes(30)) + defer CleanupWithLogs(t, profile, cancel) + + // start the minikube with containerd runtime + args := append([]string{"start", "-p", profile}, StartArgs()...) + cmd := exec.CommandContext(ctx, Target(), args...) + startResult, err := Run(t, cmd) + if err != nil { + t.Errorf("failed to start minikube with args: %q : %v", startResult.Command(), err) + } + time.Sleep(time.Second * 10) + + // execute 'minikube docker-env --ssh-host --ssh-add' and extract the 'DOCKER_HOST' environment value + cmd = exec.CommandContext(ctx, "/bin/bash", "-c", fmt.Sprintf("%s docker-env --ssh-host --ssh-add -p %s", Target(), profile)) + result, err := Run(t, cmd) + if err != nil { + t.Errorf("failed to execute minikube docker-env --ssh-host --ssh-add, error: %v, output: %s", err, result.Output()) + } + + output := result.Output() + groups := regexp.MustCompile(`DOCKER_HOST="(\S*)"`).FindStringSubmatch(output) + if len(groups) < 2 { + t.Errorf("DOCKER_HOST doesn't match expected format, output is %s", output) + } + dockerHost := groups[1] + segments := strings.Split(dockerHost, ":") + if len(segments) < 3 { + t.Errorf("DOCKER_HOST doesn't match expected format, output is %s", dockerHost) + } + + // get SSH_AUTH_SOCK + groups = regexp.MustCompile(`SSH_AUTH_SOCK=(\S*)`).FindStringSubmatch(output) + if len(groups) < 2 { + t.Errorf("failed to acquire SSH_AUTH_SOCK, output is %s", output) + } + sshAuthSock := groups[1] + // get SSH_AGENT_PID + groups = regexp.MustCompile(`SSH_AGENT_PID=(\S*)`).FindStringSubmatch(output) + if len(groups) < 2 { + t.Errorf("failed to acquire SSH_AUTH_PID, output is %s", output) + } + sshAgentPid := groups[1] + + cmd = exec.CommandContext(ctx, "/bin/bash", "-c", fmt.Sprintf("SSH_AUTH_SOCK=%s SSH_AGENT_PID=%s DOCKER_HOST=%s docker version", sshAuthSock, sshAgentPid, dockerHost)) + + result, err = Run(t, cmd) + if err != nil { + t.Fatalf("failed to execute 'docker version', error: %v, output: %s", err, result.Output()) + } + // if we are really connecting to nerdctld inside node, docker version output should have word 'nerdctl' + // If everything works properly, in the output of `docker version` you should be able to see something like + /* + Server: + nerdctl: + Version: 1.0.0 + buildctl: + Version: 0.10.3 + GitCommit: c8d25d9a103b70dc300a4fd55e7e576472284e31 + containerd: + Version: 1.6.10 + GitCommit: 770bd0108c32f3fb5c73ae1264f7e503fe7b2661 + */ + if !strings.Contains(result.Output(), "nerdctl") { + t.Fatal("failed to detect keyword 'nerdctl' in output of docker version") + } + + // now try to build an image + cmd = exec.CommandContext(ctx, "/bin/bash", "-c", fmt.Sprintf("SSH_AUTH_SOCK=%s SSH_AGENT_PID=%s DOCKER_HOST=%s DOCKER_BUILDKIT=0 docker build -t local/minikube-dockerenv-containerd-test:latest testdata/docker-env", sshAuthSock, sshAgentPid, dockerHost)) + result, err = Run(t, cmd) + if err != nil { + t.Errorf("failed to build images, error: %v, output:%s", err, result.Output()) + } + + // and check whether that image is really available + cmd = exec.CommandContext(ctx, "/bin/bash", "-c", fmt.Sprintf("SSH_AUTH_SOCK=%s SSH_AGENT_PID=%s DOCKER_HOST=%s docker image ls", sshAuthSock, sshAgentPid, dockerHost)) + result, err = Run(t, cmd) + if err != nil { + t.Fatalf("failed to execute 'docker image ls', error: %v, output: %s", err, result.Output()) + } + if !strings.Contains(result.Output(), "local/minikube-dockerenv-containerd-test") { + t.Fatal("failed to detect image 'local/minikube-dockerenv-containerd-test' in output of docker image ls") + } +} diff --git a/test/integration/testdata/docker-env/Dockerfile b/test/integration/testdata/docker-env/Dockerfile new file mode 100644 index 000000000000..b5e77a7d5190 --- /dev/null +++ b/test/integration/testdata/docker-env/Dockerfile @@ -0,0 +1,3 @@ +FROM alpine:latest + +CMD [ "/bin/bash" ] \ No newline at end of file diff --git a/translations/de.json b/translations/de.json index 0ce5fc208fa9..36d51883e87d 100644 --- a/translations/de.json +++ b/translations/de.json @@ -879,6 +879,7 @@ "Using rootless driver was required, but the current driver does not seem rootless": "", "Using rootless {{.driver_name}} driver": "", "Using the '{{.runtime}}' runtime with the 'none' driver is an untested configuration!": "Das Verwenden der '{{.runtime}}' Laufzeitumgebung mit dem 'none' Treiber ist eine ungetestete Konfiguration!", + "Using the docker-env command with the containerd runtime is a highly experimental feature, please provide feedback or contribute to make it better": "", "Using the {{.driver}} driver based on existing profile": "Verwende den Treiber {{.driver}} basierend auf dem existierenden Profil", "Using the {{.driver}} driver based on user configuration": "Verwende den Treiber {{.driver}} basierend auf der Benutzer-Konfiguration", "Using {{.driver_name}} driver with root privileges": "", diff --git a/translations/es.json b/translations/es.json index e2f0d236b2fc..ff859d432af3 100644 --- a/translations/es.json +++ b/translations/es.json @@ -711,7 +711,6 @@ "The cri socket path to be used": "La ruta del socket de cri", "The cri socket path to be used.": "", "The docker-env command is incompatible with multi-node clusters. Use the 'registry' add-on: https://minikube.sigs.k8s.io/docs/handbook/registry/": "", - "The docker-env command is only compatible with the \"docker\" runtime, but this cluster was configured to use the \"{{.runtime}}\" runtime.": "", "The driver '{{.driver}}' is not supported on {{.os}}/{{.arch}}": "El controlador \"{{.driver}}\" no se puede utilizar en {{.os}}/{{.arch}}", "The existing \"{{.name}}\" cluster was created using the \"{{.old}}\" driver, which is incompatible with requested \"{{.new}}\" driver.": "", "The existing node configuration appears to be corrupt. Run 'minikube delete'": "", @@ -878,6 +877,7 @@ "Using rootless driver was required, but the current driver does not seem rootless": "", "Using rootless {{.driver_name}} driver": "", "Using the '{{.runtime}}' runtime with the 'none' driver is an untested configuration!": "", + "Using the docker-env command with the containerd runtime is a highly experimental feature, please provide feedback or contribute to make it better": "", "Using the {{.driver}} driver based on existing profile": "", "Using the {{.driver}} driver based on user configuration": "", "Using {{.driver_name}} driver with root privileges": "", diff --git a/translations/fr.json b/translations/fr.json index cbbe31d98309..d3a456637798 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -859,6 +859,7 @@ "Using rootless driver was required, but the current driver does not seem rootless": "L'utilisation d'un pilote sans root était nécessaire, mais le pilote actuel ne semble pas sans root", "Using rootless {{.driver_name}} driver": "Utilisation du pilote {{.driver_name}} sans root", "Using the '{{.runtime}}' runtime with the 'none' driver is an untested configuration!": "L'utilisation du runtime '{{.runtime}}' avec le pilote 'none' est une configuration non testée !", + "Using the docker-env command with the containerd runtime is a highly experimental feature, please provide feedback or contribute to make it better": "", "Using the {{.driver}} driver based on existing profile": "Utilisation du pilote {{.driver}} basé sur le profil existant", "Using the {{.driver}} driver based on user configuration": "Utilisation du pilote {{.driver}} basé sur la configuration de l'utilisateur", "Using {{.driver_name}} driver with root privileges": "Utilisation du pilote {{.driver_name}} avec le privilège root", diff --git a/translations/ja.json b/translations/ja.json index dc3781d03a22..d93edf744800 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -824,6 +824,7 @@ "Using rootless driver was required, but the current driver does not seem rootless": "rootless ドライバー使用が必要でしたが、現在のドライバーは rootless が必要ないようです", "Using rootless {{.driver_name}} driver": "rootless {{.driver_name}} ドライバー使用", "Using the '{{.runtime}}' runtime with the 'none' driver is an untested configuration!": "' none' ドライバーでの '{{.runtime}}' ランタイム使用は、未テストの設定です!", + "Using the docker-env command with the containerd runtime is a highly experimental feature, please provide feedback or contribute to make it better": "", "Using the {{.driver}} driver based on existing profile": "既存のプロファイルを元に、{{.driver}} ドライバーを使用します", "Using the {{.driver}} driver based on user configuration": "ユーザーの設定に基づいて {{.driver}} ドライバーを使用します", "Using {{.driver_name}} driver with root privileges": "root 権限を持つ {{.driver_name}} ドライバーを使用", diff --git a/translations/ko.json b/translations/ko.json index e9430c792841..fd975c76dcdd 100644 --- a/translations/ko.json +++ b/translations/ko.json @@ -716,7 +716,6 @@ "The control plane node must be running for this command": "컨트롤 플레인 노드는 실행 상태여야 합니다", "The cri socket path to be used.": "", "The docker-env command is incompatible with multi-node clusters. Use the 'registry' add-on: https://minikube.sigs.k8s.io/docs/handbook/registry/": "", - "The docker-env command is only compatible with the \"docker\" runtime, but this cluster was configured to use the \"{{.runtime}}\" runtime.": "", "The driver '{{.driver}}' is not supported on {{.os}}/{{.arch}}": "", "The existing \"{{.name}}\" cluster was created using the \"{{.old}}\" driver, which is incompatible with requested \"{{.new}}\" driver.": "", "The existing node configuration appears to be corrupt. Run 'minikube delete'": "", @@ -877,6 +876,7 @@ "Using rootless driver was required, but the current driver does not seem rootless": "", "Using rootless {{.driver_name}} driver": "", "Using the '{{.runtime}}' runtime with the 'none' driver is an untested configuration!": "", + "Using the docker-env command with the containerd runtime is a highly experimental feature, please provide feedback or contribute to make it better": "", "Using the {{.driver}} driver based on existing profile": "기존 프로필에 기반하여 {{.driver}} 드라이버를 사용하는 중", "Using the {{.driver}} driver based on user configuration": "유저 환경 설정 정보에 기반하여 {{.driver}} 드라이버를 사용하는 중", "Using {{.driver_name}} driver with root privileges": "", diff --git a/translations/pl.json b/translations/pl.json index 9ef2617663ff..d143a39368da 100644 --- a/translations/pl.json +++ b/translations/pl.json @@ -724,7 +724,6 @@ "The cri socket path to be used.": "", "The docker service is currently not active": "Serwis docker jest nieaktywny", "The docker-env command is incompatible with multi-node clusters. Use the 'registry' add-on: https://minikube.sigs.k8s.io/docs/handbook/registry/": "", - "The docker-env command is only compatible with the \"docker\" runtime, but this cluster was configured to use the \"{{.runtime}}\" runtime.": "", "The driver '{{.driver}}' is not supported on {{.os}}/{{.arch}}": "Sterownik '{{.driver}} jest niewspierany przez system {{.os}}/{{.arch}}", "The existing \"{{.name}}\" cluster was created using the \"{{.old}}\" driver, which is incompatible with requested \"{{.new}}\" driver.": "", "The existing node configuration appears to be corrupt. Run 'minikube delete'": "", @@ -887,6 +886,7 @@ "Using rootless driver was required, but the current driver does not seem rootless": "", "Using rootless {{.driver_name}} driver": "", "Using the '{{.runtime}}' runtime with the 'none' driver is an untested configuration!": "", + "Using the docker-env command with the containerd runtime is a highly experimental feature, please provide feedback or contribute to make it better": "", "Using the {{.driver}} driver based on existing profile": "", "Using the {{.driver}} driver based on user configuration": "", "Using {{.driver_name}} driver with root privileges": "", diff --git a/translations/ru.json b/translations/ru.json index a9b5e405cf28..1d35a5ac9509 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -658,7 +658,6 @@ "The control plane node must be running for this command": "", "The cri socket path to be used.": "", "The docker-env command is incompatible with multi-node clusters. Use the 'registry' add-on: https://minikube.sigs.k8s.io/docs/handbook/registry/": "", - "The docker-env command is only compatible with the \"docker\" runtime, but this cluster was configured to use the \"{{.runtime}}\" runtime.": "", "The driver '{{.driver}}' is not supported on {{.os}}/{{.arch}}": "", "The existing \"{{.name}}\" cluster was created using the \"{{.old}}\" driver, which is incompatible with requested \"{{.new}}\" driver.": "", "The existing node configuration appears to be corrupt. Run 'minikube delete'": "", @@ -813,6 +812,7 @@ "Using rootless driver was required, but the current driver does not seem rootless": "", "Using rootless {{.driver_name}} driver": "", "Using the '{{.runtime}}' runtime with the 'none' driver is an untested configuration!": "", + "Using the docker-env command with the containerd runtime is a highly experimental feature, please provide feedback or contribute to make it better": "", "Using the {{.driver}} driver based on existing profile": "Используется драйвер {{.driver}} на основе существующего профиля", "Using the {{.driver}} driver based on user configuration": "Используется драйвер {{.driver}} на основе конфига пользователя", "Using {{.driver_name}} driver with root privileges": "", diff --git a/translations/strings.txt b/translations/strings.txt index 8170ac573ef5..d104a0929a98 100644 --- a/translations/strings.txt +++ b/translations/strings.txt @@ -658,7 +658,6 @@ "The control plane node must be running for this command": "", "The cri socket path to be used.": "", "The docker-env command is incompatible with multi-node clusters. Use the 'registry' add-on: https://minikube.sigs.k8s.io/docs/handbook/registry/": "", - "The docker-env command is only compatible with the \"docker\" runtime, but this cluster was configured to use the \"{{.runtime}}\" runtime.": "", "The driver '{{.driver}}' is not supported on {{.os}}/{{.arch}}": "", "The existing \"{{.name}}\" cluster was created using the \"{{.old}}\" driver, which is incompatible with requested \"{{.new}}\" driver.": "", "The existing node configuration appears to be corrupt. Run 'minikube delete'": "", @@ -813,6 +812,7 @@ "Using rootless driver was required, but the current driver does not seem rootless": "", "Using rootless {{.driver_name}} driver": "", "Using the '{{.runtime}}' runtime with the 'none' driver is an untested configuration!": "", + "Using the docker-env command with the containerd runtime is a highly experimental feature, please provide feedback or contribute to make it better": "", "Using the {{.driver}} driver based on existing profile": "", "Using the {{.driver}} driver based on user configuration": "", "Using {{.driver_name}} driver with root privileges": "", diff --git a/translations/zh-CN.json b/translations/zh-CN.json index e32c3040ba4b..21f135c95a47 100644 --- a/translations/zh-CN.json +++ b/translations/zh-CN.json @@ -989,6 +989,7 @@ "Using rootless driver was required, but the current driver does not seem rootless": "", "Using rootless {{.driver_name}} driver": "", "Using the '{{.runtime}}' runtime with the 'none' driver is an untested configuration!": "同时使用 'none' 驱动以及 '{{.runtime}}' 运行时是未经测试过的配置!", + "Using the docker-env command with the containerd runtime is a highly experimental feature, please provide feedback or contribute to make it better": "", "Using the running {{.driver_name}} \"{{.profile_name}}\" VM ...": "使用正在运行的 {{.driver_name}} \"{{.profile_name}}\" 虚拟机", "Using the {{.driver}} driver based on existing profile": "根据现有的配置文件使用 {{.driver}} 驱动程序", "Using the {{.driver}} driver based on user configuration": "根据用户配置使用 {{.driver}} 驱动程序",