diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index 75e2b00128..a9be0d00d8 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -77,6 +77,7 @@ const ( apiServerPort = "apiserver-port" dnsDomain = "dns-domain" serviceCIDR = "service-cluster-ip-range" + imageRepository = "image-repository" mountString = "mount-string" disableDriverMounts = "disable-driver-mounts" cacheImages = "cache-images" @@ -123,6 +124,7 @@ func init() { startCmd.Flags().String(serviceCIDR, pkgutil.DefaultServiceCIDR, "The CIDR to be used for service cluster IPs.") 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, "", "Image repository to pull down docker images.") startCmd.Flags().String(containerRuntime, "docker", "The container runtime to be used (docker, crio, containerd)") startCmd.Flags().String(criSocket, "", "The cri socket path to be used") startCmd.Flags().String(kubernetesVersion, constants.DefaultKubernetesVersion, "The kubernetes version that the minikube VM will use (ex: v1.2.3)") @@ -237,7 +239,7 @@ func beginCacheImages(g *errgroup.Group, kVersion string) { } console.OutStyle("caching", "Caching images in the background ...") g.Go(func() error { - return machine.CacheImagesForBootstrapper(kVersion, viper.GetString(cmdcfg.Bootstrapper)) + return machine.CacheImagesForBootstrapper(viper.GetString(imageRepository), kVersion, viper.GetString(cmdcfg.Bootstrapper)) }) } @@ -296,6 +298,7 @@ func generateConfig(cmd *cobra.Command, kVersion string) (cfg.Config, error) { CRISocket: viper.GetString(criSocket), NetworkPlugin: selectedNetworkPlugin, ServiceCIDR: viper.GetString(serviceCIDR), + ImageRepository: viper.GetString(imageRepository), ExtraOptions: extraOptions, ShouldLoadCachedImages: viper.GetBool(cacheImages), EnableDefaultCNI: selectedEnableDefaultCNI, diff --git a/deploy/addons/addon-manager.yaml b/deploy/addons/addon-manager.yaml index 105bfd76b8..56f6bb036d 100644 --- a/deploy/addons/addon-manager.yaml +++ b/deploy/addons/addon-manager.yaml @@ -25,7 +25,7 @@ spec: hostNetwork: true containers: - name: kube-addon-manager - image: k8s.gcr.io/kube-addon-manager:v8.6 + image: {{default "k8s.gcr.io" .ImageRepository}}/kube-addon-manager:v8.6 env: - name: KUBECONFIG value: /var/lib/minikube/kubeconfig diff --git a/deploy/addons/dashboard/dashboard-dp.yaml b/deploy/addons/dashboard/dashboard-dp.yaml index b9b4917984..6bf897b625 100644 --- a/deploy/addons/dashboard/dashboard-dp.yaml +++ b/deploy/addons/dashboard/dashboard-dp.yaml @@ -37,7 +37,7 @@ spec: spec: containers: - name: kubernetes-dashboard - image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1 + image: {{default "k8s.gcr.io" .ImageRepository}}/kubernetes-dashboard-amd64:v1.10.1 imagePullPolicy: IfNotPresent ports: - containerPort: 9090 diff --git a/deploy/addons/storage-provisioner/storage-provisioner.yaml b/deploy/addons/storage-provisioner/storage-provisioner.yaml index 72ee7feefb..4832acb4cf 100644 --- a/deploy/addons/storage-provisioner/storage-provisioner.yaml +++ b/deploy/addons/storage-provisioner/storage-provisioner.yaml @@ -51,7 +51,7 @@ spec: hostNetwork: true containers: - name: storage-provisioner - image: gcr.io/k8s-minikube/storage-provisioner:v1.8.1 + image: {{default "gcr.io/k8s-minikube" .ImageRepository}}/storage-provisioner:v1.8.1 command: ["/storage-provisioner"] imagePullPolicy: IfNotPresent volumeMounts: diff --git a/pkg/minikube/assets/addons.go b/pkg/minikube/assets/addons.go index b6db690e76..e21a5aba1f 100644 --- a/pkg/minikube/assets/addons.go +++ b/pkg/minikube/assets/addons.go @@ -62,222 +62,260 @@ var Addons = map[string]*Addon{ "deploy/addons/addon-manager.yaml", "/etc/kubernetes/manifests/", "addon-manager.yaml", - "0640"), + "0640", + true), }, true, "addon-manager"), "dashboard": NewAddon([]*BinDataAsset{ NewBinDataAsset( "deploy/addons/dashboard/dashboard-dp.yaml", constants.AddonsPath, "dashboard-dp.yaml", - "0640"), + "0640", + true), NewBinDataAsset( "deploy/addons/dashboard/dashboard-svc.yaml", constants.AddonsPath, "dashboard-svc.yaml", - "0640"), + "0640", + false), }, false, "dashboard"), "default-storageclass": NewAddon([]*BinDataAsset{ NewBinDataAsset( "deploy/addons/storageclass/storageclass.yaml", constants.AddonsPath, "storageclass.yaml", - "0640"), + "0640", + false), }, true, "default-storageclass"), "storage-provisioner": NewAddon([]*BinDataAsset{ NewBinDataAsset( "deploy/addons/storage-provisioner/storage-provisioner.yaml", constants.AddonsPath, "storage-provisioner.yaml", - "0640"), + "0640", + true), }, true, "storage-provisioner"), "storage-provisioner-gluster": NewAddon([]*BinDataAsset{ NewBinDataAsset( "deploy/addons/storage-provisioner-gluster/storage-gluster-ns.yaml", constants.AddonsPath, "storage-gluster-ns.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/storage-provisioner-gluster/glusterfs-daemonset.yaml", constants.AddonsPath, "glusterfs-daemonset.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/storage-provisioner-gluster/heketi-deployment.yaml", constants.AddonsPath, "heketi-deployment.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/storage-provisioner-gluster/storage-provisioner-glusterfile.yaml", constants.AddonsPath, "storage-privisioner-glusterfile.yaml", - "0640"), + "0640", + false), }, false, "storage-provisioner-gluster"), "heapster": NewAddon([]*BinDataAsset{ NewBinDataAsset( "deploy/addons/heapster/influx-grafana-rc.yaml", constants.AddonsPath, "influxGrafana-rc.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/heapster/grafana-svc.yaml", constants.AddonsPath, "grafana-svc.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/heapster/influxdb-svc.yaml", constants.AddonsPath, "influxdb-svc.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/heapster/heapster-rc.yaml", constants.AddonsPath, "heapster-rc.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/heapster/heapster-svc.yaml", constants.AddonsPath, "heapster-svc.yaml", - "0640"), + "0640", + false), }, false, "heapster"), "efk": NewAddon([]*BinDataAsset{ NewBinDataAsset( "deploy/addons/efk/elasticsearch-rc.yaml", constants.AddonsPath, "elasticsearch-rc.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/efk/elasticsearch-svc.yaml", constants.AddonsPath, "elasticsearch-svc.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/efk/fluentd-es-rc.yaml", constants.AddonsPath, "fluentd-es-rc.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/efk/fluentd-es-configmap.yaml", constants.AddonsPath, "fluentd-es-configmap.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/efk/kibana-rc.yaml", constants.AddonsPath, "kibana-rc.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/efk/kibana-svc.yaml", constants.AddonsPath, "kibana-svc.yaml", - "0640"), + "0640", + false), }, false, "efk"), "ingress": NewAddon([]*BinDataAsset{ NewBinDataAsset( "deploy/addons/ingress/ingress-configmap.yaml", constants.AddonsPath, "ingress-configmap.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/ingress/ingress-rbac.yaml", constants.AddonsPath, "ingress-rbac.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/ingress/ingress-dp.yaml", constants.AddonsPath, "ingress-dp.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/ingress/ingress-svc.yaml", constants.AddonsPath, "ingress-svc.yaml", - "0640"), + "0640", + false), }, false, "ingress"), "metrics-server": NewAddon([]*BinDataAsset{ NewBinDataAsset( "deploy/addons/metrics-server/metrics-apiservice.yaml", constants.AddonsPath, "metrics-apiservice.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/metrics-server/metrics-server-deployment.yaml", constants.AddonsPath, "metrics-server-deployment.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/metrics-server/metrics-server-service.yaml", constants.AddonsPath, "metrics-server-service.yaml", - "0640"), + "0640", + false), }, false, "metrics-server"), "registry": NewAddon([]*BinDataAsset{ NewBinDataAsset( "deploy/addons/registry/registry-rc.yaml", constants.AddonsPath, "registry-rc.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/registry/registry-svc.yaml", constants.AddonsPath, "registry-svc.yaml", - "0640"), + "0640", + false), }, false, "registry"), "registry-creds": NewAddon([]*BinDataAsset{ NewBinDataAsset( "deploy/addons/registry-creds/registry-creds-rc.yaml", constants.AddonsPath, "registry-creds-rc.yaml", - "0640"), + "0640", + false), }, false, "registry-creds"), "freshpod": NewAddon([]*BinDataAsset{ NewBinDataAsset( "deploy/addons/freshpod/freshpod-rc.yaml", constants.AddonsPath, "freshpod-rc.yaml", - "0640"), + "0640", + false), }, false, "freshpod"), "nvidia-driver-installer": NewAddon([]*BinDataAsset{ NewBinDataAsset( "deploy/addons/gpu/nvidia-driver-installer.yaml", constants.AddonsPath, "nvidia-driver-installer.yaml", - "0640"), + "0640", + false), }, false, "nvidia-driver-installer"), "nvidia-gpu-device-plugin": NewAddon([]*BinDataAsset{ NewBinDataAsset( "deploy/addons/gpu/nvidia-gpu-device-plugin.yaml", constants.AddonsPath, "nvidia-gpu-device-plugin.yaml", - "0640"), + "0640", + false), }, false, "nvidia-gpu-device-plugin"), "logviewer": NewAddon([]*BinDataAsset{ NewBinDataAsset( "deploy/addons/logviewer/logviewer-dp-and-svc.yaml", constants.AddonsPath, "logviewer-dp-and-svc.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/logviewer/logviewer-rbac.yaml", constants.AddonsPath, "logviewer-rbac.yaml", - "0640"), + "0640", + false), }, false, "logviewer"), "gvisor": NewAddon([]*BinDataAsset{ NewBinDataAsset( "deploy/addons/gvisor/gvisor-pod.yaml", constants.AddonsPath, "gvisor-pod.yaml", - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/gvisor/gvisor-config.toml", constants.GvisorFilesPath, constants.GvisorConfigTomlTargetName, - "0640"), + "0640", + false), NewBinDataAsset( "deploy/addons/gvisor/gvisor-containerd-shim.toml", constants.GvisorFilesPath, constants.GvisorContainerdShimTargetName, - "0640"), + "0640", + false), }, false, "gvisor"), } diff --git a/pkg/minikube/assets/vm_assets.go b/pkg/minikube/assets/vm_assets.go index 27d668a7ea..8c5d5a463b 100644 --- a/pkg/minikube/assets/vm_assets.go +++ b/pkg/minikube/assets/vm_assets.go @@ -18,6 +18,7 @@ package assets import ( "bytes" + "html/template" "io" "os" "path" @@ -134,32 +135,73 @@ func NewMemoryAsset(d []byte, targetDir, targetName, permissions string) *Memory type BinDataAsset struct { BaseAsset + template *template.Template } -func NewBinDataAsset(assetName, targetDir, targetName, permissions string) *BinDataAsset { +func NewBinDataAsset(assetName, targetDir, targetName, permissions string, isTemplate bool) *BinDataAsset { m := &BinDataAsset{ - BaseAsset{ + BaseAsset: BaseAsset{ AssetName: assetName, TargetDir: targetDir, TargetName: targetName, Permissions: permissions, }, + template: nil, } - m.loadData() + m.loadData(isTemplate) return m } -func (m *BinDataAsset) loadData() error { +func defaultValue(defValue string, val interface{}) string { + if val == nil { + return defValue + } + strVal, ok := val.(string) + if !ok || strVal == "" { + return defValue + } + return strVal +} + +func (m *BinDataAsset) loadData(isTemplate bool) error { contents, err := Asset(m.AssetName) if err != nil { return err } + + if isTemplate { + tpl, err := template.New(m.AssetName).Funcs(template.FuncMap{"default": defaultValue}).Parse(string(contents)) + if err != nil { + return err + } + + m.template = tpl + } + m.data = contents m.Length = len(contents) m.reader = bytes.NewReader(m.data) return nil } +func (m *BinDataAsset) IsTemplate() bool { + return m.template != nil +} + +func (m *BinDataAsset) Evaluate(data interface{}) (*MemoryAsset, error){ + if !m.IsTemplate() { + return nil, errors.Errorf("the asset %s is not a template", m.AssetName) + + } + + var buf bytes.Buffer + if err := m.template.Execute(&buf, data); err != nil { + return nil, err + } + + return NewMemoryAsset(buf.Bytes(), m.GetTargetDir(), m.GetTargetName(), m.GetPermissions()), nil +} + func (m *BinDataAsset) GetLength() int { return m.Length } diff --git a/pkg/minikube/bootstrapper/bootstrapper.go b/pkg/minikube/bootstrapper/bootstrapper.go index 4140f58548..ecc7197f2b 100644 --- a/pkg/minikube/bootstrapper/bootstrapper.go +++ b/pkg/minikube/bootstrapper/bootstrapper.go @@ -50,10 +50,11 @@ const ( BootstrapperTypeKubeadm = "kubeadm" ) -func GetCachedImageList(version string, bootstrapper string) []string { +func GetCachedImageList(imageRepository string, version string, bootstrapper string) []string { switch bootstrapper { case BootstrapperTypeKubeadm: - return constants.GetKubeadmCachedImages(version) + _, images := constants.GetKubeadmImages(imageRepository, version) + return images default: return []string{} } diff --git a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go index aa68d68c0f..182f51ae7f 100644 --- a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go +++ b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go @@ -32,7 +32,7 @@ import ( "github.com/docker/machine/libmachine" "github.com/docker/machine/libmachine/state" "github.com/golang/glog" - download "github.com/jimmidyson/go-download" + "github.com/jimmidyson/go-download" "github.com/pkg/errors" "golang.org/x/sync/errgroup" "k8s.io/minikube/pkg/minikube/assets" @@ -184,7 +184,7 @@ func (k *KubeadmBootstrapper) StartCluster(k8s config.KubernetesConfig) error { return nil } -func addAddons(files *[]assets.CopyableFile) error { +func addAddons(files *[]assets.CopyableFile, data interface{}) error { // add addons to file list // custom addons if err := assets.AddMinikubeDirAssets(files); err != nil { @@ -194,7 +194,16 @@ func addAddons(files *[]assets.CopyableFile) error { for _, addonBundle := range assets.Addons { if isEnabled, err := addonBundle.IsEnabled(); err == nil && isEnabled { for _, addon := range addonBundle.Assets { - *files = append(*files, addon) + if addon.IsTemplate() { + addonFile, err := addon.Evaluate(data) + if err != nil { + return errors.Wrapf(err, "evaluate bundled addon %s asset", addon.GetAssetName()) + } + + *files = append(*files, addonFile) + } else { + *files = append(*files, addon) + } } } else if err != nil { return nil @@ -286,7 +295,10 @@ func NewKubeletConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, extraOpts["network-plugin"] = k8s.NetworkPlugin } - extraFlags := convertToFlags(extraOpts) + podInfraContainerImage, _ := constants.GetKubeadmImages(k8s.ImageRepository, k8s.KubernetesVersion) + if _, ok := extraOpts["pod-infra-container-image"]; !ok && k8s.ImageRepository != "" && podInfraContainerImage != "" { + extraOpts["pod-infra-container-image"] = podInfraContainerImage + } // parses a map of the feature gates for kubelet _, kubeletFeatureArgs, err := ParseFeatureArgs(k8s.FeatureGates) @@ -294,14 +306,18 @@ func NewKubeletConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, return "", errors.Wrap(err, "parses feature gate config for kubelet") } + if kubeletFeatureArgs != "" { + extraOpts["feature-gates"] = kubeletFeatureArgs + } + + extraFlags := convertToFlags(extraOpts) + b := bytes.Buffer{} opts := struct { ExtraOptions string - FeatureGates string ContainerRuntime string }{ ExtraOptions: extraFlags, - FeatureGates: kubeletFeatureArgs, ContainerRuntime: k8s.ContainerRuntime, } if err := kubeletSystemdTemplate.Execute(&b, opts); err != nil { @@ -312,8 +328,9 @@ func NewKubeletConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, } func (k *KubeadmBootstrapper) UpdateCluster(cfg config.KubernetesConfig) error { + _, images := constants.GetKubeadmImages(cfg.ImageRepository, cfg.KubernetesVersion) if cfg.ShouldLoadCachedImages { - err := machine.LoadImages(k.c, constants.GetKubeadmCachedImages(cfg.KubernetesVersion), constants.ImageCacheDir) + err := machine.LoadImages(k.c, images, constants.ImageCacheDir) if err != nil { return errors.Wrap(err, "loading cached images") } @@ -322,7 +339,7 @@ func (k *KubeadmBootstrapper) UpdateCluster(cfg config.KubernetesConfig) error { if err != nil { return errors.Wrap(err, "runtime") } - kubeadmCfg, err := generateConfig(cfg, r) + kubeadmCfg, opts, err := generateConfig(cfg, r) if err != nil { return errors.Wrap(err, "generating kubeadm cfg") } @@ -370,7 +387,7 @@ func (k *KubeadmBootstrapper) UpdateCluster(cfg config.KubernetesConfig) error { return errors.Wrap(err, "downloading binaries") } - if err := addAddons(&files); err != nil { + if err := addAddons(&files, opts); err != nil { return errors.Wrap(err, "adding addons") } @@ -391,22 +408,22 @@ sudo systemctl start kubelet return nil } -func generateConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, error) { +func generateConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, interface{}, error) { version, err := ParseKubernetesVersion(k8s.KubernetesVersion) if err != nil { - return "", errors.Wrap(err, "parsing kubernetes version") + return "", nil, errors.Wrap(err, "parsing kubernetes version") } // parses a map of the feature gates for kubeadm and component kubeadmFeatureArgs, componentFeatureArgs, err := ParseFeatureArgs(k8s.FeatureGates) if err != nil { - return "", errors.Wrap(err, "parses feature gate config for kubeadm and component") + return "", nil, errors.Wrap(err, "parses feature gate config for kubeadm and component") } // generates a map of component to extra args for apiserver, controller-manager, and scheduler extraComponentConfig, err := NewComponentExtraArgs(k8s.ExtraOptions, version, componentFeatureArgs) if err != nil { - return "", errors.Wrap(err, "generating extra component config for kubeadm") + return "", nil, errors.Wrap(err, "generating extra component config for kubeadm") } // In case of no port assigned, use util.APIServerPort @@ -424,6 +441,7 @@ func generateConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, er EtcdDataDir string NodeName string CRISocket string + ImageRepository string ExtraArgs []ComponentExtraArgs FeatureArgs map[string]bool NoTaintMaster bool @@ -436,6 +454,7 @@ func generateConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, er EtcdDataDir: "/data/minikube", //TODO(r2d4): change to something else persisted NodeName: k8s.NodeName, CRISocket: r.SocketPath(), + ImageRepository: k8s.ImageRepository, ExtraArgs: extraComponentConfig, FeatureArgs: kubeadmFeatureArgs, NoTaintMaster: false, // That does not work with k8s 1.12+ @@ -455,10 +474,10 @@ func generateConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, er kubeadmConfigTemplate = kubeadmConfigTemplateV1Alpha3 } if err := kubeadmConfigTemplate.Execute(&b, opts); err != nil { - return "", err + return "", nil, err } - return b.String(), nil + return b.String(), opts, nil } func maybeDownloadAndCache(binary, version string) (string, error) { diff --git a/pkg/minikube/bootstrapper/kubeadm/kubeadm_test.go b/pkg/minikube/bootstrapper/kubeadm/kubeadm_test.go index 01ad19cd03..10e780de9c 100644 --- a/pkg/minikube/bootstrapper/kubeadm/kubeadm_test.go +++ b/pkg/minikube/bootstrapper/kubeadm/kubeadm_test.go @@ -264,7 +264,7 @@ apiServerExtraArgs: } t.Run(test.description, func(t *testing.T) { - actualCfg, err := generateConfig(test.cfg, runtime) + actualCfg, _, err := generateConfig(test.cfg, runtime) if err != nil && !test.shouldErr { t.Errorf("got unexpected error generating config: %v", err) return diff --git a/pkg/minikube/bootstrapper/kubeadm/templates.go b/pkg/minikube/bootstrapper/kubeadm/templates.go index 8b35b2b827..ee27272fe3 100644 --- a/pkg/minikube/bootstrapper/kubeadm/templates.go +++ b/pkg/minikube/bootstrapper/kubeadm/templates.go @@ -38,7 +38,8 @@ networking: etcd: dataDir: {{.EtcdDataDir}} nodeName: {{.NodeName}} -{{if .CRISocket}}criSocket: {{.CRISocket}} +{{if .ImageRepository}}imageRepository: {{.ImageRepository}} +{{end}}{{if .CRISocket}}criSocket: {{.CRISocket}} {{end}}{{range .ExtraArgs}}{{.Component}}:{{range $i, $val := printMapInOrder .Options ": " }} {{$val}}{{end}} {{end}}{{if .FeatureArgs}}featureGates: {{range $i, $val := .FeatureArgs}} @@ -67,7 +68,8 @@ nodeRegistration: --- apiVersion: kubeadm.k8s.io/v1alpha3 kind: ClusterConfiguration -{{range .ExtraArgs}}{{.Component}}:{{range $i, $val := printMapInOrder .Options ": " }} +{{if .ImageRepository}}imageRepository: {{.ImageRepository}} +{{end}}{{range .ExtraArgs}}{{.Component}}:{{range $i, $val := printMapInOrder .Options ": " }} {{$val}}{{end}} {{end}}{{if .FeatureArgs}}featureGates: {{range $i, $val := .FeatureArgs}} {{$i}}: {{$val}}{{end}} @@ -101,7 +103,7 @@ var kubeletSystemdTemplate = template.Must(template.New("kubeletSystemdTemplate" [Service] ExecStart= -ExecStart=/usr/bin/kubelet {{.ExtraOptions}} {{if .FeatureGates}}--feature-gates={{.FeatureGates}}{{end}} +ExecStart=/usr/bin/kubelet{{if .ExtraOptions}} {{.ExtraOptions}}{{end}} [Install] `)) diff --git a/pkg/minikube/config/types.go b/pkg/minikube/config/types.go index 3f9a7a1c3e..7982d04c4c 100644 --- a/pkg/minikube/config/types.go +++ b/pkg/minikube/config/types.go @@ -69,6 +69,7 @@ type KubernetesConfig struct { NetworkPlugin string FeatureGates string ServiceCIDR string + ImageRepository string ExtraOptions util.ExtraOptionSlice ShouldLoadCachedImages bool diff --git a/pkg/minikube/constants/constants.go b/pkg/minikube/constants/constants.go index 2fa11c50c7..8182cca43e 100644 --- a/pkg/minikube/constants/constants.go +++ b/pkg/minikube/constants/constants.go @@ -176,13 +176,24 @@ const IsMinikubeChildProcess = "IS_MINIKUBE_CHILD_PROCESS" const DriverNone = "none" const FileScheme = "file" -func GetKubeadmCachedImages(kubernetesVersionStr string) []string { +func GetKubeadmImages(imageRepository string, kubernetesVersionStr string) (string, []string) { + minikubeRepository := imageRepository + if imageRepository == "" { + imageRepository = "k8s.gcr.io" + minikubeRepository = "gcr.io/k8s-minikube" + } + if !strings.HasSuffix(imageRepository, "/") { + imageRepository += "/" + } + if !strings.HasSuffix(minikubeRepository, "/") { + minikubeRepository += "/" + } var images = []string{ - "k8s.gcr.io/kube-proxy-amd64:" + kubernetesVersionStr, - "k8s.gcr.io/kube-scheduler-amd64:" + kubernetesVersionStr, - "k8s.gcr.io/kube-controller-manager-amd64:" + kubernetesVersionStr, - "k8s.gcr.io/kube-apiserver-amd64:" + kubernetesVersionStr, + imageRepository + "kube-proxy-amd64:" + kubernetesVersionStr, + imageRepository + "kube-scheduler-amd64:" + kubernetesVersionStr, + imageRepository + "kube-controller-manager-amd64:" + kubernetesVersionStr, + imageRepository + "kube-apiserver-amd64:" + kubernetesVersionStr, } ge_v1_13 := semver.MustParseRange(">=1.13.0") @@ -197,74 +208,84 @@ func GetKubeadmCachedImages(kubernetesVersionStr string) []string { glog.Errorln("Error parsing version semver: ", err) } + var podInfraContainerImage string if ge_v1_13(kubernetesVersion) { + podInfraContainerImage = imageRepository + "pause-amd64:3.1" images = append(images, []string{ - "k8s.gcr.io/pause-amd64:3.1", - "k8s.gcr.io/pause:3.1", - "k8s.gcr.io/k8s-dns-kube-dns-amd64:1.14.8", - "k8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64:1.14.8", - "k8s.gcr.io/k8s-dns-sidecar-amd64:1.14.8", - "k8s.gcr.io/etcd-amd64:3.2.24", - "k8s.gcr.io/coredns:1.2.6", + podInfraContainerImage, + imageRepository + "pause:3.1", + imageRepository + "k8s-dns-kube-dns-amd64:1.14.8", + imageRepository + "k8s-dns-dnsmasq-nanny-amd64:1.14.8", + imageRepository + "k8s-dns-sidecar-amd64:1.14.8", + imageRepository + "etcd-amd64:3.2.24", + imageRepository + "coredns:1.2.6", }...) } else if v1_12(kubernetesVersion) { + podInfraContainerImage = imageRepository + "pause-amd64:3.1" images = append(images, []string{ - "k8s.gcr.io/pause-amd64:3.1", - "k8s.gcr.io/pause:3.1", - "k8s.gcr.io/k8s-dns-kube-dns-amd64:1.14.8", - "k8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64:1.14.8", - "k8s.gcr.io/k8s-dns-sidecar-amd64:1.14.8", - "k8s.gcr.io/etcd-amd64:3.2.24", - "k8s.gcr.io/coredns:1.2.2", + podInfraContainerImage, + imageRepository + "pause:3.1", + imageRepository + "k8s-dns-kube-dns-amd64:1.14.8", + imageRepository + "k8s-dns-dnsmasq-nanny-amd64:1.14.8", + imageRepository + "k8s-dns-sidecar-amd64:1.14.8", + imageRepository + "etcd-amd64:3.2.24", + imageRepository + "coredns:1.2.2", }...) } else if v1_11(kubernetesVersion) { + podInfraContainerImage = imageRepository + "pause-amd64:3.1" images = append(images, []string{ - "k8s.gcr.io/pause-amd64:3.1", - "k8s.gcr.io/pause:3.1", - "k8s.gcr.io/k8s-dns-kube-dns-amd64:1.14.8", - "k8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64:1.14.8", - "k8s.gcr.io/k8s-dns-sidecar-amd64:1.14.8", - "k8s.gcr.io/etcd-amd64:3.2.18", - "k8s.gcr.io/coredns:1.1.3", + podInfraContainerImage, + imageRepository + "pause:3.1", + imageRepository + "k8s-dns-kube-dns-amd64:1.14.8", + imageRepository + "k8s-dns-dnsmasq-nanny-amd64:1.14.8", + imageRepository + "k8s-dns-sidecar-amd64:1.14.8", + imageRepository + "etcd-amd64:3.2.18", + imageRepository + "coredns:1.1.3", }...) } else if v1_10(kubernetesVersion) { + podInfraContainerImage = imageRepository + "pause-amd64:3.1" images = append(images, []string{ - "k8s.gcr.io/pause-amd64:3.1", - "k8s.gcr.io/k8s-dns-kube-dns-amd64:1.14.8", - "k8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64:1.14.8", - "k8s.gcr.io/k8s-dns-sidecar-amd64:1.14.8", - "k8s.gcr.io/etcd-amd64:3.1.12", + podInfraContainerImage, + imageRepository + "k8s-dns-kube-dns-amd64:1.14.8", + imageRepository + "k8s-dns-dnsmasq-nanny-amd64:1.14.8", + imageRepository + "k8s-dns-sidecar-amd64:1.14.8", + imageRepository + "etcd-amd64:3.1.12", }...) } else if v1_9(kubernetesVersion) { + podInfraContainerImage = imageRepository + "pause-amd64:3.0" images = append(images, []string{ - "k8s.gcr.io/pause-amd64:3.0", - "k8s.gcr.io/k8s-dns-kube-dns-amd64:1.14.7", - "k8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64:1.14.7", - "k8s.gcr.io/k8s-dns-sidecar-amd64:1.14.7", - "k8s.gcr.io/etcd-amd64:3.1.10", + podInfraContainerImage, + imageRepository + "k8s-dns-kube-dns-amd64:1.14.7", + imageRepository + "k8s-dns-dnsmasq-nanny-amd64:1.14.7", + imageRepository + "k8s-dns-sidecar-amd64:1.14.7", + imageRepository + "etcd-amd64:3.1.10", }...) } else if v1_8(kubernetesVersion) { + podInfraContainerImage = imageRepository + "pause-amd64:3.0" images = append(images, []string{ - "k8s.gcr.io/pause-amd64:3.0", - "k8s.gcr.io/k8s-dns-kube-dns-amd64:1.14.5", - "k8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64:1.14.5", - "k8s.gcr.io/k8s-dns-sidecar-amd64:1.14.5", - "k8s.gcr.io/etcd-amd64:3.0.17", + podInfraContainerImage, + imageRepository + "k8s-dns-kube-dns-amd64:1.14.5", + imageRepository + "k8s-dns-dnsmasq-nanny-amd64:1.14.5", + imageRepository + "k8s-dns-sidecar-amd64:1.14.5", + imageRepository + "etcd-amd64:3.0.17", }...) + + } else { + podInfraContainerImage = imageRepository + "/pause-amd64:3.0" } images = append(images, []string{ - "k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1", - "k8s.gcr.io/kube-addon-manager:v8.6", - "gcr.io/k8s-minikube/storage-provisioner:v1.8.1", + imageRepository + "kubernetes-dashboard-amd64:v1.10.1", + imageRepository + "kube-addon-manager:v8.6", + minikubeRepository + "storage-provisioner:v1.8.1", }...) - return images + return podInfraContainerImage, images } var ImageCacheDir = MakeMiniPath("cache", "images") diff --git a/pkg/minikube/machine/cache_images.go b/pkg/minikube/machine/cache_images.go index 9123b62c91..2afcc60522 100644 --- a/pkg/minikube/machine/cache_images.go +++ b/pkg/minikube/machine/cache_images.go @@ -48,8 +48,8 @@ var getWindowsVolumeName = getWindowsVolumeNameCmd // loadImageLock is used to serialize image loads to avoid overloading the guest VM var loadImageLock sync.Mutex -func CacheImagesForBootstrapper(version string, clusterBootstrapper string) error { - images := bootstrapper.GetCachedImageList(version, clusterBootstrapper) +func CacheImagesForBootstrapper(imageRepository string, version string, clusterBootstrapper string) error { + images := bootstrapper.GetCachedImageList(imageRepository, version, clusterBootstrapper) if err := CacheImages(images, constants.ImageCacheDir); err != nil { return errors.Wrapf(err, "Caching images for %s", clusterBootstrapper)