diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index df661362d08a..24961fd7a62c 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" imageRepository = "image-repository" mountString = "mount-string" disableDriverMounts = "disable-driver-mounts" @@ -126,6 +127,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(imageRepository, "", "Alternative image repository to pull docker images from. This can be used when you have limited access to gcr.io. For Chinese mainland users, you may use local gcr.io mirrors such as registry.cn-hangzhou.aliyuncs.com/google_containers") @@ -332,6 +334,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), ImageRepository: viper.GetString(imageRepository), ExtraOptions: extraOptions, ShouldLoadCachedImages: viper.GetBool(cacheImages), diff --git a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go index 6be7e6b2ab6b..106780397c8d 100644 --- a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go +++ b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go @@ -535,6 +535,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 @@ -548,6 +549,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 a43fe782c533..31aeb46d2d74 100644 --- a/pkg/minikube/bootstrapper/kubeadm/kubeadm_test.go +++ b/pkg/minikube/bootstrapper/kubeadm/kubeadm_test.go @@ -177,6 +177,7 @@ func TestGenerateConfig(t *testing.T) { {"crio-options-gates", "crio", false, config.KubernetesConfig{ExtraOptions: extraOpts, FeatureGates: "a=b"}}, {"unknown-omponent", "docker", true, config.KubernetesConfig{ExtraOptions: util.ExtraOptionSlice{util.ExtraOption{Component: "not-a-real-component", Key: "killswitch", Value: "true"}}}}, {"containerd-api-port", "containerd", false, config.KubernetesConfig{NodePort: 12345}}, + {"containerd-pod-network-cidr", "containerd", false, config.KubernetesConfig{PodSubnet: "192.168.32.0/20"}}, {"image-repository", "docker", false, config.KubernetesConfig{ImageRepository: "test/repo"}}, } for vname, version := range versions { diff --git a/pkg/minikube/bootstrapper/kubeadm/templates.go b/pkg/minikube/bootstrapper/kubeadm/templates.go index e5a63efc4456..e1b14bc1840f 100644 --- a/pkg/minikube/bootstrapper/kubeadm/templates.go +++ b/pkg/minikube/bootstrapper/kubeadm/templates.go @@ -85,7 +85,7 @@ etcd: kubernetesVersion: {{.KubernetesVersion}} networking: dnsDomain: cluster.local - podSubnet: "" + podSubnet: {{if .PodSubnet}}{{.PodSubnet}}{{else}}""{{end}} serviceSubnet: {{.ServiceCIDR}} --- apiVersion: kubelet.config.k8s.io/v1beta1 diff --git a/pkg/minikube/bootstrapper/kubeadm/testdata/containerd-pod-network-cidr__default.yaml b/pkg/minikube/bootstrapper/kubeadm/testdata/containerd-pod-network-cidr__default.yaml new file mode 100644 index 000000000000..147a6ccbec0d --- /dev/null +++ b/pkg/minikube/bootstrapper/kubeadm/testdata/containerd-pod-network-cidr__default.yaml @@ -0,0 +1,43 @@ +apiVersion: kubeadm.k8s.io/v1beta1 +kind: InitConfiguration +localAPIEndpoint: + advertiseAddress: 1.1.1.1 + bindPort: 8443 +bootstrapTokens: + - groups: + - system:bootstrappers:kubeadm:default-node-token + ttl: 24h0m0s + usages: + - signing + - authentication +nodeRegistration: + criSocket: /run/containerd/containerd.sock + name: mk + taints: [] +--- +apiVersion: kubeadm.k8s.io/v1beta1 +kind: ClusterConfiguration +apiServer: + extraArgs: + enable-admission-plugins: "NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota" +certificatesDir: /var/lib/minikube/certs/ +clusterName: kubernetes +controlPlaneEndpoint: localhost:8443 +dns: + type: CoreDNS +etcd: + local: + dataDir: /data/minikube +kubernetesVersion: v1.14.0 +networking: + dnsDomain: cluster.local + podSubnet: "" + serviceSubnet: 10.96.0.0/12 +--- +apiVersion: kubelet.config.k8s.io/v1beta1 +kind: KubeletConfiguration +imageGCHighThresholdPercent: 100 +evictionHard: + nodefs.available: "0%" + nodefs.inodesFree: "0%" + imagefs.available: "0%" diff --git a/pkg/minikube/bootstrapper/kubeadm/testdata/containerd-pod-network-cidr__new.yaml b/pkg/minikube/bootstrapper/kubeadm/testdata/containerd-pod-network-cidr__new.yaml new file mode 100644 index 000000000000..147a6ccbec0d --- /dev/null +++ b/pkg/minikube/bootstrapper/kubeadm/testdata/containerd-pod-network-cidr__new.yaml @@ -0,0 +1,43 @@ +apiVersion: kubeadm.k8s.io/v1beta1 +kind: InitConfiguration +localAPIEndpoint: + advertiseAddress: 1.1.1.1 + bindPort: 8443 +bootstrapTokens: + - groups: + - system:bootstrappers:kubeadm:default-node-token + ttl: 24h0m0s + usages: + - signing + - authentication +nodeRegistration: + criSocket: /run/containerd/containerd.sock + name: mk + taints: [] +--- +apiVersion: kubeadm.k8s.io/v1beta1 +kind: ClusterConfiguration +apiServer: + extraArgs: + enable-admission-plugins: "NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota" +certificatesDir: /var/lib/minikube/certs/ +clusterName: kubernetes +controlPlaneEndpoint: localhost:8443 +dns: + type: CoreDNS +etcd: + local: + dataDir: /data/minikube +kubernetesVersion: v1.14.0 +networking: + dnsDomain: cluster.local + podSubnet: "" + serviceSubnet: 10.96.0.0/12 +--- +apiVersion: kubelet.config.k8s.io/v1beta1 +kind: KubeletConfiguration +imageGCHighThresholdPercent: 100 +evictionHard: + nodefs.available: "0%" + nodefs.inodesFree: "0%" + imagefs.available: "0%" diff --git a/pkg/minikube/bootstrapper/kubeadm/testdata/containerd-pod-network-cidr__obsolete.yaml b/pkg/minikube/bootstrapper/kubeadm/testdata/containerd-pod-network-cidr__obsolete.yaml new file mode 100644 index 000000000000..b2d73f912bff --- /dev/null +++ b/pkg/minikube/bootstrapper/kubeadm/testdata/containerd-pod-network-cidr__obsolete.yaml @@ -0,0 +1,17 @@ +apiVersion: kubeadm.k8s.io/v1alpha1 +kind: MasterConfiguration +noTaintMaster: true +api: + advertiseAddress: 1.1.1.1 + bindPort: 8443 + controlPlaneEndpoint: localhost +kubernetesVersion: v1.10.0 +certificatesDir: /var/lib/minikube/certs/ +networking: + serviceSubnet: 10.96.0.0/12 +etcd: + dataDir: /data/minikube +nodeName: mk +criSocket: /run/containerd/containerd.sock +apiServerExtraArgs: + admission-control: "Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota" diff --git a/pkg/minikube/bootstrapper/kubeadm/testdata/containerd-pod-network-cidr__old.yaml b/pkg/minikube/bootstrapper/kubeadm/testdata/containerd-pod-network-cidr__old.yaml new file mode 100644 index 000000000000..64bf678f0229 --- /dev/null +++ b/pkg/minikube/bootstrapper/kubeadm/testdata/containerd-pod-network-cidr__old.yaml @@ -0,0 +1,39 @@ +apiVersion: kubeadm.k8s.io/v1alpha3 +kind: InitConfiguration +apiEndpoint: + advertiseAddress: 1.1.1.1 + bindPort: 8443 +bootstrapTokens: + - groups: + - system:bootstrappers:kubeadm:default-node-token + ttl: 24h0m0s + usages: + - signing + - authentication +nodeRegistration: + criSocket: /run/containerd/containerd.sock + name: mk + 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%" diff --git a/pkg/minikube/bootstrapper/kubeadm/testdata/containerd-pod-network-cidr__recent.yaml b/pkg/minikube/bootstrapper/kubeadm/testdata/containerd-pod-network-cidr__recent.yaml new file mode 100644 index 000000000000..ecc9a146311f --- /dev/null +++ b/pkg/minikube/bootstrapper/kubeadm/testdata/containerd-pod-network-cidr__recent.yaml @@ -0,0 +1,39 @@ +apiVersion: kubeadm.k8s.io/v1alpha3 +kind: InitConfiguration +apiEndpoint: + advertiseAddress: 1.1.1.1 + bindPort: 8443 +bootstrapTokens: + - groups: + - system:bootstrappers:kubeadm:default-node-token + ttl: 24h0m0s + usages: + - signing + - authentication +nodeRegistration: + criSocket: /run/containerd/containerd.sock + name: mk + 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.13.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%" diff --git a/pkg/minikube/config/types.go b/pkg/minikube/config/types.go index 2537ebbd2fd8..4a82698ce408 100644 --- a/pkg/minikube/config/types.go +++ b/pkg/minikube/config/types.go @@ -71,6 +71,7 @@ type KubernetesConfig struct { NetworkPlugin string FeatureGates string ServiceCIDR string + PodSubnet string ImageRepository string ExtraOptions util.ExtraOptionSlice diff --git a/test/integration/start_stop_delete_test.go b/test/integration/start_stop_delete_test.go index 839283654d68..6bd3a982b551 100644 --- a/test/integration/start_stop_delete_test.go +++ b/test/integration/start_stop_delete_test.go @@ -20,6 +20,7 @@ package integration import ( "fmt" + "encoding/json" "net" "strings" "testing" @@ -32,29 +33,33 @@ import ( func TestStartStop(t *testing.T) { tests := []struct { - name string - args []string + name string + args []string + assertCustom func(t *testing.T) }{ {"nocache_oldest", []string{ "--cache-images=false", fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion), - }}, + }, nil}, {"feature_gates_newest_cni", []string{ "--feature-gates", "ServerSideApply=true", "--network-plugin=cni", "--extra-config=kubelet.network-plugin=cni", fmt.Sprintf("--kubernetes-version=%s", constants.NewestKubernetesVersion), - }}, + }, nil}, {"containerd", []string{ "--container-runtime=containerd", "--docker-opt containerd=/var/run/containerd/containerd.sock", - }}, + }, nil}, {"crio_ignore_preflights", []string{ "--container-runtime=crio", "--extra-config", "kubeadm.ignore-preflight-errors=SystemVerification", - }}, + }, nil}, + {"podCidr", []string{ + "--pod-network-cidr=192.168.111.111/16", + }, assertPodCIDR}, } for _, test := range tests { @@ -70,6 +75,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 { @@ -93,3 +102,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) + } + } +}