diff --git a/Makefile b/Makefile index 564359501bba..6c4f73b8262a 100755 --- a/Makefile +++ b/Makefile @@ -500,8 +500,8 @@ storage-provisioner-image: out/storage-provisioner-$(GOARCH) ## Build storage-pr .PHONY: kic-base-image kic-base-image: ## builds the base image used for kic. - docker rmi -f $(REGISTRY)/kicbase:v0.0.4-snapshot || true - docker build -f ./hack/images/kicbase.Dockerfile -t $(REGISTRY)/kicbase:v0.0.4-snapshot --build-arg COMMIT_SHA=${VERSION}-$(COMMIT) . + docker rmi -f $(REGISTRY)/kicbase:v0.0.5-snapshot || true + docker build -f ./hack/images/kicbase.Dockerfile -t $(REGISTRY)/kicbase:v0.0.5-snapshot --build-arg COMMIT_SHA=${VERSION}-$(COMMIT) . diff --git a/hack/images/kicbase.Dockerfile b/hack/images/kicbase.Dockerfile index 1636d288bc84..836f359a66b0 100644 --- a/hack/images/kicbase.Dockerfile +++ b/hack/images/kicbase.Dockerfile @@ -12,6 +12,7 @@ RUN apt-get update && apt-get install -y \ && apt-get clean -y # disable containerd by default RUN systemctl disable containerd +RUN rm /etc/crictl.yaml # enable docker which is default RUN systemctl enable docker # making SSH work for docker container diff --git a/pkg/drivers/kic/types.go b/pkg/drivers/kic/types.go index 62826954ca01..317ee956f0a1 100644 --- a/pkg/drivers/kic/types.go +++ b/pkg/drivers/kic/types.go @@ -26,7 +26,7 @@ const ( // DefaultBindIPV4 is The default IP the container will bind to. DefaultBindIPV4 = "127.0.0.1" // BaseImage is the base image is used to spin up kic containers. it uses same base-image as kind. - BaseImage = "gcr.io/k8s-minikube/kicbase:v0.0.4@sha256:01552b7ffc7cb0c49c6106796ed73f69647691d8fbae89fed8ee317dc7f1015a" + BaseImage = "gcr.io/k8s-minikube/kicbase:v0.0.5@sha256:3ddd8461dfb5c3e452ccc44d87750b87a574ec23fc425da67dccc1f0c57d428a" // OverlayImage is the cni plugin used for overlay image, created by kind. // CNI plugin image used for kic drivers created by kind. OverlayImage = "kindest/kindnetd:0.5.3" diff --git a/pkg/minikube/machine/client.go b/pkg/minikube/machine/client.go index 9d8b0e7236d4..a07cda9d2217 100644 --- a/pkg/minikube/machine/client.go +++ b/pkg/minikube/machine/client.go @@ -36,6 +36,7 @@ import ( "github.com/docker/machine/libmachine/host" "github.com/docker/machine/libmachine/mcnutils" "github.com/docker/machine/libmachine/persist" + lib_provision "github.com/docker/machine/libmachine/provision" "github.com/docker/machine/libmachine/ssh" "github.com/docker/machine/libmachine/state" "github.com/docker/machine/libmachine/swarm" @@ -207,10 +208,15 @@ func (api *LocalClient) Create(h *host.Host) error { { "provisioning", func() error { - if driver.BareMetal(h.Driver.DriverName()) || driver.IsKIC(h.Driver.DriverName()) { + if driver.BareMetal(h.Driver.DriverName()) { return nil } - pv := provision.NewBuildrootProvisioner(h.Driver) + var pv lib_provision.Provisioner + if driver.IsKIC(h.Driver.DriverName()) { + pv = provision.NewUbuntuProvisioner(h.Driver) + } else { + pv = provision.NewBuildrootProvisioner(h.Driver) + } return pv.Provision(*h.HostOptions.SwarmOptions, *h.HostOptions.AuthOptions, *h.HostOptions.EngineOptions) }, }, diff --git a/pkg/provision/buildroot.go b/pkg/provision/buildroot.go index 41798fe3aed3..e1701baf18b2 100644 --- a/pkg/provision/buildroot.go +++ b/pkg/provision/buildroot.go @@ -19,29 +19,18 @@ package provision import ( "bytes" "fmt" - "os/exec" "path" - "path/filepath" - "strings" "text/template" "time" "github.com/docker/machine/libmachine/auth" - "github.com/docker/machine/libmachine/cert" "github.com/docker/machine/libmachine/drivers" "github.com/docker/machine/libmachine/engine" "github.com/docker/machine/libmachine/log" - "github.com/docker/machine/libmachine/mcnutils" "github.com/docker/machine/libmachine/provision" "github.com/docker/machine/libmachine/provision/pkgaction" "github.com/docker/machine/libmachine/provision/serviceaction" "github.com/docker/machine/libmachine/swarm" - "github.com/pkg/errors" - "k8s.io/minikube/pkg/minikube/assets" - "k8s.io/minikube/pkg/minikube/command" - "k8s.io/minikube/pkg/minikube/config" - "k8s.io/minikube/pkg/minikube/sshutil" - "k8s.io/minikube/pkg/util" "k8s.io/minikube/pkg/util/retry" ) @@ -50,15 +39,6 @@ type BuildrootProvisioner struct { provision.SystemdProvisioner } -// for escaping systemd template specifiers (e.g. '%i'), which are not supported by minikube -var systemdSpecifierEscaper = strings.NewReplacer("%", "%%") - -func init() { - provision.Register("Buildroot", &provision.RegisteredProvisioner{ - New: NewBuildrootProvisioner, - }) -} - // NewBuildrootProvisioner creates a new BuildrootProvisioner func NewBuildrootProvisioner(d drivers.Driver) provision.Provisioner { return &BuildrootProvisioner{ @@ -75,17 +55,6 @@ func (p *BuildrootProvisioner) CompatibleWithHost() bool { return p.OsReleaseInfo.ID == "buildroot" } -// escapeSystemdDirectives escapes special characters in the input variables used to create the -// systemd unit file, which would otherwise be interpreted as systemd directives. An example -// are template specifiers (e.g. '%i') which are predefined variables that get evaluated dynamically -// (see systemd man pages for more info). This is not supported by minikube, thus needs to be escaped. -func escapeSystemdDirectives(engineConfigContext *provision.EngineConfigContext) { - // escape '%' in Environment option so that it does not evaluate into a template specifier - engineConfigContext.EngineOptions.Env = util.ReplaceChars(engineConfigContext.EngineOptions.Env, systemdSpecifierEscaper) - // input might contain whitespaces, wrap it in quotes - engineConfigContext.EngineOptions.Env = util.ConcatStrings(engineConfigContext.EngineOptions.Env, "\"", "\"") -} - // GenerateDockerOptions generates the *provision.DockerOptions for this provisioner func (p *BuildrootProvisioner) GenerateDockerOptions(dockerPort int) (*provision.DockerOptions, error) { var engineCfg bytes.Buffer @@ -192,14 +161,6 @@ WantedBy=multi-user.target return dockerCfg, nil } -func rootFileSystemType(p *BuildrootProvisioner) (string, error) { - fs, err := p.SSHCommand("df --output=fstype / | tail -n 1") - if err != nil { - return "", err - } - return strings.TrimSpace(fs), nil -} - // Package installs a package func (p *BuildrootProvisioner) Package(name string, action pkgaction.PackageAction) error { return nil @@ -235,176 +196,10 @@ func (p *BuildrootProvisioner) Provision(swarmOptions swarm.Options, authOptions } log.Debugf("setting minikube options for container-runtime") - if err := setContainerRuntimeOptions(p); err != nil { + if err := setContainerRuntimeOptions(p.Driver.GetMachineName(), p); err != nil { log.Debugf("Error setting container-runtime options during provisioning %v", err) return err } return nil } - -func setRemoteAuthOptions(p provision.Provisioner) auth.Options { - dockerDir := p.GetDockerOptionsDir() - authOptions := p.GetAuthOptions() - - // due to windows clients, we cannot use filepath.Join as the paths - // will be mucked on the linux hosts - authOptions.CaCertRemotePath = path.Join(dockerDir, "ca.pem") - authOptions.ServerCertRemotePath = path.Join(dockerDir, "server.pem") - authOptions.ServerKeyRemotePath = path.Join(dockerDir, "server-key.pem") - - return authOptions -} - -func setContainerRuntimeOptions(p *BuildrootProvisioner) error { - c, err := config.Load(p.Driver.GetMachineName()) - if err != nil { - return errors.Wrap(err, "getting cluster config") - } - - switch c.KubernetesConfig.ContainerRuntime { - case "crio", "cri-o": - return p.setCrioOptions() - case "containerd": - return nil - default: - _, err := p.GenerateDockerOptions(engine.DefaultPort) - return err - } -} - -func (p *BuildrootProvisioner) setCrioOptions() error { - // pass through --insecure-registry - var ( - crioOptsTmpl = ` -CRIO_MINIKUBE_OPTIONS='{{ range .EngineOptions.InsecureRegistry }}--insecure-registry {{.}} {{ end }}' -` - crioOptsPath = "/etc/sysconfig/crio.minikube" - ) - t, err := template.New("crioOpts").Parse(crioOptsTmpl) - if err != nil { - return err - } - var crioOptsBuf bytes.Buffer - if err := t.Execute(&crioOptsBuf, p); err != nil { - return err - } - - if _, err = p.SSHCommand(fmt.Sprintf("sudo mkdir -p %s && printf %%s \"%s\" | sudo tee %s", path.Dir(crioOptsPath), crioOptsBuf.String(), crioOptsPath)); err != nil { - return err - } - - return nil -} - -func configureAuth(p *BuildrootProvisioner) error { - log.Infof("configureAuth start") - start := time.Now() - defer func() { - log.Infof("configureAuth took %s", time.Since(start)) - }() - - driver := p.GetDriver() - machineName := driver.GetMachineName() - authOptions := p.GetAuthOptions() - org := mcnutils.GetUsername() + "." + machineName - bits := 2048 - - ip, err := driver.GetIP() - if err != nil { - return errors.Wrap(err, "error getting ip during provisioning") - } - - if err := copyHostCerts(authOptions); err != nil { - return err - } - - // The Host IP is always added to the certificate's SANs list - hosts := append(authOptions.ServerCertSANs, ip, "localhost") - log.Debugf("generating server cert: %s ca-key=%s private-key=%s org=%s san=%s", - authOptions.ServerCertPath, - authOptions.CaCertPath, - authOptions.CaPrivateKeyPath, - org, - hosts, - ) - - err = cert.GenerateCert(&cert.Options{ - Hosts: hosts, - CertFile: authOptions.ServerCertPath, - KeyFile: authOptions.ServerKeyPath, - CAFile: authOptions.CaCertPath, - CAKeyFile: authOptions.CaPrivateKeyPath, - Org: org, - Bits: bits, - }) - - if err != nil { - return fmt.Errorf("error generating server cert: %v", err) - } - - return copyRemoteCerts(authOptions, driver) -} - -func copyHostCerts(authOptions auth.Options) error { - log.Infof("copyHostCerts") - execRunner := &command.ExecRunner{} - hostCerts := map[string]string{ - authOptions.CaCertPath: path.Join(authOptions.StorePath, "ca.pem"), - authOptions.ClientCertPath: path.Join(authOptions.StorePath, "cert.pem"), - authOptions.ClientKeyPath: path.Join(authOptions.StorePath, "key.pem"), - } - - if _, err := execRunner.RunCmd(exec.Command("mkdir", "-p", authOptions.StorePath)); err != nil { - return err - } - for src, dst := range hostCerts { - f, err := assets.NewFileAsset(src, path.Dir(dst), filepath.Base(dst), "0777") - if err != nil { - return errors.Wrapf(err, "open cert file: %s", src) - } - if err := execRunner.Copy(f); err != nil { - return errors.Wrapf(err, "transferring file: %+v", f) - } - } - - return nil -} - -func copyRemoteCerts(authOptions auth.Options, driver drivers.Driver) error { - log.Infof("copyRemoteCerts") - - remoteCerts := map[string]string{ - authOptions.CaCertPath: authOptions.CaCertRemotePath, - authOptions.ServerCertPath: authOptions.ServerCertRemotePath, - authOptions.ServerKeyPath: authOptions.ServerKeyRemotePath, - } - - sshClient, err := sshutil.NewSSHClient(driver) - if err != nil { - return errors.Wrap(err, "provisioning: error getting ssh client") - } - sshRunner := command.NewSSHRunner(sshClient) - - dirs := []string{} - for _, dst := range remoteCerts { - dirs = append(dirs, path.Dir(dst)) - } - - args := append([]string{"mkdir", "-p"}, dirs...) - if _, err = sshRunner.RunCmd(exec.Command("sudo", args...)); err != nil { - return err - } - - for src, dst := range remoteCerts { - f, err := assets.NewFileAsset(src, path.Dir(dst), filepath.Base(dst), "0640") - if err != nil { - return errors.Wrapf(err, "error copying %s to %s", src, dst) - } - if err := sshRunner.Copy(f); err != nil { - return errors.Wrapf(err, "transferring file to machine %v", f) - } - } - - return nil -} diff --git a/pkg/provision/provision.go b/pkg/provision/provision.go new file mode 100644 index 000000000000..0ef9f69664cc --- /dev/null +++ b/pkg/provision/provision.go @@ -0,0 +1,252 @@ +/* +Copyright 2019 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package provision + +import ( + "bytes" + "fmt" + "os/exec" + "path" + "path/filepath" + "strings" + "text/template" + "time" + + "github.com/docker/machine/libmachine/auth" + "github.com/docker/machine/libmachine/cert" + "github.com/docker/machine/libmachine/drivers" + "github.com/docker/machine/libmachine/engine" + "github.com/docker/machine/libmachine/log" + "github.com/docker/machine/libmachine/mcnutils" + "github.com/docker/machine/libmachine/provision" + "github.com/docker/machine/libmachine/swarm" + "github.com/pkg/errors" + "k8s.io/minikube/pkg/minikube/assets" + "k8s.io/minikube/pkg/minikube/command" + "k8s.io/minikube/pkg/minikube/config" + "k8s.io/minikube/pkg/minikube/sshutil" + "k8s.io/minikube/pkg/util" +) + +// generic interface for minikube provisioner +type miniProvisioner interface { + String() string + CompatibleWithHost() bool + GenerateDockerOptions(int) (*provision.DockerOptions, error) + Provision(swarmOptions swarm.Options, authOptions auth.Options, engineOptions engine.Options) error + GetDriver() drivers.Driver + GetAuthOptions() auth.Options + SSHCommand(string) (string, error) +} + +// for escaping systemd template specifiers (e.g. '%i'), which are not supported by minikube +var systemdSpecifierEscaper = strings.NewReplacer("%", "%%") + +func init() { + provision.Register("Buildroot", &provision.RegisteredProvisioner{ + New: NewBuildrootProvisioner, + }) + provision.Register("Ubuntu", &provision.RegisteredProvisioner{ + New: NewUbuntuProvisioner, + }) + +} + +func configureAuth(p miniProvisioner) error { + log.Infof("configureAuth start") + start := time.Now() + defer func() { + log.Infof("configureAuth took %s", time.Since(start)) + }() + + driver := p.GetDriver() + machineName := driver.GetMachineName() + authOptions := p.GetAuthOptions() + org := mcnutils.GetUsername() + "." + machineName + bits := 2048 + + ip, err := driver.GetIP() + if err != nil { + return errors.Wrap(err, "error getting ip during provisioning") + } + + if err := copyHostCerts(authOptions); err != nil { + return err + } + + // The Host IP is always added to the certificate's SANs list + hosts := append(authOptions.ServerCertSANs, ip, "localhost", "127.0.0.1") + log.Debugf("generating server cert: %s ca-key=%s private-key=%s org=%s san=%s", + authOptions.ServerCertPath, + authOptions.CaCertPath, + authOptions.CaPrivateKeyPath, + org, + hosts, + ) + + err = cert.GenerateCert(&cert.Options{ + Hosts: hosts, + CertFile: authOptions.ServerCertPath, + KeyFile: authOptions.ServerKeyPath, + CAFile: authOptions.CaCertPath, + CAKeyFile: authOptions.CaPrivateKeyPath, + Org: org, + Bits: bits, + }) + + if err != nil { + return fmt.Errorf("error generating server cert: %v", err) + } + + return copyRemoteCerts(authOptions, driver) +} + +func copyHostCerts(authOptions auth.Options) error { + log.Infof("copyHostCerts") + execRunner := &command.ExecRunner{} + hostCerts := map[string]string{ + authOptions.CaCertPath: path.Join(authOptions.StorePath, "ca.pem"), + authOptions.ClientCertPath: path.Join(authOptions.StorePath, "cert.pem"), + authOptions.ClientKeyPath: path.Join(authOptions.StorePath, "key.pem"), + } + + if _, err := execRunner.RunCmd(exec.Command("mkdir", "-p", authOptions.StorePath)); err != nil { + return err + } + for src, dst := range hostCerts { + f, err := assets.NewFileAsset(src, path.Dir(dst), filepath.Base(dst), "0777") + if err != nil { + return errors.Wrapf(err, "open cert file: %s", src) + } + if err := execRunner.Copy(f); err != nil { + return errors.Wrapf(err, "transferring file: %+v", f) + } + } + + return nil +} + +func copyRemoteCerts(authOptions auth.Options, driver drivers.Driver) error { + log.Infof("copyRemoteCerts") + + remoteCerts := map[string]string{ + authOptions.CaCertPath: authOptions.CaCertRemotePath, + authOptions.ServerCertPath: authOptions.ServerCertRemotePath, + authOptions.ServerKeyPath: authOptions.ServerKeyRemotePath, + } + + sshClient, err := sshutil.NewSSHClient(driver) + if err != nil { + return errors.Wrap(err, "provisioning: error getting ssh client") + } + sshRunner := command.NewSSHRunner(sshClient) + + dirs := []string{} + for _, dst := range remoteCerts { + dirs = append(dirs, path.Dir(dst)) + } + + args := append([]string{"mkdir", "-p"}, dirs...) + if _, err = sshRunner.RunCmd(exec.Command("sudo", args...)); err != nil { + return err + } + + for src, dst := range remoteCerts { + f, err := assets.NewFileAsset(src, path.Dir(dst), filepath.Base(dst), "0640") + if err != nil { + return errors.Wrapf(err, "error copying %s to %s", src, dst) + } + if err := sshRunner.Copy(f); err != nil { + return errors.Wrapf(err, "transferring file to machine %v", f) + } + } + + return nil +} + +func setRemoteAuthOptions(p provision.Provisioner) auth.Options { + dockerDir := p.GetDockerOptionsDir() + authOptions := p.GetAuthOptions() + + // due to windows clients, we cannot use filepath.Join as the paths + // will be mucked on the linux hosts + authOptions.CaCertRemotePath = path.Join(dockerDir, "ca.pem") + authOptions.ServerCertRemotePath = path.Join(dockerDir, "server.pem") + authOptions.ServerKeyRemotePath = path.Join(dockerDir, "server-key.pem") + + return authOptions +} + +func setContainerRuntimeOptions(name string, p miniProvisioner) error { + c, err := config.Load(name) + if err != nil { + return errors.Wrap(err, "getting cluster config") + } + + switch c.KubernetesConfig.ContainerRuntime { + case "crio", "cri-o": + return setCrioOptions(p) + case "containerd": + return nil + default: + _, err := p.GenerateDockerOptions(engine.DefaultPort) + return err + } +} + +func setCrioOptions(p provision.SSHCommander) error { + // pass through --insecure-registry + var ( + crioOptsTmpl = ` +CRIO_MINIKUBE_OPTIONS='{{ range .EngineOptions.InsecureRegistry }}--insecure-registry {{.}} {{ end }}' +` + crioOptsPath = "/etc/sysconfig/crio.minikube" + ) + t, err := template.New("crioOpts").Parse(crioOptsTmpl) + if err != nil { + return err + } + var crioOptsBuf bytes.Buffer + if err := t.Execute(&crioOptsBuf, p); err != nil { + return err + } + + if _, err = p.SSHCommand(fmt.Sprintf("sudo mkdir -p %s && printf %%s \"%s\" | sudo tee %s", path.Dir(crioOptsPath), crioOptsBuf.String(), crioOptsPath)); err != nil { + return err + } + + return nil +} + +func rootFileSystemType(p provision.SSHCommander) (string, error) { + fs, err := p.SSHCommand("df --output=fstype / | tail -n 1") + if err != nil { + return "", err + } + return strings.TrimSpace(fs), nil +} + +// escapeSystemdDirectives escapes special characters in the input variables used to create the +// systemd unit file, which would otherwise be interpreted as systemd directives. An example +// are template specifiers (e.g. '%i') which are predefined variables that get evaluated dynamically +// (see systemd man pages for more info). This is not supported by minikube, thus needs to be escaped. +func escapeSystemdDirectives(engineConfigContext *provision.EngineConfigContext) { + // escape '%' in Environment option so that it does not evaluate into a template specifier + engineConfigContext.EngineOptions.Env = util.ReplaceChars(engineConfigContext.EngineOptions.Env, systemdSpecifierEscaper) + // input might contain whitespaces, wrap it in quotes + engineConfigContext.EngineOptions.Env = util.ConcatStrings(engineConfigContext.EngineOptions.Env, "\"", "\"") +} diff --git a/pkg/provision/ubuntu.go b/pkg/provision/ubuntu.go new file mode 100644 index 000000000000..8ff0c778ee82 --- /dev/null +++ b/pkg/provision/ubuntu.go @@ -0,0 +1,209 @@ +/* +Copyright 2019 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package provision + +import ( + "bytes" + "fmt" + "path" + "text/template" + "time" + + "github.com/docker/machine/libmachine/auth" + "github.com/docker/machine/libmachine/drivers" + "github.com/docker/machine/libmachine/engine" + "github.com/docker/machine/libmachine/log" + "github.com/docker/machine/libmachine/provision" + "github.com/docker/machine/libmachine/provision/pkgaction" + "github.com/docker/machine/libmachine/provision/serviceaction" + "github.com/docker/machine/libmachine/swarm" + "k8s.io/minikube/pkg/util/retry" +) + +// UbuntuProvisioner provisions the ubuntu +type UbuntuProvisioner struct { + BuildrootProvisioner +} + +// NewUbuntuProvisioner creates a new UbuntuProvisioner +func NewUbuntuProvisioner(d drivers.Driver) provision.Provisioner { + return &UbuntuProvisioner{ + BuildrootProvisioner{ + provision.NewSystemdProvisioner("ubuntu", d), + }, + } +} + +func (p *UbuntuProvisioner) String() string { + return "ubuntu" +} + +// CompatibleWithHost checks if provisioner is compatible with host +func (p *UbuntuProvisioner) CompatibleWithHost() bool { + return p.OsReleaseInfo.ID == "ubuntu" +} + +// GenerateDockerOptions generates the *provision.DockerOptions for this provisioner +func (p *UbuntuProvisioner) GenerateDockerOptions(dockerPort int) (*provision.DockerOptions, error) { + var engineCfg bytes.Buffer + + drvLabel := fmt.Sprintf("provider=%s", p.Driver.DriverName()) + p.EngineOptions.Labels = append(p.EngineOptions.Labels, drvLabel) + + noPivot := true + // Using pivot_root is not supported on fstype rootfs + if fstype, err := rootFileSystemType(p); err == nil { + log.Debugf("root file system type: %s", fstype) + noPivot = fstype == "rootfs" + } + + engineConfigTmpl := `[Unit] +Description=Docker Application Container Engine +Documentation=https://docs.docker.com +BindsTo=containerd.service +After=network-online.target firewalld.service containerd.service +Wants=network-online.target +Requires=docker.socket + +[Service] +Type=notify +` + if noPivot { + log.Warn("Using fundamentally insecure --no-pivot option") + engineConfigTmpl += ` +# DOCKER_RAMDISK disables pivot_root in Docker, using MS_MOVE instead. +Environment=DOCKER_RAMDISK=yes +` + } + engineConfigTmpl += ` +{{range .EngineOptions.Env}}Environment={{.}} +{{end}} + +# This file is a systemd drop-in unit that inherits from the base dockerd configuration. +# The base configuration already specifies an 'ExecStart=...' command. The first directive +# here is to clear out that command inherited from the base configuration. Without this, +# the command from the base configuration and the command specified here are treated as +# a sequence of commands, which is not the desired behavior, nor is it valid -- systemd +# will catch this invalid input and refuse to start the service with an error like: +# Service has more than one ExecStart= setting, which is only allowed for Type=oneshot services. + +# NOTE: default-ulimit=nofile is set to an arbitrary number for consistency with other +# container runtimes. If left unlimited, it may result in OOM issues with MySQL. +ExecStart= +ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:{{.DockerPort}} -H unix:///var/run/docker.sock --default-ulimit=nofile=1048576:1048576 --tlsverify --tlscacert {{.AuthOptions.CaCertRemotePath}} --tlscert {{.AuthOptions.ServerCertRemotePath}} --tlskey {{.AuthOptions.ServerKeyRemotePath}} {{ range .EngineOptions.Labels }}--label {{.}} {{ end }}{{ range .EngineOptions.InsecureRegistry }}--insecure-registry {{.}} {{ end }}{{ range .EngineOptions.RegistryMirror }}--registry-mirror {{.}} {{ end }}{{ range .EngineOptions.ArbitraryFlags }}--{{.}} {{ end }} +ExecReload=/bin/kill -s HUP $MAINPID + +# Having non-zero Limit*s causes performance problems due to accounting overhead +# in the kernel. We recommend using cgroups to do container-local accounting. +LimitNOFILE=infinity +LimitNPROC=infinity +LimitCORE=infinity + +# Uncomment TasksMax if your systemd version supports it. +# Only systemd 226 and above support this version. +TasksMax=infinity +TimeoutStartSec=0 + +# set delegate yes so that systemd does not reset the cgroups of docker containers +Delegate=yes + +# kill only the docker process, not all processes in the cgroup +KillMode=process + +[Install] +WantedBy=multi-user.target +` + t, err := template.New("engineConfig").Parse(engineConfigTmpl) + if err != nil { + return nil, err + } + + engineConfigContext := provision.EngineConfigContext{ + DockerPort: dockerPort, + AuthOptions: p.AuthOptions, + EngineOptions: p.EngineOptions, + } + + escapeSystemdDirectives(&engineConfigContext) + + if err := t.Execute(&engineCfg, engineConfigContext); err != nil { + return nil, err + } + + dockerCfg := &provision.DockerOptions{ + EngineOptions: engineCfg.String(), + EngineOptionsPath: "/lib/systemd/system/docker.service", + } + + log.Info("Setting Docker configuration on the remote daemon...") + + if _, err = p.SSHCommand(fmt.Sprintf("sudo mkdir -p %s && printf %%s \"%s\" | sudo tee %s", path.Dir(dockerCfg.EngineOptionsPath), dockerCfg.EngineOptions, dockerCfg.EngineOptionsPath)); err != nil { + return nil, err + } + + if err := p.Service("docker", serviceaction.Enable); err != nil { + return nil, err + } + + if err := p.Service("docker", serviceaction.Restart); err != nil { + return nil, err + } + return dockerCfg, nil +} + +// Package installs a package +func (p *UbuntuProvisioner) Package(name string, action pkgaction.PackageAction) error { + return nil +} + +// Provision does the provisioning +func (p *UbuntuProvisioner) Provision(swarmOptions swarm.Options, authOptions auth.Options, engineOptions engine.Options) error { + p.SwarmOptions = swarmOptions + p.AuthOptions = authOptions + p.EngineOptions = engineOptions + + log.Infof("provisioning hostname %q", p.Driver.GetMachineName()) + if err := p.SetHostname(p.Driver.GetMachineName()); err != nil { + return err + } + + p.AuthOptions = setRemoteAuthOptions(p) + log.Debugf("set auth options %+v", p.AuthOptions) + + log.Debugf("setting up certificates") + configAuth := func() error { + if err := configureAuth(p); err != nil { + log.Warnf("configureAuth failed: %v", err) + return &retry.RetriableError{Err: err} + } + return nil + } + + err := retry.Expo(configAuth, time.Second, 2*time.Minute) + if err != nil { + log.Debugf("Error configuring auth during provisioning %v", err) + return err + } + + log.Debugf("setting minikube options for container-runtime") + if err := setContainerRuntimeOptions(p.Driver.GetMachineName(), p); err != nil { + log.Debugf("Error setting container-runtime options during provisioning %v", err) + return err + } + + return nil +}