diff --git a/api/v1beta1/aerospikebackupservice_types.go b/api/v1beta1/aerospikebackupservice_types.go index 871ba4c8..1d7d78dc 100644 --- a/api/v1beta1/aerospikebackupservice_types.go +++ b/api/v1beta1/aerospikebackupservice_types.go @@ -90,6 +90,12 @@ type AerospikeBackupServiceStatus struct { // Specify additional configuration for the AerospikeBackupService pods PodSpec ServicePodSpec `json:"podSpec,omitempty"` + // Resources define the requests and limits for the backup service container. + // Resources.Limits should be more than Resources.Requests. + // Deprecated: Resources field is now part of status.podSpec.serviceContainer + // +optional + Resources *corev1.ResourceRequirements `json:"resources,omitempty"` + // SecretMounts is the list of secret to be mounted in the backup service. SecretMounts []SecretMount `json:"secrets,omitempty"` @@ -118,6 +124,11 @@ type ServicePodSpec struct { // SchedulingPolicy controls pods placement on Kubernetes nodes. SchedulingPolicy `json:",inline"` + // ServiceAccountName is the name of the ServiceAccount to use to run the backup service pod. + // Defaults to "aerospike-backup-service" if not provided. + // +optional + ServiceAccountName string `json:"serviceAccountName,omitempty"` + // ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of // the images used by this PodSpec. ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 59aa7bd1..ad0b8fa9 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -218,6 +218,11 @@ func (in *AerospikeBackupServiceStatus) DeepCopyInto(out *AerospikeBackupService *out = *in in.Config.DeepCopyInto(&out.Config) in.PodSpec.DeepCopyInto(&out.PodSpec) + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } if in.SecretMounts != nil { in, out := &in.SecretMounts, &out.SecretMounts *out = make([]SecretMount, len(*in)) diff --git a/config/crd/bases/asdb.aerospike.com_aerospikebackupservices.yaml b/config/crd/bases/asdb.aerospike.com_aerospikebackupservices.yaml index 559ff147..1c251e28 100644 --- a/config/crd/bases/asdb.aerospike.com_aerospikebackupservices.yaml +++ b/config/crd/bases/asdb.aerospike.com_aerospikebackupservices.yaml @@ -1000,6 +1000,11 @@ spec: type: string description: NodeSelector constraints for this pod. type: object + serviceAccountName: + description: |- + ServiceAccountName is the name of the ServiceAccount to use to run the backup service pod. + Defaults to "aerospike-backup-service" if not provided. + type: string serviceContainer: description: |- ServiceContainerSpec configures the backup service container @@ -2361,6 +2366,11 @@ spec: type: string description: NodeSelector constraints for this pod. type: object + serviceAccountName: + description: |- + ServiceAccountName is the name of the ServiceAccount to use to run the backup service pod. + Defaults to "aerospike-backup-service" if not provided. + type: string serviceContainer: description: |- ServiceContainerSpec configures the backup service container @@ -2638,6 +2648,64 @@ spec: description: Port is the listening port of backup service format: int32 type: integer + resources: + description: |- + Resources define the requests and limits for the backup service container. + Resources.Limits should be more than Resources.Requests. + Deprecated: Resources field is now part of status.podSpec.serviceContainer + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object secrets: description: SecretMounts is the list of secret to be mounted in the backup service. diff --git a/helm-charts/aerospike-backup-service/templates/serviceaccount.yaml b/helm-charts/aerospike-backup-service/templates/serviceaccount.yaml deleted file mode 100644 index b62d09c3..00000000 --- a/helm-charts/aerospike-backup-service/templates/serviceaccount.yaml +++ /dev/null @@ -1,13 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: aerospike-backup-service - namespace: {{ .Release.Namespace }} - labels: - {{- include "aerospike-backup-service.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/helm-charts/aerospike-backup-service/values.yaml b/helm-charts/aerospike-backup-service/values.yaml index df74dfe7..d40e1a38 100644 --- a/helm-charts/aerospike-backup-service/values.yaml +++ b/helm-charts/aerospike-backup-service/values.yaml @@ -16,13 +16,6 @@ image: ## Custom labels that will be applied on the AerospikeBackupService resource customLabels: {} -## ServiceAccount to be used for the Aerospike Backup Service pod -serviceAccount: - # Specifies whether a service account should be created - create: true - # Annotations to add to the service account - annotations: {} - ## Config is the free form configuration for the backup service in YAML format. ## This config is used to start the backup service. The config is passed as a file to the backup service. backupServiceConfig: {} @@ -52,6 +45,7 @@ secrets: [] # mountPath: /root/.aws/credentials # subPath: credentials +# Deprecated: Resources field is now part of spec.podSpec.serviceContainer ## Resources define the requests and limits for the backup service container. ## Resources.Limits should be more than Resources.Requests. resources: {} @@ -69,6 +63,7 @@ service: {} ## Specify additional configuration for the AerospikeBackupService pods podSpec: {} +# serviceAccountName: aerospike-backup-service # metadata: # labels: # label-test-1: test1 diff --git a/helm-charts/aerospike-kubernetes-operator/crds/customresourcedefinition_aerospikebackupservices.asdb.aerospike.com.yaml b/helm-charts/aerospike-kubernetes-operator/crds/customresourcedefinition_aerospikebackupservices.asdb.aerospike.com.yaml index 559ff147..1c251e28 100644 --- a/helm-charts/aerospike-kubernetes-operator/crds/customresourcedefinition_aerospikebackupservices.asdb.aerospike.com.yaml +++ b/helm-charts/aerospike-kubernetes-operator/crds/customresourcedefinition_aerospikebackupservices.asdb.aerospike.com.yaml @@ -1000,6 +1000,11 @@ spec: type: string description: NodeSelector constraints for this pod. type: object + serviceAccountName: + description: |- + ServiceAccountName is the name of the ServiceAccount to use to run the backup service pod. + Defaults to "aerospike-backup-service" if not provided. + type: string serviceContainer: description: |- ServiceContainerSpec configures the backup service container @@ -2361,6 +2366,11 @@ spec: type: string description: NodeSelector constraints for this pod. type: object + serviceAccountName: + description: |- + ServiceAccountName is the name of the ServiceAccount to use to run the backup service pod. + Defaults to "aerospike-backup-service" if not provided. + type: string serviceContainer: description: |- ServiceContainerSpec configures the backup service container @@ -2638,6 +2648,64 @@ spec: description: Port is the listening port of backup service format: int32 type: integer + resources: + description: |- + Resources define the requests and limits for the backup service container. + Resources.Limits should be more than Resources.Requests. + Deprecated: Resources field is now part of status.podSpec.serviceContainer + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object secrets: description: SecretMounts is the list of secret to be mounted in the backup service. diff --git a/internal/controller/backup-service/reconciler.go b/internal/controller/backup-service/reconciler.go index e848716a..ef701e69 100644 --- a/internal/controller/backup-service/reconciler.go +++ b/internal/controller/backup-service/reconciler.go @@ -389,8 +389,7 @@ func (r *SingleBackupServiceReconciler) getDeploymentObject() (*app.Deployment, Labels: svcLabels, }, Spec: corev1.PodSpec{ - // TODO: Finalise on this. Who should create this SA? - ServiceAccountName: common.AerospikeBackupService, + ServiceAccountName: r.getServiceAccount(), Containers: []corev1.Container{ { Name: common.AerospikeBackupService, @@ -435,6 +434,14 @@ func (r *SingleBackupServiceReconciler) getDeploymentObject() (*app.Deployment, return deploy, nil } +func (r *SingleBackupServiceReconciler) getServiceAccount() string { + if r.aeroBackupService.Spec.PodSpec.ServiceAccountName != "" { + return r.aeroBackupService.Spec.PodSpec.ServiceAccountName + } + + return common.AerospikeBackupService +} + func (r *SingleBackupServiceReconciler) updateDeploymentFromPodSpec(deploy *app.Deployment) { r.updateDeploymentSchedulingPolicy(deploy) @@ -756,6 +763,7 @@ func (r *SingleBackupServiceReconciler) CopySpecToStatus() *asdbv1beta1.Aerospik status.Config = r.aeroBackupService.Spec.Config statusServicePodSpec := lib.DeepCopy(r.aeroBackupService.Spec.PodSpec).(asdbv1beta1.ServicePodSpec) status.PodSpec = statusServicePodSpec + status.Resources = r.aeroBackupService.Spec.Resources status.SecretMounts = r.aeroBackupService.Spec.SecretMounts status.Service = r.aeroBackupService.Spec.Service diff --git a/test/backup_service/backup_service_test.go b/test/backup_service/backup_service_test.go index 49dd15ed..68a5ab1f 100644 --- a/test/backup_service/backup_service_test.go +++ b/test/backup_service/backup_service_test.go @@ -344,7 +344,7 @@ var _ = Describe( Expect(podList.Items[0].Spec.Affinity.NodeAffinity).Should(Equal(nodeAffinity)) }) - It("Should add resources and securitycontext in the backup service container", func() { + It("Should add resources and securityContext in the backup service container", func() { backupService, err = NewBackupService() Expect(err).ToNot(HaveOccurred()) err = DeployBackupService(k8sClient, backupService) @@ -380,6 +380,43 @@ var _ = Describe( By("Remove SecurityContext") updateBackupServiceSecurityContext(k8sClient, nil) }) + + It("Should deploy backup service with custom Service Account", func() { + validateSA := func(serviceAccount string) { + podList, gErr := getBackupServicePodList(k8sClient, backupService) + Expect(gErr).ToNot(HaveOccurred()) + Expect(len(podList.Items)).To(Equal(1)) + Expect(podList.Items[0].Spec.ServiceAccountName).Should(Equal(serviceAccount)) + } + + backupService, err = NewBackupService() + Expect(err).ToNot(HaveOccurred()) + err = DeployBackupService(k8sClient, backupService) + Expect(err).ToNot(HaveOccurred()) + + validateSA(common.AerospikeBackupService) + + By("Update Service Account") + backupService, err = getBackupServiceObj(k8sClient, name, namespace) + Expect(err).ToNot(HaveOccurred()) + + backupService.Spec.PodSpec.ServiceAccountName = "default" + err = updateBackupService(k8sClient, backupService) + Expect(err).ToNot(HaveOccurred()) + + validateSA("default") + + By("Revert back to previous Service Account") + backupService, err = getBackupServiceObj(k8sClient, name, namespace) + Expect(err).ToNot(HaveOccurred()) + + backupService.Spec.PodSpec.ServiceAccountName = "" + err = updateBackupService(k8sClient, backupService) + Expect(err).ToNot(HaveOccurred()) + + validateSA(common.AerospikeBackupService) + }) + }) }, )