Skip to content

Commit

Permalink
fix: The number of component replicas cannot be set to 0 (#120)
Browse files Browse the repository at this point in the history
* fix: The number of component replicas cannot be set to 0

* chore: sort package

* feat: replicas validation check
  • Loading branch information
daviderli614 authored Dec 12, 2023
1 parent c583e7d commit adb3de7
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 29 deletions.
18 changes: 15 additions & 3 deletions apis/v1alpha1/defaulting.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"strings"

"github.com/imdario/mergo"
"google.golang.org/protobuf/proto"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/intstr"
Expand All @@ -38,6 +39,11 @@ var (
defaultOpenTSDBServicePort = 4242
defaultMetaServicePort = 3002

// The default replicas for frontend/meta/datanode.
defaultFrontendReplicas int32 = 1
defaultMetaReplicas int32 = 1
defaultDatanodeReplicas int32 = 3

// The default storage settings for datanode.
defaultDataNodeStorageName = "datanode"
defaultDataNodeStorageSize = "10Gi"
Expand Down Expand Up @@ -98,30 +104,33 @@ func (in *GreptimeDBCluster) SetDefaults() error {
if in.Spec.Frontend != nil {
defaultGreptimeDBClusterSpec.Frontend = &FrontendSpec{
ComponentSpec: ComponentSpec{
Replicas: 1,
Template: &PodTemplateSpec{},
},
Service: ServiceSpec{
Type: corev1.ServiceTypeClusterIP,
},
}
if in.Spec.Frontend.Replicas == nil {
in.Spec.Frontend.Replicas = proto.Int32(defaultFrontendReplicas)
}
}

if in.Spec.Meta != nil {
defaultGreptimeDBClusterSpec.Meta = &MetaSpec{
ComponentSpec: ComponentSpec{
Replicas: 1,
Template: &PodTemplateSpec{},
},
ServicePort: int32(defaultMetaServicePort),
EnableRegionFailover: false,
}
if in.Spec.Meta.Replicas == nil {
in.Spec.Meta.Replicas = proto.Int32(defaultMetaReplicas)
}
}

if in.Spec.Datanode != nil {
defaultGreptimeDBClusterSpec.Datanode = &DatanodeSpec{
ComponentSpec: ComponentSpec{
Replicas: 3,
Template: &PodTemplateSpec{},
},
Storage: StorageSpec{
Expand All @@ -132,6 +141,9 @@ func (in *GreptimeDBCluster) SetDefaults() error {
WalDir: defaultDataNodeStorageMountPath + "/wal",
},
}
if in.Spec.Datanode.Replicas == nil {
in.Spec.Datanode.Replicas = proto.Int32(defaultDatanodeReplicas)
}
}

if err := mergo.Merge(&in.Spec, defaultGreptimeDBClusterSpec); err != nil {
Expand Down
95 changes: 83 additions & 12 deletions apis/v1alpha1/defaulting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@
package v1alpha1

import (
"k8s.io/apimachinery/pkg/util/intstr"
"reflect"
"testing"

"google.golang.org/protobuf/proto"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/intstr"
)

func TestSetDefaults(t *testing.T) {
Expand All @@ -39,17 +40,17 @@ func TestSetDefaults(t *testing.T) {
},
Frontend: &FrontendSpec{
ComponentSpec: ComponentSpec{
Replicas: 3,
Replicas: proto.Int32(3),
},
},
Meta: &MetaSpec{
ComponentSpec: ComponentSpec{
Replicas: 3,
Replicas: proto.Int32(3),
},
},
Datanode: &DatanodeSpec{
ComponentSpec: ComponentSpec{
Replicas: 1,
Replicas: proto.Int32(1),
},
},
},
Expand Down Expand Up @@ -82,7 +83,7 @@ func TestSetDefaults(t *testing.T) {
},
Frontend: &FrontendSpec{
ComponentSpec: ComponentSpec{
Replicas: 3,
Replicas: proto.Int32(3),
Template: &PodTemplateSpec{
MainContainer: &MainContainerSpec{
Image: "greptime/greptimedb:latest",
Expand Down Expand Up @@ -113,7 +114,7 @@ func TestSetDefaults(t *testing.T) {
},
Meta: &MetaSpec{
ComponentSpec: ComponentSpec{
Replicas: 3,
Replicas: proto.Int32(3),
Template: &PodTemplateSpec{
MainContainer: &MainContainerSpec{
Image: "greptime/greptimedb:latest",
Expand Down Expand Up @@ -142,7 +143,7 @@ func TestSetDefaults(t *testing.T) {
},
Datanode: &DatanodeSpec{
ComponentSpec: ComponentSpec{
Replicas: 1,
Replicas: proto.Int32(1),
Template: &PodTemplateSpec{
MainContainer: &MainContainerSpec{
Image: "greptime/greptimedb:latest",
Expand Down Expand Up @@ -273,7 +274,7 @@ func TestSetDefaults(t *testing.T) {
},
Frontend: &FrontendSpec{
ComponentSpec: ComponentSpec{
Replicas: 1,
Replicas: proto.Int32(defaultFrontendReplicas),
Template: &PodTemplateSpec{
MainContainer: &MainContainerSpec{
Image: "greptime/frontend:latest",
Expand Down Expand Up @@ -308,7 +309,7 @@ func TestSetDefaults(t *testing.T) {
},
Meta: &MetaSpec{
ComponentSpec: ComponentSpec{
Replicas: 1,
Replicas: proto.Int32(defaultMetaReplicas),
Template: &PodTemplateSpec{
MainContainer: &MainContainerSpec{
Image: "greptime/meta:latest",
Expand Down Expand Up @@ -344,7 +345,7 @@ func TestSetDefaults(t *testing.T) {
},
Datanode: &DatanodeSpec{
ComponentSpec: ComponentSpec{
Replicas: 3,
Replicas: proto.Int32(defaultDatanodeReplicas),
Template: &PodTemplateSpec{
MainContainer: &MainContainerSpec{
Image: "greptime/greptimedb:latest",
Expand Down Expand Up @@ -400,7 +401,17 @@ func TestSetDefaults(t *testing.T) {
},
Datanode: &DatanodeSpec{
ComponentSpec: ComponentSpec{
Replicas: 3,
Replicas: proto.Int32(0),
},
},
Frontend: &FrontendSpec{
ComponentSpec: ComponentSpec{
Replicas: proto.Int32(0),
},
},
Meta: &MetaSpec{
ComponentSpec: ComponentSpec{
Replicas: proto.Int32(0),
},
},
},
Expand Down Expand Up @@ -431,9 +442,69 @@ func TestSetDefaults(t *testing.T) {
},
},
},
Frontend: &FrontendSpec{
ComponentSpec: ComponentSpec{
Replicas: proto.Int32(0),
Template: &PodTemplateSpec{
MainContainer: &MainContainerSpec{
Image: "greptime/greptimedb:latest",
Resources: &corev1.ResourceRequirements{
Requests: map[corev1.ResourceName]resource.Quantity{
"cpu": resource.MustParse(defaultCPU),
"memory": resource.MustParse(defaultMemory),
},
Limits: map[corev1.ResourceName]resource.Quantity{
"cpu": resource.MustParse(defaultCPU),
"memory": resource.MustParse(defaultMemory),
},
},
ReadinessProbe: &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
HTTPGet: &corev1.HTTPGetAction{
Path: "/health",
Port: intstr.FromInt(defaultHTTPServicePort),
},
},
},
},
},
},
Service: ServiceSpec{
Type: corev1.ServiceTypeClusterIP,
},
},
Meta: &MetaSpec{
ComponentSpec: ComponentSpec{
Replicas: proto.Int32(0),
Template: &PodTemplateSpec{
MainContainer: &MainContainerSpec{
Image: "greptime/greptimedb:latest",
Resources: &corev1.ResourceRequirements{
Requests: map[corev1.ResourceName]resource.Quantity{
"cpu": resource.MustParse(defaultCPU),
"memory": resource.MustParse(defaultMemory),
},
Limits: map[corev1.ResourceName]resource.Quantity{
"cpu": resource.MustParse(defaultCPU),
"memory": resource.MustParse(defaultMemory),
},
},
ReadinessProbe: &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
HTTPGet: &corev1.HTTPGetAction{
Path: "/health",
Port: intstr.FromInt(defaultHTTPServicePort),
},
},
},
},
},
},
ServicePort: int32(defaultMetaServicePort),
},
Datanode: &DatanodeSpec{
ComponentSpec: ComponentSpec{
Replicas: 3,
Replicas: proto.Int32(0),
Template: &PodTemplateSpec{
MainContainer: &MainContainerSpec{
Image: "greptime/greptimedb:latest",
Expand Down
4 changes: 2 additions & 2 deletions apis/v1alpha1/greptimedbcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,9 @@ type PodTemplateSpec struct {
// ComponentSpec is the common specification for all components(frontend/meta/datanode).
type ComponentSpec struct {
// The number of replicas of the components.
// +kubebuilder:validation:Minimum=0
// +optional
Replicas int32 `json:"replicas"`
// +kubebuilder:validation:Minimum=0
Replicas *int32 `json:"replicas"`

// The content of the configuration file of the component in TOML format.
// +optional
Expand Down
5 changes: 5 additions & 0 deletions apis/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion controllers/greptimedbcluster/deployers/datanode.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ func (b *datanodeBuilder) BuildStatefulSet() deployer.Builder {
},
Spec: appsv1.StatefulSetSpec{
ServiceName: ResourceName(b.Cluster.Name, b.ComponentKind),
Replicas: &b.Cluster.Spec.Datanode.Replicas,
Replicas: b.Cluster.Spec.Datanode.Replicas,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
GreptimeDBComponentName: ResourceName(b.Cluster.Name, b.ComponentKind),
Expand Down
2 changes: 1 addition & 1 deletion controllers/greptimedbcluster/deployers/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func (b *frontendBuilder) BuildDeployment() deployer.Builder {
Namespace: b.Cluster.Namespace,
},
Spec: appsv1.DeploymentSpec{
Replicas: &b.Cluster.Spec.Frontend.Replicas,
Replicas: b.Cluster.Spec.Frontend.Replicas,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
GreptimeDBComponentName: ResourceName(b.Cluster.Name, b.ComponentKind),
Expand Down
2 changes: 1 addition & 1 deletion controllers/greptimedbcluster/deployers/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ func (b *metaBuilder) BuildDeployment() deployer.Builder {
Namespace: b.Cluster.Namespace,
},
Spec: appsv1.DeploymentSpec{
Replicas: &b.Cluster.Spec.Meta.Replicas,
Replicas: b.Cluster.Spec.Meta.Replicas,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
GreptimeDBComponentName: ResourceName(b.Cluster.Name, b.ComponentKind),
Expand Down
19 changes: 10 additions & 9 deletions controllers/greptimedbcluster/greptimedbcluster_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"google.golang.org/protobuf/proto"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -124,20 +125,20 @@ func createCluster(name, namespace string) *v1alpha1.GreptimeDBCluster {
},
Frontend: &v1alpha1.FrontendSpec{
ComponentSpec: v1alpha1.ComponentSpec{
Replicas: 1,
Replicas: proto.Int32(1),
},
},
Meta: &v1alpha1.MetaSpec{
ComponentSpec: v1alpha1.ComponentSpec{
Replicas: 3,
Replicas: proto.Int32(1),
},
EtcdEndpoints: []string{
"etcd.default:2379",
},
},
Datanode: &v1alpha1.DatanodeSpec{
ComponentSpec: v1alpha1.ComponentSpec{
Replicas: 1,
Replicas: proto.Int32(3),
},
},
},
Expand All @@ -158,15 +159,15 @@ func checkResource(namespace, name string, object client.Object, request reconci
}, 30*time.Second, time.Second).Should(BeNil())
}

func makeStatefulSetReady(statefulSet *appsv1.StatefulSet, replicas int32) error {
statefulSet.Status.ReadyReplicas = replicas
statefulSet.Status.Replicas = replicas
func makeStatefulSetReady(statefulSet *appsv1.StatefulSet, replicas *int32) error {
statefulSet.Status.ReadyReplicas = *replicas
statefulSet.Status.Replicas = *replicas
return reconciler.Status().Update(ctx, statefulSet)
}

func makeDeploymentReady(deployment *appsv1.Deployment, replicas int32) error {
deployment.Status.Replicas = replicas
deployment.Status.ReadyReplicas = replicas
func makeDeploymentReady(deployment *appsv1.Deployment, replicas *int32) error {
deployment.Status.Replicas = *replicas
deployment.Status.ReadyReplicas = *replicas
deployment.Status.Conditions = append(deployment.Status.Conditions, appsv1.DeploymentCondition{
Type: appsv1.DeploymentProgressing,
Status: corev1.ConditionTrue,
Expand Down

0 comments on commit adb3de7

Please sign in to comment.