add support of imagePullPolicy to kubeadm

Signed-off-by: wangyysde <net_use@bzhy.com>
This commit is contained in:
wangyysde 2021-06-16 09:40:22 +08:00
parent 36a19df91b
commit 459fe7d08a
9 changed files with 52 additions and 21 deletions

View File

@ -57,6 +57,7 @@ func fuzzInitConfiguration(obj *kubeadm.InitConfiguration, c fuzz.Continue) {
}, },
} }
obj.SkipPhases = nil obj.SkipPhases = nil
obj.NodeRegistration.ImagePullPolicy = ""
} }
func fuzzNodeRegistration(obj *kubeadm.NodeRegistrationOptions, c fuzz.Continue) { func fuzzNodeRegistration(obj *kubeadm.NodeRegistrationOptions, c fuzz.Continue) {
@ -118,6 +119,7 @@ func fuzzJoinConfiguration(obj *kubeadm.JoinConfiguration, c fuzz.Continue) {
Timeout: &metav1.Duration{Duration: 1234}, Timeout: &metav1.Duration{Duration: 1234},
} }
obj.SkipPhases = nil obj.SkipPhases = nil
obj.NodeRegistration.ImagePullPolicy = ""
} }
func fuzzJoinControlPlane(obj *kubeadm.JoinControlPlane, c fuzz.Continue) { func fuzzJoinControlPlane(obj *kubeadm.JoinControlPlane, c fuzz.Continue) {

View File

@ -217,6 +217,11 @@ type NodeRegistrationOptions struct {
// IgnorePreflightErrors provides a slice of pre-flight errors to be ignored when the current node is registered. // IgnorePreflightErrors provides a slice of pre-flight errors to be ignored when the current node is registered.
IgnorePreflightErrors []string IgnorePreflightErrors []string
// ImagePullPolicy specifies the policy for image pulling during kubeadm "init" and "join" operations.
// The value of this field must be one of "Always", "IfNotPresent" or "Never".
// If this field is unset kubeadm will default it to "IfNotPresent", or pull the required images if not present on the host.
ImagePullPolicy v1.PullPolicy `json:"imagePullPolicy,omitempty"`
} }
// Networking contains elements describing cluster's networking configuration. // Networking contains elements describing cluster's networking configuration.

View File

@ -43,3 +43,8 @@ func Convert_v1beta2_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in *Cl
func Convert_kubeadm_JoinConfiguration_To_v1beta2_JoinConfiguration(in *kubeadm.JoinConfiguration, out *JoinConfiguration, s conversion.Scope) error { func Convert_kubeadm_JoinConfiguration_To_v1beta2_JoinConfiguration(in *kubeadm.JoinConfiguration, out *JoinConfiguration, s conversion.Scope) error {
return autoConvert_kubeadm_JoinConfiguration_To_v1beta2_JoinConfiguration(in, out, s) return autoConvert_kubeadm_JoinConfiguration_To_v1beta2_JoinConfiguration(in, out, s)
} }
// Convert_kubeadm_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOption is required since v1beta2 does not have NodeRegistrationOption.ImagePullPolicy
func Convert_kubeadm_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error {
return autoConvert_kubeadm_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in, out, s)
}

View File

