diff --git a/api/v1beta1/common_types.go b/api/v1beta1/common_types.go index eef898d30..f4a2d7ae6 100644 --- a/api/v1beta1/common_types.go +++ b/api/v1beta1/common_types.go @@ -17,16 +17,18 @@ limitations under the License. package v1beta1 import ( + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" ) // KubernetesConfig will be the JSON struct for Basic Redis Config type KubernetesConfig struct { - Image string `json:"image"` - ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` - Resources *corev1.ResourceRequirements `json:"resources,omitempty"` - ExistingPasswordSecret *ExistingPasswordSecret `json:"redisSecret,omitempty"` - ImagePullSecrets *[]corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` + Image string `json:"image"` + ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + Resources *corev1.ResourceRequirements `json:"resources,omitempty"` + ExistingPasswordSecret *ExistingPasswordSecret `json:"redisSecret,omitempty"` + ImagePullSecrets *[]corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` + UpdateStrategy appsv1.StatefulSetUpdateStrategy `json:"updateStrategy,omitempty"` } // RedisConfig defines the external configuration of Redis diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index f8d062a2c..9f30cdc7c 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -73,6 +73,7 @@ func (in *KubernetesConfig) DeepCopyInto(out *KubernetesConfig) { copy(*out, *in) } } + in.UpdateStrategy.DeepCopyInto(&out.UpdateStrategy) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesConfig. diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml index 3bba43617..9da37e5bb 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml @@ -992,6 +992,28 @@ spec: to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + updateStrategy: + description: StatefulSetUpdateStrategy indicates the strategy + that the StatefulSet controller will use to perform updates. + It includes any additional parameters necessary to perform the + update for the indicated strategy. + properties: + rollingUpdate: + description: RollingUpdate is used to communicate parameters + when Type is RollingUpdateStatefulSetStrategyType. + properties: + partition: + description: Partition indicates the ordinal at which + the StatefulSet should be partitioned. Default value + is 0. + format: int32 + type: integer + type: object + type: + description: Type indicates the type of the StatefulSetUpdateStrategy. + Default is RollingUpdate. + type: string + type: object required: - image type: object diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml index 05c1c7577..b96602473 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml @@ -190,6 +190,28 @@ spec: to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + updateStrategy: + description: StatefulSetUpdateStrategy indicates the strategy + that the StatefulSet controller will use to perform updates. + It includes any additional parameters necessary to perform the + update for the indicated strategy. + properties: + rollingUpdate: + description: RollingUpdate is used to communicate parameters + when Type is RollingUpdateStatefulSetStrategyType. + properties: + partition: + description: Partition indicates the ordinal at which + the StatefulSet should be partitioned. Default value + is 0. + format: int32 + type: integer + type: object + type: + description: Type indicates the type of the StatefulSetUpdateStrategy. + Default is RollingUpdate. + type: string + type: object required: - image type: object diff --git a/example/upgrade-strategy/clusterd.yaml b/example/upgrade-strategy/clusterd.yaml new file mode 100644 index 000000000..32e7cd7f0 --- /dev/null +++ b/example/upgrade-strategy/clusterd.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + clusterVersion: v7 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + persistenceEnabled: true + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + updateStrategy: + type: OnDelete + # type: RollingUpdate + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/example/upgrade-strategy/standalone.yaml b/example/upgrade-strategy/standalone.yaml new file mode 100644 index 000000000..bfc1b445e --- /dev/null +++ b/example/upgrade-strategy/standalone.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: Redis +metadata: + name: redis-standalone +spec: + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + updateStrategy: + type: OnDelete +# type: RollingUpdate + securityContext: + runAsUser: 1000 + fsGroup: 1000 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 \ No newline at end of file diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index eedc348e2..1bd6e906e 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -31,6 +31,7 @@ func generateRedisClusterParams(cr *redisv1beta1.RedisCluster, replicas int32, e Affinity: affinity, Tolerations: cr.Spec.Tolerations, ServiceAccountName: cr.Spec.ServiceAccountName, + UpdateStrategy: cr.Spec.KubernetesConfig.UpdateStrategy, } if cr.Spec.RedisExporter != nil { res.EnableMetrics = cr.Spec.RedisExporter.Enabled diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go index 3d4007e14..5c5c443e9 100644 --- a/k8sutils/redis-standalone.go +++ b/k8sutils/redis-standalone.go @@ -61,6 +61,7 @@ func generateRedisStandaloneParams(cr *redisv1beta1.Redis) statefulSetParameters PriorityClassName: cr.Spec.PriorityClassName, Affinity: cr.Spec.Affinity, Tolerations: cr.Spec.Tolerations, + UpdateStrategy: cr.Spec.KubernetesConfig.UpdateStrategy, } if cr.Spec.KubernetesConfig.ImagePullSecrets != nil { res.ImagePullSecrets = cr.Spec.KubernetesConfig.ImagePullSecrets diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 9835ef35e..e84813eca 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -35,6 +35,7 @@ type statefulSetParameters struct { ImagePullSecrets *[]corev1.LocalObjectReference ExternalConfig *string ServiceAccountName *string + UpdateStrategy appsv1.StatefulSetUpdateStrategy } // containerParameters will define container input params @@ -182,14 +183,14 @@ func generateStatefulSetsDef(stsMeta metav1.ObjectMeta, params statefulSetParame TypeMeta: generateMetaInformation("StatefulSet", "apps/v1"), ObjectMeta: stsMeta, Spec: appsv1.StatefulSetSpec{ - Selector: LabelSelectors(stsMeta.GetLabels()), - ServiceName: fmt.Sprintf("%s-headless", stsMeta.Name), - Replicas: params.Replicas, + Selector: LabelSelectors(stsMeta.GetLabels()), + ServiceName: fmt.Sprintf("%s-headless", stsMeta.Name), + Replicas: params.Replicas, + UpdateStrategy: params.UpdateStrategy, Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: stsMeta.GetLabels(), Annotations: generateStatefulSetsAnots(stsMeta), - // Annotations: stsMeta.Annotations, }, Spec: corev1.PodSpec{ Containers: generateContainerDef(stsMeta.GetName(), containerParams, params.EnableMetrics, params.ExternalConfig, sidecars),