Merge pull request #6043 from tstromberg/correct-kubernetes-images

Sync cached image list for Kubernetes v1.17
pull/6050/head
Thomas Strömberg 2019-12-10 15:24:04 -08:00 committed by GitHub
commit 0ca6c6c4c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 444 additions and 203 deletions

View File

@ -646,7 +646,7 @@ func validateDriver(name string, existing *cfg.MachineConfig) {
exit.WithCodeT(exit.Config, "Exiting.")
}
func selectImageRepository(mirrorCountry string, k8sVersion string) (bool, string, error) {
func selectImageRepository(mirrorCountry string) (bool, string, error) {
var tryCountries []string
var fallback string
glog.Infof("selecting image repository for country %s ...", mirrorCountry)
@ -674,7 +674,7 @@ func selectImageRepository(mirrorCountry string, k8sVersion string) (bool, strin
}
checkRepository := func(repo string) error {
pauseImage := images.PauseImage(repo, k8sVersion)
pauseImage := images.Pause(repo)
ref, err := name.ParseReference(pauseImage, name.WeakValidation)
if err != nil {
return err
@ -867,7 +867,7 @@ func generateCfgFromFlags(cmd *cobra.Command, k8sVersion string, drvName string)
repository := viper.GetString(imageRepository)
mirrorCountry := strings.ToLower(viper.GetString(imageMirrorCountry))
if strings.ToLower(repository) == "auto" || mirrorCountry != "" {
found, autoSelectedRepository, err := selectImageRepository(mirrorCountry, k8sVersion)
found, autoSelectedRepository, err := selectImageRepository(mirrorCountry)
if err != nil {
exit.WithError("Failed to check main repository and mirrors for images for images", err)
}
@ -1109,7 +1109,7 @@ func tryRegistry(r command.Runner) {
repo := viper.GetString(imageRepository)
if repo == "" {
repo = images.DefaultImageRepo
repo = images.DefaultKubernetesRepo
}
opts = append(opts, fmt.Sprintf("https://%s/", repo))

View File

@ -64,12 +64,11 @@ func GetCachedBinaryList(bootstrapper string) []string {
}
// GetCachedImageList returns the list of images for a version
func GetCachedImageList(imageRepository string, version string, bootstrapper string) []string {
func GetCachedImageList(imageRepository string, version string, bootstrapper string) ([]string, error) {
switch bootstrapper {
case BootstrapperTypeKubeadm:
images := images.CachedImages(imageRepository, version)
return images
return images.Kubeadm(imageRepository, version)
default:
return []string{}
return []string{}, nil
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright 2019 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.
@ -14,188 +14,63 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Package images implements helpers for getting image names
package images
import (
"path"
"runtime"
"strings"
"github.com/blang/semver"
"github.com/golang/glog"
minikubeVersion "k8s.io/minikube/pkg/version"
)
const (
// DefaultImageRepo is the default repository for images
DefaultImageRepo = "k8s.gcr.io"
// DefaultMinikubeRepo is the default repository for minikube
DefaultMinikubeRepo = "gcr.io/k8s-minikube"
)
// getImageRepositories returns either the k8s image registry on GCR or a mirror if specified
func getImageRepository(imageRepository string) string {
if imageRepository == "" {
imageRepository = DefaultImageRepo
}
if !strings.HasSuffix(imageRepository, "/") {
imageRepository += "/"
}
return imageRepository
}
// getMinikubeRepository returns either the minikube image registry on GCR or a mirror if specified
func getMinikubeRepository(imageRepository string) string {
minikubeRepository := imageRepository
if minikubeRepository == "" {
minikubeRepository = DefaultMinikubeRepo
}
if !strings.HasSuffix(minikubeRepository, "/") {
minikubeRepository += "/"
}
return minikubeRepository
}
// CachedImages gets the images to cache for kubeadm for a version
func CachedImages(imageRepositoryStr string, kubernetesVersionStr string) []string {
imageRepository := getImageRepository(imageRepositoryStr)
minikubeRepository := getMinikubeRepository(imageRepositoryStr)
v1_16plus := semver.MustParseRange(">=1.16.0")
v1_14plus := semver.MustParseRange(">=1.14.0 <1.16.0")
v1_13 := semver.MustParseRange(">=1.13.0 <1.14.0")
v1_12 := semver.MustParseRange(">=1.12.0 <1.13.0")
v1_11 := semver.MustParseRange(">=1.11.0 <1.12.0")
v1_12plus := semver.MustParseRange(">=1.12.0")
kubernetesVersion, err := semver.Make(strings.TrimPrefix(kubernetesVersionStr, minikubeVersion.VersionPrefix))
if err != nil {
glog.Errorln("Error parsing version semver: ", err)
}
var images []string
if v1_12plus(kubernetesVersion) {
images = append(images, []string{
imageRepository + "kube-proxy" + ArchTag(false) + kubernetesVersionStr,
imageRepository + "kube-scheduler" + ArchTag(false) + kubernetesVersionStr,
imageRepository + "kube-controller-manager" + ArchTag(false) + kubernetesVersionStr,
imageRepository + "kube-apiserver" + ArchTag(false) + kubernetesVersionStr,
}...)
} else {
images = append(images, []string{
imageRepository + "kube-proxy" + ArchTag(true) + kubernetesVersionStr,
imageRepository + "kube-scheduler" + ArchTag(true) + kubernetesVersionStr,
imageRepository + "kube-controller-manager" + ArchTag(true) + kubernetesVersionStr,
imageRepository + "kube-apiserver" + ArchTag(true) + kubernetesVersionStr,
}...)
}
podInfraContainerImage := PauseImage(imageRepository, kubernetesVersionStr)
if v1_16plus(kubernetesVersion) {
images = append(images, []string{
podInfraContainerImage,
imageRepository + "k8s-dns-kube-dns" + ArchTag(true) + "1.14.13",
imageRepository + "k8s-dns-dnsmasq-nanny" + ArchTag(true) + "1.14.13",
imageRepository + "k8s-dns-sidecar" + ArchTag(true) + "1.14.13",
imageRepository + "etcd" + ArchTag(false) + "3.3.15-0",
imageRepository + "coredns" + ArchTag(false) + "1.6.2",
}...)
} else if v1_14plus(kubernetesVersion) {
images = append(images, []string{
podInfraContainerImage,
imageRepository + "k8s-dns-kube-dns" + ArchTag(true) + "1.14.13",
imageRepository + "k8s-dns-dnsmasq-nanny" + ArchTag(true) + "1.14.13",
imageRepository + "k8s-dns-sidecar" + ArchTag(true) + "1.14.13",
imageRepository + "etcd" + ArchTag(false) + "3.3.10",
imageRepository + "coredns" + ArchTag(false) + "1.3.1",
}...)
} else if v1_13(kubernetesVersion) {
images = append(images, []string{
podInfraContainerImage,
imageRepository + "k8s-dns-kube-dns" + ArchTag(true) + "1.14.8",
imageRepository + "k8s-dns-dnsmasq-nanny" + ArchTag(true) + "1.14.8",
imageRepository + "k8s-dns-sidecar" + ArchTag(true) + "1.14.8",
imageRepository + "etcd" + ArchTag(false) + "3.2.24",
imageRepository + "coredns:1.2.6",
}...)
} else if v1_12(kubernetesVersion) {
images = append(images, []string{
podInfraContainerImage,
imageRepository + "k8s-dns-kube-dns" + ArchTag(true) + "1.14.8",
imageRepository + "k8s-dns-dnsmasq-nanny" + ArchTag(true) + "1.14.8",
imageRepository + "k8s-dns-sidecar" + ArchTag(true) + "1.14.8",
imageRepository + "etcd" + ArchTag(false) + "3.2.24",
imageRepository + "coredns:1.2.2",
}...)
} else if v1_11(kubernetesVersion) {
images = append(images, []string{
podInfraContainerImage,
imageRepository + "k8s-dns-kube-dns" + ArchTag(true) + "1.14.8",
imageRepository + "k8s-dns-dnsmasq-nanny" + ArchTag(true) + "1.14.8",
imageRepository + "k8s-dns-sidecar" + ArchTag(true) + "1.14.8",
imageRepository + "etcd" + ArchTag(true) + "3.2.18",
imageRepository + "coredns:1.1.3",
}...)
}
images = append(images, []string{
imageRepository + "kube-addon-manager" + ArchTag(false) + "v9.0.2",
// This must match deploy/addons/dashboard/dashboard-dp.yaml
"kubernetesui/dashboard:v2.0.0-beta8",
minikubeRepository + "storage-provisioner" + ArchTag(false) + "v1.8.1",
}...)
return images
}
// PauseImage returns the image name for pause image (for pod infra)
func PauseImage(imageRepositoryStr string, kubernetesVersionStr string) string {
imageRepository := getImageRepository(imageRepositoryStr)
v1_16plus := semver.MustParseRange(">=1.16.0")
v1_14plus := semver.MustParseRange(">=1.14.0 <1.16.0")
v1_13 := semver.MustParseRange(">=1.13.0 <1.14.0")
v1_12 := semver.MustParseRange(">=1.12.0 <1.13.0")
v1_11 := semver.MustParseRange(">=1.11.0 <1.12.0")
kubernetesVersion, err := semver.Make(strings.TrimPrefix(kubernetesVersionStr, minikubeVersion.VersionPrefix))
if err != nil {
glog.Errorln("Error parsing version semver: ", err)
}
var podInfraContainerImage string
switch {
case v1_16plus(kubernetesVersion):
podInfraContainerImage = imageRepository + "pause:3.1"
case v1_14plus(kubernetesVersion):
podInfraContainerImage = imageRepository + "pause:3.1"
case v1_13(kubernetesVersion):
podInfraContainerImage = imageRepository + "pause" + ArchTag(false) + "3.1"
case v1_12(kubernetesVersion):
podInfraContainerImage = imageRepository + "pause:3.1"
case v1_11(kubernetesVersion):
podInfraContainerImage = imageRepository + "pause" + ArchTag(false) + "3.1"
default:
podInfraContainerImage = imageRepository + "pause" + ArchTag(false) + "3.0"
}
return podInfraContainerImage
}
// ArchTag returns the archtag for images
// ArchTag returns a CPU architecture suffix for images
func ArchTag(hasTag bool) string {
if runtime.GOARCH == "amd64" && !hasTag {
return ":"
}
return "-" + runtime.GOARCH + ":"
}
// Auxiliary returns images that are helpful for running minikube
func Auxiliary(mirror string) []string {
return []string{
addonManager(mirror),
storageProvisioner(mirror),
dashboardFrontend(mirror),
dashboardMetrics(mirror),
}
}
// Pause returns the image name to pull for the pause image
func Pause(mirror string) string {
// Should match `PauseVersion` in:
// https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/constants/constants.go
return path.Join(KubernetesRepo(mirror), "pause"+ArchTag(false)+"3.1")
}
// storageProvisioner returns the minikube storage provisioner image
func storageProvisioner(mirror string) string {
return path.Join(minikubeRepo(mirror), "storage-provisioner"+ArchTag(false)+"v1.8.1")
}
// addonManager returns the Kubernetes addon manager image
func addonManager(mirror string) string {
return path.Join(KubernetesRepo(mirror), "kube-addon-manager"+ArchTag(false)+"v9.0.2")
}
// dashboardFrontend returns the image used for the dashboard frontend
func dashboardFrontend(repo string) string {
if repo == "" {
repo = "kubernetesui"
}
// See 'kubernetes-dashboard' in deploy/addons/dashboard/dashboard-dp.yaml
return path.Join(repo, "dashboard:v2.0.0-beta8")
}
// dashboardMetrics returns the image used for the dashboard metrics scraper
func dashboardMetrics(repo string) string {
if repo == "" {
repo = "kubernetesui"
}
// See 'dashboard-metrics-scraper' in deploy/addons/dashboard/dashboard-dp.yaml
return path.Join(repo, "metrics-scraper:v1.0.2")
}

View File

@ -0,0 +1,49 @@
/*
Copyright 2019 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 images
import (
"testing"
"github.com/google/go-cmp/cmp"
)
func TestAuxiliary(t *testing.T) {
want := []string{
"k8s.gcr.io/kube-addon-manager:v9.0.2",
"gcr.io/k8s-minikube/storage-provisioner:v1.8.1",
"kubernetesui/dashboard:v2.0.0-beta8",
"kubernetesui/metrics-scraper:v1.0.2",
}
got := Auxiliary("")
if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("images mismatch (-want +got):\n%s", diff)
}
}
func TestAuxiliaryMirror(t *testing.T) {
want := []string{
"test.mirror/kube-addon-manager:v9.0.2",
"test.mirror/storage-provisioner:v1.8.1",
"test.mirror/dashboard:v2.0.0-beta8",
"test.mirror/metrics-scraper:v1.0.2",
}
got := Auxiliary("test.mirror")
if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("images mismatch (-want +got):\n%s", diff)
}
}

View File

@ -0,0 +1,101 @@
/*
Copyright 2019 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 images
import (
"fmt"
"path"
"strings"
"github.com/blang/semver"
"github.com/pkg/errors"
)
// Kubeadm returns a list of images necessary to bootstrap kubeadm
func Kubeadm(mirror string, version string) ([]string, error) {
v, err := semver.Make(strings.TrimPrefix(version, "v"))
if err != nil {
return nil, errors.Wrap(err, "semver")
}
imgs := []string{
componentImage("kube-proxy", v, mirror),
componentImage("kube-scheduler", v, mirror),
componentImage("kube-controller-manager", v, mirror),
componentImage("kube-apiserver", v, mirror),
coreDNS(v, mirror),
etcd(v, mirror),
Pause(mirror),
}
imgs = append(imgs, Auxiliary(mirror)...)
return imgs, nil
}
// componentImage returns a Kubernetes component image to pull
func componentImage(name string, v semver.Version, mirror string) string {
needsArchSuffix := false
ancient := semver.MustParseRange("<1.12.0")
if ancient(v) {
needsArchSuffix = true
}
return fmt.Sprintf("%sv%s", path.Join(KubernetesRepo(mirror), name+ArchTag(needsArchSuffix)), v)
}
// coreDNS returns the images used for CoreDNS
func coreDNS(v semver.Version, mirror string) string {
// Should match `CoreDNSVersion` in
// https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/constants/constants.go
cv := "1.6.5"
switch v.Minor {
case 16:
cv = "1.6.2"
case 15, 14:
cv = "1.3.1"
case 13:
cv = "1.2.6"
case 12:
cv = "1.2.2"
case 11:
cv = "1.1.3"
}
return path.Join(KubernetesRepo(mirror), "coredns"+ArchTag(false)+cv)
}
// etcd returns the image used for etcd
func etcd(v semver.Version, mirror string) string {
needsArchSuffix := false
ancient := semver.MustParseRange("<1.12.0")
if ancient(v) {
needsArchSuffix = true
}
// Should match `DefaultEtcdVersion` in:
// https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/constants/constants.go
ev := "3.4.3-0"
switch v.Minor {
case 16:
ev = "3.3.15-0"
case 14, 15:
ev = "3.3.10"
case 12, 13:
ev = "3.2.24"
case 11:
ev = "3.2.18"
}
return path.Join(KubernetesRepo(mirror), "etcd"+ArchTag(needsArchSuffix)+ev)
}

View File

@ -0,0 +1,135 @@
/*
Copyright 2019 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 images
import (
"sort"
"testing"
"github.com/google/go-cmp/cmp"
)
func TestKubeadmImages(t *testing.T) {
tests := []struct {
version string
mirror string
want []string
}{
{"v1.17.0", "", []string{
"k8s.gcr.io/kube-proxy:v1.17.0",
"k8s.gcr.io/kube-scheduler:v1.17.0",
"k8s.gcr.io/kube-controller-manager:v1.17.0",
"k8s.gcr.io/kube-apiserver:v1.17.0",
"k8s.gcr.io/coredns:1.6.5",
"k8s.gcr.io/etcd:3.4.3-0",
"k8s.gcr.io/pause:3.1",
"k8s.gcr.io/kube-addon-manager:v9.0.2",
"gcr.io/k8s-minikube/storage-provisioner:v1.8.1",
"kubernetesui/dashboard:v2.0.0-beta8",
"kubernetesui/metrics-scraper:v1.0.2",
}},
{"v1.16.1", "mirror.k8s.io", []string{
"mirror.k8s.io/kube-proxy:v1.16.1",
"mirror.k8s.io/kube-scheduler:v1.16.1",
"mirror.k8s.io/kube-controller-manager:v1.16.1",
"mirror.k8s.io/kube-apiserver:v1.16.1",
"mirror.k8s.io/coredns:1.6.2",
"mirror.k8s.io/etcd:3.3.15-0",
"mirror.k8s.io/pause:3.1",
"mirror.k8s.io/kube-addon-manager:v9.0.2",
"mirror.k8s.io/storage-provisioner:v1.8.1",
"mirror.k8s.io/dashboard:v2.0.0-beta8",
"mirror.k8s.io/metrics-scraper:v1.0.2",
}},
{"v1.15.0", "", []string{
"k8s.gcr.io/kube-proxy:v1.15.0",
"k8s.gcr.io/kube-scheduler:v1.15.0",
"k8s.gcr.io/kube-controller-manager:v1.15.0",
"k8s.gcr.io/kube-apiserver:v1.15.0",
"k8s.gcr.io/coredns:1.3.1",
"k8s.gcr.io/etcd:3.3.10",
"k8s.gcr.io/pause:3.1",
"k8s.gcr.io/kube-addon-manager:v9.0.2",
"gcr.io/k8s-minikube/storage-provisioner:v1.8.1",
"kubernetesui/dashboard:v2.0.0-beta8",
"kubernetesui/metrics-scraper:v1.0.2",
}},
{"v1.14.0", "", []string{
"k8s.gcr.io/kube-proxy:v1.14.0",
"k8s.gcr.io/kube-scheduler:v1.14.0",
"k8s.gcr.io/kube-controller-manager:v1.14.0",
"k8s.gcr.io/kube-apiserver:v1.14.0",
"k8s.gcr.io/coredns:1.3.1",
"k8s.gcr.io/etcd:3.3.10",
"k8s.gcr.io/pause:3.1",
"k8s.gcr.io/kube-addon-manager:v9.0.2",
"gcr.io/k8s-minikube/storage-provisioner:v1.8.1",
"kubernetesui/dashboard:v2.0.0-beta8",
"kubernetesui/metrics-scraper:v1.0.2",
}},
{"v1.13.0", "", []string{
"k8s.gcr.io/kube-proxy:v1.13.0",
"k8s.gcr.io/kube-scheduler:v1.13.0",
"k8s.gcr.io/kube-controller-manager:v1.13.0",
"k8s.gcr.io/kube-apiserver:v1.13.0",
"k8s.gcr.io/coredns:1.2.6",
"k8s.gcr.io/etcd:3.2.24",
"k8s.gcr.io/pause:3.1",
"k8s.gcr.io/kube-addon-manager:v9.0.2",
"gcr.io/k8s-minikube/storage-provisioner:v1.8.1",
"kubernetesui/dashboard:v2.0.0-beta8",
"kubernetesui/metrics-scraper:v1.0.2",
}},
{"v1.12.0", "", []string{
"k8s.gcr.io/kube-proxy:v1.12.0",
"k8s.gcr.io/kube-scheduler:v1.12.0",
"k8s.gcr.io/kube-controller-manager:v1.12.0",
"k8s.gcr.io/kube-apiserver:v1.12.0",
"k8s.gcr.io/coredns:1.2.2",
"k8s.gcr.io/etcd:3.2.24",
"k8s.gcr.io/pause:3.1",
"k8s.gcr.io/kube-addon-manager:v9.0.2",
"gcr.io/k8s-minikube/storage-provisioner:v1.8.1",
"kubernetesui/dashboard:v2.0.0-beta8",
"kubernetesui/metrics-scraper:v1.0.2",
}},
{"v1.11.10", "", []string{
"k8s.gcr.io/kube-proxy-amd64:v1.11.10",
"k8s.gcr.io/kube-scheduler-amd64:v1.11.10",
"k8s.gcr.io/kube-controller-manager-amd64:v1.11.10",
"k8s.gcr.io/kube-apiserver-amd64:v1.11.10",
"k8s.gcr.io/coredns:1.1.3",
"k8s.gcr.io/etcd-amd64:3.2.18",
"k8s.gcr.io/pause:3.1",
"k8s.gcr.io/kube-addon-manager:v9.0.2",
"gcr.io/k8s-minikube/storage-provisioner:v1.8.1",
"kubernetesui/dashboard:v2.0.0-beta8",
"kubernetesui/metrics-scraper:v1.0.2",
}},
}
for _, tc := range tests {
got, err := Kubeadm(tc.mirror, tc.version)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
sort.Strings(got)
sort.Strings(tc.want)
if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("%s images mismatch (-want +got):\n%s", tc.version, diff)
}
}
}

View File

@ -0,0 +1,36 @@
/*
Copyright 2019 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 images
// DefaultKubernetesRepo is the default Kubernetes repository
const DefaultKubernetesRepo = "k8s.gcr.io"
// KubernetesRepo returns the official Kubernetes repository, or an alternate
func KubernetesRepo(mirror string) string {
if mirror != "" {
return mirror
}
return DefaultKubernetesRepo
}
// minikubeRepo returns the official minikube repository, or an alternate
func minikubeRepo(mirror string) string {
if mirror != "" {
return mirror
}
return "gcr.io/k8s-minikube"
}

View File

@ -596,7 +596,7 @@ func NewKubeletConfig(k8s config.KubernetesConfig, r cruntime.Manager) ([]byte,
extraOpts["node-ip"] = k8s.NodeIP
}
pauseImage := images.PauseImage(k8s.ImageRepository, k8s.KubernetesVersion)
pauseImage := images.Pause(k8s.ImageRepository)
if _, ok := extraOpts["pod-infra-container-image"]; !ok && k8s.ImageRepository != "" && pauseImage != "" && k8s.ContainerRuntime != remoteContainerRuntime {
extraOpts["pod-infra-container-image"] = pauseImage
}
@ -630,7 +630,11 @@ func NewKubeletConfig(k8s config.KubernetesConfig, r cruntime.Manager) ([]byte,
// UpdateCluster updates the cluster
func (k *Bootstrapper) UpdateCluster(cfg config.MachineConfig) error {
images := images.CachedImages(cfg.KubernetesConfig.ImageRepository, cfg.KubernetesConfig.KubernetesVersion)
images, err := images.Kubeadm(cfg.KubernetesConfig.ImageRepository, cfg.KubernetesConfig.KubernetesVersion)
if err != nil {
return errors.Wrap(err, "kubeadm images")
}
if cfg.KubernetesConfig.ShouldLoadCachedImages {
if err := machine.LoadImages(&cfg, k.c, images, constants.ImageCacheDir); err != nil {
out.FailureT("Unable to load cached images: {{.error}}", out.V{"error": err})

View File

@ -169,13 +169,13 @@ func (r *Containerd) Available() error {
}
// generateContainerdConfig sets up /etc/containerd/config.toml
func generateContainerdConfig(cr CommandRunner, imageRepository string, k8sVersion string) error {
func generateContainerdConfig(cr CommandRunner, imageRepository string) error {
cPath := containerdConfigFile
t, err := template.New("containerd.config.toml").Parse(containerdConfigTemplate)
if err != nil {
return err
}
pauseImage := images.PauseImage(imageRepository, k8sVersion)
pauseImage := images.Pause(imageRepository)
opts := struct{ PodInfraContainerImage string }{PodInfraContainerImage: pauseImage}
var b bytes.Buffer
if err := t.Execute(&b, opts); err != nil {
@ -198,7 +198,7 @@ func (r *Containerd) Enable(disOthers bool) error {
if err := populateCRIConfig(r.Runner, r.SocketPath()); err != nil {
return err
}
if err := generateContainerdConfig(r.Runner, r.ImageRepository, r.KubernetesVersion); err != nil {
if err := generateContainerdConfig(r.Runner, r.ImageRepository); err != nil {
return err
}
if err := enableIPForwarding(r.Runner); err != nil {

View File

@ -407,13 +407,13 @@ image-endpoint: unix://{{.Socket}}
}
// generateCRIOConfig sets up /etc/crio/crio.conf
func generateCRIOConfig(cr CommandRunner, imageRepository string, k8sVersion string) error {
func generateCRIOConfig(cr CommandRunner, imageRepository string) error {
cPath := crioConfigFile
t, err := template.New("crio.conf").Parse(crioConfigTemplate)
if err != nil {
return err
}
pauseImage := images.PauseImage(imageRepository, k8sVersion)
pauseImage := images.Pause(imageRepository)
opts := struct{ PodInfraContainerImage string }{PodInfraContainerImage: pauseImage}
var b bytes.Buffer
if err := t.Execute(&b, opts); err != nil {

View File

@ -98,7 +98,7 @@ func (r *CRIO) Enable(disOthers bool) error {
if err := populateCRIConfig(r.Runner, r.SocketPath()); err != nil {
return err
}
if err := generateCRIOConfig(r.Runner, r.ImageRepository, r.KubernetesVersion); err != nil {
if err := generateCRIOConfig(r.Runner, r.ImageRepository); err != nil {
return err
}
if err := enableIPForwarding(r.Runner); err != nil {

View File

@ -57,7 +57,10 @@ var loadImageLock sync.Mutex
// CacheImagesForBootstrapper will cache images for a bootstrapper
func CacheImagesForBootstrapper(imageRepository string, version string, clusterBootstrapper string) error {
images := bootstrapper.GetCachedImageList(imageRepository, version, clusterBootstrapper)
images, err := bootstrapper.GetCachedImageList(imageRepository, version, clusterBootstrapper)
if err != nil {
return errors.Wrap(err, "cached images list")
}
if err := CacheImages(images, constants.ImageCacheDir); err != nil {
return errors.Wrapf(err, "Caching images for %s", clusterBootstrapper)

View File

@ -67,7 +67,11 @@ func TestDownloadOnly(t *testing.T) {
t.Errorf("%s failed: %v", args, err)
}
imgs := images.CachedImages("", v)
imgs, err := images.Kubeadm("", v)
if err != nil {
t.Errorf("kubeadm images: %v", v)
}
for _, img := range imgs {
img = strings.Replace(img, ":", "_", 1) // for example kube-scheduler:v1.15.2 --> kube-scheduler_v1.15.2
fp := filepath.Join(localpath.MiniPath(), "cache", "images", img)

View File

@ -38,7 +38,7 @@ func TestDockerFlags(t *testing.T) {
defer CleanupWithLogs(t, profile, cancel)
// Use the most verbose logging for the simplest test. If it fails, something is very wrong.
args := append([]string{"start", "-p", profile, "--wait=false", "--docker-env=FOO=BAR", "--docker-env=BAZ=BAT", "--docker-opt=debug", "--docker-opt=icc=true", "--alsologtostderr", "-v=5"}, StartArgs()...)
args := append([]string{"start", "-p", profile, "--cache-images=false", "--wait=false", "--docker-env=FOO=BAR", "--docker-env=BAZ=BAT", "--docker-opt=debug", "--docker-opt=icc=true", "--alsologtostderr", "-v=5"}, StartArgs()...)
rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
if err != nil {
t.Errorf("%s failed: %v", rr.Args, err)

View File

@ -20,15 +20,19 @@ package integration
import (
"context"
"encoding/json"
"fmt"
"os/exec"
"path/filepath"
"sort"
"strconv"
"strings"
"testing"
"time"
"github.com/docker/machine/libmachine/state"
"github.com/google/go-cmp/cmp"
"k8s.io/minikube/pkg/minikube/bootstrapper/images"
"k8s.io/minikube/pkg/minikube/constants"
)
@ -37,12 +41,11 @@ func TestStartStop(t *testing.T) {
t.Run("group", func(t *testing.T) {
tests := []struct {
name string
args []string
name string
version string
args []string
}{
{"docker", []string{
"--cache-images=false",
fmt.Sprintf("--kubernetes-version=%s", constants.OldestKubernetesVersion),
{"old-docker", constants.OldestKubernetesVersion, []string{
// default is the network created by libvirt, if we change the name minikube won't boot
// because the given network doesn't exist
"--kvm-network=default",
@ -51,21 +54,20 @@ func TestStartStop(t *testing.T) {
"--keep-context=false",
"--container-runtime=docker",
}},
{"cni", []string{
{"newest-cni", constants.NewestKubernetesVersion, []string{
"--feature-gates",
"ServerSideApply=true",
"--network-plugin=cni",
"--extra-config=kubelet.network-plugin=cni",
"--extra-config=kubeadm.pod-network-cidr=192.168.111.111/16",
fmt.Sprintf("--kubernetes-version=%s", constants.NewestKubernetesVersion),
}},
{"containerd", []string{
{"containerd", constants.DefaultKubernetesVersion, []string{
"--container-runtime=containerd",
"--docker-opt",
"containerd=/var/run/containerd/containerd.sock",
"--apiserver-port=8444",
}},
{"crio", []string{
{"crio", "v1.15.0", []string{
"--container-runtime=crio",
"--disable-driver-mounts",
"--extra-config=kubeadm.ignore-preflight-errors=SystemVerification",
@ -88,6 +90,7 @@ func TestStartStop(t *testing.T) {
startArgs := append([]string{"start", "-p", profile, "--alsologtostderr", "-v=3", "--wait=true"}, tc.args...)
startArgs = append(startArgs, StartArgs()...)
startArgs = append(startArgs, fmt.Sprintf("--kubernetes-version=%s", tc.version))
rr, err := Run(t, exec.CommandContext(ctx, Target(), startArgs...))
if err != nil {
// Fatal so that we may collect logs before stop/delete steps
@ -144,6 +147,38 @@ func TestStartStop(t *testing.T) {
t.Fatalf("%s failed: %v", rr.Args, err)
}
// Make sure that kubeadm did not need to pull in additional images
rr, err = Run(t, exec.CommandContext(ctx, Target(), "ssh", "-p", profile, "sudo crictl images -o json"))
if err != nil {
t.Errorf("%s failed: %v", rr.Args, err)
}
jv := map[string][]struct {
Tags []string `json:"repoTags"`
}{}
err = json.Unmarshal(rr.Stdout.Bytes(), &jv)
if err != nil {
t.Errorf("images unmarshal: %v", err)
}
gotImages := []string{}
for _, img := range jv["images"] {
for _, i := range img.Tags {
// Ignore non-Kubernetes images
if !strings.Contains(i, "ingress") && !strings.Contains(i, "busybox") {
// Remove docker.io for naming consistency between container runtimes
gotImages = append(gotImages, strings.TrimPrefix(i, "docker.io/"))
}
}
}
want, err := images.Kubeadm("", tc.version)
if err != nil {
t.Errorf("kubeadm images: %v", tc.version)
}
sort.Strings(want)
sort.Strings(gotImages)
if diff := cmp.Diff(want, gotImages); diff != "" {
t.Errorf("%s images mismatch (-want +got):\n%s", tc.version, diff)
}
if strings.Contains(tc.name, "cni") {
t.Logf("WARNING: cni mode requires additional setup before pods can schedule :(")
} else if _, err := PodWait(ctx, t, profile, "default", "integration-test=busybox", 2*time.Minute); err != nil {
@ -155,7 +190,7 @@ func TestStartStop(t *testing.T) {
t.Errorf("status = %q; want = %q", got, state.Running)
}
if !*cleanup {
if *cleanup {
// Normally handled by cleanuprofile, but not fatal there
rr, err = Run(t, exec.CommandContext(ctx, Target(), "delete", "-p", profile))
if err != nil {