@ -212,11 +212,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil { }); err != nil {
return err return err
} }
if err := s.AddGeneratedConversionFunc((*kubeadm.NodeRegistrationOptions)(nil), (*NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(a.(*kubeadm.NodeRegistrationOptions), b.(*NodeRegistrationOptions), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*kubeadm.InitConfiguration)(nil), (*InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { if err := s.AddConversionFunc((*kubeadm.InitConfiguration)(nil), (*InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_InitConfiguration_To_v1beta2_InitConfiguration(a.(*kubeadm.InitConfiguration), b.(*InitConfiguration), scope) return Convert_kubeadm_InitConfiguration_To_v1beta2_InitConfiguration(a.(*kubeadm.InitConfiguration), b.(*InitConfiguration), scope)
}); err != nil { }); err != nil {
@ -227,6 +222,11 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil { }); err != nil {
return err return err
} }
if err := s.AddConversionFunc((*kubeadm.NodeRegistrationOptions)(nil), (*NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_kubeadm_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(a.(*kubeadm.NodeRegistrationOptions), b.(*NodeRegistrationOptions), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*ClusterConfiguration)(nil), (*kubeadm.ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { if err := s.AddConversionFunc((*ClusterConfiguration)(nil), (*kubeadm.ClusterConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta2_ClusterConfiguration_To_kubeadm_ClusterConfiguration(a.(*ClusterConfiguration), b.(*kubeadm.ClusterConfiguration), scope) return Convert_v1beta2_ClusterConfiguration_To_kubeadm_ClusterConfiguration(a.(*ClusterConfiguration), b.(*kubeadm.ClusterConfiguration), scope)
}); err != nil { }); err != nil {
@ -782,10 +782,6 @@ func autoConvert_kubeadm_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOpti
out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints)) out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs)) out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors))
// WARNING: in.ImagePullPolicy requires manual conversion: does not exist in peer-type
return nil return nil
} }
// Convert_kubeadm_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions is an autogenerated conversion function.
func Convert_kubeadm_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in *kubeadm.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error {
return autoConvert_kubeadm_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in, out, s)
}

View File

@ -31,6 +31,10 @@ limitations under the License.
// This would result in the field values to be omitted when API structures are printed with klog. // This would result in the field values to be omitted when API structures are printed with klog.
// - Add "InitConfiguration.SkipPhases", "JoinConfiguration.SkipPhases" to allow skipping // - Add "InitConfiguration.SkipPhases", "JoinConfiguration.SkipPhases" to allow skipping
// a list of phases during kubeadm init/join command execution. // a list of phases during kubeadm init/join command execution.
// - Add "InitConfiguration.NodeRegistration.ImagePullPolicy" and "JoinConfiguration.NodeRegistration.ImagePullPolicy"
// to allow specifying the images pull policy during kubeadm "init" and "join". The value must be one of "Always", "Never" or
// "IfNotPresent". "IfNotPresent" is the default, which has been the existing behavior prior to this addition.
// //
// Migration from old kubeadm config versions // Migration from old kubeadm config versions
// //
@ -175,6 +179,7 @@ limitations under the License.
// v: 4 // v: 4
// ignorePreflightErrors: // ignorePreflightErrors:
// - IsPrivilegedUser // - IsPrivilegedUser
// imagePullPolicy: "IfNotPresent"
// localAPIEndpoint: // localAPIEndpoint:
// advertiseAddress: "10.100.0.1" // advertiseAddress: "10.100.0.1"
// bindPort: 6443 // bindPort: 6443

View File

@ -220,6 +220,12 @@ type NodeRegistrationOptions struct {
// IgnorePreflightErrors provides a slice of pre-flight errors to be ignored when the current node is registered. // IgnorePreflightErrors provides a slice of pre-flight errors to be ignored when the current node is registered.
// +optional // +optional
IgnorePreflightErrors []string `json:"ignorePreflightErrors,omitempty"` IgnorePreflightErrors []string `json:"ignorePreflightErrors,omitempty"`
// ImagePullPolicy specifies the policy for image pulling during kubeadm "init" and "join" operations.
// The value of this field must be one of "Always", "IfNotPresent" or "Never".
// If this field is unset kubeadm will default it to "IfNotPresent", or pull the required images if not present on the host.
// +optional
ImagePullPolicy v1.PullPolicy `json:"imagePullPolicy,omitempty"`
} }
// Networking contains elements describing cluster's networking configuration // Networking contains elements describing cluster's networking configuration

View File

