Repository: kubernetes/kops (go)

Issue:
Allow to define resources for controller manager and scheduler
/kind feature

**1. Describe IN DETAIL the feature/behavior/change you would like to see.**

Like for `kube-apiserver` we need to be able to provide custom resources for `kube-controller-manager` and `kube-scheduler`

**2. Feel free to provide a design supporting your feature request.**




Pull request description:
feat(components): permit to define kube-controller-manager and kube-scheduler resources
<!--
Thanks for contributing to kubernetes/kops!  Here are some tips for you:
1. If this is your first time, read our contributor guidelines:

 https://git.k8s.io/kops/CONTRIBUTING.md

2. Also, you'll probably want to checkout our development documentation:

https://git.k8s.io/kops/docs/development

3. If the PR is unfinished, see how to mark it: https://git.k8s.io/community/contributors/guide/pull-requests.md#marking-unfinished-pull-requests

4. Finally, make sure all verifications and tests pass by running:
```
 make pr
```
-->

**What this PR does / why we need it**:

Add ability to define custom resources for `kube-controller-manager` and `kube-scheduler`

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:

fixes #16604


**Special notes for your reviewer**:


Patch:
diff --git a/k8s/crds/kops.k8s.io_clusters.yaml b/k8s/crds/kops.k8s.io_clusters.yaml
index e62ce1ff19..073dac79ba 100644
--- a/k8s/crds/kops.k8s.io_clusters.yaml
+++ b/k8s/crds/kops.k8s.io_clusters.yaml
@@ -2254,6 +2254,22 @@ spec:
                     items:
                       type: string
                     type: array
+                  cpuLimit:
+                    anyOf:
+                    - type: integer
+                    - type: string
+                    description: CPULimit, cpu limit compute resource for kube-controler-manager
+                      e.g. "500m"
+                    pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                    x-kubernetes-int-or-string: true
+                  cpuRequest:
+                    anyOf:
+                    - type: integer
+                    - type: string
+                    description: CPURequest, cpu request compute resource for kube-controler-manager.
+                      Defaults to "100m"
+                    pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                    x-kubernetes-int-or-string: true
                   disableAttachDetachReconcileSync:
                     description: |-
                       DisableAttachDetachReconcileSync disables the reconcile sync loop in the attach-detach controller.
@@ -2421,6 +2437,22 @@ spec:
                   master:
                     description: Master is the url for the kube api master
                     type: string
+                  memoryLimit:
+                    anyOf:
+                    - type: integer
+                    - type: string
+                    description: MemoryLimit, memory limit compute resource for kube-controler-manager
+                      e.g. "30Mi"
+                    pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                    x-kubernetes-int-or-string: true
+                  memoryRequest:
+                    anyOf:
+                    - type: integer
+                    - type: string
+                    description: MemoryRequest, memory request compute resource for
+                      kube-controler-manager e.g. "30Mi"
+                    pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                    x-kubernetes-int-or-string: true
                   minResyncPeriod:
                     description: |-
                       MinResyncPeriod indicates the resync period in reflectors.
@@ -3708,6 +3740,22 @@ spec:
                       the burst quota is exhausted
                     format: int32
                     type: integer
+                  cpuLimit:
+                    anyOf:
+                    - type: integer
+                    - type: string
+                    description: CPULimit, cpu limit compute resource for scheduler
+                      e.g. "500m"
+                    pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                    x-kubernetes-int-or-string: true
+                  cpuRequest:
+                    anyOf:
+                    - type: integer
+                    - type: string
+                    description: CPURequest, cpu request compute resource for scheduler.
+                      Defaults to "100m"
+                    pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                    x-kubernetes-int-or-string: true
                   enableContentionProfiling:
                     description: EnableContentionProfiling enables block profiling,
                       if profiling is enabled
@@ -3801,6 +3849,22 @@ spec:
                       as outlined: https://kubernetes.io/docs/concepts/storage/storage-limits/
                     format: int32
                     type: integer
