From 131dc8b4ae5ef14be48cb30facf2fe607504c4c4 Mon Sep 17 00:00:00 2001 From: AnyISalIn Date: Mon, 28 Sep 2020 23:53:40 +0800 Subject: [PATCH 1/2] support redis standalone mode --- README.md | 20 ++++++++++ .../crds/redis_v1beta1_rediscluster_crd.yaml | 2 +- pkg/apis/redis/v1beta1/rediscluster_types.go | 7 ++++ pkg/apis/redis/v1beta1/validate.go | 8 ++-- pkg/controller/rediscluster/checker.go | 12 ++++-- pkg/controller/rediscluster/ensurer.go | 33 +++++++++------- pkg/controller/service/generator.go | 38 ++++++++++++------- 7 files changed, 86 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 887deea..a638a54 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ In addition to the sentinel's own capabilities, redis-operator can: * False delete automatic recovery * Persistence * Custom SecurityContext +* Standalone Mode ## Quick Start @@ -344,6 +345,25 @@ spec: value: "1024" ``` +#### Redis Standalone Mode + +If you only requires single node, non auto failover redis instance, You can deploy standalone redis instance, this will change headless service to normal. + +``` +apiVersion: redis.kun/v1beta1 +kind: RedisCluster +metadata: + name: standalone +spec: + size: 1 +``` + +``` +# kubectl get svc redis-cluster-standalone + +redis-cluster-standalone ClusterIP 172.31.254.96 +``` + ### Cleanup ``` diff --git a/deploy/crds/redis_v1beta1_rediscluster_crd.yaml b/deploy/crds/redis_v1beta1_rediscluster_crd.yaml index 15bd4d0..4128fcd 100644 --- a/deploy/crds/redis_v1beta1_rediscluster_crd.yaml +++ b/deploy/crds/redis_v1beta1_rediscluster_crd.yaml @@ -101,7 +101,7 @@ spec: size: format: int32 type: integer - minimum: 3 + minimum: 1 maximum: 10 storage: properties: diff --git a/pkg/apis/redis/v1beta1/rediscluster_types.go b/pkg/apis/redis/v1beta1/rediscluster_types.go index 392ae46..265ecb1 100644 --- a/pkg/apis/redis/v1beta1/rediscluster_types.go +++ b/pkg/apis/redis/v1beta1/rediscluster_types.go @@ -45,6 +45,13 @@ type RedisCluster struct { Status RedisClusterStatus `json:"status,omitempty"` } +func (r *RedisCluster) Standalone() bool { + if r.Spec.Sentinel.Replicas == 0 { + return true + } + return false +} + // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // RedisClusterList contains a list of RedisCluster diff --git a/pkg/apis/redis/v1beta1/validate.go b/pkg/apis/redis/v1beta1/validate.go index 8553350..d5e62c9 100644 --- a/pkg/apis/redis/v1beta1/validate.go +++ b/pkg/apis/redis/v1beta1/validate.go @@ -30,13 +30,15 @@ func (r *RedisCluster) Validate() error { if r.Spec.Size == 0 { r.Spec.Size = defaultRedisNumber - } else if r.Spec.Size < defaultRedisNumber { + } else if r.Spec.Size < defaultRedisNumber && r.Spec.Size != 1 { return errors.New("number of redis in spec is less than the minimum") } if r.Spec.Sentinel.Replicas == 0 { - r.Spec.Sentinel.Replicas = defaultSentinelNumber - } else if r.Spec.Sentinel.Replicas < defaultSentinelNumber { + if r.Spec.Size > 1 { + r.Spec.Sentinel.Replicas = defaultSentinelNumber + } + } else if r.Spec.Sentinel.Replicas < defaultSentinelNumber { return errors.New("number of sentinels in spec is less than the minimum") } diff --git a/pkg/controller/rediscluster/checker.go b/pkg/controller/rediscluster/checker.go index cd9e4f9..919faf9 100644 --- a/pkg/controller/rediscluster/checker.go +++ b/pkg/controller/rediscluster/checker.go @@ -36,9 +36,11 @@ func (r *RedisClusterHandler) CheckAndHeal(meta *clustercache.Meta) error { r.eventsCli.UpdateCluster(meta.Obj, "wait for all redis server start") return needRequeueErr } - if err := r.rcChecker.CheckSentinelNumber(meta.Obj); err != nil { - r.eventsCli.FailedCluster(meta.Obj, err.Error()) - return nil + if !meta.Obj.Standalone() { + if err := r.rcChecker.CheckSentinelNumber(meta.Obj); err != nil { + r.eventsCli.FailedCluster(meta.Obj, err.Error()) + return nil + } } nMasters, err := r.rcChecker.GetNumberMasters(meta.Obj, meta.Auth) @@ -88,6 +90,10 @@ func (r *RedisClusterHandler) CheckAndHeal(meta *clustercache.Meta) error { return err } + if meta.Obj.Standalone() { + return nil + } + sentinels, err := r.rcChecker.GetSentinelsIPs(meta.Obj) if err != nil { return err diff --git a/pkg/controller/rediscluster/ensurer.go b/pkg/controller/rediscluster/ensurer.go index 74025fb..cccf5a5 100644 --- a/pkg/controller/rediscluster/ensurer.go +++ b/pkg/controller/rediscluster/ensurer.go @@ -11,27 +11,32 @@ func (r *RedisClusterHandler) Ensure(rc *redisv1beta1.RedisCluster, labels map[s if err := r.rcService.EnsureRedisService(rc, labels, or); err != nil { return err } - if err := r.rcService.EnsureSentinelService(rc, labels, or); err != nil { - return err - } - if err := r.rcService.EnsureSentinelHeadlessService(rc, labels, or); err != nil { - return err - } - if err := r.rcService.EnsureSentinelConfigMap(rc, labels, or); err != nil { - return err - } - if err := r.rcService.EnsureSentinelProbeConfigMap(rc, labels, or); err != nil { - return err + if !rc.Standalone() { + if err := r.rcService.EnsureSentinelService(rc, labels, or); err != nil { + return err + } + if err := r.rcService.EnsureSentinelHeadlessService(rc, labels, or); err != nil { + return err + } + if err := r.rcService.EnsureSentinelConfigMap(rc, labels, or); err != nil { + return err + } + if err := r.rcService.EnsureSentinelProbeConfigMap(rc, labels, or); err != nil { + return err + } } + if err := r.rcService.EnsureRedisShutdownConfigMap(rc, labels, or); err != nil { return err } if err := r.rcService.EnsureRedisStatefulset(rc, labels, or); err != nil { return err } - if err := r.rcService.EnsureSentinelStatefulset(rc, labels, or); err != nil { - return err + if !rc.Standalone() { + if err := r.rcService.EnsureSentinelStatefulset(rc, labels, or); err != nil { + return err + } } - return nil } + diff --git a/pkg/controller/service/generator.go b/pkg/controller/service/generator.go index b2d79bd..9e8081a 100644 --- a/pkg/controller/service/generator.go +++ b/pkg/controller/service/generator.go @@ -56,6 +56,24 @@ func generateRedisService(rc *redisv1beta1.RedisCluster, labels map[string]strin labels = util.MergeLabels(labels, generateSelectorLabels(util.RedisRoleName, rc.Name)) redisTargetPort := intstr.FromInt(6379) + + spec := corev1.ServiceSpec{ + Type: corev1.ServiceTypeClusterIP, + Ports: []corev1.ServicePort{ + { + Port: 6379, + Protocol: corev1.ProtocolTCP, + Name: "redis", + TargetPort: redisTargetPort, + }, + }, + Selector: labels, + } + + if !rc.Standalone() { + spec.ClusterIP = corev1.ClusterIPNone + } + return &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -63,19 +81,7 @@ func generateRedisService(rc *redisv1beta1.RedisCluster, labels map[string]strin Labels: labels, OwnerReferences: ownerRefs, }, - Spec: corev1.ServiceSpec{ - Type: corev1.ServiceTypeClusterIP, - ClusterIP: corev1.ClusterIPNone, - Ports: []corev1.ServicePort{ - { - Port: 6379, - Protocol: corev1.ProtocolTCP, - Name: "redis", - TargetPort: redisTargetPort, - }, - }, - Selector: labels, - }, + Spec: spec, } } @@ -667,6 +673,12 @@ func getRedisCommand(rc *redisv1beta1.RedisCluster) []string { "--save 300 10", } + if rc.Standalone() { + cmds = []string{ + "redis-server", + } + } + if rc.Spec.Password != "" { cmds = append(cmds, fmt.Sprintf("--requirepass '%s'", rc.Spec.Password), fmt.Sprintf("--masterauth '%s'", rc.Spec.Password)) From 697343b697339f5385b0d48024d6f1005fab243f Mon Sep 17 00:00:00 2001 From: AnyISalIn Date: Tue, 29 Sep 2020 14:01:00 +0800 Subject: [PATCH 2/2] standalone mode skip redis sentinel check --- pkg/controller/rediscluster/controller.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/controller/rediscluster/controller.go b/pkg/controller/rediscluster/controller.go index 66e8893..e2ef319 100644 --- a/pkg/controller/rediscluster/controller.go +++ b/pkg/controller/rediscluster/controller.go @@ -222,9 +222,11 @@ func (r *ReconcileRedisCluster) Reconcile(request reconcile.Request) (reconcile. return reconcile.Result{}, err } - if err = r.handler.rcChecker.CheckSentinelReadyReplicas(instance); err != nil { - reqLogger.Info(err.Error()) - return reconcile.Result{RequeueAfter: 20 * time.Second}, nil + if !instance.Standalone() { + if err = r.handler.rcChecker.CheckSentinelReadyReplicas(instance); err != nil { + reqLogger.Info(err.Error()) + return reconcile.Result{RequeueAfter: 20 * time.Second}, nil + } } return reconcile.Result{RequeueAfter: time.Duration(reconcileTime) * time.Second}, nil