diff --git a/cmd/localkube/cmd/options.go b/cmd/localkube/cmd/options.go index 5f832aa7ad..084630ceca 100644 --- a/cmd/localkube/cmd/options.go +++ b/cmd/localkube/cmd/options.go @@ -63,6 +63,8 @@ func AddFlags(s *localkube.LocalkubeServer) { flag.BoolVar(&s.ShowVersion, "version", s.ShowVersion, "If localkube should just print the version and exit.") flag.Var(&s.RuntimeConfig, "runtime-config", "A set of key=value pairs that describe runtime configuration that may be passed to apiserver. apis/ key can be used to turn on/off specific api versions. apis// can be used to turn on/off specific resources. api/all and api/legacy are special keys to control all and legacy api versions respectively.") flag.IPVar(&s.NodeIP, "node-ip", s.NodeIP, "IP address of the node. If set, kubelet will use this IP address for the node.") + flag.StringVar(&s.ContainerRuntime, "container-runtime", "", "The container runtime to be used") + flag.StringVar(&s.NetworkPlugin, "network-plugin", "", "The name of the network plugin") // These two come from vendor/ packages that use flags. We should hide them flag.CommandLine.MarkHidden("google-json-key") diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index 5b129c3e49..99faa6d727 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -43,6 +43,8 @@ const ( vmDriver = "vm-driver" kubernetesVersion = "kubernetes-version" hostOnlyCIDR = "host-only-cidr" + containerRuntime = "container-runtime" + networkPlugin = "network-plugin" ) var ( @@ -99,6 +101,8 @@ func runStart(cmd *cobra.Command, args []string) { kubernetesConfig := cluster.KubernetesConfig{ KubernetesVersion: viper.GetString(kubernetesVersion), NodeIP: ip, + ContainerRuntime: viper.GetString(containerRuntime), + NetworkPlugin: viper.GetString(networkPlugin), } if err := cluster.UpdateCluster(host, host.Driver, kubernetesConfig); err != nil { glog.Errorln("Error updating cluster: ", err) @@ -195,6 +199,8 @@ func init() { startCmd.Flags().StringSliceVar(&insecureRegistry, "insecure-registry", nil, "Insecure Docker registries to pass to the Docker daemon") startCmd.Flags().StringSliceVar(®istryMirror, "registry-mirror", nil, "Registry mirrors to pass to the Docker daemon") startCmd.Flags().String(kubernetesVersion, constants.DefaultKubernetesVersion, "The kubernetes version that the minikube VM will (ex: v1.2.3) \n OR a URI which contains a localkube binary (ex: https://storage.googleapis.com/minikube/k8sReleases/v1.3.0/localkube-linux-amd64)") + startCmd.Flags().String(containerRuntime, "", "The container runtime to be used") + startCmd.Flags().String(networkPlugin, "", "The name of the network plugin") viper.BindPFlags(startCmd.Flags()) RootCmd.AddCommand(startCmd) } diff --git a/cmd/minikube/main.go b/cmd/minikube/main.go index 0f613a04a3..30d7bb8864 100644 --- a/cmd/minikube/main.go +++ b/cmd/minikube/main.go @@ -19,6 +19,8 @@ package main import ( "k8s.io/minikube/cmd/minikube/cmd" "k8s.io/minikube/pkg/minikube/machine" + + _ "k8s.io/minikube/pkg/provision" ) func main() { diff --git a/docs/minikube_start.md b/docs/minikube_start.md index a2c3cd1361..038ecd1eed 100644 --- a/docs/minikube_start.md +++ b/docs/minikube_start.md @@ -15,6 +15,7 @@ minikube start ### Options ``` + --container-runtime="": The container runtime to be used --cpus=1: Number of CPUs allocated to the minikube VM --disk-size="20g": Disk size allocated to the minikube VM (format: [], where unit = b, k, m or g) --docker-env=[]: Environment variables to pass to the Docker daemon. (format: key=value) @@ -24,6 +25,7 @@ minikube start --kubernetes-version="v1.3.5": The kubernetes version that the minikube VM will (ex: v1.2.3) OR a URI which contains a localkube binary (ex: https://storage.googleapis.com/minikube/k8sReleases/v1.3.0/localkube-linux-amd64) --memory=1024: Amount of RAM allocated to the minikube VM + --network-plugin="": The name of the network plugin --registry-mirror=[]: Registry mirrors to pass to the Docker daemon --vm-driver="virtualbox": VM driver is one of: [virtualbox vmwarefusion kvm xhyve hyperv] ``` diff --git a/pkg/localkube/kubelet.go b/pkg/localkube/kubelet.go index 78415739ee..c28b401c34 100644 --- a/pkg/localkube/kubelet.go +++ b/pkg/localkube/kubelet.go @@ -43,6 +43,15 @@ func StartKubeletServer(lk LocalkubeServer) func() error { config.NodeIP = lk.NodeIP.String() + if lk.NetworkPlugin != "" { + config.NetworkPluginName = lk.NetworkPlugin + } + + // Runtime + if lk.ContainerRuntime != "" { + config.ContainerRuntime = lk.ContainerRuntime + } + // Use the host's resolver config if lk.Containerized { config.ResolverConfig = "/rootfs/etc/resolv.conf" diff --git a/pkg/localkube/localkube.go b/pkg/localkube/localkube.go index 85348a1677..70797ec23f 100644 --- a/pkg/localkube/localkube.go +++ b/pkg/localkube/localkube.go @@ -52,6 +52,8 @@ type LocalkubeServer struct { ShowVersion bool RuntimeConfig config.ConfigurationMap NodeIP net.IP + ContainerRuntime string + NetworkPlugin string } func (lk *LocalkubeServer) AddServer(server Server) { diff --git a/pkg/minikube/cluster/cluster.go b/pkg/minikube/cluster/cluster.go index c9db6a117d..c5f7faaa88 100644 --- a/pkg/minikube/cluster/cluster.go +++ b/pkg/minikube/cluster/cluster.go @@ -190,6 +190,8 @@ type MachineConfig struct { type KubernetesConfig struct { KubernetesVersion string NodeIP string + ContainerRuntime string + NetworkPlugin string } // StartCluster starts a k8s cluster on the specified Host. diff --git a/pkg/minikube/cluster/commands.go b/pkg/minikube/cluster/commands.go index 1e907a3ce7..6164197777 100644 --- a/pkg/minikube/cluster/commands.go +++ b/pkg/minikube/cluster/commands.go @@ -40,8 +40,25 @@ func GetStartCommand(kubernetesConfig KubernetesConfig) string { flagVals = append(flagVals, fmt.Sprintf("--%s %s", logFlag, logVal.Value.String())) } } + + if kubernetesConfig.ContainerRuntime != "" { + flagVals = append(flagVals, "--container-runtime="+kubernetesConfig.ContainerRuntime) + } + + if kubernetesConfig.NetworkPlugin != "" { + flagVals = append(flagVals, "--network-plugin="+kubernetesConfig.NetworkPlugin) + } + flags := strings.Join(flagVals, " ") - return fmt.Sprintf(startCommandFmtStr, flags, kubernetesConfig.NodeIP, constants.RemoteLocalKubeErrPath, constants.RemoteLocalKubeOutPath, constants.LocalkubePIDPath) + + return fmt.Sprintf( + startCommandFmtStr, + flags, + kubernetesConfig.NodeIP, + constants.RemoteLocalKubeErrPath, + constants.RemoteLocalKubeOutPath, + constants.LocalkubePIDPath, + ) } var localkubeStatusCommand = fmt.Sprintf(` diff --git a/pkg/minikube/sshutil/sshutil.go b/pkg/minikube/sshutil/sshutil.go index 577813e45a..4373135355 100644 --- a/pkg/minikube/sshutil/sshutil.go +++ b/pkg/minikube/sshutil/sshutil.go @@ -91,7 +91,8 @@ func Transfer(reader io.Reader, readerLen int, remotedir, filename string, perm io.Copy(w, reader) fmt.Fprint(w, "\x00") }() - scpcmd := fmt.Sprintf("sudo /usr/local/bin/scp -t %s", remotedir) + + scpcmd := fmt.Sprintf("sudo scp -t %s", remotedir) if err := s.Run(scpcmd); err != nil { return errors.Wrap(err, "Error running scp command") } diff --git a/pkg/provision/buildroot.go b/pkg/provision/buildroot.go new file mode 100644 index 0000000000..a81707f3af --- /dev/null +++ b/pkg/provision/buildroot.go @@ -0,0 +1,150 @@ +/* +Copyright 2016 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" + "html/template" + "path" + + "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/swarm" +) + +type BuildrootProvisioner struct { + provision.SystemdProvisioner +} + +func init() { + provision.Register("Buildroot", &provision.RegisteredProvisioner{ + New: NewBuildrootProvisioner, + }) +} + +func NewBuildrootProvisioner(d drivers.Driver) provision.Provisioner { + return &BuildrootProvisioner{ + provision.NewSystemdProvisioner("buildroot", d), + } +} + +func (p *BuildrootProvisioner) String() string { + return "buildroot" +} + +func (p *BuildrootProvisioner) GenerateDockerOptions(dockerPort int) (*provision.DockerOptions, error) { + var engineCfg bytes.Buffer + + driverNameLabel := fmt.Sprintf("provider=%s", p.Driver.DriverName()) + p.EngineOptions.Labels = append(p.EngineOptions.Labels, driverNameLabel) + + engineConfigTmpl := `[Unit] +Description=Docker Application Container Engine +Documentation=https://docs.docker.com +After=network.target docker.socket +Requires=docker.socket + +[Service] +Type=notify + +# DOCKER_RAMDISK disables pivot_root in Docker, using MS_MOVE instead. +Environment=DOCKER_RAMDISK=yes + +ExecStart=/usr/bin/docker daemon -H tcp://0.0.0.0:{{.DockerPort}} -H unix:///var/run/docker.sock --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, + } + + t.Execute(&engineCfg, engineConfigContext) + + return &provision.DockerOptions{ + EngineOptions: engineCfg.String(), + EngineOptionsPath: p.DaemonOptionsFile, + }, nil +} + +func (p *BuildrootProvisioner) Package(name string, action pkgaction.PackageAction) error { + return nil +} + +func (p *BuildrootProvisioner) Provision(swarmOptions swarm.Options, authOptions auth.Options, engineOptions engine.Options) error { + p.SwarmOptions = swarmOptions + p.AuthOptions = authOptions + p.EngineOptions = engineOptions + + log.Debugf("setting 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") + if err := provision.ConfigureAuth(p); err != nil { + 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 +}