+                  memoryLimit:
+                    anyOf:
+                    - type: integer
+                    - type: string
+                    description: MemoryLimit, memory limit compute resource for scheduler
+                      e.g. "30Mi"
+                    pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                    x-kubernetes-int-or-string: true
+                  memoryRequest:
+                    anyOf:
+                    - type: integer
+                    - type: string
+                    description: MemoryRequest, memory request compute resource for
+                      scheduler e.g. "30Mi"
+                    pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                    x-kubernetes-int-or-string: true
                   qps:
                     anyOf:
                     - type: integer
diff --git a/nodeup/pkg/model/kube_controller_manager.go b/nodeup/pkg/model/kube_controller_manager.go
index dafcf5bd86..0726f12a9c 100644
--- a/nodeup/pkg/model/kube_controller_manager.go
+++ b/nodeup/pkg/model/kube_controller_manager.go
@@ -202,6 +202,27 @@ func (b *KubeControllerManagerBuilder) buildPod(kcm *kops.KubeControllerManagerC
 	// Add the volumePluginDir flag if provided in the kubelet spec, or set above based on the OS
 	flags = append(flags, "--flex-volume-plugin-dir="+volumePluginDir)
 
+	resourceRequests := v1.ResourceList{}
+	resourceLimits := v1.ResourceList{}
+
+	cpuRequest := resource.MustParse("100m")
+	if kcm.CPURequest != nil {
+		cpuRequest = *kcm.CPURequest
+	}
+	resourceRequests["cpu"] = cpuRequest
+
+	if kcm.CPULimit != nil {
+		resourceLimits["cpu"] = *kcm.CPULimit
+	}
+
+	if kcm.MemoryRequest != nil {
+		resourceRequests["memory"] = *kcm.MemoryRequest
+	}
+
+	if kcm.MemoryLimit != nil {
+		resourceLimits["memory"] = *kcm.MemoryLimit
+	}
+
 	image := b.RemapImage(kcm.Image)
 
 	container := &v1.Container{
@@ -221,9 +242,8 @@ func (b *KubeControllerManagerBuilder) buildPod(kcm *kops.KubeControllerManagerC
 			TimeoutSeconds:      15,
 		},
 		Resources: v1.ResourceRequirements{
-			Requests: v1.ResourceList{
-				v1.ResourceCPU: resource.MustParse("100m"),
-			},
+			Requests: resourceRequests,
+			Limits:   resourceLimits,
 		},
 	}
 
diff --git a/nodeup/pkg/model/kube_scheduler.go b/nodeup/pkg/model/kube_scheduler.go
index 36e2203ea8..046c5a082b 100644
--- a/nodeup/pkg/model/kube_scheduler.go
+++ b/nodeup/pkg/model/kube_scheduler.go
@@ -213,6 +213,27 @@ func (b *KubeSchedulerBuilder) buildPod(kubeScheduler *kops.KubeSchedulerConfig)
 		},
 	}
 
+	resourceRequests := v1.ResourceList{}
+	resourceLimits := v1.ResourceList{}
+
+	cpuRequest := resource.MustParse("100m")
+	if kubeScheduler.CPURequest != nil {
+		cpuRequest = *kubeScheduler.CPURequest
+	}
+	resourceRequests["cpu"] = cpuRequest
+
+	if kubeScheduler.CPULimit != nil {
+		resourceLimits["cpu"] = *kubeScheduler.CPULimit
+	}
+
+	if kubeScheduler.MemoryRequest != nil {
+		resourceRequests["memory"] = *kubeScheduler.MemoryRequest
+	}
+
+	if kubeScheduler.MemoryLimit != nil {
+		resourceLimits["memory"] = *kubeScheduler.MemoryLimit
+	}
+
 	image := b.RemapImage(kubeScheduler.Image)
 
 	healthAction := &v1.HTTPGetAction{
@@ -232,9 +253,8 @@ func (b *KubeSchedulerBuilder) buildPod(kubeScheduler *kops.KubeSchedulerConfig)
 			TimeoutSeconds:      15,
 		},
 		Resources: v1.ResourceRequirements{
-			Requests: v1.ResourceList{
-				v1.ResourceCPU: resource.MustParse("100m"),
-			},
+			Requests: resourceRequests,
+			Limits:   resourceLimits,
 		},
 	}
 	kubemanifest.AddHostPathMapping(pod, container, "varlibkubescheduler", "/var/lib/kube-scheduler")
