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/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
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))