diff --git a/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go b/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go index 60e1f44032d..5257c953425 100644 --- a/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go +++ b/cmd/kubeadm/app/apis/kubeadm/fuzzer/fuzzer.go @@ -92,10 +92,12 @@ func fuzzClusterConfiguration(obj *kubeadm.ClusterConfiguration, c fuzz.Continue obj.Scheduler.ExtraEnvs = []kubeadm.EnvVar{} obj.Etcd.Local.ExtraEnvs = []kubeadm.EnvVar{} obj.EncryptionAlgorithm = kubeadm.EncryptionAlgorithmRSA + obj.Proxy.Disabled = false } func fuzzDNS(obj *kubeadm.DNS, c fuzz.Continue) { c.FuzzNoCustom(obj) + obj.Disabled = false } func fuzzComponentConfigMap(obj *kubeadm.ComponentConfigMap, c fuzz.Continue) { diff --git a/cmd/kubeadm/app/apis/kubeadm/types.go b/cmd/kubeadm/app/apis/kubeadm/types.go index 617994600a8..daa2dcc79cf 100644 --- a/cmd/kubeadm/app/apis/kubeadm/types.go +++ b/cmd/kubeadm/app/apis/kubeadm/types.go @@ -120,6 +120,9 @@ type ClusterConfiguration struct { // DNS defines the options for the DNS add-on installed in the cluster. DNS DNS + // Proxy defines the options for the proxy add-on installed in the cluster. + Proxy Proxy + // CertificatesDir specifies where to store or look for all required certificates. CertificatesDir string @@ -175,8 +178,17 @@ type APIServer struct { // DNS defines the DNS addon that should be used in the cluster type DNS struct { - // ImageMeta allows to customize the image used for the DNS component + // ImageMeta allows to customize the image used for the DNS addon ImageMeta `json:",inline"` + + // Disabled specifies whether to disable this addon in the cluster + Disabled bool +} + +// Proxy defines the proxy addon that should be used in the cluster +type Proxy struct { + // Disabled specifies whether to disable this addon in the cluster + Disabled bool } // ImageMeta allows to customize the image used for components that are not diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta3/conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1beta3/conversion.go index 80b45a55533..e10e82729b2 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta3/conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta3/conversion.go @@ -99,6 +99,11 @@ func Convert_kubeadm_NodeRegistrationOptions_To_v1beta3_NodeRegistrationOptions( return autoConvert_kubeadm_NodeRegistrationOptions_To_v1beta3_NodeRegistrationOptions(in, out, s) } +// Convert_kubeadm_DNS_To_v1beta3_DNS converts a private DNS to public DNS. +func Convert_kubeadm_DNS_To_v1beta3_DNS(in *kubeadm.DNS, out *DNS, s conversion.Scope) error { + return autoConvert_kubeadm_DNS_To_v1beta3_DNS(in, out, s) +} + // convertToArgs takes a argument map and converts it to a slice of arguments. // Te resulting argument slice is sorted alpha-numerically. func convertToArgs(in map[string]string) []kubeadm.Arg { diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta3/zz_generated.conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1beta3/zz_generated.conversion.go index 95abd68c4a2..2d81af6aeea 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta3/zz_generated.conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta3/zz_generated.conversion.go @@ -74,11 +74,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*kubeadm.DNS)(nil), (*DNS)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_kubeadm_DNS_To_v1beta3_DNS(a.(*kubeadm.DNS), b.(*DNS), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*Discovery)(nil), (*kubeadm.Discovery)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta3_Discovery_To_kubeadm_Discovery(a.(*Discovery), b.(*kubeadm.Discovery), scope) }); err != nil { @@ -184,6 +179,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*kubeadm.DNS)(nil), (*DNS)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_kubeadm_DNS_To_v1beta3_DNS(a.(*kubeadm.DNS), b.(*DNS), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*kubeadm.InitConfiguration)(nil), (*InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_kubeadm_InitConfiguration_To_v1beta3_InitConfiguration(a.(*kubeadm.InitConfiguration), b.(*InitConfiguration), scope) }); err != nil { @@ -359,6 +359,7 @@ func autoConvert_kubeadm_ClusterConfiguration_To_v1beta3_ClusterConfiguration(in if err := Convert_kubeadm_DNS_To_v1beta3_DNS(&in.DNS, &out.DNS, s); err != nil { return err } + // WARNING: in.Proxy requires manual conversion: does not exist in peer-type out.CertificatesDir = in.CertificatesDir out.ImageRepository = in.ImageRepository // INFO: in.CIImageRepository opted out of conversion generation @@ -397,14 +398,10 @@ func autoConvert_kubeadm_DNS_To_v1beta3_DNS(in *kubeadm.DNS, out *DNS, s convers if err := Convert_kubeadm_ImageMeta_To_v1beta3_ImageMeta(&in.ImageMeta, &out.ImageMeta, s); err != nil { return err } + // WARNING: in.Disabled requires manual conversion: does not exist in peer-type return nil } -// Convert_kubeadm_DNS_To_v1beta3_DNS is an autogenerated conversion function. -func Convert_kubeadm_DNS_To_v1beta3_DNS(in *kubeadm.DNS, out *DNS, s conversion.Scope) error { - return autoConvert_kubeadm_DNS_To_v1beta3_DNS(in, out, s) -} - func autoConvert_v1beta3_Discovery_To_kubeadm_Discovery(in *Discovery, out *kubeadm.Discovery, s conversion.Scope) error { out.BootstrapToken = (*kubeadm.BootstrapTokenDiscovery)(unsafe.Pointer(in.BootstrapToken)) out.File = (*kubeadm.FileDiscovery)(unsafe.Pointer(in.File)) diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta4/doc.go b/cmd/kubeadm/app/apis/kubeadm/v1beta4/doc.go index abe48a58612..7c1e008a73c 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta4/doc.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta4/doc.go @@ -35,6 +35,9 @@ limitations under the License. // - Add `ClusterConfiguration.EncryptionAlgorithm` that can be used to set the asymmetric encryption algorithm // used for this cluster's keys and certificates. Can be "RSA" (default algorithm, key size is 2048) or // "ECDSA" (uses the P-256 elliptic curve). +// - Add `ClusterConfiguration.DNS.Disabled` and `ClusterConfiguration.Proxy.Disabled` that can be used to disable +// the CoreDNS and kube-proxy addons during cluster initialization. Skipping the related addons phases, +// during cluster creation will set the same fields to `false`. // // Migration from old kubeadm config versions // diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta4/types.go b/cmd/kubeadm/app/apis/kubeadm/v1beta4/types.go index 75db9e179ba..021d13503da 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta4/types.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta4/types.go @@ -122,6 +122,9 @@ type ClusterConfiguration struct { // +optional DNS DNS `json:"dns,omitempty"` + // Proxy defines the options for the proxy add-on installed in the cluster. + Proxy Proxy `json:"proxy,omitempty"` + // CertificatesDir specifies where to store or look for all required certificates. // +optional CertificatesDir string `json:"certificatesDir,omitempty"` @@ -181,8 +184,19 @@ type APIServer struct { // DNS defines the DNS addon that should be used in the cluster type DNS struct { - // ImageMeta allows to customize the image used for the DNS component + // ImageMeta allows to customize the image used for the DNS addon ImageMeta `json:",inline"` + + // Disabled specifies whether to disable this addon in the cluster + // +optional + Disabled bool `json:"disabled,omitempty"` +} + +// Proxy defines the proxy addon that should be used in the cluster +type Proxy struct { + // Disabled specifies whether to disable this addon in the cluster + // +optional + Disabled bool `json:"disabled,omitempty"` } // ImageMeta allows to customize the image used for components that are not diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.conversion.go b/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.conversion.go index ed01f88d9f6..277939145b0 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.conversion.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.conversion.go @@ -239,6 +239,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddGeneratedConversionFunc((*Proxy)(nil), (*kubeadm.Proxy)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta4_Proxy_To_kubeadm_Proxy(a.(*Proxy), b.(*kubeadm.Proxy), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*kubeadm.Proxy)(nil), (*Proxy)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_kubeadm_Proxy_To_v1beta4_Proxy(a.(*kubeadm.Proxy), b.(*Proxy), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*ResetConfiguration)(nil), (*kubeadm.ResetConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta4_ResetConfiguration_To_kubeadm_ResetConfiguration(a.(*ResetConfiguration), b.(*kubeadm.ResetConfiguration), scope) }); err != nil { @@ -381,6 +391,9 @@ func autoConvert_v1beta4_ClusterConfiguration_To_kubeadm_ClusterConfiguration(in if err := Convert_v1beta4_DNS_To_kubeadm_DNS(&in.DNS, &out.DNS, s); err != nil { return err } + if err := Convert_v1beta4_Proxy_To_kubeadm_Proxy(&in.Proxy, &out.Proxy, s); err != nil { + return err + } out.CertificatesDir = in.CertificatesDir out.ImageRepository = in.ImageRepository out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) @@ -417,6 +430,9 @@ func autoConvert_kubeadm_ClusterConfiguration_To_v1beta4_ClusterConfiguration(in if err := Convert_kubeadm_DNS_To_v1beta4_DNS(&in.DNS, &out.DNS, s); err != nil { return err } + if err := Convert_kubeadm_Proxy_To_v1beta4_Proxy(&in.Proxy, &out.Proxy, s); err != nil { + return err + } out.CertificatesDir = in.CertificatesDir out.ImageRepository = in.ImageRepository // INFO: in.CIImageRepository opted out of conversion generation @@ -459,6 +475,7 @@ func autoConvert_v1beta4_DNS_To_kubeadm_DNS(in *DNS, out *kubeadm.DNS, s convers if err := Convert_v1beta4_ImageMeta_To_kubeadm_ImageMeta(&in.ImageMeta, &out.ImageMeta, s); err != nil { return err } + out.Disabled = in.Disabled return nil } @@ -471,6 +488,7 @@ func autoConvert_kubeadm_DNS_To_v1beta4_DNS(in *kubeadm.DNS, out *DNS, s convers if err := Convert_kubeadm_ImageMeta_To_v1beta4_ImageMeta(&in.ImageMeta, &out.ImageMeta, s); err != nil { return err } + out.Disabled = in.Disabled return nil } @@ -848,6 +866,26 @@ func Convert_kubeadm_Patches_To_v1beta4_Patches(in *kubeadm.Patches, out *Patche return autoConvert_kubeadm_Patches_To_v1beta4_Patches(in, out, s) } +func autoConvert_v1beta4_Proxy_To_kubeadm_Proxy(in *Proxy, out *kubeadm.Proxy, s conversion.Scope) error { + out.Disabled = in.Disabled + return nil +} + +// Convert_v1beta4_Proxy_To_kubeadm_Proxy is an autogenerated conversion function. +func Convert_v1beta4_Proxy_To_kubeadm_Proxy(in *Proxy, out *kubeadm.Proxy, s conversion.Scope) error { + return autoConvert_v1beta4_Proxy_To_kubeadm_Proxy(in, out, s) +} + +func autoConvert_kubeadm_Proxy_To_v1beta4_Proxy(in *kubeadm.Proxy, out *Proxy, s conversion.Scope) error { + out.Disabled = in.Disabled + return nil +} + +// Convert_kubeadm_Proxy_To_v1beta4_Proxy is an autogenerated conversion function. +func Convert_kubeadm_Proxy_To_v1beta4_Proxy(in *kubeadm.Proxy, out *Proxy, s conversion.Scope) error { + return autoConvert_kubeadm_Proxy_To_v1beta4_Proxy(in, out, s) +} + func autoConvert_v1beta4_ResetConfiguration_To_kubeadm_ResetConfiguration(in *ResetConfiguration, out *kubeadm.ResetConfiguration, s conversion.Scope) error { out.CleanupTmpDir = in.CleanupTmpDir out.CertificatesDir = in.CertificatesDir diff --git a/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.deepcopy.go b/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.deepcopy.go index 872a6e116c2..03033797d17 100644 --- a/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.deepcopy.go +++ b/cmd/kubeadm/app/apis/kubeadm/v1beta4/zz_generated.deepcopy.go @@ -118,6 +118,7 @@ func (in *ClusterConfiguration) DeepCopyInto(out *ClusterConfiguration) { in.ControllerManager.DeepCopyInto(&out.ControllerManager) in.Scheduler.DeepCopyInto(&out.Scheduler) out.DNS = in.DNS + out.Proxy = in.Proxy if in.FeatureGates != nil { in, out := &in.FeatureGates, &out.FeatureGates *out = make(map[string]bool, len(*in)) @@ -546,6 +547,22 @@ func (in *Patches) DeepCopy() *Patches { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Proxy) DeepCopyInto(out *Proxy) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Proxy. +func (in *Proxy) DeepCopy() *Proxy { + if in == nil { + return nil + } + out := new(Proxy) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResetConfiguration) DeepCopyInto(out *ResetConfiguration) { *out = *in diff --git a/cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go b/cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go index f0265b9a3e7..29c2dadb6df 100644 --- a/cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go +++ b/cmd/kubeadm/app/apis/kubeadm/zz_generated.deepcopy.go @@ -125,6 +125,7 @@ func (in *ClusterConfiguration) DeepCopyInto(out *ClusterConfiguration) { in.ControllerManager.DeepCopyInto(&out.ControllerManager) in.Scheduler.DeepCopyInto(&out.Scheduler) out.DNS = in.DNS + out.Proxy = in.Proxy if in.FeatureGates != nil { in, out := &in.FeatureGates, &out.FeatureGates *out = make(map[string]bool, len(*in)) @@ -576,6 +577,22 @@ func (in *Patches) DeepCopy() *Patches { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Proxy) DeepCopyInto(out *Proxy) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Proxy. +func (in *Proxy) DeepCopy() *Proxy { + if in == nil { + return nil + } + out := new(Proxy) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResetConfiguration) DeepCopyInto(out *ResetConfiguration) { *out = *in diff --git a/cmd/kubeadm/app/cmd/config_test.go b/cmd/kubeadm/app/cmd/config_test.go index 6ff0f00df8c..9ecb3792c01 100644 --- a/cmd/kubeadm/app/cmd/config_test.go +++ b/cmd/kubeadm/app/cmd/config_test.go @@ -235,9 +235,9 @@ func TestConfigImagesListOutput(t *testing.T) { registry.k8s.io/kube-controller-manager:{{.KubeVersion}} registry.k8s.io/kube-scheduler:{{.KubeVersion}} registry.k8s.io/kube-proxy:{{.KubeVersion}} +registry.k8s.io/coredns/coredns:{{.CoreDNSVersion}} registry.k8s.io/pause:{{.PauseVersion}} registry.k8s.io/etcd:{{.EtcdVersion}} -registry.k8s.io/coredns/coredns:{{.CoreDNSVersion}} `, }, { @@ -254,9 +254,9 @@ registry.k8s.io/coredns/coredns:{{.CoreDNSVersion}} "registry.k8s.io/kube-controller-manager:{{.KubeVersion}}", "registry.k8s.io/kube-scheduler:{{.KubeVersion}}", "registry.k8s.io/kube-proxy:{{.KubeVersion}}", + "registry.k8s.io/coredns/coredns:{{.CoreDNSVersion}}", "registry.k8s.io/pause:{{.PauseVersion}}", - "registry.k8s.io/etcd:{{.EtcdVersion}}", - "registry.k8s.io/coredns/coredns:{{.CoreDNSVersion}}" + "registry.k8s.io/etcd:{{.EtcdVersion}}" ] } `, @@ -273,9 +273,9 @@ images: - registry.k8s.io/kube-controller-manager:{{.KubeVersion}} - registry.k8s.io/kube-scheduler:{{.KubeVersion}} - registry.k8s.io/kube-proxy:{{.KubeVersion}} +- registry.k8s.io/coredns/coredns:{{.CoreDNSVersion}} - registry.k8s.io/pause:{{.PauseVersion}} - registry.k8s.io/etcd:{{.EtcdVersion}} -- registry.k8s.io/coredns/coredns:{{.CoreDNSVersion}} kind: Images `, }, @@ -289,9 +289,9 @@ kind: Images registry.k8s.io/kube-controller-manager:{{.KubeVersion}} registry.k8s.io/kube-scheduler:{{.KubeVersion}} registry.k8s.io/kube-proxy:{{.KubeVersion}} +registry.k8s.io/coredns/coredns:{{.CoreDNSVersion}} registry.k8s.io/pause:{{.PauseVersion}} registry.k8s.io/etcd:{{.EtcdVersion}} -registry.k8s.io/coredns/coredns:{{.CoreDNSVersion}} `, }, { @@ -301,7 +301,7 @@ registry.k8s.io/coredns/coredns:{{.CoreDNSVersion}} }, outputFormat: `jsonpath={range.images[*]}{@} {end}`, expectedOutput: "registry.k8s.io/kube-apiserver:{{.KubeVersion}} registry.k8s.io/kube-controller-manager:{{.KubeVersion}} registry.k8s.io/kube-scheduler:{{.KubeVersion}} " + - "registry.k8s.io/kube-proxy:{{.KubeVersion}} registry.k8s.io/pause:{{.PauseVersion}} registry.k8s.io/etcd:{{.EtcdVersion}} registry.k8s.io/coredns/coredns:{{.CoreDNSVersion}} ", + "registry.k8s.io/kube-proxy:{{.KubeVersion}} registry.k8s.io/coredns/coredns:{{.CoreDNSVersion}} registry.k8s.io/pause:{{.PauseVersion}} registry.k8s.io/etcd:{{.EtcdVersion}} ", }, } diff --git a/cmd/kubeadm/app/cmd/init.go b/cmd/kubeadm/app/cmd/init.go index f57acf12d8c..9d6ba55bc0d 100644 --- a/cmd/kubeadm/app/cmd/init.go +++ b/cmd/kubeadm/app/cmd/init.go @@ -66,6 +66,17 @@ type initOptions struct { skipCRIDetect bool } +const ( + // CoreDNSPhase is the name of CoreDNS subphase in "kubeadm init" + coreDNSPhase = "addon/coredns" + + // KubeProxyPhase is the name of kube-proxy subphase during "kubeadm init" + kubeProxyPhase = "addon/kube-proxy" + + // AddonPhase is the name of addon phase during "kubeadm init" + addonPhase = "addon" +) + // compile-time assert that the local data object satisfies the phases data interface. var _ phases.InitData = &initData{} @@ -164,6 +175,8 @@ func newCmdInit(out io.Writer, initOptions *initOptions) *cobra.Command { if len(initRunner.Options.SkipPhases) == 0 { initRunner.Options.SkipPhases = data.cfg.SkipPhases } + + initRunner.Options.SkipPhases = manageSkippedAddons(&data.cfg.ClusterConfiguration, initRunner.Options.SkipPhases) return data, nil }) @@ -538,3 +551,43 @@ func (d *initData) PatchesDir() string { } return "" } + +// manageSkippedAddons syncs proxy and DNS "Disabled" status and skipPhases. +func manageSkippedAddons(cfg *kubeadmapi.ClusterConfiguration, skipPhases []string) []string { + var ( + skipDNSPhase = false + skipProxyPhase = false + ) + // If the DNS or Proxy addons are disabled, skip the corresponding phase. + // Alternatively, update the proxy and DNS "Disabled" status based on skipped addon phases. + if isPhaseInSkipPhases(addonPhase, skipPhases) { + skipDNSPhase = true + skipProxyPhase = true + cfg.DNS.Disabled = true + cfg.Proxy.Disabled = true + } + if isPhaseInSkipPhases(coreDNSPhase, skipPhases) { + skipDNSPhase = true + cfg.DNS.Disabled = true + } + if isPhaseInSkipPhases(kubeProxyPhase, skipPhases) { + skipProxyPhase = true + cfg.Proxy.Disabled = true + } + if cfg.DNS.Disabled && !skipDNSPhase { + skipPhases = append(skipPhases, coreDNSPhase) + } + if cfg.Proxy.Disabled && !skipProxyPhase { + skipPhases = append(skipPhases, kubeProxyPhase) + } + return skipPhases +} + +func isPhaseInSkipPhases(phase string, skipPhases []string) bool { + for _, item := range skipPhases { + if item == phase { + return true + } + } + return false +} diff --git a/cmd/kubeadm/app/cmd/init_test.go b/cmd/kubeadm/app/cmd/init_test.go index 2f859752819..13bfb7deb2c 100644 --- a/cmd/kubeadm/app/cmd/init_test.go +++ b/cmd/kubeadm/app/cmd/init_test.go @@ -24,6 +24,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" @@ -212,6 +213,131 @@ func TestNewInitData(t *testing.T) { } } +func TestManageSkippedAddons(t *testing.T) { + testcases := []struct { + name string + cfg *kubeadmapi.ClusterConfiguration + expectedCfg *kubeadmapi.ClusterConfiguration + skipPhases []string + expectedSkipPhases []string + }{ + { + name: "disable proxy and DNS if 'addon' is in skipPhases", + cfg: &kubeadmapi.ClusterConfiguration{}, + expectedCfg: &kubeadmapi.ClusterConfiguration{ + DNS: kubeadmapi.DNS{ + Disabled: true, + }, + Proxy: kubeadmapi.Proxy{ + Disabled: true, + }, + }, + skipPhases: []string{"addon"}, + expectedSkipPhases: []string{"addon"}, + }, + { + name: "disable proxy and DNS if 'addon/coredns' and 'addon/kube-proxy' are in skipPhases", + cfg: &kubeadmapi.ClusterConfiguration{}, + expectedCfg: &kubeadmapi.ClusterConfiguration{ + DNS: kubeadmapi.DNS{ + Disabled: true, + }, + Proxy: kubeadmapi.Proxy{ + Disabled: true, + }, + }, + skipPhases: []string{"addon/coredns", "addon/kube-proxy"}, + expectedSkipPhases: []string{"addon/coredns", "addon/kube-proxy"}, + }, + { + name: "disable proxy if 'addon/kube-proxy' is in skipPhases", + cfg: &kubeadmapi.ClusterConfiguration{}, + expectedCfg: &kubeadmapi.ClusterConfiguration{ + Proxy: kubeadmapi.Proxy{ + Disabled: true, + }, + }, + skipPhases: []string{"addon/kube-proxy"}, + expectedSkipPhases: []string{"addon/kube-proxy"}, + }, + { + name: "disable DNS if 'addon/coredns' is in skipPhases", + cfg: &kubeadmapi.ClusterConfiguration{}, + expectedCfg: &kubeadmapi.ClusterConfiguration{ + DNS: kubeadmapi.DNS{ + Disabled: true, + }, + }, + skipPhases: []string{"addon/coredns"}, + expectedSkipPhases: []string{"addon/coredns"}, + }, + { + name: "add 'addon/coredns' and 'addon/kube-proxy' to skipPhases if DNS and proxy are disabled", + cfg: &kubeadmapi.ClusterConfiguration{ + DNS: kubeadmapi.DNS{ + Disabled: true, + }, + Proxy: kubeadmapi.Proxy{ + Disabled: true, + }, + }, + expectedCfg: &kubeadmapi.ClusterConfiguration{ + DNS: kubeadmapi.DNS{ + Disabled: true, + }, + Proxy: kubeadmapi.Proxy{ + Disabled: true, + }, + }, + expectedSkipPhases: []string{"addon/coredns", "addon/kube-proxy"}, + }, + { + name: "don't add duplicates in skipPhases", + cfg: &kubeadmapi.ClusterConfiguration{ + DNS: kubeadmapi.DNS{ + Disabled: true, + }, + }, + expectedCfg: &kubeadmapi.ClusterConfiguration{ + DNS: kubeadmapi.DNS{ + Disabled: true, + }, + }, + skipPhases: []string{"addon/coredns"}, + expectedSkipPhases: []string{"addon/coredns"}, + }, + { + name: "overwrite addon Disabled status if skipPhases is set", + cfg: &kubeadmapi.ClusterConfiguration{ + DNS: kubeadmapi.DNS{ + Disabled: false, + }, + }, + expectedCfg: &kubeadmapi.ClusterConfiguration{ + DNS: kubeadmapi.DNS{ + Disabled: true, + }, + }, + skipPhases: []string{"addon/coredns"}, + expectedSkipPhases: []string{"addon/coredns"}, + }, + { + name: "do nothing if addon Disabled field and skipPhases are not configured", + cfg: &kubeadmapi.ClusterConfiguration{}, + expectedCfg: &kubeadmapi.ClusterConfiguration{}, + skipPhases: []string{}, + expectedSkipPhases: []string{}, + }, + } + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + skipPhases := manageSkippedAddons(tc.cfg, tc.skipPhases) + assert.Equal(t, tc.expectedSkipPhases, skipPhases) + assert.Equal(t, tc.expectedCfg, tc.cfg) + }) + } +} + func expectedInitIgnorePreflightErrors(expectedItems ...string) func(t *testing.T, data *initData) { expected := sets.New(expectedItems...) return func(t *testing.T, data *initData) { diff --git a/cmd/kubeadm/app/images/images.go b/cmd/kubeadm/app/images/images.go index 4a26573132b..7ac426e8121 100644 --- a/cmd/kubeadm/app/images/images.go +++ b/cmd/kubeadm/app/images/images.go @@ -94,7 +94,19 @@ func GetControlPlaneImages(cfg *kubeadmapi.ClusterConfiguration) []string { images = append(images, GetKubernetesImage(constants.KubeAPIServer, cfg)) images = append(images, GetKubernetesImage(constants.KubeControllerManager, cfg)) images = append(images, GetKubernetesImage(constants.KubeScheduler, cfg)) - images = append(images, GetKubernetesImage(constants.KubeProxy, cfg)) + + // if Proxy addon is not disable then add the image + if cfg.Proxy.Disabled { + klog.V(1).Infof("skipping the kube-proxy image pull since the bundled addon is disabled") + } else { + images = append(images, GetKubernetesImage(constants.KubeProxy, cfg)) + } + // if DNS addon is not disable then add the image + if cfg.DNS.Disabled { + klog.V(1).Infof("skipping the CoreDNS image pull since the bundled addon is disabled") + } else { + images = append(images, GetDNSImage(cfg)) + } // pause is not available on the ci image repository so use the default image repository. images = append(images, GetPauseImage(cfg)) @@ -104,9 +116,6 @@ func GetControlPlaneImages(cfg *kubeadmapi.ClusterConfiguration) []string { images = append(images, GetEtcdImage(cfg)) } - // Append the appropriate DNS images - images = append(images, GetDNSImage(cfg)) - return images } diff --git a/cmd/kubeadm/app/images/images_test.go b/cmd/kubeadm/app/images/images_test.go index 054ba81fcfb..0f8478a1a83 100644 --- a/cmd/kubeadm/app/images/images_test.go +++ b/cmd/kubeadm/app/images/images_test.go @@ -18,9 +18,9 @@ package images import ( "fmt" - "strings" "testing" + "github.com/stretchr/testify/assert" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapiv1beta3 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3" "k8s.io/kubernetes/cmd/kubeadm/app/constants" @@ -190,23 +190,37 @@ func TestGetPauseImage(t *testing.T) { func TestGetAllImages(t *testing.T) { testcases := []struct { - name string - expect string - cfg *kubeadmapi.ClusterConfiguration + name string + expectedImages []string + cfg *kubeadmapi.ClusterConfiguration }{ { name: "defined CIImageRepository", cfg: &kubeadmapi.ClusterConfiguration{ CIImageRepository: "test.repo", }, - expect: "test.repo", + expectedImages: []string{ + "test.repo/kube-apiserver:", + "test.repo/kube-controller-manager:", + "test.repo/kube-scheduler:", + "test.repo/kube-proxy:", + "/coredns:" + constants.CoreDNSVersion, + "/pause:" + constants.PauseVersion, + }, }, { name: "undefined CIImagerRepository should contain the default image prefix", cfg: &kubeadmapi.ClusterConfiguration{ ImageRepository: "real.repo", }, - expect: "real.repo", + expectedImages: []string{ + "real.repo/kube-apiserver:", + "real.repo/kube-controller-manager:", + "real.repo/kube-scheduler:", + "real.repo/kube-proxy:", + "real.repo/coredns:" + constants.CoreDNSVersion, + "real.repo/pause:" + constants.PauseVersion, + }, }, { name: "test that etcd is returned when it is not external", @@ -215,23 +229,82 @@ func TestGetAllImages(t *testing.T) { Local: &kubeadmapi.LocalEtcd{}, }, }, - expect: constants.Etcd, + expectedImages: []string{ + "/kube-apiserver:", + "/kube-controller-manager:", + "/kube-scheduler:", + "/kube-proxy:", + "/coredns:" + constants.CoreDNSVersion, + "/pause:" + constants.PauseVersion, + "/etcd:" + constants.DefaultEtcdVersion, + }, }, { - name: "CoreDNS image is returned", - cfg: &kubeadmapi.ClusterConfiguration{}, - expect: constants.CoreDNSImageName, + name: "CoreDNS and kube-proxy image are returned", + cfg: &kubeadmapi.ClusterConfiguration{}, + expectedImages: []string{ + "/kube-apiserver:", + "/kube-controller-manager:", + "/kube-scheduler:", + "/kube-proxy:", + "/coredns:" + constants.CoreDNSVersion, + "/pause:" + constants.PauseVersion, + }, + }, + { + name: "CoreDNS image is skipped", + cfg: &kubeadmapi.ClusterConfiguration{ + DNS: kubeadmapi.DNS{ + Disabled: true, + }, + }, + expectedImages: []string{ + "/kube-apiserver:", + "/kube-controller-manager:", + "/kube-scheduler:", + "/kube-proxy:", + "/pause:" + constants.PauseVersion, + }, + }, + { + name: "kube-proxy image is skipped", + cfg: &kubeadmapi.ClusterConfiguration{ + Proxy: kubeadmapi.Proxy{ + Disabled: true, + }, + }, + expectedImages: []string{ + "/kube-apiserver:", + "/kube-controller-manager:", + "/kube-scheduler:", + "/coredns:" + constants.CoreDNSVersion, + "/pause:" + constants.PauseVersion, + }, + }, + { + name: "setting addons Disabled to false has no effect", + cfg: &kubeadmapi.ClusterConfiguration{ + DNS: kubeadmapi.DNS{ + Disabled: false, + }, + Proxy: kubeadmapi.Proxy{ + Disabled: false, + }, + }, + expectedImages: []string{ + "/kube-apiserver:", + "/kube-controller-manager:", + "/kube-scheduler:", + "/kube-proxy:", + "/coredns:" + constants.CoreDNSVersion, + "/pause:" + constants.PauseVersion, + }, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { imgs := GetControlPlaneImages(tc.cfg) - for _, img := range imgs { - if strings.Contains(img, tc.expect) { - return - } - } - t.Fatalf("did not find %q in %q", tc.expect, imgs) + assert.Equal(t, tc.expectedImages, imgs) }) } }