Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement multi-node cluster capabilities #6787

Merged
merged 50 commits into from
Mar 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
8536fb7
changes and things
sharifelgamal Feb 19, 2020
ec19111
let's move some start code around
sharifelgamal Feb 21, 2020
7853387
add new setup cluster file
sharifelgamal Feb 22, 2020
4af8291
Merge branch 'master' of github.com:kubernetes/minikube into m2
sharifelgamal Feb 23, 2020
f22efd8
mostly moving code around and adding UpdateNode
sharifelgamal Feb 24, 2020
9a3ecab
fixed more stuff
sharifelgamal Feb 24, 2020
be9c5f4
pass in the node object into add
sharifelgamal Feb 24, 2020
f0ca34b
fix unit tests
sharifelgamal Feb 25, 2020
b2ba874
SaveNode is simpler yeah
sharifelgamal Feb 25, 2020
f5bdba6
fix kvm2 configurator
sharifelgamal Feb 25, 2020
feaa9fc
hyperv and none drivers needed fixing too
sharifelgamal Feb 25, 2020
3d72152
fixing lint and other random incorrect stuff
sharifelgamal Feb 25, 2020
39f03bc
prepareNone was in the wrong spot
sharifelgamal Feb 25, 2020
0fadf91
i think it works?
sharifelgamal Feb 26, 2020
e3826a5
fix ip command
sharifelgamal Feb 26, 2020
676588f
refactor machine name creation into a function
sharifelgamal Feb 26, 2020
d7df027
fix delete and stop
sharifelgamal Feb 26, 2020
e7f8abc
fix waitfornode
sharifelgamal Feb 26, 2020
9f82d68
actually cache images on cluster startup
sharifelgamal Feb 26, 2020
2bf3b9a
move caching code to cluster
sharifelgamal Feb 27, 2020
0cc0a25
passing correct machine name around
sharifelgamal Feb 27, 2020
a349b86
correct machine name for selectDriver
sharifelgamal Feb 27, 2020
64ca925
Merge branch 'master' of github.com:kubernetes/minikube into m2
sharifelgamal Mar 9, 2020
05116ab
more fallout for the merge-pocalypse
sharifelgamal Mar 10, 2020
ef93b29
fix build failures
sharifelgamal Mar 10, 2020
e3227a2
Merge branch 'master' of github.com:kubernetes/minikube into m2
sharifelgamal Mar 10, 2020
3ed818c
cosmetic fixes
sharifelgamal Mar 12, 2020
b6ab293
run all necessary steps on all nodes
sharifelgamal Mar 13, 2020
a9b73b8
fixing up minikube start path
sharifelgamal Mar 13, 2020
3608903
Merge branch 'master' of github.com:kubernetes/minikube into m2
sharifelgamal Mar 13, 2020
d98ebcf
lint
sharifelgamal Mar 13, 2020
c3b56b6
let's rearrange a bunch of code
sharifelgamal Mar 14, 2020
74b1f34
Merge branch 'master' of github.com:kubernetes/minikube into m2
sharifelgamal Mar 16, 2020
577dfa3
it works again
sharifelgamal Mar 16, 2020
c1c2653
fix unit tests
sharifelgamal Mar 16, 2020
376111b
fix unit tests pt 2
sharifelgamal Mar 16, 2020
f387032
Merge branch 'master' of github.com:kubernetes/minikube into m2
sharifelgamal Mar 16, 2020
f99d335
fix docker driver
sharifelgamal Mar 16, 2020
84939da
fix docker driver again
sharifelgamal Mar 17, 2020
66a6f4e
fix docker status
sharifelgamal Mar 17, 2020
a24aa5d
dramatically simplify start code path
sharifelgamal Mar 18, 2020
add1c8f
missing file
sharifelgamal Mar 18, 2020
efac79e
account for hyphens in profile name
sharifelgamal Mar 19, 2020
fa97a5b
fix machine name creation
sharifelgamal Mar 19, 2020
f9b38dc
clean up status output and have multinode survive cluster restarts
sharifelgamal Mar 19, 2020
6a6b77a
Merge branch 'master' of github.com:kubernetes/minikube into m2
sharifelgamal Mar 20, 2020
4c00ae0
Merge branch 'master' of github.com:kubernetes/minikube into m2
sharifelgamal Mar 20, 2020
35aec77
code comments
sharifelgamal Mar 20, 2020
a09aa62
delete admin.conf before running kubedm init
sharifelgamal Mar 20, 2020
05814cc
only apply kic networking overlay to control plane
sharifelgamal Mar 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions cmd/minikube/cmd/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ import (

// nodeCmd represents the set of node subcommands
var nodeCmd = &cobra.Command{
Use: "node",
Short: "Node operations",
Long: "Operations on nodes",
Hidden: true, // This won't be fully functional and thus should not be documented yet
Use: "node",
Short: "Node operations",
Long: "Operations on nodes",
Run: func(cmd *cobra.Command, args []string) {
exit.UsageT("Usage: minikube node [add|start|stop|delete]")
},
Expand Down
23 changes: 14 additions & 9 deletions cmd/minikube/cmd/node_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ limitations under the License.
package cmd

import (
"fmt"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/driver"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/node"
"k8s.io/minikube/pkg/minikube/out"
Expand All @@ -43,19 +42,25 @@ var nodeAddCmd = &cobra.Command{
exit.WithError("Error getting config", err)
}

//name := profile + strconv.Itoa(len(mc.Nodes)+1)
name := fmt.Sprintf("m%d", len(cc.Nodes)+1)
if driver.BareMetal(cc.Driver) {
out.ErrT(out.FailureType, "none driver does not support multi-node clusters")
}

name := node.Name(len(cc.Nodes) + 1)

out.T(out.Happy, "Adding node {{.name}} to cluster {{.cluster}}", out.V{"name": name, "cluster": profile})

n, err := node.Add(cc, name, cp, worker, "", profile)
if err != nil {
exit.WithError("Error adding node to cluster", err)
// TODO: Deal with parameters better. Ideally we should be able to acceot any node-specific minikube start params here.
n := config.Node{
Name: name,
Worker: worker,
ControlPlane: cp,
KubernetesVersion: cc.KubernetesConfig.KubernetesVersion,
}

_, err = node.Start(*cc, *n, false, nil)
err = node.Add(cc, n)
if err != nil {
exit.WithError("Error starting node", err)
exit.WithError("Error adding node to cluster", err)
}

out.T(out.Ready, "Successfully added {{.name}} to {{.cluster}}!", out.V{"name": name, "cluster": profile})
Expand Down
2 changes: 1 addition & 1 deletion cmd/minikube/cmd/node_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ var nodeDeleteCmd = &cobra.Command{

err = node.Delete(*cc, name)
if err != nil {
out.FatalT("Failed to delete node {{.name}}", out.V{"name": name})
exit.WithError("deleting node", err)
tstromberg marked this conversation as resolved.
Show resolved Hide resolved
}

out.T(out.Deleted, "Node {{.name}} was successfully deleted.", out.V{"name": name})
Expand Down
5 changes: 1 addition & 4 deletions cmd/minikube/cmd/node_start.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,7 @@ var nodeStartCmd = &cobra.Command{
}

// Start it up baby
_, err = node.Start(*cc, *n, false, nil)
if err != nil {
out.FatalT("Failed to start node {{.name}}", out.V{"name": name})
}
node.Start(*cc, *n, nil, false)
},
}

Expand Down
24 changes: 17 additions & 7 deletions cmd/minikube/cmd/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"k8s.io/minikube/pkg/minikube/driver"
"k8s.io/minikube/pkg/minikube/exit"
"k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/node"
"k8s.io/minikube/pkg/minikube/out"
)

Expand All @@ -49,12 +50,20 @@ var sshCmd = &cobra.Command{
if err != nil {
exit.WithError("Error getting config", err)
}
// TODO: allow choice of node to ssh into
cp, err := config.PrimaryControlPlane(cc)
if err != nil {
exit.WithError("Error getting primary control plane", err)
var n *config.Node
if nodeName == "" {
cp, err := config.PrimaryControlPlane(cc)
if err != nil {
exit.WithError("Getting primary control plane", err)
}
n = &cp
} else {
n, _, err = node.Retrieve(cc, nodeName)
if err != nil {
exit.WithCodeT(exit.Unavailable, "Node {{.nodeName}} does not exist.", out.V{"nodeName": nodeName})
}
}
host, err := machine.LoadHost(api, driver.MachineName(*cc, cp))
host, err := machine.LoadHost(api, driver.MachineName(*cc, *n))
if err != nil {
exit.WithError("Error getting host", err)
}
Expand All @@ -67,7 +76,7 @@ var sshCmd = &cobra.Command{
ssh.SetDefaultClient(ssh.External)
}

err = machine.CreateSSHShell(api, *cc, cp, args)
err = machine.CreateSSHShell(api, *cc, *n, args)
if err != nil {
// This is typically due to a non-zero exit code, so no need for flourish.
out.ErrLn("ssh: %v", err)
Expand All @@ -78,5 +87,6 @@ var sshCmd = &cobra.Command{
}

func init() {
sshCmd.Flags().BoolVar(&nativeSSHClient, nativeSSH, true, "Use native Golang SSH client (default true). Set to 'false' to use the command line 'ssh' command when accessing the docker machine. Useful for the machine drivers when they will not start with 'Waiting for SSH'.")
sshCmd.Flags().Bool(nativeSSH, true, "Use native Golang SSH client (default true). Set to 'false' to use the command line 'ssh' command when accessing the docker machine. Useful for the machine drivers when they will not start with 'Waiting for SSH'.")
sshCmd.Flags().StringVarP(&nodeName, "node", "n", "", "The node to ssh into. Defaults to the primary control plane.")
}
76 changes: 48 additions & 28 deletions cmd/minikube/cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ const (
autoUpdate = "auto-update-drivers"
hostOnlyNicType = "host-only-nic-type"
natNicType = "nat-nic-type"
nodes = "nodes"
)

var (
Expand Down Expand Up @@ -162,7 +163,7 @@ func initMinikubeFlags() {
startCmd.Flags().String(containerRuntime, "docker", "The container runtime to be used (docker, crio, containerd).")
startCmd.Flags().Bool(createMount, false, "This will start the mount daemon and automatically mount files into minikube.")
startCmd.Flags().String(mountString, constants.DefaultMountDir+":/minikube-host", "The argument to pass the minikube mount command on start.")
startCmd.Flags().StringArrayVar(&node.AddonList, "addons", nil, "Enable addons. see `minikube addons list` for a list of valid addon names.")
startCmd.Flags().StringArrayVar(&config.AddonList, "addons", nil, "Enable addons. see `minikube addons list` for a list of valid addon names.")
startCmd.Flags().String(criSocket, "", "The cri socket path to be used.")
startCmd.Flags().String(networkPlugin, "", "The name of the network plugin.")
startCmd.Flags().Bool(enableDefaultCNI, false, "Enable the default CNI plugin (/etc/cni/net.d/k8s.conf). Used in conjunction with \"--network-plugin=cni\".")
Expand All @@ -171,12 +172,13 @@ func initMinikubeFlags() {
startCmd.Flags().Bool(nativeSSH, true, "Use native Golang SSH client (default true). Set to 'false' to use the command line 'ssh' command when accessing the docker machine. Useful for the machine drivers when they will not start with 'Waiting for SSH'.")
startCmd.Flags().Bool(autoUpdate, true, "If set, automatically updates drivers to the latest version. Defaults to true.")
startCmd.Flags().Bool(installAddons, true, "If set, install addons. Defaults to true.")
startCmd.Flags().IntP(nodes, "n", 1, "The number of nodes to spin up. Defaults to 1.")
}

// initKubernetesFlags inits the commandline flags for kubernetes related options
func initKubernetesFlags() {
startCmd.Flags().String(kubernetesVersion, "", "The kubernetes version that the minikube VM will use (ex: v1.2.3)")
startCmd.Flags().Var(&node.ExtraOptions, "extra-config",
startCmd.Flags().Var(&config.ExtraOptions, "extra-config",
`A set of key=value pairs that describe configuration that may be passed to different components.
The key should be '.' separated, and the first part before the dot is the component to apply the configuration to.
Valid components are: kubelet, kubeadm, apiserver, controller-manager, etcd, proxy, scheduler
Expand Down Expand Up @@ -229,8 +231,8 @@ func initNetworkingFlags() {
startCmd.Flags().String(imageRepository, "", "Alternative image repository to pull docker images from. This can be used when you have limited access to gcr.io. Set it to \"auto\" to let minikube decide one for you. For Chinese mainland users, you may use local gcr.io mirrors such as registry.cn-hangzhou.aliyuncs.com/google_containers")
startCmd.Flags().String(imageMirrorCountry, "", "Country code of the image mirror to be used. Leave empty to use the global one. For Chinese mainland users, set it to cn.")
startCmd.Flags().String(serviceCIDR, constants.DefaultServiceCIDR, "The CIDR to be used for service cluster IPs.")
startCmd.Flags().StringArrayVar(&node.DockerEnv, "docker-env", nil, "Environment variables to pass to the Docker daemon. (format: key=value)")
startCmd.Flags().StringArrayVar(&node.DockerOpt, "docker-opt", nil, "Specify arbitrary flags to pass to the Docker daemon. (format: key=value)")
startCmd.Flags().StringArrayVar(&config.DockerEnv, "docker-env", nil, "Environment variables to pass to the Docker daemon. (format: key=value)")
startCmd.Flags().StringArrayVar(&config.DockerOpt, "docker-opt", nil, "Specify arbitrary flags to pass to the Docker daemon. (format: key=value)")
}

// startCmd represents the start command
Expand Down Expand Up @@ -313,7 +315,7 @@ func runStart(cmd *cobra.Command, args []string) {
}

k8sVersion := getKubernetesVersion(existing)
mc, n, err := generateCfgFromFlags(cmd, k8sVersion, driverName)
cc, n, err := generateCfgFromFlags(cmd, k8sVersion, driverName)
if err != nil {
exit.WithError("Failed to generate config", err)
}
Expand All @@ -324,12 +326,12 @@ func runStart(cmd *cobra.Command, args []string) {
return
}

if !driver.BareMetal(driverName) && !driver.IsKIC(driverName) {
if driver.IsVM(driverName) {
url, err := download.ISO(viper.GetStringSlice(isoURL), cmd.Flags().Changed(isoURL))
if err != nil {
exit.WithError("Failed to cache ISO", err)
}
mc.MinikubeISO = url
cc.MinikubeISO = url
}

if viper.GetBool(nativeSSH) {
Expand All @@ -338,12 +340,41 @@ func runStart(cmd *cobra.Command, args []string) {
ssh.SetDefaultClient(ssh.External)
}

kubeconfig, err := startNode(existing, mc, n)
if err != nil {
exit.WithError("Starting node", err)
var existingAddons map[string]bool
if viper.GetBool(installAddons) {
existingAddons = map[string]bool{}
if existing != nil && existing.Addons != nil {
existingAddons = existing.Addons
}
}

if err := showKubectlInfo(kubeconfig, k8sVersion, mc.Name); err != nil {
kubeconfig := node.Start(cc, n, existingAddons, true)

numNodes := viper.GetInt(nodes)
if numNodes == 1 && existing != nil {
numNodes = len(existing.Nodes)
}
if numNodes > 1 {
if driver.BareMetal(driverName) {
exit.WithCodeT(exit.Config, "The none driver is not compatible with multi-node clusters.")
} else {
for i := 1; i < numNodes; i++ {
nodeName := node.Name(i + 1)
n := config.Node{
Name: nodeName,
Worker: true,
ControlPlane: false,
KubernetesVersion: cc.KubernetesConfig.KubernetesVersion,
}
err := node.Add(&cc, n)
if err != nil {
exit.WithError("adding node", err)
}
}
}
}

if err := showKubectlInfo(kubeconfig, k8sVersion, cc.Name); err != nil {
glog.Errorf("kubectl info: %v", err)
}
}
Expand Down Expand Up @@ -383,17 +414,6 @@ func displayEnviron(env []string) {
}
}

func startNode(existing *config.ClusterConfig, mc config.ClusterConfig, n config.Node) (*kubeconfig.Settings, error) {
var existingAddons map[string]bool
if viper.GetBool(installAddons) {
existingAddons = map[string]bool{}
if existing != nil && existing.Addons != nil {
existingAddons = existing.Addons
}
}
return node.Start(mc, n, true, existingAddons)
}

func showKubectlInfo(kcs *kubeconfig.Settings, k8sVersion string, machineName string) error {
if kcs.KeepContext {
out.T(out.Kubectl, "To connect to this cluster, use: kubectl --context={{.name}}", out.V{"name": kcs.ClusterName})
Expand Down Expand Up @@ -796,7 +816,7 @@ func validateFlags(cmd *cobra.Command, drvName string) {
}

// check that kubeadm extra args contain only whitelisted parameters
for param := range node.ExtraOptions.AsMap().Get(bsutil.Kubeadm) {
for param := range config.ExtraOptions.AsMap().Get(bsutil.Kubeadm) {
if !config.ContainsParam(bsutil.KubeadmExtraArgsWhitelist[bsutil.KubeadmCmdParam], param) &&
!config.ContainsParam(bsutil.KubeadmExtraArgsWhitelist[bsutil.KubeadmConfigParam], param) {
exit.UsageT("Sorry, the kubeadm.{{.parameter_name}} parameter is currently not supported by --extra-config", out.V{"parameter_name": param})
Expand Down Expand Up @@ -924,8 +944,8 @@ func createNode(cmd *cobra.Command, k8sVersion, kubeNodeName, drvName, repositor
HyperkitVSockPorts: viper.GetStringSlice(vsockPorts),
NFSShare: viper.GetStringSlice(nfsShare),
NFSSharesRoot: viper.GetString(nfsSharesRoot),
DockerEnv: node.DockerEnv,
DockerOpt: node.DockerOpt,
DockerEnv: config.DockerEnv,
DockerOpt: config.DockerOpt,
InsecureRegistry: insecureRegistry,
RegistryMirror: registryMirror,
HostOnlyCIDR: viper.GetString(hostOnlyCIDR),
Expand Down Expand Up @@ -956,7 +976,7 @@ func createNode(cmd *cobra.Command, k8sVersion, kubeNodeName, drvName, repositor
NetworkPlugin: selectedNetworkPlugin,
ServiceCIDR: viper.GetString(serviceCIDR),
ImageRepository: repository,
ExtraOptions: node.ExtraOptions,
ExtraOptions: config.ExtraOptions,
ShouldLoadCachedImages: viper.GetBool(cacheImages),
EnableDefaultCNI: selectedEnableDefaultCNI,
},
Expand All @@ -978,7 +998,7 @@ func setDockerProxy() {
continue
}
}
node.DockerEnv = append(node.DockerEnv, fmt.Sprintf("%s=%s", k, v))
config.DockerEnv = append(config.DockerEnv, fmt.Sprintf("%s=%s", k, v))
}
}
}
Expand All @@ -990,7 +1010,7 @@ func autoSetDriverOptions(cmd *cobra.Command, drvName string) (err error) {
if !cmd.Flags().Changed("extra-config") && len(hints.ExtraOptions) > 0 {
for _, eo := range hints.ExtraOptions {
glog.Infof("auto setting extra-config to %q.", eo)
err = node.ExtraOptions.Set(eo)
err = config.ExtraOptions.Set(eo)
if err != nil {
err = errors.Wrapf(err, "setting extra option %s", eo)
}
Expand Down
Loading