Skip to content

Commit

Permalink
feat: enhance RedisCluster resource management by introducing separat…
Browse files Browse the repository at this point in the history
…e resource handling for leader and follower

- Added methods to retrieve resources for Redis leader and follower, allowing for more granular resource management.
- Updated RedisClusterSpec to deprecate the unified resources field in favor of individual configurations for leader and follower.
- Adjusted related tests and YAML configurations to reflect these changes, ensuring consistency and correctness in resource allocation.

This update improves the flexibility and efficiency of resource management in RedisCluster deployments.

Signed-off-by: drivebyer <wuyangmuc@gmail.com>
  • Loading branch information
drivebyer committed Jan 5, 2025
1 parent 888e0ed commit fcbacf6
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 19 deletions.
33 changes: 26 additions & 7 deletions api/v1beta2/rediscluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@ type RedisClusterSpec struct {
// +kubebuilder:default:=6379
Port *int `json:"port,omitempty"`
// +kubebuilder:default:=v7
ClusterVersion *string `json:"clusterVersion,omitempty"`
RedisLeader RedisLeader `json:"redisLeader,omitempty"`
RedisFollower RedisFollower `json:"redisFollower,omitempty"`
RedisExporter *RedisExporter `json:"redisExporter,omitempty"`
Storage *ClusterStorage `json:"storage,omitempty"`
PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"`
PriorityClassName string `json:"priorityClassName,omitempty"`
ClusterVersion *string `json:"clusterVersion,omitempty"`
RedisLeader RedisLeader `json:"redisLeader,omitempty"`
RedisFollower RedisFollower `json:"redisFollower,omitempty"`
RedisExporter *RedisExporter `json:"redisExporter,omitempty"`
Storage *ClusterStorage `json:"storage,omitempty"`
PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"`
PriorityClassName string `json:"priorityClassName,omitempty"`
// Deprecated: use kubernetesConfig.Resources instead for both leader and follower
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`
TLS *TLSConfig `json:"TLS,omitempty"`
ACL *ACLConfig `json:"acl,omitempty"`
Expand All @@ -58,6 +59,24 @@ func (cr *RedisClusterSpec) GetReplicaCounts(t string) int32 {
return *replica
}

// GetRedisLeaderResources returns the resources for the redis leader, if not set, it will return the default resources
func (cr *RedisClusterSpec) GetRedisLeaderResources() *corev1.ResourceRequirements {
if cr.RedisLeader.Resources != nil {
return cr.RedisLeader.Resources
}

return cr.KubernetesConfig.Resources
}

// GetRedisFollowerResources returns the resources for the redis follower, if not set, it will return the default resources
func (cr *RedisClusterSpec) GetRedisFollowerResources() *corev1.ResourceRequirements {
if cr.RedisFollower.Resources != nil {
return cr.RedisFollower.Resources
}

return cr.KubernetesConfig.Resources
}

// RedisLeader interface will have the redis leader configuration
type RedisLeader struct {
common.RedisLeader `json:",inline"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10851,7 +10851,8 @@ spec:
type: array
type: object
resources:
description: ResourceRequirements describes the compute resource requirements.
description: 'Deprecated: use kubernetesConfig.Resources instead for
both leader and follower'
properties:
claims:
description: |-
Expand Down
9 changes: 5 additions & 4 deletions pkg/controllers/rediscluster/rediscluster_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ var _ = Describe("Redis Cluster Controller", func() {
})

It("should create all required resources", func() {
By("verifying the Redis Cluster Leader StatefulSet is created")
By("verifying the Redis Cluster StatefulSet is created")
leaderSts := &appsv1.StatefulSet{}
Eventually(func() error {
return k8sClient.Get(context.Background(), types.NamespacedName{
Expand Down Expand Up @@ -80,6 +80,7 @@ var _ = Describe("Redis Cluster Controller", func() {
Expect(leaderSts.Spec.Template.Spec.SecurityContext).To(Equal(redisCluster.Spec.PodSecurityContext))
Expect(leaderSts.Spec.Template.Spec.Containers[0].Image).To(Equal(redisCluster.Spec.KubernetesConfig.Image))
Expect(leaderSts.Spec.Template.Spec.Containers[0].ImagePullPolicy).To(Equal(redisCluster.Spec.KubernetesConfig.ImagePullPolicy))
Expect(leaderSts.Spec.Template.Spec.Containers[0].Resources).To(Equal(*redisCluster.Spec.GetRedisLeaderResources()))

By("verifying Service specifications")
expectedLabels := map[string]string{
Expand All @@ -104,10 +105,10 @@ var _ = Describe("Redis Cluster Controller", func() {
By("verifying Redis Cluster configuration")
Expect(leaderSts.Spec.ServiceName).To(Equal(redisCluster.Name + "-leader-headless"))

By("verifying resource requirements")
By("verifying resource requirements") // when set resources in redisLeader, it should be used instead of kubernetesConfig.resources
container := leaderSts.Spec.Template.Spec.Containers[0]
Expect(container.Resources.Limits).To(Equal(redisCluster.Spec.KubernetesConfig.Resources.Limits))
Expect(container.Resources.Requests).To(Equal(redisCluster.Spec.KubernetesConfig.Resources.Requests))
Expect(container.Resources.Limits).To(Equal(redisCluster.Spec.RedisLeader.Resources.Limits))
Expect(container.Resources.Requests).To(Equal(redisCluster.Spec.RedisLeader.Resources.Requests))

By("verifying Redis Exporter configuration")
var exporterContainer *corev1.Container
Expand Down
8 changes: 8 additions & 0 deletions pkg/controllers/rediscluster/testdata/full.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ spec:
limits:
cpu: 101m
memory: 128Mi
redisLeader:
resources:
requests:
cpu: 102m
memory: 129Mi
limits:
cpu: 102m
memory: 129Mi
redisExporter:
enabled: true
image: quay.io/opstree/redis-exporter:v1.44.0
Expand Down
10 changes: 5 additions & 5 deletions pkg/k8sutils/redis-cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,14 @@ func generateRedisClusterInitContainerParams(cr *redisv1beta2.RedisCluster) init
}

// generateRedisClusterContainerParams generates Redis container information
func generateRedisClusterContainerParams(ctx context.Context, cl kubernetes.Interface, cr *redisv1beta2.RedisCluster, securityContext *corev1.SecurityContext, readinessProbeDef *corev1.Probe, livenessProbeDef *corev1.Probe, role string) containerParameters {
func generateRedisClusterContainerParams(ctx context.Context, cl kubernetes.Interface, cr *redisv1beta2.RedisCluster, securityContext *corev1.SecurityContext, readinessProbeDef *corev1.Probe, livenessProbeDef *corev1.Probe, role string, resources *corev1.ResourceRequirements) containerParameters {
trueProperty := true
falseProperty := false
containerProp := containerParameters{
Role: "cluster",
Image: cr.Spec.KubernetesConfig.Image,
ImagePullPolicy: cr.Spec.KubernetesConfig.ImagePullPolicy,
Resources: cr.Spec.KubernetesConfig.Resources,
Resources: resources,
SecurityContext: securityContext,
Port: cr.Spec.Port,
}
Expand Down Expand Up @@ -218,7 +218,7 @@ func generateRedisClusterContainerParams(ctx context.Context, cl kubernetes.Inte
func CreateRedisLeader(ctx context.Context, cr *redisv1beta2.RedisCluster, cl kubernetes.Interface) error {
prop := RedisClusterSTS{
RedisStateFulType: "leader",
Resources: cr.Spec.RedisLeader.Resources,
Resources: cr.Spec.GetRedisLeaderResources(),
SecurityContext: cr.Spec.RedisLeader.SecurityContext,
Affinity: cr.Spec.RedisLeader.Affinity,
TerminationGracePeriodSeconds: cr.Spec.RedisLeader.TerminationGracePeriodSeconds,
Expand All @@ -239,7 +239,7 @@ func CreateRedisLeader(ctx context.Context, cr *redisv1beta2.RedisCluster, cl ku
func CreateRedisFollower(ctx context.Context, cr *redisv1beta2.RedisCluster, cl kubernetes.Interface) error {
prop := RedisClusterSTS{
RedisStateFulType: "follower",
Resources: cr.Spec.RedisFollower.Resources,
Resources: cr.Spec.GetRedisFollowerResources(),
SecurityContext: cr.Spec.RedisFollower.SecurityContext,
Affinity: cr.Spec.RedisFollower.Affinity,
TerminationGracePeriodSeconds: cr.Spec.RedisFollower.TerminationGracePeriodSeconds,
Expand Down Expand Up @@ -288,7 +288,7 @@ func (service RedisClusterSTS) CreateRedisClusterSetup(ctx context.Context, cr *
generateRedisClusterParams(ctx, cr, service.getReplicaCount(cr), service.ExternalConfig, service),
redisClusterAsOwner(cr),
generateRedisClusterInitContainerParams(cr),
generateRedisClusterContainerParams(ctx, cl, cr, service.SecurityContext, service.ReadinessProbe, service.LivenessProbe, service.RedisStateFulType),
generateRedisClusterContainerParams(ctx, cl, cr, service.SecurityContext, service.ReadinessProbe, service.LivenessProbe, service.RedisStateFulType, service.Resources),
cr.Spec.Sidecars,
)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions pkg/k8sutils/redis-cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,10 +433,10 @@ func Test_generateRedisClusterContainerParams(t *testing.T) {
t.Fatalf("Failed to unmarshal file %s: %v", path, err)
}

actualLeaderContainer := generateRedisClusterContainerParams(context.TODO(), fake.NewSimpleClientset(), input, input.Spec.RedisLeader.SecurityContext, input.Spec.RedisLeader.ReadinessProbe, input.Spec.RedisLeader.LivenessProbe, "leader")
actualLeaderContainer := generateRedisClusterContainerParams(context.TODO(), fake.NewSimpleClientset(), input, input.Spec.RedisLeader.SecurityContext, input.Spec.RedisLeader.ReadinessProbe, input.Spec.RedisLeader.LivenessProbe, "leader", input.Spec.GetRedisLeaderResources())
assert.EqualValues(t, expectedLeaderContainer, actualLeaderContainer, "Expected %+v, got %+v", expectedLeaderContainer, actualLeaderContainer)

actualFollowerContainer := generateRedisClusterContainerParams(context.TODO(), fake.NewSimpleClientset(), input, input.Spec.RedisFollower.SecurityContext, input.Spec.RedisFollower.ReadinessProbe, input.Spec.RedisFollower.LivenessProbe, "follower")
actualFollowerContainer := generateRedisClusterContainerParams(context.TODO(), fake.NewSimpleClientset(), input, input.Spec.RedisFollower.SecurityContext, input.Spec.RedisFollower.ReadinessProbe, input.Spec.RedisFollower.LivenessProbe, "follower", input.Spec.GetRedisFollowerResources())
assert.EqualValues(t, expectedFollowerContainer, actualFollowerContainer, "Expected %+v, got %+v", expectedFollowerContainer, actualFollowerContainer)
}

Expand Down

0 comments on commit fcbacf6

Please sign in to comment.