diff --git a/pkg/apis/kops/componentconfig.go b/pkg/apis/kops/componentconfig.go
index 67f1abd7be..4cb04f5c1f 100644
--- a/pkg/apis/kops/componentconfig.go
+++ b/pkg/apis/kops/componentconfig.go
@@ -694,6 +694,15 @@ type KubeControllerManagerConfig struct {
 	EnableContentionProfiling *bool `json:"enableContentionProfiling,omitempty" flag:"contention-profiling"`
 	// EnableLeaderMigration enables controller leader migration.
 	EnableLeaderMigration *bool `json:"enableLeaderMigration,omitempty" flag:"enable-leader-migration"`
+
+	// CPURequest, cpu request compute resource for kube-controler-manager. Defaults to "100m"
+	CPURequest *resource.Quantity `json:"cpuRequest,omitempty"`
+	// CPULimit, cpu limit compute resource for kube-controler-manager e.g. "500m"
+	CPULimit *resource.Quantity `json:"cpuLimit,omitempty"`
+	// MemoryRequest, memory request compute resource for kube-controler-manager e.g. "30Mi"
+	MemoryRequest *resource.Quantity `json:"memoryRequest,omitempty"`
+	// MemoryLimit, memory limit compute resource for kube-controler-manager e.g. "30Mi"
+	MemoryLimit *resource.Quantity `json:"memoryLimit,omitempty"`
 }
 
 // CloudControllerManagerConfig is the configuration of the cloud controller
@@ -783,6 +792,15 @@ type KubeSchedulerConfig struct {
 	TLSCertFile *string `json:"tlsCertFile,omitempty" flag:"tls-cert-file"`
 	// TLSPrivateKeyFile is the file containing the private key for the TLS server certificate.
 	TLSPrivateKeyFile string `json:"tlsPrivateKeyFile,omitempty" flag:"tls-private-key-file"`
+
+	// CPURequest, cpu request compute resource for scheduler. Defaults to "100m"
+	CPURequest *resource.Quantity `json:"cpuRequest,omitempty"`
+	// CPULimit, cpu limit compute resource for scheduler e.g. "500m"
+	CPULimit *resource.Quantity `json:"cpuLimit,omitempty"`
+	// MemoryRequest, memory request compute resource for scheduler e.g. "30Mi"
+	MemoryRequest *resource.Quantity `json:"memoryRequest,omitempty"`
+	// MemoryLimit, memory limit compute resource for scheduler e.g. "30Mi"
+	MemoryLimit *resource.Quantity `json:"memoryLimit,omitempty"`
 }
 
 // LeaderElectionConfiguration defines the configuration of leader election
diff --git a/pkg/apis/kops/v1alpha2/componentconfig.go b/pkg/apis/kops/v1alpha2/componentconfig.go
index be02744976..76274f1ac0 100644
--- a/pkg/apis/kops/v1alpha2/componentconfig.go
+++ b/pkg/apis/kops/v1alpha2/componentconfig.go
@@ -700,6 +700,15 @@ type KubeControllerManagerConfig struct {
 	EnableContentionProfiling *bool `json:"enableContentionProfiling,omitempty" flag:"contention-profiling"`
 	// EnableLeaderMigration enables controller leader migration.
 	EnableLeaderMigration *bool `json:"enableLeaderMigration,omitempty" flag:"enable-leader-migration"`
+
+	// CPURequest, cpu request compute resource for kube-controler-manager. Defaults to "100m"
+	CPURequest *resource.Quantity `json:"cpuRequest,omitempty"`
+	// CPULimit, cpu limit compute resource for kube-controler-manager e.g. "500m"
+	CPULimit *resource.Quantity `json:"cpuLimit,omitempty"`
+	// MemoryRequest, memory request compute resource for kube-controler-manager e.g. "30Mi"
+	MemoryRequest *resource.Quantity `json:"memoryRequest,omitempty"`
+	// MemoryLimit, memory limit compute resource for kube-controler-manager e.g. "30Mi"
+	MemoryLimit *resource.Quantity `json:"memoryLimit,omitempty"`
 }
 
 // CloudControllerManagerConfig is the configuration of the cloud controller
