diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index b8c3dbdf526f..cd5daf6747d1 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -76,6 +76,7 @@ const ( apiServerPort = "apiserver-port" dnsDomain = "dns-domain" serviceCIDR = "service-cluster-ip-range" + podSubnet = "pod-network-cidr" mountString = "mount-string" disableDriverMounts = "disable-driver-mounts" cacheImages = "cache-images" @@ -124,6 +125,7 @@ func init() { startCmd.Flags().IPSliceVar(&apiServerIPs, "apiserver-ips", nil, "A set of apiserver IP Addresses 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") startCmd.Flags().String(dnsDomain, constants.ClusterDNSDomain, "The cluster dns domain name used in the kubernetes cluster") startCmd.Flags().String(serviceCIDR, pkgutil.DefaultServiceCIDR, "The CIDR to be used for service cluster IPs.") + startCmd.Flags().String(podSubnet, "", "Specify range of IP addresses for the pod network. If set, the control plane will automatically allocate CIDRs for every node.") startCmd.Flags().StringSliceVar(&insecureRegistry, "insecure-registry", nil, "Insecure Docker registries to pass to the Docker daemon. The default service CIDR range will automatically be added.") startCmd.Flags().StringSliceVar(®istryMirror, "registry-mirror", nil, "Registry mirrors to pass to the Docker daemon") startCmd.Flags().String(containerRuntime, "docker", "The container runtime to be used (docker, crio, containerd)") @@ -316,6 +318,7 @@ func generateConfig(cmd *cobra.Command, k8sVersion string) (cfg.Config, error) { CRISocket: viper.GetString(criSocket), NetworkPlugin: selectedNetworkPlugin, ServiceCIDR: viper.GetString(serviceCIDR), + PodSubnet: viper.GetString(podSubnet), ExtraOptions: extraOptions, ShouldLoadCachedImages: viper.GetBool(cacheImages), EnableDefaultCNI: selectedEnableDefaultCNI, diff --git a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go index 2504bcff10d4..b25de679d7d2 100644 --- a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go +++ b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go @@ -511,6 +511,7 @@ func generateConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, er opts := struct { CertDir string ServiceCIDR string + PodSubnet string AdvertiseAddress string APIServerPort int KubernetesVersion string @@ -523,6 +524,7 @@ func generateConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, er }{ CertDir: util.DefaultCertPath, ServiceCIDR: util.DefaultServiceCIDR, + PodSubnet: k8s.PodSubnet, AdvertiseAddress: k8s.NodeIP, APIServerPort: nodePort, KubernetesVersion: k8s.KubernetesVersion, diff --git a/pkg/minikube/bootstrapper/kubeadm/kubeadm_test.go b/pkg/minikube/bootstrapper/kubeadm/kubeadm_test.go index 351a6ad4b68a..e7930d812360 100644 --- a/pkg/minikube/bootstrapper/kubeadm/kubeadm_test.go +++ b/pkg/minikube/bootstrapper/kubeadm/kubeadm_test.go @@ -169,8 +169,7 @@ imageGCHighThresholdPercent: 100 evictionHard: nodefs.available: "0%" nodefs.inodesFree: "0%" - imagefs.available: "0%" -`, + imagefs.available: "0%"`, }, { description: "two extra args for one component", cfg: config.KubernetesConfig{ @@ -323,6 +322,104 @@ apiServerExtraArgs: admission-control: "Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota" `, }, + { + description: "no PodSubnet", + cfg: config.KubernetesConfig{ + NodeIP: "192.168.1.100", + KubernetesVersion: "v1.12.0", + NodeName: "minikube", + PodSubnet: "", + }, + expectedCfg: `apiVersion: kubeadm.k8s.io/v1alpha3 +kind: InitConfiguration +apiEndpoint: + advertiseAddress: 192.168.1.100 + bindPort: 8443 +bootstrapTokens: +- groups: + - system:bootstrappers:kubeadm:default-node-token + ttl: 24h0m0s + usages: + - signing + - authentication +nodeRegistration: + criSocket: /var/run/dockershim.sock + name: minikube + taints: [] +--- +apiVersion: kubeadm.k8s.io/v1alpha3 +kind: ClusterConfiguration +apiServerExtraArgs: + enable-admission-plugins: "Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota" + +certificatesDir: /var/lib/minikube/certs/ +clusterName: kubernetes +controlPlaneEndpoint: localhost:8443 +etcd: + local: + dataDir: /data/minikube +kubernetesVersion: v1.12.0 +networking: + dnsDomain: cluster.local + podSubnet: "" + serviceSubnet: 10.96.0.0/12 +--- +apiVersion: kubelet.config.k8s.io/v1beta1 +kind: KubeletConfiguration +evictionHard: + nodefs.available: "0%" + nodefs.inodesFree: "0%" + imagefs.available: "0%"`, + }, + { + description: "with PodSubnet", + cfg: config.KubernetesConfig{ + NodeIP: "192.168.1.100", + KubernetesVersion: "v1.12.0", + NodeName: "minikube", + PodSubnet: "192.168.32.0/20", + }, + expectedCfg: `apiVersion: kubeadm.k8s.io/v1alpha3 +kind: InitConfiguration +apiEndpoint: + advertiseAddress: 192.168.1.100 + bindPort: 8443 +bootstrapTokens: +- groups: + - system:bootstrappers:kubeadm:default-node-token + ttl: 24h0m0s + usages: + - signing + - authentication +nodeRegistration: + criSocket: /var/run/dockershim.sock + name: minikube + taints: [] +--- +apiVersion: kubeadm.k8s.io/v1alpha3 +kind: ClusterConfiguration +apiServerExtraArgs: + enable-admission-plugins: "Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota" + +certificatesDir: /var/lib/minikube/certs/ +clusterName: kubernetes +controlPlaneEndpoint: localhost:8443 +etcd: + local: + dataDir: /data/minikube +kubernetesVersion: v1.12.0 +networking: + dnsDomain: cluster.local + podSubnet: 192.168.32.0/20 + serviceSubnet: 10.96.0.0/12 +--- +apiVersion: kubelet.config.k8s.io/v1beta1 +kind: KubeletConfiguration +evictionHard: + nodefs.available: "0%" + nodefs.inodesFree: "0%" + imagefs.available: "0%"`, + }, } for _, test := range tests { diff --git a/pkg/minikube/bootstrapper/kubeadm/templates.go b/pkg/minikube/bootstrapper/kubeadm/templates.go index 172342723065..c9170f9a4ffe 100644 --- a/pkg/minikube/bootstrapper/kubeadm/templates.go +++ b/pkg/minikube/bootstrapper/kubeadm/templates.go @@ -82,7 +82,7 @@ etcd: kubernetesVersion: {{.KubernetesVersion}} networking: dnsDomain: cluster.local - podSubnet: "" + podSubnet: {{if .PodSubnet}}{{.PodSubnet}}{{else}}""{{end}} serviceSubnet: {{.ServiceCIDR}} --- apiVersion: kubelet.config.k8s.io/v1beta1 @@ -90,8 +90,7 @@ kind: KubeletConfiguration evictionHard: nodefs.available: "0%" nodefs.inodesFree: "0%" - imagefs.available: "0%" -`)) + imagefs.available: "0%"`)) // configTmplV1Beta1 is for Kubernetes v1.13+ var configTmplV1Beta1 = template.Must(template.New("configTmpl-v1beta1").Funcs(template.FuncMap{ @@ -141,8 +140,7 @@ imageGCHighThresholdPercent: 100 evictionHard: nodefs.available: "0%" nodefs.inodesFree: "0%" - imagefs.available: "0%" -`)) + imagefs.available: "0%"`)) var kubeletSystemdTemplate = template.Must(template.New("kubeletSystemdTemplate").Parse(` [Unit] diff --git a/pkg/minikube/config/types.go b/pkg/minikube/config/types.go index 2be009f7bf89..c9f56f143253 100644 --- a/pkg/minikube/config/types.go +++ b/pkg/minikube/config/types.go @@ -70,6 +70,7 @@ type KubernetesConfig struct { NetworkPlugin string FeatureGates string ServiceCIDR string + PodSubnet string ExtraOptions util.ExtraOptionSlice ShouldLoadCachedImages bool diff --git a/pkg/minikube/constants/constants.go b/pkg/minikube/constants/constants.go index eb2e06d83cf1..7bcfc15924fb 100644 --- a/pkg/minikube/constants/constants.go +++ b/pkg/minikube/constants/constants.go @@ -202,7 +202,7 @@ const ( // DefaultMsize is the default number of bytes to use for 9p packet payload DefaultMsize = 262144 // DefaultMountVersion is the default 9p version to use for mount - DefaultMountVersion = "9p2000.L" + DefaultMountVersion = "9p2000.L" ) // GetKubernetesReleaseURL gets the location of a kubernetes client diff --git a/test/integration/start_stop_delete_test.go b/test/integration/start_stop_delete_test.go index 851c455a4ef0..aa5643b6ae26 100644 --- a/test/integration/start_stop_delete_test.go +++ b/test/integration/start_stop_delete_test.go @@ -19,23 +19,25 @@ limitations under the License. package integration import ( + "encoding/json" + "github.com/docker/machine/libmachine/state" + "k8s.io/minikube/test/integration/util" "net" "strings" "testing" "time" - - "github.com/docker/machine/libmachine/state" - "k8s.io/minikube/test/integration/util" ) func TestStartStop(t *testing.T) { tests := []struct { - name string - args []string + name string + args []string + assertCustom func(t *testing.T) }{ - {"docker+cache", []string{"--container-runtime=docker", "--cache-images"}}, - {"containerd+cache", []string{"--container-runtime=containerd", "--docker-opt containerd=/var/run/containerd/containerd.sock", "--cache-images"}}, - {"crio+cache", []string{"--container-runtime=crio", "--cache-images"}}, + {"docker+cache", []string{"--container-runtime=docker", "--cache-images"}, nil}, + {"containerd+cache", []string{"--container-runtime=containerd", "--docker-opt containerd=/var/run/containerd/containerd.sock", "--cache-images"}, nil}, + {"crio+cache", []string{"--container-runtime=crio", "--cache-images"}, nil}, + {"podCidr", []string{"--pod-network-cidr=192.168.111.111/16"}, assertPodCIDR}, } for _, test := range tests { @@ -51,6 +53,10 @@ func TestStartStop(t *testing.T) { r.Start(test.args...) r.CheckStatus(state.Running.String()) + if test.assertCustom != nil { + test.assertCustom(t) + } + ip := r.RunCommand("ip", true) ip = strings.TrimRight(ip, "\n") if net.ParseIP(ip) == nil { @@ -74,3 +80,24 @@ func TestStartStop(t *testing.T) { }) } } + +func assertPodCIDR(t *testing.T) { + kr := util.NewKubectlRunner(t) + out, err := kr.RunCommand([]string{"get", "nodes", "-o", "json"}) + if err != nil { + t.Fatalf("Failed to obtain nodes info") + } + + var result map[string]interface{} + json.Unmarshal([]byte(out), &result) + + items := result["items"].([]interface{}) + for _, item := range items { + spec := item.(map[string]interface{})["spec"] + podCidr := spec.(map[string]interface{})["podCIDR"].(string) + + if !strings.HasPrefix(podCidr, "192.168.0.0") { + t.Errorf("Unexpected podCIDR: %s", podCidr) + } + } +} diff --git a/test/integration/util/util.go b/test/integration/util/util.go index 83cbc67f8b8d..6b2ec9b437ec 100644 --- a/test/integration/util/util.go +++ b/test/integration/util/util.go @@ -191,6 +191,7 @@ func (m *MinikubeRunner) RunDaemon2(command string) (*exec.Cmd, *bufio.Reader, * } return cmd, bufio.NewReader(stdoutPipe), bufio.NewReader(stderrPipe) } + // SSH returns the output of running a command using SSH func (m *MinikubeRunner) SSH(command string) (string, error) { path, _ := filepath.Abs(m.BinaryPath)