Skip to content

Commit ede71f5

Browse files
author
Jonathan Knight
authored
Added an initialReplicas field that is used to set an initial cluster size when using the horizontal Pod autoscaler or kubectl scale to later resize a cluster. (#822)
1 parent 958ef64 commit ede71f5

File tree

5 files changed

+118
-9
lines changed

5 files changed

+118
-9
lines changed

api/v1/coherenceresource_types.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,10 @@ func (in *Coherence) GetReplicas() int32 {
181181
if in == nil {
182182
return DefaultReplicas
183183
}
184-
if in.Spec.Replicas == nil {
184+
if in.Spec.Replicas == nil && in.Spec.InitialReplicas == nil {
185185
if in.Status.Replicas > 0 {
186186
return in.Status.Replicas
187187
}
188-
return DefaultReplicas
189188
}
190189
return in.Spec.GetReplicas()
191190
}

api/v1/coherenceresourcespec_types.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ import (
1010
"bytes"
1111
"encoding/base64"
1212
"fmt"
13+
"strconv"
14+
"strings"
15+
1316
"github.com/oracle/coherence-operator/pkg/operator"
1417
batchv1 "k8s.io/api/batch/v1"
1518
corev1 "k8s.io/api/core/v1"
1619
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1720
"k8s.io/apimachinery/pkg/util/intstr"
1821
"k8s.io/utils/ptr"
19-
"strconv"
20-
"strings"
2122
)
2223

2324
// NOTE: This file is used to generate the CRDs use by the Operator. The CRD files should not be manually edited
@@ -46,12 +47,30 @@ type CoherenceResourceSpec struct {
4647
// +optional
4748
ImagePullSecrets []LocalObjectReference `json:"imagePullSecrets,omitempty"`
4849
// The desired number of cluster members of this deployment.
50+
//
51+
// If the cluster will be scaled using the Horizontal Pod Autoscaler or the kubectl scale command
52+
// then this field should be left unset and the initial cluster size should be specified using the
53+
// `initialReplicas` field.
54+
//
4955
// This is a pointer to distinguish between explicit zero and not specified.
5056
// If not specified a default value of 3 will be used.
5157
// This field cannot be negative.
5258
// +kubebuilder:validation:Minimum:=0
5359
// +optional
5460
Replicas *int32 `json:"replicas,omitempty"`
61+
// The initial number of cluster members of this deployment when first created.
62+
//
63+
// If the `replicas` field is set this field is ignored.
64+
//
65+
// This field is to set an initial size for a cluster that is then resized only using the
66+
// Horizontal Pod Autoscaler or the kubectl scale command.
67+
//
68+
// This is a pointer to distinguish between explicit zero and not specified.
69+
// If not specified a default value of 3 will be used.
70+
// This field cannot be negative.
71+
// +kubebuilder:validation:Minimum:=0
72+
// +optional
73+
InitialReplicas *int32 `json:"initialReplicas,omitempty"`
5574
// The name of the role that this deployment represents in a Coherence cluster.
5675
// This value will be used to set the Coherence role property for all members of this role
5776
// +optional
@@ -327,9 +346,15 @@ type ActionJob struct {
327346
// return either the actual Replica value or the default (DefaultReplicas const)
328347
// if the Replicas field is nil.
329348
func (in *CoherenceResourceSpec) GetReplicas() int32 {
330-
if in == nil || in.Replicas == nil {
349+
if in == nil {
331350
return DefaultReplicas
332351
}
352+
if in.Replicas == nil {
353+
if in.InitialReplicas == nil {
354+
return DefaultReplicas
355+
}
356+
return *in.InitialReplicas
357+
}
333358
return *in.Replicas
334359
}
335360

api/v1/create_statefulset_test.go

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ package v1_test
88

99
import (
1010
"fmt"
11+
"testing"
12+
1113
coh "github.com/oracle/coherence-operator/api/v1"
1214
corev1 "k8s.io/api/core/v1"
1315
"k8s.io/apimachinery/pkg/api/resource"
1416
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1517
"k8s.io/apimachinery/pkg/util/intstr"
1618
"k8s.io/utils/ptr"
17-
"testing"
1819
)
1920

2021
func TestCreateStatefulSetFromMinimalRoleSpec(t *testing.T) {
@@ -56,6 +57,40 @@ func TestCreateStatefulSetWithReplicas(t *testing.T) {
5657
deployment := createTestDeployment(spec)
5758
// Create expected StatefulSet
5859
stsExpected := createMinimalExpectedStatefulSet(deployment)
60+
stsExpected.Spec.Replicas = ptr.To(int32(50))
61+
62+
// assert that the StatefulSet is as expected
63+
assertStatefulSetCreation(t, deployment, stsExpected)
64+
}
65+
66+
func TestCreateStatefulSetWithInitialReplicas(t *testing.T) {
67+
// create a spec with a name
68+
spec := coh.CoherenceResourceSpec{
69+
InitialReplicas: ptr.To(int32(50)),
70+
}
71+
72+
// Create the test deployment
73+
deployment := createTestDeployment(spec)
74+
// Create expected StatefulSet
75+
stsExpected := createMinimalExpectedStatefulSet(deployment)
76+
stsExpected.Spec.Replicas = ptr.To(int32(50))
77+
78+
// assert that the StatefulSet is as expected
79+
assertStatefulSetCreation(t, deployment, stsExpected)
80+
}
81+
82+
func TestCreateStatefulSetWhenReplicasAndInitialReplicasSet(t *testing.T) {
83+
// create a spec with a name
84+
spec := coh.CoherenceResourceSpec{
85+
Replicas: ptr.To(int32(100)),
86+
InitialReplicas: ptr.To(int32(50)),
87+
}
88+
89+
// Create the test deployment
90+
deployment := createTestDeployment(spec)
91+
// Create expected StatefulSet
92+
stsExpected := createMinimalExpectedStatefulSet(deployment)
93+
stsExpected.Spec.Replicas = ptr.To(int32(100))
5994

6095
// assert that the StatefulSet is as expected
6196
assertStatefulSetCreation(t, deployment, stsExpected)

docs/about/04_coherence_spec.adoc

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,18 @@ CoherenceResourceSpec defines the specification of a Coherence resource. A Coher
281281
m| image | The name of the image. More info: https://kubernetes.io/docs/concepts/containers/images m| *string | false
282282
m| imagePullPolicy | Image pull policy. One of Always, Never, IfNotPresent. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images m| *https://pkg.go.dev/k8s.io/api/core/v1#PullPolicy | false
283283
m| imagePullSecrets | ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod m| []<<LocalObjectReference,LocalObjectReference>> | false
284-
m| replicas | The desired number of cluster members of this deployment. This is a pointer to distinguish between explicit zero and not specified. If not specified a default value of 3 will be used. This field cannot be negative. m| &#42;int32 | false
284+
m| replicas | The desired number of cluster members of this deployment. +
285+
+
286+
If the cluster will be scaled using the Horizontal Pod Autoscaler or the kubectl scale command then this field should be left unset and the initial cluster size should be specified using the `initialReplicas` field. +
287+
+
288+
This is a pointer to distinguish between explicit zero and not specified. If not specified a default value of 3 will be used. This field cannot be negative. m| &#42;int32 | false
289+
m| initialReplicas | The initial number of cluster members of this deployment when first created. +
290+
+
291+
If the `replicas` field is set this field is ignored. +
292+
+
293+
This field is to set an initial size for a cluster that is then resized only using the Horizontal Pod Autoscaler or the kubectl scale command. +
294+
+
295+
This is a pointer to distinguish between explicit zero and not specified. If not specified a default value of 3 will be used. This field cannot be negative. m| &#42;int32 | false
285296
m| role | The name of the role that this deployment represents in a Coherence cluster. This value will be used to set the Coherence role property for all members of this role m| string | false
286297
m| appLabel | An optional app label to apply to resources created for this deployment. This is useful for example to apply an app label for use by Istio. This field follows standard Kubernetes label syntax. m| &#42;string | false
287298
m| versionLabel | An optional version label to apply to resources created for this deployment. This is useful for example to apply a version label for use by Istio. This field follows standard Kubernetes label syntax. m| &#42;string | false

docs/scaling/010_overview.adoc

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,21 @@ This is probably not what was desired.
106106
One solution is to always make sure the replicas in the yaml is set to the "correct" value before applying it.
107107
This can be awkward in some environments, and especially if using the Kubernetes HPA to control scaling.
108108
109-
=== The Solution
109+
=== The Solutions
110110
111-
If you intend to use `kubectl scale` or the Kubernetes HPA to control scaling then it is best to not set the
111+
If you intend to use `kubectl scale` or the Kubernetes HPA to control scaling there are two options to fix the
112+
issue described above.
113+
114+
1: <<replicas_not_set,Do not set the replicas field.>>
115+
116+
2: <<initial_replicas_set,Set the initial cluster size using the `initialReplicas` field.>>
117+
118+
[#replicas_not_set]
119+
==== 1: Do Not Set Replicas
120+
121+
If you intend to use `kubectl scale` or the Kubernetes HPA to control scaling then you can choose not to set the
112122
`replicas` field in the YAML file used to create and update the Coherence cluster.
123+
The operator will then create a cluster with the default three replicas.
113124
114125
For example, the initial YAML above could have been created like this:
115126
@@ -145,6 +156,34 @@ stay at whatever value it was scaled to.
145156
Another solution would be to create the initial YAML with the `replicas` field set to the desired initial size.
146157
Then later when applying updates, ensure that the `replicas` field has been deleted from the YAML file.
147158
159+
[#initial_replicas_set]
160+
==== 2: Use the `initialReplicas` Field
161+
162+
The `Coherence` resource spec contains an `initialReplicas` field which can be used to specify the initial size of the
163+
cluster. This field can be used when a cluster needs an initial size greater or smaller than the operator's default
164+
size of three replicas.
165+
166+
For example, the yaml below will create a StatefulSet with a replica count of six.
167+
[source,yaml]
168+
.storage-cluster.yaml
169+
----
170+
apiVersion: coherence.oracle.com/v1
171+
kind: Coherence
172+
metadata:
173+
name: storage
174+
spec:
175+
initialReplicas: 6
176+
----
177+
178+
[NOTE]
179+
====
180+
If both the `initialReplicas` field and the `replicas` field are set then the `replicas` field willl be used to set the cluster size.
181+
====
182+
183+
When the Coherence cluster is scaled using either the HPA or the `kubectl scale` command then they will set the `replicas`
184+
field in the Coherence spec which will scale up or down the cluster.
185+
When an upgrade is performed by editing the original yaml that contains no `replicas` field and only the `initialReplicas`
186+
field the resulting patch applied will not change whatever the current `replicas` value is that was set by the HPA or scale command.
148187
149188
== Controlling Safe Scaling
150189

0 commit comments

Comments
 (0)