diff --git a/pkg/apis/mysql/v1alpha1/types.go b/pkg/apis/mysql/v1alpha1/types.go index 826e5a138..7d028c961 100644 --- a/pkg/apis/mysql/v1alpha1/types.go +++ b/pkg/apis/mysql/v1alpha1/types.go @@ -64,11 +64,13 @@ type ClusterSpec struct { // and server key for group replication SSL. // +optional SSLSecret *corev1.LocalObjectReference `json:"sslSecret,omitempty"` - // SecurityContext holds pod-level security attributes and common container settings. + // SecurityContext holds Pod-level security attributes and common Container settings. SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"` // Tolerations allows specifying a list of tolerations for controlling which - // set of nodes a pod can be scheduled on + // set of Nodes a Pod can be scheduled on Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` + // Resources holds ResourceRequirements for the MySQL Agent & Server Containers + Resources *Resources `json:"resources,omitempty"` } // ClusterConditionType represents a valid condition of a Cluster. @@ -125,6 +127,12 @@ type ClusterList struct { Items []Cluster `json:"items"` } +// Resources holds ResourceRequirements for the MySQL Agent & Server Containers +type Resources struct { + Agent *corev1.ResourceRequirements `json:"agent,omitempty"` + Server *corev1.ResourceRequirements `json:"server,omitempty"` +} + // Database represents a database to backup. type Database struct { Name string `json:"name"` diff --git a/pkg/resources/statefulsets/statefulset.go b/pkg/resources/statefulsets/statefulset.go index 103f1827a..f97436adc 100644 --- a/pkg/resources/statefulsets/statefulset.go +++ b/pkg/resources/statefulsets/statefulset.go @@ -22,6 +22,7 @@ import ( apps "k8s.io/api/apps/v1beta1" "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/intstr" @@ -193,6 +194,12 @@ func mysqlServerContainer(cluster *v1alpha1.Cluster, mysqlServerImage string, ro # a unique server id for this instance. index=$(cat /etc/hostname | grep -o '[^-]*$') /entrypoint.sh %s`, baseServerID, entryPointArgs) + + var resourceLimits corev1.ResourceRequirements + if cluster.Spec.Resources != nil && cluster.Spec.Resources.Server != nil { + resourceLimits = *cluster.Spec.Resources.Server + } + return v1.Container{ Name: MySQLServerName, // TODO(apryde): Add BaseImage to cluster CRD. @@ -215,6 +222,7 @@ func mysqlServerContainer(cluster *v1alpha1.Cluster, mysqlServerImage string, ro Value: "true", }, }, + Resources: resourceLimits, } } @@ -226,6 +234,11 @@ func mysqlAgentContainer(cluster *v1alpha1.Cluster, mysqlAgentImage string, root replicationGroupSeeds := getReplicationGroupSeeds(cluster.Name, members) + var resourceLimits corev1.ResourceRequirements + if cluster.Spec.Resources != nil && cluster.Spec.Resources.Agent != nil { + resourceLimits = *cluster.Spec.Resources.Agent + } + return v1.Container{ Name: MySQLAgentName, Image: fmt.Sprintf("%s:%s", mysqlAgentImage, agentVersion), @@ -262,6 +275,7 @@ func mysqlAgentContainer(cluster *v1alpha1.Cluster, mysqlAgentImage string, root }, }, }, + Resources: resourceLimits, } } diff --git a/pkg/resources/statefulsets/statefulset_test.go b/pkg/resources/statefulsets/statefulset_test.go index 5f8b6bafe..650d14d0c 100644 --- a/pkg/resources/statefulsets/statefulset_test.go +++ b/pkg/resources/statefulsets/statefulset_test.go @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/oracle/mysql-operator/pkg/apis/mysql/v1alpha1" @@ -221,3 +222,68 @@ func TestClusterWithTolerations(t *testing.T) { } } } + +func TestClusterWithResourceRequirements(t *testing.T) { + mysqlServerResourceRequirements := corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceMemory: resource.MustParse("2Gi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("1Gi"), + }, + } + + mysqlAgentResourceRequirements := corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("512Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + } + + cluster := &v1alpha1.Cluster{ + Spec: v1alpha1.ClusterSpec{ + Resources: &v1alpha1.Resources{ + Server: &mysqlServerResourceRequirements, + Agent: &mysqlAgentResourceRequirements, + }, + }, + } + + statefulSet := NewForCluster(cluster, mockOperatorConfig().Images, "mycluster") + + assert.Equal(t, mysqlServerResourceRequirements, statefulSet.Spec.Template.Spec.Containers[0].Resources, "MySQL-Server container resource requirements do not match expected.") + assert.Equal(t, mysqlAgentResourceRequirements, statefulSet.Spec.Template.Spec.Containers[1].Resources, "MySQL-Agent container resource requirements do not match expected.") +} + +func TestClusterWithOnlyMysqlServerResourceRequirements(t *testing.T) { + mysqlServerResourceRequirements := corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("2"), + corev1.ResourceMemory: resource.MustParse("2Gi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("1Gi"), + }, + } + + cluster := &v1alpha1.Cluster{ + Spec: v1alpha1.ClusterSpec{ + Resources: &v1alpha1.Resources{ + Server: &mysqlServerResourceRequirements, + }, + }, + } + + statefulSet := NewForCluster(cluster, mockOperatorConfig().Images, "mycluster") + + assert.Equal(t, mysqlServerResourceRequirements, statefulSet.Spec.Template.Spec.Containers[0].Resources, "MySQL-Server container resource requirements do not match expected.") + assert.Nil(t, statefulSet.Spec.Template.Spec.Containers[1].Resources.Limits, "MySQL-Agent container has resource limits set which were not initially defined in the spec") + assert.Nil(t, statefulSet.Spec.Template.Spec.Containers[1].Resources.Requests, "MySQL-Agent container has resource requests set which were not initially defined in the spec") +}