Skip to content

Commit c54c0fa

Browse files
committed
feat(vpa): thread prediction store through disruption path
1 parent 2266468 commit c54c0fa

18 files changed

Lines changed: 1017 additions & 26 deletions

File tree

kwok/charts/templates/clusterrole.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ rules:
4444
- apiGroups: ["apps"]
4545
resources: ["daemonsets", "deployments", "replicasets", "statefulsets"]
4646
verbs: ["get", "list", "watch"]
47+
- apiGroups: ["batch"]
48+
resources: ["jobs"]
49+
verbs: ["get", "list", "watch"]
4750
- apiGroups: ["autoscaling.k8s.io"]
4851
resources: ["verticalpodautoscalers"]
4952
verbs: ["get", "list", "watch"]

pkg/controllers/controllers.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,16 @@ import (
7373
)
7474

7575
type ControllerOptions struct {
76-
registrationHooks []cloudprovider.NodeLifecycleHook
77-
disableVPAPrediction bool
76+
registrationHooks []cloudprovider.NodeLifecycleHook
77+
enableVPAPrediction bool
7878
}
7979

80-
// WithoutVPAPrediction disables the VPA prediction controller. Use this when
81-
// a different prediction source is registered separately.
82-
func WithoutVPAPrediction() option.Function[ControllerOptions] {
80+
// WithVPAPrediction enables the VPA prediction controller as the prediction source.
81+
// When enabled alongside the PredictionEnabled feature gate, Karpenter uses VPA
82+
// recommendations to size nodes during provisioning and disruption.
83+
func WithVPAPrediction() option.Function[ControllerOptions] {
8384
return func(o *ControllerOptions) {
84-
o.disableVPAPrediction = true
85+
o.enableVPAPrediction = true
8586
}
8687
}
8788

@@ -111,7 +112,7 @@ func NewControllers(
111112
o := option.Resolve(opts...)
112113
deviceAllocationController := deviceallocation.NewController(kubeClient)
113114
virtualPodCache := virtualpods.NewVirtualPodCache(kubeClient)
114-
p := provisioning.NewProvisioner(kubeClient, recorder, cloudProvider, cluster, clock, deviceAllocationController, virtualPodCache)
115+
p := provisioning.NewProvisioner(kubeClient, recorder, cloudProvider, cluster, clock, deviceAllocationController, virtualPodCache, predictionStore)
115116
evictionQueue := terminator.NewQueue(clock, kubeClient, recorder)
116117
disruptionQueue := disruption.NewQueue(kubeClient, recorder, cluster, clock, p)
117118
npState := nodepoolhealth.NewState()
@@ -206,7 +207,7 @@ func NewControllers(
206207
}
207208
}
208209

209-
if !o.disableVPAPrediction {
210+
if o.enableVPAPrediction && options.FromContext(ctx).FeatureGates.PredictionEnabled {
210211
controllers = append(controllers, informer.NewVPAController(kubeClient, mgr.GetAPIReader(), predictionStore))
211212
}
212213

pkg/controllers/disruption/controller.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import (
4848
"sigs.k8s.io/karpenter/pkg/events"
4949
"sigs.k8s.io/karpenter/pkg/metrics"
5050
"sigs.k8s.io/karpenter/pkg/operator/injection"
51+
"sigs.k8s.io/karpenter/pkg/operator/options"
5152
"sigs.k8s.io/karpenter/pkg/state/cost"
5253
nodepoolutils "sigs.k8s.io/karpenter/pkg/utils/nodepool"
5354
"sigs.k8s.io/karpenter/pkg/utils/pretty"
@@ -125,6 +126,7 @@ func (c *Controller) Register(_ context.Context, m manager.Manager) error {
125126
Complete(singleton.AsReconciler(c))
126127
}
127128

129+
//nolint:gocyclo
128130
func (c *Controller) Reconcile(ctx context.Context) (reconciler.Result, error) {
129131
ctx = injection.WithControllerName(ctx, c.Name())
130132

@@ -143,6 +145,9 @@ func (c *Controller) Reconcile(ctx context.Context) (reconciler.Result, error) {
143145
if !c.cluster.Synced(ctx) {
144146
return reconciler.Result{RequeueAfter: time.Second}, nil
145147
}
148+
if options.FromContext(ctx).FeatureGates.PredictionEnabled && !c.provisioner.PredictionStoreHydrated(ctx) {
149+
return reconciler.Result{RequeueAfter: time.Second}, nil
150+
}
146151

147152
// Karpenter taints nodes with a karpenter.sh/disruption taint as part of the disruption process while it progresses in memory.
148153
// If Karpenter restarts or fails with an error during a disruption action, some nodes can be left tainted.

0 commit comments

Comments
 (0)