@@ -789,6 +798,15 @@ type KubeSchedulerConfig struct {
 	TLSCertFile *string `json:"tlsCertFile,omitempty" flag:"tls-cert-file"`
 	// TLSPrivateKeyFile is the file containing the private key for the TLS server certificate.
 	TLSPrivateKeyFile string `json:"tlsPrivateKeyFile,omitempty" flag:"tls-private-key-file"`
+
+	// CPURequest, cpu request compute resource for scheduler. Defaults to "100m"
+	CPURequest *resource.Quantity `json:"cpuRequest,omitempty"`
+	// CPULimit, cpu limit compute resource for scheduler e.g. "500m"
+	CPULimit *resource.Quantity `json:"cpuLimit,omitempty"`
+	// MemoryRequest, memory request compute resource for scheduler e.g. "30Mi"
+	MemoryRequest *resource.Quantity `json:"memoryRequest,omitempty"`
+	// MemoryLimit, memory limit compute resource for scheduler e.g. "30Mi"
+	MemoryLimit *resource.Quantity `json:"memoryLimit,omitempty"`
 }
 
 // LeaderElectionConfiguration defines the configuration of leader election
diff --git a/pkg/apis/kops/v1alpha2/zz_generated.conversion.go b/pkg/apis/kops/v1alpha2/zz_generated.conversion.go
index ccbf677f96..ce8a7a6123 100644
--- a/pkg/apis/kops/v1alpha2/zz_generated.conversion.go
+++ b/pkg/apis/kops/v1alpha2/zz_generated.conversion.go
@@ -5158,6 +5158,10 @@ func autoConvert_v1alpha2_KubeControllerManagerConfig_To_kops_KubeControllerMana
 	out.EnableProfiling = in.EnableProfiling
 	out.EnableContentionProfiling = in.EnableContentionProfiling
 	out.EnableLeaderMigration = in.EnableLeaderMigration
+	out.CPURequest = in.CPURequest
+	out.CPULimit = in.CPULimit
+	out.MemoryRequest = in.MemoryRequest
+	out.MemoryLimit = in.MemoryLimit
 	return nil
 }
 
@@ -5234,6 +5238,10 @@ func autoConvert_kops_KubeControllerManagerConfig_To_v1alpha2_KubeControllerMana
 	out.EnableProfiling = in.EnableProfiling
 	out.EnableContentionProfiling = in.EnableContentionProfiling
 	out.EnableLeaderMigration = in.EnableLeaderMigration
+	out.CPURequest = in.CPURequest
+	out.CPULimit = in.CPULimit
+	out.MemoryRequest = in.MemoryRequest
+	out.MemoryLimit = in.MemoryLimit
 	return nil
 }
 
@@ -5396,6 +5404,10 @@ func autoConvert_v1alpha2_KubeSchedulerConfig_To_kops_KubeSchedulerConfig(in *Ku
 	out.EnableContentionProfiling = in.EnableContentionProfiling
 	out.TLSCertFile = in.TLSCertFile
 	out.TLSPrivateKeyFile = in.TLSPrivateKeyFile
+	out.CPURequest = in.CPURequest
+	out.CPULimit = in.CPULimit
+	out.MemoryRequest = in.MemoryRequest
+	out.MemoryLimit = in.MemoryLimit
 	return nil
 }
 
@@ -5432,6 +5444,10 @@ func autoConvert_kops_KubeSchedulerConfig_To_v1alpha2_KubeSchedulerConfig(in *ko
 	out.EnableContentionProfiling = in.EnableContentionProfiling
 	out.TLSCertFile = in.TLSCertFile
 	out.TLSPrivateKeyFile = in.TLSPrivateKeyFile
+	out.CPURequest = in.CPURequest
+	out.CPULimit = in.CPULimit
+	out.MemoryRequest = in.MemoryRequest
+	out.MemoryLimit = in.MemoryLimit
 	return nil
 }
 
diff --git a/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go b/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go
index b9394021bf..dbc6565237 100644
--- a/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go
+++ b/pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go
@@ -3643,6 +3643,26 @@ func (in *KubeControllerManagerConfig) DeepCopyInto(out *KubeControllerManagerCo
 		*out = new(bool)
 		**out = **in
 	}
