Skip to content

Commit 5c9c01a

Browse files
committed
Implement priority class support for Velero components
- Add --server-priority-class-name flag for Velero server deployment - Add --node-agent-priority-class-name flag for node agent daemonset - Add ServerPriorityClassName and NodeAgentPriorityClassName to VeleroOptions - Add PriorityClassName field to JobConfigs struct for maintenance jobs - Maintenance jobs get priority class from configmap (global config only) - Data mover pods get priority class from node-agent-configmap - Add tests for priority class functionality This allows different Velero components to use different priority classes based on their importance and resource requirements. Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> codespell Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
1 parent ff8a070 commit 5c9c01a

33 files changed

Lines changed: 1560 additions & 32 deletions
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Implement PriorityClass Support

pkg/cmd/cli/install/install.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package install
1818

1919
import (
20+
"context"
2021
"fmt"
2122
"os"
2223
"path/filepath"
@@ -26,6 +27,7 @@ import (
2627
"github.com/vmware-tanzu/velero/pkg/uploader"
2728

2829
"github.com/pkg/errors"
30+
"github.com/sirupsen/logrus"
2931
"github.com/spf13/cobra"
3032
"github.com/spf13/pflag"
3133
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -90,6 +92,8 @@ type Options struct {
9092
NodeAgentConfigMap string
9193
ItemBlockWorkerCount int
9294
NodeAgentDisableHostPath bool
95+
ServerPriorityClassName string
96+
NodeAgentPriorityClassName string
9397
}
9498

9599
// BindFlags adds command line values to the options struct.
@@ -191,6 +195,18 @@ func (o *Options) BindFlags(flags *pflag.FlagSet) {
191195
o.ItemBlockWorkerCount,
192196
"Number of worker threads to process ItemBlocks. Default is one. Optional.",
193197
)
198+
flags.StringVar(
199+
&o.ServerPriorityClassName,
200+
"server-priority-class-name",
201+
o.ServerPriorityClassName,
202+
"Priority class name for the Velero server deployment. Optional.",
203+
)
204+
flags.StringVar(
205+
&o.NodeAgentPriorityClassName,
206+
"node-agent-priority-class-name",
207+
o.NodeAgentPriorityClassName,
208+
"Priority class name for the node agent daemonset. Optional.",
209+
)
194210
}
195211

196212
// NewInstallOptions instantiates a new, default InstallOptions struct.
@@ -296,6 +312,8 @@ func (o *Options) AsVeleroOptions() (*install.VeleroOptions, error) {
296312
NodeAgentConfigMap: o.NodeAgentConfigMap,
297313
ItemBlockWorkerCount: o.ItemBlockWorkerCount,
298314
NodeAgentDisableHostPath: o.NodeAgentDisableHostPath,
315+
ServerPriorityClassName: o.ServerPriorityClassName,
316+
NodeAgentPriorityClassName: o.NodeAgentPriorityClassName,
299317
}, nil
300318
}
301319

@@ -384,6 +402,23 @@ func (o *Options) Run(c *cobra.Command, f client.Factory) error {
384402
if err != nil {
385403
return err
386404
}
405+
406+
// Get Kubernetes client for priority class validation
407+
kubeClient, err := f.KubeClient()
408+
if err != nil {
409+
return err
410+
}
411+
412+
// Validate priority classes if specified
413+
logger := logrus.New()
414+
logger.SetOutput(os.Stdout)
415+
if o.ServerPriorityClassName != "" {
416+
kubeutil.ValidatePriorityClass(context.Background(), kubeClient, o.ServerPriorityClassName, logger.WithField("component", "server"))
417+
}
418+
if o.NodeAgentPriorityClassName != "" {
419+
kubeutil.ValidatePriorityClass(context.Background(), kubeClient, o.NodeAgentPriorityClassName, logger.WithField("component", "node-agent"))
420+
}
421+
387422
errorMsg := fmt.Sprintf("\n\nError installing Velero. Use `kubectl logs deploy/velero -n %s` to check the deploy logs", o.Namespace)
388423

389424
err = install.Install(dynamicFactory, kbClient, resources, os.Stdout)
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
Copyright the Velero contributors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package install
18+
19+
import (
20+
"testing"
21+
22+
"github.com/spf13/pflag"
23+
"github.com/stretchr/testify/assert"
24+
"github.com/stretchr/testify/require"
25+
)
26+
27+
func TestPriorityClassNameFlag(t *testing.T) {
28+
// Test that the flag is properly defined
29+
o := NewInstallOptions()
30+
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
31+
o.BindFlags(flags)
32+
33+
// Verify the server priority class flag exists
34+
serverFlag := flags.Lookup("server-priority-class-name")
35+
assert.NotNil(t, serverFlag, "server-priority-class-name flag should exist")
36+
assert.Equal(t, "Priority class name for the Velero server deployment. Optional.", serverFlag.Usage)
37+
38+
// Verify the node agent priority class flag exists
39+
nodeAgentFlag := flags.Lookup("node-agent-priority-class-name")
40+
assert.NotNil(t, nodeAgentFlag, "node-agent-priority-class-name flag should exist")
41+
assert.Equal(t, "Priority class name for the node agent daemonset. Optional.", nodeAgentFlag.Usage)
42+
43+
// Test with values for both server and node agent
44+
testCases := []struct {
45+
name string
46+
serverPriorityClassName string
47+
nodeAgentPriorityClassName string
48+
expectedServerValue string
49+
expectedNodeAgentValue string
50+
}{
51+
{
52+
name: "with both priority class names",
53+
serverPriorityClassName: "high-priority",
54+
nodeAgentPriorityClassName: "medium-priority",
55+
expectedServerValue: "high-priority",
56+
expectedNodeAgentValue: "medium-priority",
57+
},
58+
{
59+
name: "with only server priority class name",
60+
serverPriorityClassName: "high-priority",
61+
nodeAgentPriorityClassName: "",
62+
expectedServerValue: "high-priority",
63+
expectedNodeAgentValue: "",
64+
},
65+
{
66+
name: "with only node agent priority class name",
67+
serverPriorityClassName: "",
68+
nodeAgentPriorityClassName: "medium-priority",
69+
expectedServerValue: "",
70+
expectedNodeAgentValue: "medium-priority",
71+
},
72+
{
73+
name: "without priority class names",
74+
serverPriorityClassName: "",
75+
nodeAgentPriorityClassName: "",
76+
expectedServerValue: "",
77+
expectedNodeAgentValue: "",
78+
},
79+
}
80+
81+
for _, tc := range testCases {
82+
t.Run(tc.name, func(t *testing.T) {
83+
o := NewInstallOptions()
84+
o.ServerPriorityClassName = tc.serverPriorityClassName
85+
o.NodeAgentPriorityClassName = tc.nodeAgentPriorityClassName
86+
87+
veleroOptions, err := o.AsVeleroOptions()
88+
require.NoError(t, err)
89+
assert.Equal(t, tc.expectedServerValue, veleroOptions.ServerPriorityClassName)
90+
assert.Equal(t, tc.expectedNodeAgentValue, veleroOptions.NodeAgentPriorityClassName)
91+
})
92+
}
93+
}

pkg/cmd/cli/nodeagent/server.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ func (s *nodeAgentServer) run() {
340340
s.config.dataMoverPrepareTimeout,
341341
s.logger,
342342
s.metrics,
343+
s.config.nodeAgentConfig,
343344
)
344345
if err := dataUploadReconciler.SetupWithManager(s.mgr); err != nil {
345346
s.logger.WithError(err).Fatal("Unable to create the data upload controller")
@@ -364,6 +365,7 @@ func (s *nodeAgentServer) run() {
364365
s.config.dataMoverPrepareTimeout,
365366
s.logger,
366367
s.metrics,
368+
s.config.nodeAgentConfig,
367369
)
368370

369371
if err := dataDownloadReconciler.SetupWithManager(s.mgr); err != nil {

pkg/controller/data_download_controller.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ type DataDownloadReconciler struct {
7171
preparingTimeout time.Duration
7272
metrics *metrics.ServerMetrics
7373
cancelledDataDownload map[string]time.Time
74+
nodeAgentConfigMap string
7475
}
7576

7677
func NewDataDownloadReconciler(
@@ -86,6 +87,7 @@ func NewDataDownloadReconciler(
8687
preparingTimeout time.Duration,
8788
logger logrus.FieldLogger,
8889
metrics *metrics.ServerMetrics,
90+
nodeAgentConfigMap string,
8991
) *DataDownloadReconciler {
9092
return &DataDownloadReconciler{
9193
client: client,
@@ -103,6 +105,7 @@ func NewDataDownloadReconciler(
103105
preparingTimeout: preparingTimeout,
104106
metrics: metrics,
105107
cancelledDataDownload: make(map[string]time.Time),
108+
nodeAgentConfigMap: nodeAgentConfigMap,
106109
}
107110
}
108111

@@ -892,6 +895,8 @@ func (r *DataDownloadReconciler) setupExposeParam(dd *velerov2alpha1api.DataDown
892895
NodeOS: nodeOS,
893896
RestorePVCConfig: r.restorePVCConfig,
894897
LoadAffinity: affinity,
898+
NodeAgentNamespace: dd.Namespace,
899+
NodeAgentConfigMap: r.nodeAgentConfigMap,
895900
}, nil
896901
}
897902

pkg/controller/data_download_controller_test.go

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -130,19 +130,7 @@ func initDataDownloadReconcilerWithError(t *testing.T, objects []any, needError
130130

131131
dataPathMgr := datapath.NewManager(1)
132132

133-
return NewDataDownloadReconciler(
134-
&fakeClient,
135-
nil,
136-
fakeKubeClient,
137-
dataPathMgr,
138-
nil,
139-
nil,
140-
nodeagent.RestorePVC{},
141-
corev1api.ResourceRequirements{},
142-
"test-node",
143-
time.Minute*5,
144-
velerotest.NewLogger(),
145-
metrics.NewServerMetrics()), nil
133+
return NewDataDownloadReconciler(&fakeClient, nil, fakeKubeClient, dataPathMgr, nil, nil, nodeagent.RestorePVC{}, corev1api.ResourceRequirements{}, "test-node", time.Minute*5, velerotest.NewLogger(), metrics.NewServerMetrics(), ""), nil
146134
}
147135

148136
func TestDataDownloadReconcile(t *testing.T) {

pkg/controller/data_upload_controller.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ type DataUploadReconciler struct {
8181
preparingTimeout time.Duration
8282
metrics *metrics.ServerMetrics
8383
cancelledDataUpload map[string]time.Time
84+
nodeAgentConfigMap string
8485
}
8586

8687
func NewDataUploadReconciler(
@@ -98,6 +99,7 @@ func NewDataUploadReconciler(
9899
preparingTimeout time.Duration,
99100
log logrus.FieldLogger,
100101
metrics *metrics.ServerMetrics,
102+
nodeAgentConfigMap string,
101103
) *DataUploadReconciler {
102104
return &DataUploadReconciler{
103105
client: client,
@@ -122,6 +124,7 @@ func NewDataUploadReconciler(
122124
preparingTimeout: preparingTimeout,
123125
metrics: metrics,
124126
cancelledDataUpload: make(map[string]time.Time),
127+
nodeAgentConfigMap: nodeAgentConfigMap,
125128
}
126129
}
127130

@@ -973,6 +976,8 @@ func (r *DataUploadReconciler) setupExposeParam(du *velerov2alpha1api.DataUpload
973976
BackupPVCConfig: r.backupPVCConfig,
974977
Resources: r.podResources,
975978
NodeOS: nodeOS,
979+
NodeAgentNamespace: du.Namespace,
980+
NodeAgentConfigMap: r.nodeAgentConfigMap,
976981
}, nil
977982
}
978983

pkg/controller/data_upload_controller_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ func initDataUploaderReconcilerWithError(needError ...error) (*DataUploadReconci
249249
time.Minute*5,
250250
velerotest.NewLogger(),
251251
metrics.NewServerMetrics(),
252+
"",
252253
), nil
253254
}
254255

pkg/exposer/csi_snapshot.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ type CSISnapshotExposeParam struct {
8282

8383
// NodeOS specifies the OS of node that the source volume is attaching
8484
NodeOS string
85+
86+
// NodeAgentNamespace is the namespace where the node agent is running
87+
NodeAgentNamespace string
88+
89+
// NodeAgentConfigMap is the name of the ConfigMap containing node agent configurations
90+
NodeAgentConfigMap string
8591
}
8692

8793
// CSISnapshotExposeWaitParam define the input param for WaitExposed of CSI snapshots
@@ -224,6 +230,8 @@ func (e *csiSnapshotExposer) Expose(ctx context.Context, ownerObject corev1api.O
224230
backupPVCReadOnly,
225231
spcNoRelabeling,
226232
csiExposeParam.NodeOS,
233+
csiExposeParam.NodeAgentNamespace,
234+
csiExposeParam.NodeAgentConfigMap,
227235
)
228236
if err != nil {
229237
return errors.Wrap(err, "error to create backup pod")
@@ -538,6 +546,8 @@ func (e *csiSnapshotExposer) createBackupPod(
538546
backupPVCReadOnly bool,
539547
spcNoRelabeling bool,
540548
nodeOS string,
549+
nodeAgentNamespace string,
550+
nodeAgentConfigMap string,
541551
) (*corev1api.Pod, error) {
542552
podName := ownerObject.Name
543553

@@ -549,6 +559,16 @@ func (e *csiSnapshotExposer) createBackupPod(
549559
return nil, errors.Wrap(err, "error to get inherited pod info from node-agent")
550560
}
551561

562+
// Get the priority class name from node-agent-configmap if available
563+
priorityClassName, err := kube.GetDataMoverPriorityClassName(ctx, nodeAgentNamespace, e.kubeClient, nodeAgentConfigMap)
564+
if err != nil {
565+
e.log.WithError(err).Warn("Failed to get priority class name from node-agent-configmap, using empty value")
566+
priorityClassName = ""
567+
}
568+
if priorityClassName != "" {
569+
e.log.Debugf("Setting priority class %q for data mover pod %s", priorityClassName, podName)
570+
}
571+
552572
var gracePeriod int64
553573
volumeMounts, volumeDevices, volumePath := kube.MakePodPVCAttachment(volumeName, backupPVC.Spec.VolumeMode, backupPVCReadOnly)
554574
volumeMounts = append(volumeMounts, podInfo.volumeMounts...)
@@ -679,6 +699,7 @@ func (e *csiSnapshotExposer) createBackupPod(
679699
Resources: resources,
680700
},
681701
},
702+
PriorityClassName: priorityClassName,
682703
ServiceAccountName: podInfo.serviceAccount,
683704
TerminationGracePeriodSeconds: &gracePeriod,
684705
Volumes: volumes,

0 commit comments

Comments
 (0)