kubeadm: Support imagePullPolicy option in the kubeadm init configuration file
This commit is contained in:
@@ -17,6 +17,7 @@ go_library(
|
|||||||
deps = [
|
deps = [
|
||||||
"//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library",
|
"//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library",
|
||||||
"//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library",
|
"//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
|
@@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package kubeadm
|
package kubeadm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
|
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
|
||||||
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
|
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
|
||||||
@@ -92,6 +93,9 @@ type MasterConfiguration struct {
|
|||||||
// CertificatesDir specifies where to store or look for all required certificates.
|
// CertificatesDir specifies where to store or look for all required certificates.
|
||||||
CertificatesDir string
|
CertificatesDir string
|
||||||
|
|
||||||
|
// ImagePullPolicy for control plane images. Can be Always, IfNotPresent or Never.
|
||||||
|
ImagePullPolicy v1.PullPolicy
|
||||||
|
|
||||||
// ImageRepository is the container registry to pull control plane images from.
|
// ImageRepository is the container registry to pull control plane images from.
|
||||||
ImageRepository string
|
ImageRepository string
|
||||||
|
|
||||||
|
@@ -56,6 +56,7 @@ go_library(
|
|||||||
"//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library",
|
"//pkg/kubelet/apis/kubeletconfig/v1alpha1:go_default_library",
|
||||||
"//pkg/proxy/apis/kubeproxyconfig/scheme:go_default_library",
|
"//pkg/proxy/apis/kubeproxyconfig/scheme:go_default_library",
|
||||||
"//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library",
|
"//pkg/proxy/apis/kubeproxyconfig/v1alpha1:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
|
@@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
|
kubeletconfigv1alpha1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1alpha1"
|
||||||
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
|
kubeproxyconfigv1alpha1 "k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig/v1alpha1"
|
||||||
@@ -93,6 +94,8 @@ type MasterConfiguration struct {
|
|||||||
|
|
||||||
// ImageRepository what container registry to pull control plane images from
|
// ImageRepository what container registry to pull control plane images from
|
||||||
ImageRepository string `json:"imageRepository"`
|
ImageRepository string `json:"imageRepository"`
|
||||||
|
// ImagePullPolicy that control plane images. Can be Always, IfNotPresent or Never.
|
||||||
|
ImagePullPolicy v1.PullPolicy `json:"imagePullPolicy,omitempty"`
|
||||||
// UnifiedControlPlaneImage specifies if a specific container image should
|
// UnifiedControlPlaneImage specifies if a specific container image should
|
||||||
// be used for all control plane components.
|
// be used for all control plane components.
|
||||||
UnifiedControlPlaneImage string `json:"unifiedControlPlaneImage"`
|
UnifiedControlPlaneImage string `json:"unifiedControlPlaneImage"`
|
||||||
|
@@ -23,6 +23,7 @@ package v1alpha1
|
|||||||
import (
|
import (
|
||||||
unsafe "unsafe"
|
unsafe "unsafe"
|
||||||
|
|
||||||
|
core_v1 "k8s.io/api/core/v1"
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
@@ -214,6 +215,7 @@ func autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in
|
|||||||
out.APIServerCertSANs = *(*[]string)(unsafe.Pointer(&in.APIServerCertSANs))
|
out.APIServerCertSANs = *(*[]string)(unsafe.Pointer(&in.APIServerCertSANs))
|
||||||
out.CertificatesDir = in.CertificatesDir
|
out.CertificatesDir = in.CertificatesDir
|
||||||
out.ImageRepository = in.ImageRepository
|
out.ImageRepository = in.ImageRepository
|
||||||
|
out.ImagePullPolicy = core_v1.PullPolicy(in.ImagePullPolicy)
|
||||||
out.UnifiedControlPlaneImage = in.UnifiedControlPlaneImage
|
out.UnifiedControlPlaneImage = in.UnifiedControlPlaneImage
|
||||||
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
|
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
|
||||||
return nil
|
return nil
|
||||||
@@ -255,6 +257,7 @@ func autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in
|
|||||||
out.SchedulerExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.SchedulerExtraVolumes))
|
out.SchedulerExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.SchedulerExtraVolumes))
|
||||||
out.APIServerCertSANs = *(*[]string)(unsafe.Pointer(&in.APIServerCertSANs))
|
out.APIServerCertSANs = *(*[]string)(unsafe.Pointer(&in.APIServerCertSANs))
|
||||||
out.CertificatesDir = in.CertificatesDir
|
out.CertificatesDir = in.CertificatesDir
|
||||||
|
out.ImagePullPolicy = core_v1.PullPolicy(in.ImagePullPolicy)
|
||||||
out.ImageRepository = in.ImageRepository
|
out.ImageRepository = in.ImageRepository
|
||||||
// INFO: in.CIImageRepository opted out of conversion generation
|
// INFO: in.CIImageRepository opted out of conversion generation
|
||||||
out.UnifiedControlPlaneImage = in.UnifiedControlPlaneImage
|
out.UnifiedControlPlaneImage = in.UnifiedControlPlaneImage
|
||||||
|
@@ -30,6 +30,7 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
flag "github.com/spf13/pflag"
|
flag "github.com/spf13/pflag"
|
||||||
|
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
utilflag "k8s.io/apiserver/pkg/util/flag"
|
utilflag "k8s.io/apiserver/pkg/util/flag"
|
||||||
@@ -92,10 +93,12 @@ var (
|
|||||||
This error is likely caused by:
|
This error is likely caused by:
|
||||||
- The kubelet is not running
|
- The kubelet is not running
|
||||||
- The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)
|
- The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)
|
||||||
- There is no internet connection, so the kubelet cannot pull the following control plane images:
|
- Either there is no internet connection, or imagePullPolicy is set to "Never",
|
||||||
|
so the kubelet cannot pull or find the following control plane images:
|
||||||
- {{ .APIServerImage }}
|
- {{ .APIServerImage }}
|
||||||
- {{ .ControllerManagerImage }}
|
- {{ .ControllerManagerImage }}
|
||||||
- {{ .SchedulerImage }}
|
- {{ .SchedulerImage }}
|
||||||
|
- {{ .EtcdImage }} (only if no external etcd endpoints are configured)
|
||||||
|
|
||||||
If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:
|
If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:
|
||||||
- 'systemctl status kubelet'
|
- 'systemctl status kubelet'
|
||||||
@@ -357,7 +360,7 @@ func (i *Init) Run(out io.Writer) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// waiter holds the apiclient.Waiter implementation of choice, responsible for querying the API server in various ways and waiting for conditions to be fulfilled
|
// waiter holds the apiclient.Waiter implementation of choice, responsible for querying the API server in various ways and waiting for conditions to be fulfilled
|
||||||
waiter := getWaiter(i.dryRun, client)
|
waiter := getWaiter(i, client)
|
||||||
|
|
||||||
if err := waitForAPIAndKubelet(waiter); err != nil {
|
if err := waitForAPIAndKubelet(waiter); err != nil {
|
||||||
ctx := map[string]string{
|
ctx := map[string]string{
|
||||||
@@ -365,6 +368,7 @@ func (i *Init) Run(out io.Writer) error {
|
|||||||
"APIServerImage": images.GetCoreImage(kubeadmconstants.KubeAPIServer, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage),
|
"APIServerImage": images.GetCoreImage(kubeadmconstants.KubeAPIServer, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage),
|
||||||
"ControllerManagerImage": images.GetCoreImage(kubeadmconstants.KubeControllerManager, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage),
|
"ControllerManagerImage": images.GetCoreImage(kubeadmconstants.KubeControllerManager, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage),
|
||||||
"SchedulerImage": images.GetCoreImage(kubeadmconstants.KubeScheduler, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage),
|
"SchedulerImage": images.GetCoreImage(kubeadmconstants.KubeScheduler, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage),
|
||||||
|
"EtcdImage": images.GetCoreImage(kubeadmconstants.Etcd, i.cfg.ImageRepository, i.cfg.KubernetesVersion, i.cfg.Etcd.Image),
|
||||||
}
|
}
|
||||||
|
|
||||||
kubeletFailTempl.Execute(out, ctx)
|
kubeletFailTempl.Execute(out, ctx)
|
||||||
@@ -522,11 +526,18 @@ func printFilesIfDryRunning(dryRun bool, manifestDir string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getWaiter gets the right waiter implementation for the right occasion
|
// getWaiter gets the right waiter implementation for the right occasion
|
||||||
func getWaiter(dryRun bool, client clientset.Interface) apiclient.Waiter {
|
func getWaiter(i *Init, client clientset.Interface) apiclient.Waiter {
|
||||||
if dryRun {
|
if i.dryRun {
|
||||||
return dryrunutil.NewWaiter()
|
return dryrunutil.NewWaiter()
|
||||||
}
|
}
|
||||||
return apiclient.NewKubeWaiter(client, 30*time.Minute, os.Stdout)
|
|
||||||
|
timeout := 30 * time.Minute
|
||||||
|
|
||||||
|
// No need for a large timeout if we don't expect downloads
|
||||||
|
if i.cfg.ImagePullPolicy == v1.PullNever {
|
||||||
|
timeout = 60 * time.Second
|
||||||
|
}
|
||||||
|
return apiclient.NewKubeWaiter(client, timeout, os.Stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
// waitForAPIAndKubelet waits primarily for the API server to come up. If that takes a long time, and the kubelet
|
// waitForAPIAndKubelet waits primarily for the API server to come up. If that takes a long time, and the kubelet
|
||||||
|
@@ -79,6 +79,7 @@ func GetStaticPodSpecs(cfg *kubeadmapi.MasterConfiguration, k8sVersion *version.
|
|||||||
kubeadmconstants.KubeAPIServer: staticpodutil.ComponentPod(v1.Container{
|
kubeadmconstants.KubeAPIServer: staticpodutil.ComponentPod(v1.Container{
|
||||||
Name: kubeadmconstants.KubeAPIServer,
|
Name: kubeadmconstants.KubeAPIServer,
|
||||||
Image: images.GetCoreImage(kubeadmconstants.KubeAPIServer, cfg.GetControlPlaneImageRepository(), cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage),
|
Image: images.GetCoreImage(kubeadmconstants.KubeAPIServer, cfg.GetControlPlaneImageRepository(), cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage),
|
||||||
|
ImagePullPolicy: cfg.ImagePullPolicy,
|
||||||
Command: getAPIServerCommand(cfg, k8sVersion),
|
Command: getAPIServerCommand(cfg, k8sVersion),
|
||||||
VolumeMounts: staticpodutil.VolumeMountMapToSlice(mounts.GetVolumeMounts(kubeadmconstants.KubeAPIServer)),
|
VolumeMounts: staticpodutil.VolumeMountMapToSlice(mounts.GetVolumeMounts(kubeadmconstants.KubeAPIServer)),
|
||||||
LivenessProbe: staticpodutil.ComponentProbe(cfg, kubeadmconstants.KubeAPIServer, int(cfg.API.BindPort), "/healthz", v1.URISchemeHTTPS),
|
LivenessProbe: staticpodutil.ComponentProbe(cfg, kubeadmconstants.KubeAPIServer, int(cfg.API.BindPort), "/healthz", v1.URISchemeHTTPS),
|
||||||
@@ -88,6 +89,7 @@ func GetStaticPodSpecs(cfg *kubeadmapi.MasterConfiguration, k8sVersion *version.
|
|||||||
kubeadmconstants.KubeControllerManager: staticpodutil.ComponentPod(v1.Container{
|
kubeadmconstants.KubeControllerManager: staticpodutil.ComponentPod(v1.Container{
|
||||||
Name: kubeadmconstants.KubeControllerManager,
|
Name: kubeadmconstants.KubeControllerManager,
|
||||||
Image: images.GetCoreImage(kubeadmconstants.KubeControllerManager, cfg.GetControlPlaneImageRepository(), cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage),
|
Image: images.GetCoreImage(kubeadmconstants.KubeControllerManager, cfg.GetControlPlaneImageRepository(), cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage),
|
||||||
|
ImagePullPolicy: cfg.ImagePullPolicy,
|
||||||
Command: getControllerManagerCommand(cfg, k8sVersion),
|
Command: getControllerManagerCommand(cfg, k8sVersion),
|
||||||
VolumeMounts: staticpodutil.VolumeMountMapToSlice(mounts.GetVolumeMounts(kubeadmconstants.KubeControllerManager)),
|
VolumeMounts: staticpodutil.VolumeMountMapToSlice(mounts.GetVolumeMounts(kubeadmconstants.KubeControllerManager)),
|
||||||
LivenessProbe: staticpodutil.ComponentProbe(cfg, kubeadmconstants.KubeControllerManager, 10252, "/healthz", v1.URISchemeHTTP),
|
LivenessProbe: staticpodutil.ComponentProbe(cfg, kubeadmconstants.KubeControllerManager, 10252, "/healthz", v1.URISchemeHTTP),
|
||||||
@@ -97,6 +99,7 @@ func GetStaticPodSpecs(cfg *kubeadmapi.MasterConfiguration, k8sVersion *version.
|
|||||||
kubeadmconstants.KubeScheduler: staticpodutil.ComponentPod(v1.Container{
|
kubeadmconstants.KubeScheduler: staticpodutil.ComponentPod(v1.Container{
|
||||||
Name: kubeadmconstants.KubeScheduler,
|
Name: kubeadmconstants.KubeScheduler,
|
||||||
Image: images.GetCoreImage(kubeadmconstants.KubeScheduler, cfg.GetControlPlaneImageRepository(), cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage),
|
Image: images.GetCoreImage(kubeadmconstants.KubeScheduler, cfg.GetControlPlaneImageRepository(), cfg.KubernetesVersion, cfg.UnifiedControlPlaneImage),
|
||||||
|
ImagePullPolicy: cfg.ImagePullPolicy,
|
||||||
Command: getSchedulerCommand(cfg),
|
Command: getSchedulerCommand(cfg),
|
||||||
VolumeMounts: staticpodutil.VolumeMountMapToSlice(mounts.GetVolumeMounts(kubeadmconstants.KubeScheduler)),
|
VolumeMounts: staticpodutil.VolumeMountMapToSlice(mounts.GetVolumeMounts(kubeadmconstants.KubeScheduler)),
|
||||||
LivenessProbe: staticpodutil.ComponentProbe(cfg, kubeadmconstants.KubeScheduler, 10251, "/healthz", v1.URISchemeHTTP),
|
LivenessProbe: staticpodutil.ComponentProbe(cfg, kubeadmconstants.KubeScheduler, 10251, "/healthz", v1.URISchemeHTTP),
|
||||||
|
@@ -56,6 +56,7 @@ func GetEtcdPodSpec(cfg *kubeadmapi.MasterConfiguration) v1.Pod {
|
|||||||
Name: kubeadmconstants.Etcd,
|
Name: kubeadmconstants.Etcd,
|
||||||
Command: getEtcdCommand(cfg),
|
Command: getEtcdCommand(cfg),
|
||||||
Image: images.GetCoreImage(kubeadmconstants.Etcd, cfg.ImageRepository, cfg.KubernetesVersion, cfg.Etcd.Image),
|
Image: images.GetCoreImage(kubeadmconstants.Etcd, cfg.ImageRepository, cfg.KubernetesVersion, cfg.Etcd.Image),
|
||||||
|
ImagePullPolicy: cfg.ImagePullPolicy,
|
||||||
// Mount the etcd datadir path read-write so etcd can store data in a more persistent manner
|
// Mount the etcd datadir path read-write so etcd can store data in a more persistent manner
|
||||||
VolumeMounts: []v1.VolumeMount{staticpodutil.NewVolumeMount(etcdVolumeName, cfg.Etcd.DataDir, false)},
|
VolumeMounts: []v1.VolumeMount{staticpodutil.NewVolumeMount(etcdVolumeName, cfg.Etcd.DataDir, false)},
|
||||||
LivenessProbe: staticpodutil.ComponentProbe(cfg, kubeadmconstants.Etcd, 2379, "/health", v1.URISchemeHTTP),
|
LivenessProbe: staticpodutil.ComponentProbe(cfg, kubeadmconstants.Etcd, 2379, "/health", v1.URISchemeHTTP),
|
||||||
|
Reference in New Issue
Block a user