diff --git a/api/v1beta2/job_types.go b/api/v1beta2/job_types.go index d947a327c..667e04d96 100644 --- a/api/v1beta2/job_types.go +++ b/api/v1beta2/job_types.go @@ -30,6 +30,17 @@ type JobConfig struct { // +optional Threads int `json:"threads,omitempty"` + // CPU is the amount of CPU requested for the Pod. + // +kubebuilder:default="4" + // +nullable + // +optional + CPU *resource.Quantity `json:"cpu,omitempty"` + + // MaxCPU is the amount of maximum CPU for the Pod. + // +nullable + // +optional + MaxCPU *resource.Quantity `json:"maxCpu,omitempty"` + // Memory is the amount of memory requested for the Pod. // +kubebuilder:default="4Gi" // +nullable diff --git a/charts/moco/templates/generated/crds/moco_crds.yaml b/charts/moco/templates/generated/crds/moco_crds.yaml index 72eb87c2e..ec211481c 100644 --- a/charts/moco/templates/generated/crds/moco_crds.yaml +++ b/charts/moco/templates/generated/crds/moco_crds.yaml @@ -2447,6 +2447,15 @@ spec: required: - bucketName type: object + cpu: + anyOf: + - type: integer + - type: string + default: "4" + description: CPU is the amount of CPU requested for the Pod. + nullable: true + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true env: description: List of environment variables to set in the contai items: @@ -2529,6 +2538,14 @@ spec: type: object type: object type: array + maxCpu: + anyOf: + - type: integer + - type: string + description: MaxCPU is the amount of maximum CPU for the Pod. + nullable: true + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true maxMemory: anyOf: - type: integer @@ -13566,6 +13583,15 @@ spec: required: - bucketName type: object + cpu: + anyOf: + - type: integer + - type: string + default: "4" + description: CPU is the amount of CPU requested for the Pod. + nullable: true + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true env: description: List of environment variables to set in the contai items: @@ -13648,6 +13674,14 @@ spec: type: object type: object type: array + maxCpu: + anyOf: + - type: integer + - type: string + description: MaxCPU is the amount of maximum CPU for the Pod. + nullable: true + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true maxMemory: anyOf: - type: integer diff --git a/config/crd/bases/moco.cybozu.com_backuppolicies.yaml b/config/crd/bases/moco.cybozu.com_backuppolicies.yaml index b1e71e593..b4f27164f 100644 --- a/config/crd/bases/moco.cybozu.com_backuppolicies.yaml +++ b/config/crd/bases/moco.cybozu.com_backuppolicies.yaml @@ -2644,6 +2644,15 @@ spec: required: - bucketName type: object + cpu: + anyOf: + - type: integer + - type: string + default: "4" + description: CPU is the amount of CPU requested for the Pod. + nullable: true + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true env: description: List of environment variables to set in the contai items: @@ -2734,6 +2743,14 @@ spec: type: object type: object type: array + maxCpu: + anyOf: + - type: integer + - type: string + description: MaxCPU is the amount of maximum CPU for the Pod. + nullable: true + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true maxMemory: anyOf: - type: integer diff --git a/config/crd/bases/moco.cybozu.com_mysqlclusters.yaml b/config/crd/bases/moco.cybozu.com_mysqlclusters.yaml index ab0859112..051356fb4 100644 --- a/config/crd/bases/moco.cybozu.com_mysqlclusters.yaml +++ b/config/crd/bases/moco.cybozu.com_mysqlclusters.yaml @@ -10425,6 +10425,15 @@ spec: required: - bucketName type: object + cpu: + anyOf: + - type: integer + - type: string + default: "4" + description: CPU is the amount of CPU requested for the Pod. + nullable: true + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true env: description: List of environment variables to set in the contai items: @@ -10516,6 +10525,14 @@ spec: type: object type: object type: array + maxCpu: + anyOf: + - type: integer + - type: string + description: MaxCPU is the amount of maximum CPU for the Pod. + nullable: true + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true maxMemory: anyOf: - type: integer diff --git a/config/crd/tests/apiextensions.k8s.io_v1_customresourcedefinition_backuppolicies.moco.cybozu.com.yaml b/config/crd/tests/apiextensions.k8s.io_v1_customresourcedefinition_backuppolicies.moco.cybozu.com.yaml index a861ea025..4cd85ddef 100644 --- a/config/crd/tests/apiextensions.k8s.io_v1_customresourcedefinition_backuppolicies.moco.cybozu.com.yaml +++ b/config/crd/tests/apiextensions.k8s.io_v1_customresourcedefinition_backuppolicies.moco.cybozu.com.yaml @@ -2643,6 +2643,15 @@ spec: required: - bucketName type: object + cpu: + anyOf: + - type: integer + - type: string + default: "4" + description: CPU is the amount of CPU requested for the Pod. + nullable: true + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true env: description: List of environment variables to set in the contai items: @@ -2733,6 +2742,14 @@ spec: type: object type: object type: array + maxCpu: + anyOf: + - type: integer + - type: string + description: MaxCPU is the amount of maximum CPU for the Pod. + nullable: true + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true maxMemory: anyOf: - type: integer diff --git a/config/crd/tests/apiextensions.k8s.io_v1_customresourcedefinition_mysqlclusters.moco.cybozu.com.yaml b/config/crd/tests/apiextensions.k8s.io_v1_customresourcedefinition_mysqlclusters.moco.cybozu.com.yaml index c6d62c033..0bb2fd445 100644 --- a/config/crd/tests/apiextensions.k8s.io_v1_customresourcedefinition_mysqlclusters.moco.cybozu.com.yaml +++ b/config/crd/tests/apiextensions.k8s.io_v1_customresourcedefinition_mysqlclusters.moco.cybozu.com.yaml @@ -10435,6 +10435,15 @@ spec: required: - bucketName type: object + cpu: + anyOf: + - type: integer + - type: string + default: "4" + description: CPU is the amount of CPU requested for the Pod. + nullable: true + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true env: description: List of environment variables to set in the contai items: @@ -10526,6 +10535,14 @@ spec: type: object type: object type: array + maxCpu: + anyOf: + - type: integer + - type: string + description: MaxCPU is the amount of maximum CPU for the Pod. + nullable: true + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true maxMemory: anyOf: - type: integer diff --git a/controllers/mysqlcluster_controller.go b/controllers/mysqlcluster_controller.go index 62eb1089b..62dc419d1 100644 --- a/controllers/mysqlcluster_controller.go +++ b/controllers/mysqlcluster_controller.go @@ -26,7 +26,6 @@ import ( "k8s.io/apimachinery/pkg/api/equality" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -1168,25 +1167,27 @@ func (r *MySQLClusterReconciler) reconcileV1BackupJob(ctx context.Context, req c args = append(args, cluster.Namespace, cluster.Name) resources := corev1ac.ResourceRequirements() - if jc.Memory != nil { - resources.WithRequests(corev1.ResourceList{ - corev1.ResourceCPU: *resource.NewQuantity(int64(jc.Threads), resource.DecimalSI), - corev1.ResourceMemory: *jc.Memory, - }) - } else { - resources.WithRequests( - corev1.ResourceList{ - corev1.ResourceCPU: *resource.NewQuantity(int64(jc.Threads), resource.DecimalSI), - }, - ) - } - if jc.MaxMemory != nil { - resources.WithLimits(corev1.ResourceList{ - corev1.ResourceMemory: *jc.MaxMemory, - }) - } - if noJobResource { - resources = corev1ac.ResourceRequirements() + if !noJobResource { + request := corev1.ResourceList{} + if jc.CPU != nil { + request[corev1.ResourceCPU] = *jc.CPU + } + if jc.Memory != nil { + request[corev1.ResourceMemory] = *jc.Memory + } + if len(request) > 0 { + resources.WithRequests(request) + } + limit := corev1.ResourceList{} + if jc.MaxCPU != nil { + limit[corev1.ResourceCPU] = *jc.MaxCPU + } + if jc.MaxMemory != nil { + limit[corev1.ResourceMemory] = *jc.MaxMemory + } + if len(limit) > 0 { + resources.WithLimits(limit) + } } container := corev1ac.Container(). @@ -1546,13 +1547,13 @@ func (r *MySQLClusterReconciler) reconcileV1RestoreJob(ctx context.Context, req resources := corev1ac.ResourceRequirements() if jc.Memory != nil { resources.WithRequests(corev1.ResourceList{ - corev1.ResourceCPU: *resource.NewQuantity(int64(jc.Threads), resource.DecimalSI), + corev1.ResourceCPU: *jc.CPU, corev1.ResourceMemory: *jc.Memory, }) } else { resources.WithRequests( corev1.ResourceList{ - corev1.ResourceCPU: *resource.NewQuantity(int64(jc.Threads), resource.DecimalSI), + corev1.ResourceCPU: *jc.CPU, }, ) } @@ -1561,6 +1562,11 @@ func (r *MySQLClusterReconciler) reconcileV1RestoreJob(ctx context.Context, req corev1.ResourceMemory: *jc.MaxMemory, }) } + if jc.MaxCPU != nil { + resources.WithLimits(corev1.ResourceList{ + corev1.ResourceCPU: *jc.MaxCPU, + }) + } if noJobResource { resources = corev1ac.ResourceRequirements() } diff --git a/controllers/mysqlcluster_controller_test.go b/controllers/mysqlcluster_controller_test.go index 4b5914292..2b746ef62 100644 --- a/controllers/mysqlcluster_controller_test.go +++ b/controllers/mysqlcluster_controller_test.go @@ -1113,6 +1113,8 @@ var _ = Describe("MySQLCluster reconciler", func() { jc := &bp.Spec.JobConfig jc.Threads = 3 jc.ServiceAccountName = "foo" + jc.CPU = resource.NewQuantity(1, resource.DecimalSI) + jc.MaxCPU = resource.NewQuantity(4, resource.DecimalSI) jc.Memory = resource.NewQuantity(1<<30, resource.DecimalSI) jc.MaxMemory = resource.NewQuantity(10<<30, resource.DecimalSI) jc.Env = []mocov1beta2.EnvVarApplyConfiguration{{Name: pointer.String("TEST"), Value: pointer.String("123")}} @@ -1205,7 +1207,9 @@ var _ = Describe("MySQLCluster reconciler", func() { Expect(c.Env).To(HaveLen(2)) Expect(c.VolumeMounts).To(HaveLen(2)) cpuReq := c.Resources.Requests[corev1.ResourceCPU] - Expect(cpuReq.Value()).To(BeNumerically("==", 3)) + Expect(cpuReq.Value()).To(BeNumerically("==", 1)) + cpuLim := c.Resources.Limits[corev1.ResourceCPU] + Expect(cpuLim.Value()).To(BeNumerically("==", 4)) memReq := c.Resources.Requests[corev1.ResourceMemory] Expect(memReq.Value()).To(BeNumerically("==", 1<<30)) memLim := c.Resources.Limits[corev1.ResourceMemory] @@ -1234,6 +1238,8 @@ var _ = Describe("MySQLCluster reconciler", func() { jc = &bp.Spec.JobConfig jc.Threads = 1 jc.ServiceAccountName = "oof" + jc.CPU = nil + jc.MaxCPU = nil jc.Memory = nil jc.MaxMemory = nil jc.Env = nil @@ -1285,7 +1291,8 @@ var _ = Describe("MySQLCluster reconciler", func() { Expect(c.EnvFrom).To(BeEmpty()) Expect(c.Env).To(HaveLen(1)) cpuReq = c.Resources.Requests[corev1.ResourceCPU] - Expect(cpuReq.Value()).To(BeNumerically("==", 1)) + Expect(cpuReq.Value()).To(BeNumerically("==", 4)) + Expect(c.Resources.Limits).NotTo(HaveKey(corev1.ResourceCPU)) memReq = c.Resources.Requests[corev1.ResourceMemory] Expect(memReq.Value()).To(BeNumerically("==", 4<<30)) Expect(c.Resources.Limits).NotTo(HaveKey(corev1.ResourceMemory)) @@ -1343,6 +1350,8 @@ var _ = Describe("MySQLCluster reconciler", func() { jc := &cluster.Spec.Restore.JobConfig jc.Threads = 3 jc.ServiceAccountName = "foo" + jc.CPU = resource.NewQuantity(1, resource.DecimalSI) + jc.MaxCPU = resource.NewQuantity(4, resource.DecimalSI) jc.Memory = resource.NewQuantity(1<<30, resource.DecimalSI) jc.MaxMemory = resource.NewQuantity(10<<30, resource.DecimalSI) jc.Env = []mocov1beta2.EnvVarApplyConfiguration{{Name: pointer.String("TEST"), Value: pointer.String("123")}} @@ -1430,7 +1439,9 @@ var _ = Describe("MySQLCluster reconciler", func() { Expect(c.Env).To(HaveLen(2)) Expect(c.VolumeMounts).To(HaveLen(2)) cpuReq := c.Resources.Requests[corev1.ResourceCPU] - Expect(cpuReq.Value()).To(BeNumerically("==", 3)) + Expect(cpuReq.Value()).To(BeNumerically("==", 1)) + cpuLim := c.Resources.Limits[corev1.ResourceCPU] + Expect(cpuLim.Value()).To(BeNumerically("==", 4)) memReq := c.Resources.Requests[corev1.ResourceMemory] Expect(memReq.Value()).To(BeNumerically("==", 1<<30)) memLim := c.Resources.Limits[corev1.ResourceMemory] diff --git a/docs/crd_mysqlcluster_v1beta2.md b/docs/crd_mysqlcluster_v1beta2.md index e4cc184b0..fffa2fbb7 100644 --- a/docs/crd_mysqlcluster_v1beta2.md +++ b/docs/crd_mysqlcluster_v1beta2.md @@ -208,6 +208,8 @@ JobConfig is a set of parameters for backup and restore job Pods. | bucketConfig | Specifies how to access an object storage bucket. | [BucketConfig](#bucketconfig) | true | | workVolume | WorkVolume is the volume source for the working directory. Since the backup or restore task can use a lot of bytes in the working directory, You should always give a volume with enough capacity.\n\nThe recommended volume source is a generic ephemeral volume. https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#generic-ephemeral-volumes | [VolumeSourceApplyConfiguration](https://pkg.go.dev/k8s.io/client-go/applyconfigurations/core/v1#VolumeSourceApplyConfiguration) | true | | threads | Threads is the number of threads used for backup or restoration. | int | false | +| cpu | Cpu is the amount of cpu requested for the Pod. | *[resource.Quantity](https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity) | false | +| maxCpu | MaxCpu is the amount of maximum cpu requested for the Pod. | *[resource.Quantity](https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity) | false | | memory | Memory is the amount of memory requested for the Pod. | *[resource.Quantity](https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity) | false | | maxMemory | MaxMemory is the amount of maximum memory for the Pod. | *[resource.Quantity](https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity) | false | | envFrom | List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence.\n\nYou can configure S3 bucket access parameters through environment variables. See https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config#EnvConfig | [][EnvFromSourceApplyConfiguration](https://pkg.go.dev/k8s.io/client-go/applyconfigurations/core/v1#EnvFromSourceApplyConfiguration) | false |