Merge pull request #6043 from tstromberg/correct-kubernetes-images
Sync cached image list for Kubernetes v1.17pull/6050/head
commit
0ca6c6c4c6
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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})
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue