Skip to content

Commit 4bb3471

Browse files
leonardoceMichaluxPLmnenciafcanovai
authored
feat(sidecar): add resource requirements and limits (#307)
Closes #253 Signed-off-by: MichaluxPL <[email protected]> Signed-off-by: Leonardo Cecchi <[email protected]> Signed-off-by: Marco Nenciarini <[email protected]> Signed-off-by: Francesco Canovai <[email protected]> Co-authored-by: MichaluxPL <[email protected]> Co-authored-by: Marco Nenciarini <[email protected]> Co-authored-by: Francesco Canovai <[email protected]>
1 parent c24d7ae commit 4bb3471

File tree

12 files changed

+312
-33
lines changed

12 files changed

+312
-33
lines changed

.wordlist.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ README
3333
RPO
3434
RTO
3535
RecoveryWindow
36+
ResourceRequirements
3637
RetentionPolicy
3738
SAS
3839
SFO
@@ -64,6 +65,7 @@ cmctl
6465
cnpg
6566
codebase
6667
containerPort
68+
cpu
6769
creds
6870
csi
6971
customresourcedefinition
@@ -102,6 +104,7 @@ repos
102104
retentionCheckInterval
103105
retentionPolicy
104106
rolebinding
107+
rollout
105108
sc
106109
secretKeyRef
107110
selfsigned

api/v1/objectstore_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ type InstanceSidecarConfiguration struct {
3333
// +kubebuilder:default:=1800
3434
// +optional
3535
RetentionPolicyIntervalSeconds int `json:"retentionPolicyIntervalSeconds,omitempty"`
36+
37+
// Resources define cpu/memory requests and limits for the sidecar that runs in the instance pods.
38+
// +optional
39+
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
3640
}
3741

3842
// ObjectStoreSpec defines the desired state of ObjectStore.

api/v1/zz_generated.deepcopy.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/barmancloud.cnpg.io_objectstores.yaml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,66 @@ spec:
511511
- name
512512
type: object
513513
type: array
514+
resources:
515+
description: Resources define cpu/memory requests and limits for
516+
the sidecar that runs in the instance pods.
517+
properties:
518+
claims:
519+
description: |-
520+
Claims lists the names of resources, defined in spec.resourceClaims,
521+
that are used by this container.
522+
523+
This is an alpha field and requires enabling the
524+
DynamicResourceAllocation feature gate.
525+
526+
This field is immutable. It can only be set for containers.
527+
items:
528+
description: ResourceClaim references one entry in PodSpec.ResourceClaims.
529+
properties:
530+
name:
531+
description: |-
532+
Name must match the name of one entry in pod.spec.resourceClaims of
533+
the Pod where this field is used. It makes that resource available
534+
inside a container.
535+
type: string
536+
request:
537+
description: |-
538+
Request is the name chosen for a request in the referenced claim.
539+
If empty, everything from the claim is made available, otherwise
540+
only the result of this request.
541+
type: string
542+
required:
543+
- name
544+
type: object
545+
type: array
546+
x-kubernetes-list-map-keys:
547+
- name
548+
x-kubernetes-list-type: map
549+
limits:
550+
additionalProperties:
551+
anyOf:
552+
- type: integer
553+
- type: string
554+
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
555+
x-kubernetes-int-or-string: true
556+
description: |-
557+
Limits describes the maximum amount of compute resources allowed.
558+
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
559+
type: object
560+
requests:
561+
additionalProperties:
562+
anyOf:
563+
- type: integer
564+
- type: string
565+
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
566+
x-kubernetes-int-or-string: true
567+
description: |-
568+
Requests describes the minimum amount of compute resources required.
569+
If Requests is omitted for a container, it defaults to Limits if that is explicitly specified,
570+
otherwise to an implementation-defined value. Requests cannot exceed Limits.
571+
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
572+
type: object
573+
type: object
514574
retentionPolicyIntervalSeconds:
515575
default: 1800
516576
description: |-

hack/examples/minio-store.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@ metadata:
55
spec:
66
retentionPolicy: "1m"
77
instanceSidecarConfiguration:
8-
retentionPolicyIntervalSeconds: 30
8+
retentionPolicyIntervalSeconds: 1800
9+
resources:
10+
requests:
11+
memory: "64Mi"
12+
cpu: "250m"
13+
limits:
14+
memory: "512Mi"
15+
cpu: "500m"
916
configuration:
1017
endpointCA:
1118
name: minio-server-tls
@@ -27,4 +34,3 @@ spec:
2734
- "--min-chunk-size=5MB"
2835
- "--read-timeout=60"
2936
- "-vv"
30-

internal/cnpgi/operator/lifecycle.go

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -123,15 +123,29 @@ func (impl LifecycleImplementation) reconcileJob(
123123
return nil, err
124124
}
125125

126-
return reconcileJob(ctx, cluster, request, env, certificates)
126+
resources, err := impl.collectSidecarResourcesForRecoveryJob(ctx, pluginConfiguration)
127+
if err != nil {
128+
return nil, err
129+
}
130+
131+
return reconcileJob(ctx, cluster, request, sidecarConfiguration{
132+
env: env,
133+
certificates: certificates,
134+
resources: resources,
135+
})
136+
}
137+
138+
type sidecarConfiguration struct {
139+
env []corev1.EnvVar
140+
certificates []corev1.VolumeProjection
141+
resources corev1.ResourceRequirements
127142
}
128143

129144
func reconcileJob(
130145
ctx context.Context,
131146
cluster *cnpgv1.Cluster,
132147
request *lifecycle.OperatorLifecycleRequest,
133-
env []corev1.EnvVar,
134-
certificates []corev1.VolumeProjection,
148+
config sidecarConfiguration,
135149
) (*lifecycle.OperatorLifecycleResponse, error) {
136150
contextLogger := log.FromContext(ctx).WithName("lifecycle")
137151
if pluginConfig := cluster.GetRecoverySourcePlugin(); pluginConfig == nil || pluginConfig.Name != metadata.PluginName {
@@ -169,8 +183,7 @@ func reconcileJob(
169183
corev1.Container{
170184
Args: []string{"restore"},
171185
},
172-
env,
173-
certificates,
186+
config,
174187
); err != nil {
175188
return nil, fmt.Errorf("while reconciling pod spec for job: %w", err)
176189
}
@@ -202,16 +215,24 @@ func (impl LifecycleImplementation) reconcilePod(
202215
return nil, err
203216
}
204217

205-
return reconcilePod(ctx, cluster, request, pluginConfiguration, env, certificates)
218+
resources, err := impl.collectSidecarResourcesForPod(ctx, pluginConfiguration)
219+
if err != nil {
220+
return nil, err
221+
}
222+
223+
return reconcilePod(ctx, cluster, request, pluginConfiguration, sidecarConfiguration{
224+
env: env,
225+
certificates: certificates,
226+
resources: resources,
227+
})
206228
}
207229

208230
func reconcilePod(
209231
ctx context.Context,
210232
cluster *cnpgv1.Cluster,
211233
request *lifecycle.OperatorLifecycleRequest,
212234
pluginConfiguration *config.PluginConfiguration,
213-
env []corev1.EnvVar,
214-
certificates []corev1.VolumeProjection,
235+
config sidecarConfiguration,
215236
) (*lifecycle.OperatorLifecycleResponse, error) {
216237
pod, err := decoder.DecodePodJSON(request.GetObjectDefinition())
217238
if err != nil {
@@ -232,8 +253,7 @@ func reconcilePod(
232253
corev1.Container{
233254
Args: []string{"instance"},
234255
},
235-
env,
236-
certificates,
256+
config,
237257
); err != nil {
238258
return nil, fmt.Errorf("while reconciling pod spec for pod: %w", err)
239259
}
@@ -256,9 +276,8 @@ func reconcilePodSpec(
256276
cluster *cnpgv1.Cluster,
257277
spec *corev1.PodSpec,
258278
mainContainerName string,
259-
sidecarConfig corev1.Container,
260-
additionalEnvs []corev1.EnvVar,
261-
certificates []corev1.VolumeProjection,
279+
sidecarTemplate corev1.Container,
280+
config sidecarConfiguration,
262281
) error {
263282
envs := []corev1.EnvVar{
264283
{
@@ -285,7 +304,7 @@ func reconcilePodSpec(
285304
},
286305
}
287306

288-
envs = append(envs, additionalEnvs...)
307+
envs = append(envs, config.env...)
289308

290309
baseProbe := &corev1.Probe{
291310
FailureThreshold: 10,
@@ -298,11 +317,11 @@ func reconcilePodSpec(
298317
}
299318

300319
// fixed values
301-
sidecarConfig.Name = "plugin-barman-cloud"
302-
sidecarConfig.Image = viper.GetString("sidecar-image")
303-
sidecarConfig.ImagePullPolicy = cluster.Spec.ImagePullPolicy
304-
sidecarConfig.StartupProbe = baseProbe.DeepCopy()
305-
sidecarConfig.SecurityContext = &corev1.SecurityContext{
320+
sidecarTemplate.Name = "plugin-barman-cloud"
321+
sidecarTemplate.Image = viper.GetString("sidecar-image")
322+
sidecarTemplate.ImagePullPolicy = cluster.Spec.ImagePullPolicy
323+
sidecarTemplate.StartupProbe = baseProbe.DeepCopy()
324+
sidecarTemplate.SecurityContext = &corev1.SecurityContext{
306325
AllowPrivilegeEscalation: ptr.To(false),
307326
RunAsNonRoot: ptr.To(true),
308327
Privileged: ptr.To(false),
@@ -314,20 +333,21 @@ func reconcilePodSpec(
314333
Drop: []corev1.Capability{"ALL"},
315334
},
316335
}
336+
sidecarTemplate.Resources = config.resources
317337

318338
// merge the main container envs if they aren't already set
319339
for _, container := range spec.Containers {
320340
if container.Name == mainContainerName {
321341
for _, env := range container.Env {
322342
found := false
323-
for _, existingEnv := range sidecarConfig.Env {
343+
for _, existingEnv := range sidecarTemplate.Env {
324344
if existingEnv.Name == env.Name {
325345
found = true
326346
break
327347
}
328348
}
329349
if !found {
330-
sidecarConfig.Env = append(sidecarConfig.Env, env)
350+
sidecarTemplate.Env = append(sidecarTemplate.Env, env)
331351
}
332352
}
333353
break
@@ -337,18 +357,18 @@ func reconcilePodSpec(
337357
// merge the default envs if they aren't already set
338358
for _, env := range envs {
339359
found := false
340-
for _, existingEnv := range sidecarConfig.Env {
360+
for _, existingEnv := range sidecarTemplate.Env {
341361
if existingEnv.Name == env.Name {
342362
found = true
343363
break
344364
}
345365
}
346366
if !found {
347-
sidecarConfig.Env = append(sidecarConfig.Env, env)
367+
sidecarTemplate.Env = append(sidecarTemplate.Env, env)
348368
}
349369
}
350370

351-
if err := injectPluginSidecarPodSpec(spec, &sidecarConfig, mainContainerName); err != nil {
371+
if err := injectPluginSidecarPodSpec(spec, &sidecarTemplate, mainContainerName); err != nil {
352372
return err
353373
}
354374

@@ -358,7 +378,7 @@ func reconcilePodSpec(
358378
Name: barmanCertificatesVolumeName,
359379
VolumeSource: corev1.VolumeSource{
360380
Projected: &corev1.ProjectedVolumeSource{
361-
Sources: certificates,
381+
Sources: config.certificates,
362382
},
363383
},
364384
})

internal/cnpgi/operator/lifecycle_envs.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ func (impl LifecycleImplementation) collectAdditionalEnvs(
1717
) ([]corev1.EnvVar, error) {
1818
var result []corev1.EnvVar
1919

20+
// TODO: check if the environment variables are clashing and in
21+
// that case raise an error
22+
2023
if len(pluginConfiguration.BarmanObjectName) > 0 {
2124
envs, err := impl.collectObjectStoreEnvs(
2225
ctx,
@@ -45,6 +48,20 @@ func (impl LifecycleImplementation) collectAdditionalEnvs(
4548
result = append(result, envs...)
4649
}
4750

51+
if len(pluginConfiguration.ReplicaSourceBarmanObjectName) > 0 {
52+
envs, err := impl.collectObjectStoreEnvs(
53+
ctx,
54+
types.NamespacedName{
55+
Name: pluginConfiguration.ReplicaSourceBarmanObjectName,
56+
Namespace: namespace,
57+
},
58+
)
59+
if err != nil {
60+
return nil, err
61+
}
62+
result = append(result, envs...)
63+
}
64+
4865
return result, nil
4966
}
5067

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package operator
2+
3+
import (
4+
"context"
5+
6+
corev1 "k8s.io/api/core/v1"
7+
8+
barmancloudv1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1"
9+
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
10+
)
11+
12+
func (impl LifecycleImplementation) collectSidecarResourcesForRecoveryJob(
13+
ctx context.Context,
14+
configuration *config.PluginConfiguration,
15+
) (corev1.ResourceRequirements, error) {
16+
if len(configuration.RecoveryBarmanObjectName) > 0 {
17+
var barmanObjectStore barmancloudv1.ObjectStore
18+
if err := impl.Client.Get(ctx, configuration.GetRecoveryBarmanObjectKey(), &barmanObjectStore); err != nil {
19+
return corev1.ResourceRequirements{}, err
20+
}
21+
22+
return barmanObjectStore.Spec.InstanceSidecarConfiguration.Resources, nil
23+
}
24+
25+
return corev1.ResourceRequirements{}, nil
26+
}
27+
28+
func (impl LifecycleImplementation) collectSidecarResourcesForPod(
29+
ctx context.Context,
30+
configuration *config.PluginConfiguration,
31+
) (corev1.ResourceRequirements, error) {
32+
if len(configuration.BarmanObjectName) > 0 {
33+
// On a replica cluster that also archives, the designated primary
34+
// will use both the replica source object store and the object store
35+
// of the cluster.
36+
// In this case, we use the cluster object store for configuring
37+
// the resources of the sidecar container.
38+
39+
var barmanObjectStore barmancloudv1.ObjectStore
40+
if err := impl.Client.Get(ctx, configuration.GetBarmanObjectKey(), &barmanObjectStore); err != nil {
41+
return corev1.ResourceRequirements{}, err
42+
}
43+
44+
return barmanObjectStore.Spec.InstanceSidecarConfiguration.Resources, nil
45+
}
46+
47+
if len(configuration.RecoveryBarmanObjectName) > 0 {
48+
// On a replica cluster that doesn't archive, the designated primary
49+
// uses only the replica source object store.
50+
// In this case, we use the replica source object store for configuring
51+
// the resources of the sidecar container.
52+
var barmanObjectStore barmancloudv1.ObjectStore
53+
if err := impl.Client.Get(ctx, configuration.GetRecoveryBarmanObjectKey(), &barmanObjectStore); err != nil {
54+
return corev1.ResourceRequirements{}, err
55+
}
56+
57+
return barmanObjectStore.Spec.InstanceSidecarConfiguration.Resources, nil
58+
}
59+
60+
return corev1.ResourceRequirements{}, nil
61+
}

0 commit comments

Comments
 (0)