@ -768,6 +768,7 @@ func autoConvert_v1beta3_NodeRegistrationOptions_To_kubeadm_NodeRegistrationOpti
out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints)) out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs)) out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors))
out.ImagePullPolicy = corev1.PullPolicy(in.ImagePullPolicy)
return nil return nil
} }
@ -782,6 +783,7 @@ func autoConvert_kubeadm_NodeRegistrationOptions_To_v1beta3_NodeRegistrationOpti
out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints)) out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints))
out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs)) out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs))
out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors))
out.ImagePullPolicy = corev1.PullPolicy(in.ImagePullPolicy)
return nil return nil
} }

View File

@ -36,6 +36,7 @@ import (
"github.com/PuerkitoBio/purell" "github.com/PuerkitoBio/purell"
"github.com/pkg/errors" "github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
netutil "k8s.io/apimachinery/pkg/util/net" netutil "k8s.io/apimachinery/pkg/util/net"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation"
@ -819,8 +820,9 @@ func getEtcdVersionResponse(client *http.Client, url string, target interface{})
// ImagePullCheck will pull container images used by kubeadm // ImagePullCheck will pull container images used by kubeadm
type ImagePullCheck struct { type ImagePullCheck struct {
runtime utilruntime.ContainerRuntime runtime utilruntime.ContainerRuntime
imageList []string imageList []string
imagePullPolicy v1.PullPolicy
} }
// Name returns the label for ImagePullCheck // Name returns the label for ImagePullCheck
@ -831,14 +833,20 @@ func (ImagePullCheck) Name() string {
// Check pulls images required by kubeadm. This is a mutating check // Check pulls images required by kubeadm. This is a mutating check
func (ipc ImagePullCheck) Check() (warnings, errorList []error) { func (ipc ImagePullCheck) Check() (warnings, errorList []error) {
for _, image := range ipc.imageList { for _, image := range ipc.imageList {
ret, err := ipc.runtime.ImageExists(image) switch ipc.imagePullPolicy {
if ret && err == nil { case v1.PullNever:
klog.V(1).Infof("image exists: %s", image)
continue continue
case v1.PullIfNotPresent:
ret, err := ipc.runtime.ImageExists(image)
if ret && err == nil {
klog.V(1).Infof("image exists: %s", image)
continue
}
if err != nil {
errorList = append(errorList, errors.Wrapf(err, "failed to check if image %s exists", image))
}
} }
if err != nil {
errorList = append(errorList, errors.Wrapf(err, "failed to check if image %s exists", image))
}
klog.V(1).Infof("pulling %s", image) klog.V(1).Infof("pulling %s", image)
if err := ipc.runtime.PullImage(image); err != nil { if err := ipc.runtime.PullImage(image); err != nil {
errorList = append(errorList, errors.Wrapf(err, "failed to pull image %s", image)) errorList = append(errorList, errors.Wrapf(err, "failed to pull image %s", image))
@ -1061,7 +1069,7 @@ func RunPullImagesCheck(execer utilsexec.Interface, cfg *kubeadmapi.InitConfigur
} }
checks := []Checker{ checks := []Checker{
ImagePullCheck{runtime: containerRuntime, imageList: images.GetControlPlaneImages(&cfg.ClusterConfiguration)}, ImagePullCheck{runtime: containerRuntime, imageList: images.GetControlPlaneImages(&cfg.ClusterConfiguration), imagePullPolicy: cfg.NodeRegistration.ImagePullPolicy},
} }
return RunChecks(checks, os.Stderr, ignorePreflightErrors) return RunChecks(checks, os.Stderr, ignorePreflightErrors)
} }

View File

@ -30,6 +30,7 @@ import (
"net/http" "net/http"
"os" "os"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/constants"
@ -815,8 +816,9 @@ func TestImagePullCheck(t *testing.T) {
} }
check := ImagePullCheck{ check := ImagePullCheck{
runtime: containerRuntime, runtime: containerRuntime,
imageList: []string{"img1", "img2", "img3"}, imageList: []string{"img1", "img2", "img3"},
imagePullPolicy: v1.PullIfNotPresent,
} }
warnings, errors := check.Check() warnings, errors := check.Check()
if len(warnings) != 0 { if len(warnings) != 0 {