+	if in.CPURequest != nil {
+		in, out := &in.CPURequest, &out.CPURequest
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.CPULimit != nil {
+		in, out := &in.CPULimit, &out.CPULimit
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.MemoryRequest != nil {
+		in, out := &in.MemoryRequest, &out.MemoryRequest
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.MemoryLimit != nil {
+		in, out := &in.MemoryLimit, &out.MemoryLimit
+		x := (*in).DeepCopy()
+		*out = &x
+	}
 	return
 }
 
@@ -3872,6 +3892,26 @@ func (in *KubeSchedulerConfig) DeepCopyInto(out *KubeSchedulerConfig) {
 		*out = new(string)
 		**out = **in
 	}
+	if in.CPURequest != nil {
+		in, out := &in.CPURequest, &out.CPURequest
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.CPULimit != nil {
+		in, out := &in.CPULimit, &out.CPULimit
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.MemoryRequest != nil {
+		in, out := &in.MemoryRequest, &out.MemoryRequest
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.MemoryLimit != nil {
+		in, out := &in.MemoryLimit, &out.MemoryLimit
+		x := (*in).DeepCopy()
+		*out = &x
+	}
 	return
 }
 
diff --git a/pkg/apis/kops/v1alpha3/componentconfig.go b/pkg/apis/kops/v1alpha3/componentconfig.go
index 3059eaea21..618d4105d5 100644
--- a/pkg/apis/kops/v1alpha3/componentconfig.go
+++ b/pkg/apis/kops/v1alpha3/componentconfig.go
@@ -691,6 +691,15 @@ type KubeControllerManagerConfig struct {
 	EnableContentionProfiling *bool `json:"enableContentionProfiling,omitempty" flag:"contention-profiling"`
 	// EnableLeaderMigration enables controller leader migration.
 	EnableLeaderMigration *bool `json:"enableLeaderMigration,omitempty" flag:"enable-leader-migration"`
+
+	// CPURequest, cpu request compute resource for kube-controler-manager. Defaults to "100m"
+	CPURequest *resource.Quantity `json:"cpuRequest,omitempty"`
+	// CPULimit, cpu limit compute resource for kube-controler-manager e.g. "500m"
+	CPULimit *resource.Quantity `json:"cpuLimit,omitempty"`
+	// MemoryRequest, memory request compute resource for kube-controler-manager e.g. "30Mi"
+	MemoryRequest *resource.Quantity `json:"memoryRequest,omitempty"`
+	// MemoryLimit, memory limit compute resource for kube-controler-manager e.g. "30Mi"
+	MemoryLimit *resource.Quantity `json:"memoryLimit,omitempty"`
 }
 
 // CloudControllerManagerConfig is the configuration of the cloud controller
@@ -780,6 +789,15 @@ type KubeSchedulerConfig struct {
 	TLSCertFile *string `json:"tlsCertFile,omitempty" flag:"tls-cert-file"`
 	// TLSPrivateKeyFile is the file containing the private key for the TLS server certificate.
 	TLSPrivateKeyFile string `json:"tlsPrivateKeyFile,omitempty" flag:"tls-private-key-file"`
+
+	// CPURequest, cpu request compute resource for scheduler. Defaults to "100m"
+	CPURequest *resource.Quantity `json:"cpuRequest,omitempty"`
+	// CPULimit, cpu limit compute resource for scheduler e.g. "500m"
+	CPULimit *resource.Quantity `json:"cpuLimit,omitempty"`
+	// MemoryRequest, memory request compute resource for scheduler e.g. "30Mi"
+	MemoryRequest *resource.Quantity `json:"memoryRequest,omitempty"`
+	// MemoryLimit, memory limit compute resource for scheduler e.g. "30Mi"
+	MemoryLimit *resource.Quantity `json:"memoryLimit,omitempty"`
 }
 
 // LeaderElectionConfiguration defines the configuration of leader election
diff --git a/pkg/apis/kops/v1alpha3/zz_generated.conversion.go b/pkg/apis/kops/v1alpha3/zz_generated.conversion.go
index 04bf000992..35fd2b1dd6 100644
--- a/pkg/apis/kops/v1alpha3/zz_generated.conversion.go
+++ b/pkg/apis/kops/v1alpha3/zz_generated.conversion.go
@@ -5553,6 +5553,10 @@ func autoConvert_v1alpha3_KubeControllerManagerConfig_To_kops_KubeControllerMana
 	out.EnableProfiling = in.EnableProfiling
 	out.EnableContentionProfiling = in.EnableContentionProfiling
 	out.EnableLeaderMigration = in.EnableLeaderMigration
+	out.CPURequest = in.CPURequest
+	out.CPULimit = in.CPULimit
+	out.MemoryRequest = in.MemoryRequest
+	out.MemoryLimit = in.MemoryLimit
 	return nil
 }
 
@@ -5629,6 +5633,10 @@ func autoConvert_kops_KubeControllerManagerConfig_To_v1alpha3_KubeControllerMana
 	out.EnableProfiling = in.EnableProfiling
 	out.EnableContentionProfiling = in.EnableContentionProfiling
 	out.EnableLeaderMigration = in.EnableLeaderMigration
+	out.CPURequest = in.CPURequest
+	out.CPULimit = in.CPULimit
+	out.MemoryRequest = in.MemoryRequest
+	out.MemoryLimit = in.MemoryLimit
 	return nil
 }
 
@@ -5789,6 +5797,10 @@ func autoConvert_v1alpha3_KubeSchedulerConfig_To_kops_KubeSchedulerConfig(in *Ku
 	out.EnableContentionProfiling = in.EnableContentionProfiling
 	out.TLSCertFile = in.TLSCertFile
 	out.TLSPrivateKeyFile = in.TLSPrivateKeyFile
+	out.CPURequest = in.CPURequest
+	out.CPULimit = in.CPULimit
+	out.MemoryRequest = in.MemoryRequest
+	out.MemoryLimit = in.MemoryLimit
 	return nil
 }
 
@@ -5825,6 +5837,10 @@ func autoConvert_kops_KubeSchedulerConfig_To_v1alpha3_KubeSchedulerConfig(in *ko
 	out.EnableContentionProfiling = in.EnableContentionProfiling
 	out.TLSCertFile = in.TLSCertFile
 	out.TLSPrivateKeyFile = in.TLSPrivateKeyFile
+	out.CPURequest = in.CPURequest
+	out.CPULimit = in.CPULimit
+	out.MemoryRequest = in.MemoryRequest
+	out.MemoryLimit = in.MemoryLimit
 	return nil
 }
 
diff --git a/pkg/apis/kops/v1alpha3/zz_generated.deepcopy.go b/pkg/apis/kops/v1alpha3/zz_generated.deepcopy.go
index a8653a09fc..a51e80a2be 100644
--- a/pkg/apis/kops/v1alpha3/zz_generated.deepcopy.go
+++ b/pkg/apis/kops/v1alpha3/zz_generated.deepcopy.go
@@ -3617,6 +3617,26 @@ func (in *KubeControllerManagerConfig) DeepCopyInto(out *KubeControllerManagerCo
 		*out = new(bool)
 		**out = **in
 	}
+	if in.CPURequest != nil {
+		in, out := &in.CPURequest, &out.CPURequest
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.CPULimit != nil {
+		in, out := &in.CPULimit, &out.CPULimit
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.MemoryRequest != nil {
+		in, out := &in.MemoryRequest, &out.MemoryRequest
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.MemoryLimit != nil {
+		in, out := &in.MemoryLimit, &out.MemoryLimit
+		x := (*in).DeepCopy()
+		*out = &x
+	}
 	return
 }
 
@@ -3846,6 +3866,26 @@ func (in *KubeSchedulerConfig) DeepCopyInto(out *KubeSchedulerConfig) {
 		*out = new(string)
 		**out = **in
 	}
+	if in.CPURequest != nil {
+		in, out := &in.CPURequest, &out.CPURequest
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.CPULimit != nil {
+		in, out := &in.CPULimit, &out.CPULimit
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.MemoryRequest != nil {
+		in, out := &in.MemoryRequest, &out.MemoryRequest
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.MemoryLimit != nil {
+		in, out := &in.MemoryLimit, &out.MemoryLimit
+		x := (*in).DeepCopy()
+		*out = &x
+	}
 	return
 }
 
diff --git a/pkg/apis/kops/zz_generated.deepcopy.go b/pkg/apis/kops/zz_generated.deepcopy.go
index 0908541524..4e65dc86b7 100644
--- a/pkg/apis/kops/zz_generated.deepcopy.go
+++ b/pkg/apis/kops/zz_generated.deepcopy.go
@@ -3720,6 +3720,26 @@ func (in *KubeControllerManagerConfig) DeepCopyInto(out *KubeControllerManagerCo
 		*out = new(bool)
 		**out = **in
 	}
+	if in.CPURequest != nil {
+		in, out := &in.CPURequest, &out.CPURequest
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.CPULimit != nil {
+		in, out := &in.CPULimit, &out.CPULimit
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.MemoryRequest != nil {
+		in, out := &in.MemoryRequest, &out.MemoryRequest
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.MemoryLimit != nil {
+		in, out := &in.MemoryLimit, &out.MemoryLimit
+		x := (*in).DeepCopy()
+		*out = &x
+	}
 	return
 }
 
@@ -3949,6 +3969,26 @@ func (in *KubeSchedulerConfig) DeepCopyInto(out *KubeSchedulerConfig) {
 		*out = new(string)
 		**out = **in
 	}
+	if in.CPURequest != nil {
+		in, out := &in.CPURequest, &out.CPURequest
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.CPULimit != nil {
+		in, out := &in.CPULimit, &out.CPULimit
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.MemoryRequest != nil {
+		in, out := &in.MemoryRequest, &out.MemoryRequest
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.MemoryLimit != nil {
+		in, out := &in.MemoryLimit, &out.MemoryLimit
+		x := (*in).DeepCopy()
+		*out = &x
+	}
 	return
 }
 


Test patch:
diff --git a/tests/integration/update_cluster/complex/data/aws_launch_template_master-us-test-1a.masters.complex.example.com_user_data b/tests/integration/update_cluster/complex/data/aws_launch_template_master-us-test-1a.masters.complex.example.com_user_data
index 7fd1f02fda..8ba1c7ec8d 100644
--- a/tests/integration/update_cluster/complex/data/aws_launch_template_master-us-test-1a.masters.complex.example.com_user_data
+++ b/tests/integration/update_cluster/complex/data/aws_launch_template_master-us-test-1a.masters.complex.example.com_user_data
@@ -139,7 +139,7 @@ ClusterName: complex.example.com
 ConfigBase: memfs://clusters.example.com/complex.example.com
 InstanceGroupName: master-us-test-1a
 InstanceGroupRole: ControlPlane
-NodeupConfigHash: UHWFfYNt82BPcCuW6MbwsJz+NubTfY7JsTsj9lxiQ4M=
+NodeupConfigHash: Pt1rZTv1N3aaFfH9HTNsjtOLY3uGrq7a3lRb2ip6L54=
 
 __EOF_KUBE_ENV
 
diff --git a/tests/integration/update_cluster/complex/data/aws_s3_object_cluster-completed.spec_content b/tests/integration/update_cluster/complex/data/aws_s3_object_cluster-completed.spec_content
index 843f55e43b..571a2ed914 100644
--- a/tests/integration/update_cluster/complex/data/aws_s3_object_cluster-completed.spec_content
+++ b/tests/integration/update_cluster/complex/data/aws_s3_object_cluster-completed.spec_content
@@ -136,12 +136,16 @@ spec:
     concurrentHorizontalPodAustoscalerSyncs: 10
     concurrentJobSyncs: 10
     configureCloudRoutes: false
+    cpuLimit: 500m
+    cpuRequest: 200m
     featureGates:
       InTreePluginAWSUnregister: "true"
     image: registry.k8s.io/kube-controller-manager:v1.30.0
     leaderElection:
       leaderElect: true
     logLevel: 2
+    memoryLimit: 1000Mi
+    memoryRequest: 800Mi
     useServiceAccountCredentials: true
   kubeDNS:
     cacheMaxConcurrent: 150
@@ -163,12 +167,16 @@ spec:
     image: registry.k8s.io/kube-proxy:v1.30.0
     logLevel: 2
   kubeScheduler:
+    cpuLimit: 500m
+    cpuRequest: 200m
     featureGates:
       InTreePluginAWSUnregister: "true"
     image: registry.k8s.io/kube-scheduler:v1.30.0
     leaderElection:
       leaderElect: true
     logLevel: 2
+    memoryLimit: 1000Mi
+    memoryRequest: 800Mi
   kubelet:
     anonymousAuth: false
     cgroupDriver: systemd
diff --git a/tests/integration/update_cluster/complex/data/aws_s3_object_nodeupconfig-master-us-test-1a_content b/tests/integration/update_cluster/complex/data/aws_s3_object_nodeupconfig-master-us-test-1a_content
index 398ec208d2..1d2b813b21 100644
--- a/tests/integration/update_cluster/complex/data/aws_s3_object_nodeupconfig-master-us-test-1a_content
+++ b/tests/integration/update_cluster/complex/data/aws_s3_object_nodeupconfig-master-us-test-1a_content
@@ -249,20 +249,28 @@ ControlPlaneConfig:
     concurrentHorizontalPodAustoscalerSyncs: 10
     concurrentJobSyncs: 10
     configureCloudRoutes: false
+    cpuLimit: 500m
+    cpuRequest: 200m
     featureGates:
       InTreePluginAWSUnregister: "true"
     image: registry.k8s.io/kube-controller-manager:v1.30.0
     leaderElection:
       leaderElect: true
     logLevel: 2
+    memoryLimit: 1000Mi
+    memoryRequest: 800Mi
     useServiceAccountCredentials: true
   KubeScheduler:
+    cpuLimit: 500m
+    cpuRequest: 200m
     featureGates:
       InTreePluginAWSUnregister: "true"
     image: registry.k8s.io/kube-scheduler:v1.30.0
     leaderElection:
       leaderElect: true
     logLevel: 2
+    memoryLimit: 1000Mi
+    memoryRequest: 800Mi
 DNSZone: Z1AFAKE1ZON3YO
 EtcdClusterNames:
 - main
diff --git a/tests/integration/update_cluster/complex/in-legacy-v1alpha2.yaml b/tests/integration/update_cluster/complex/in-legacy-v1alpha2.yaml
index 1f26498b86..4c74928ddc 100644
--- a/tests/integration/update_cluster/complex/in-legacy-v1alpha2.yaml
+++ b/tests/integration/update_cluster/complex/in-legacy-v1alpha2.yaml
@@ -53,6 +53,15 @@ spec:
   kubeControllerManager:
     concurrentHorizontalPodAustoscalerSyncs: 10
     concurrentJobSyncs: 10
+    cpuRequest: 200m
+    cpuLimit: 500m
+    memoryRequest: 800Mi
+    memoryLimit: 1000Mi
+  kubeScheduler:
+    cpuRequest: 200m
+    cpuLimit: 500m
+    memoryRequest: 800Mi
+    memoryLimit: 1000Mi
   kubelet:
     anonymousAuth: false
   kubernetesVersion: v1.30.0
diff --git a/tests/integration/update_cluster/complex/in-v1alpha2.yaml b/tests/integration/update_cluster/complex/in-v1alpha2.yaml
index e2d27d5a88..c0c414ea44 100644
--- a/tests/integration/update_cluster/complex/in-v1alpha2.yaml
+++ b/tests/integration/update_cluster/complex/in-v1alpha2.yaml
@@ -30,6 +30,10 @@ spec:
   kubeControllerManager:
     concurrentHorizontalPodAustoscalerSyncs: 10
     concurrentJobSyncs: 10
+    cpuRequest: 200m
+    cpuLimit: 500m
+    memoryRequest: 800Mi
+    memoryLimit: 1000Mi
   cloudProvider: aws
   cloudLabels:
     Owner: John Doe
@@ -53,6 +57,11 @@ spec:
     cpuLimit: 500m
     memoryRequest: 800Mi
     memoryLimit: 1000Mi
+  kubeScheduler:
+    cpuRequest: 200m
+    cpuLimit: 500m
+    memoryRequest: 800Mi
+    memoryLimit: 1000Mi
   kubelet:
     anonymousAuth: false
   kubernetesVersion: v1.30.0