Skip to content

Commit 08d5122

Browse files
pengzhoumlPeng Zhou
and
Peng Zhou
authored
MLE-15979 add missing reconciliation logic in enhance deployment (#14)
* MLE-15979: add missing reconciliation logic for MarkLogic Group * add hugepage resource to unit test * add complete sample * update to CRD * fix testing as per review comment * Implementation for huge page support * Add testing for Hugepages * remove debug logging --------- Co-authored-by: Peng Zhou <[email protected]>
1 parent 994e08f commit 08d5122

10 files changed

+2092
-249
lines changed

api/v1alpha1/common_types.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,17 @@ type ContainerProbe struct {
1919
}
2020

2121
// Storage is the inteface to add pvc and pv support in marklogic
22-
2322
type Storage struct {
2423
Size string `json:"size,omitempty"`
2524
VolumeMount VolumeMountWrapper `json:"volumeMount,omitempty"`
2625
}
2726

27+
type HugePages struct {
28+
Enabled bool `json:"enabled,omitempty"`
29+
// +kubebuilder:default:="/dev/hugepages"
30+
MountPath string `json:"mountPath,omitempty"`
31+
}
32+
2833
type VolumeMountWrapper struct {
2934
Volume []corev1.Volume `json:"volume,omitempty"`
3035
MountPath []corev1.VolumeMount `json:"mountPath,omitempty"`

api/v1alpha1/marklogicgroup_types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ type MarklogicGroupSpec struct {
5757
TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"`
5858
PriorityClassName string `json:"priorityClassName,omitempty"`
5959

60+
// +kubebuilder:default:={enabled: false, mountPath: "/dev/hugepages"}
61+
HugePages *HugePages `json:"hugePages,omitempty"`
62+
6063
// +kubebuilder:default:={enabled: true, initialDelaySeconds: 30, timeoutSeconds: 5, periodSeconds: 30, successThreshold: 1, failureThreshold: 3}
6164
LivenessProbe ContainerProbe `json:"livenessProbe,omitempty"`
6265
// +kubebuilder:default:={enabled: false, initialDelaySeconds: 10, timeoutSeconds: 5, periodSeconds: 30, successThreshold: 1, failureThreshold: 3}

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

charts/marklogic-operator/templates/marklogiccluster-crd.yaml

Lines changed: 470 additions & 56 deletions
Large diffs are not rendered by default.

charts/marklogic-operator/templates/marklogicgroup-crd.yaml

Lines changed: 467 additions & 55 deletions
Large diffs are not rendered by default.

config/crd/bases/database.marklogic.com_marklogicclusters.yaml

Lines changed: 483 additions & 57 deletions
Large diffs are not rendered by default.

config/crd/bases/database.marklogic.com_marklogicgroups.yaml

Lines changed: 480 additions & 56 deletions
Large diffs are not rendered by default.

config/samples/complete.yaml

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
apiVersion: database.marklogic.com/v1alpha1
2+
kind: MarklogicGroup
3+
metadata:
4+
labels:
5+
app.kubernetes.io/name: marklogicgroup
6+
app.kubernetes.io/instance: marklogicgroup-sample
7+
app.kubernetes.io/part-of: marklogic-kubernetes-operator
8+
app.kubernetes.io/managed-by: kustomize
9+
app.kubernetes.io/created-by: marklogic-kubernetes-operator
10+
name: marklogicgroup-sample
11+
spec:
12+
replicas: 1
13+
name: marklogic
14+
image: "progressofficial/marklogic-db:11.3.0-ubi-rootless"
15+
auth:
16+
adminUsername: user
17+
adminPassword: pass
18+
# storage:
19+
# size: 10Gi
20+
terminationGracePeriodSeconds: 9
21+
updateStrategy: OnDelete
22+
clusterDomain: cluster.local
23+
priorityClassName: "system-node-critical"
24+
# groupConfig:
25+
# name: "node"
26+
enableConverters: true
27+
hugePages:
28+
enabled: true
29+
mountPath: /dev/hugepages
30+
nodeSelector:
31+
node-role.kubernetes.io/master: "true"
32+
affinity:
33+
podAntiAffinity:
34+
preferredDuringSchedulingIgnoredDuringExecution:
35+
- weight: 100
36+
podAffinityTerm:
37+
labelSelector:
38+
matchExpressions:
39+
- key: app.kubernetes.io/name
40+
operator: In
41+
values:
42+
- marklogic
43+
topologyKey: kubernetes.io/hostname
44+
topologySpreadConstraints:
45+
- maxSkew: 1
46+
topologyKey: kubernetes.io/hostname
47+
whenUnsatisfiable: DoNotSchedule
48+
labelSelector:
49+
matchLabels:
50+
app.kubernetes.io/name: marklogic
51+
- maxSkew: 1
52+
topologyKey: topology.kubernetes.io/zone
53+
whenUnsatisfiable: ScheduleAnyway
54+
labelSelector:
55+
matchLabels:
56+
app.kubernetes.io/name: marklogic
57+
resources:
58+
requests:
59+
memory: "4Gi"
60+
cpu: "1"
61+
# When using huge pages requests should equal limits
62+
# refer to https://kubernetes.io/docs/tasks/manage-hugepages/scheduling-hugepages/ for more information on huge pages
63+
# hugepages-2Mi: 100Mi
64+
limits:
65+
memory: "4Gi"
66+
cpu: "1"
67+
# hugepages-2Mi: 100Mi
68+
livenessProbe:
69+
enabled: true
70+
initialDelaySeconds: 31
71+
periodSeconds: 11
72+
timeoutSeconds: 6
73+
successThreshold: 1
74+
failureThreshold: 4
75+
readinessProbe:
76+
enabled: true
77+
initialDelaySeconds: 29
78+
periodSeconds: 9
79+
timeoutSeconds: 4
80+
successThreshold: 1
81+
failureThreshold: 2

internal/controller/marklogicgroup_controller_test.go

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,27 @@ const (
4242
)
4343

4444
var replicas = int32(2)
45-
var cpu = int64(1)
46-
var memory = int64(268435456)
45+
46+
const resourceCpuValue = int64(1)
47+
const resourceMemoryValue = int64(268435456)
48+
49+
// 100Mi
50+
const resourceHugepageValue = int64(104857600)
51+
4752
var typeNamespaceName = types.NamespacedName{Name: Name, Namespace: Namespace}
4853

49-
const imageName = "marklogicdb/marklogic-db:11.1.0-centos-1.1.1"
54+
const imageName = "progressofficial/marklogic-db:11.3.0-ubi-rootless"
5055

5156
var groupConfig = databasev1alpha1.GroupConfig{
5257
Name: "dnode",
5358
EnableXdqpSsl: true,
5459
}
5560

61+
var hugePages = databasev1alpha1.HugePages{
62+
Enabled: true,
63+
MountPath: "/dev/hugepages",
64+
}
65+
5666
var _ = Describe("MarkLogicGroup controller", func() {
5767
Context("When creating an MarklogicGroup", func() {
5868
ctx := context.Background()
@@ -79,8 +89,9 @@ var _ = Describe("MarkLogicGroup controller", func() {
7989
Image: imageName,
8090
GroupConfig: groupConfig,
8191
EnableConverters: true,
92+
HugePages: &hugePages,
8293
UpdateStrategy: "OnDelete",
83-
Resources: &corev1.ResourceRequirements{Requests: corev1.ResourceList{"cpu": resource.MustParse("100m"), "memory": resource.MustParse("256Mi")}, Limits: corev1.ResourceList{"cpu": resource.MustParse("100m"), "memory": resource.MustParse("256Mi")}},
94+
Resources: &corev1.ResourceRequirements{Requests: corev1.ResourceList{"cpu": resource.MustParse("100m"), "memory": resource.MustParse("256Mi"), "hugepages-2Mi": resource.MustParse("100Mi")}, Limits: corev1.ResourceList{"cpu": resource.MustParse("100m"), "memory": resource.MustParse("256Mi"), "hugepages-2Mi": resource.MustParse("100Mi")}},
8495
PriorityClassName: "high-priority",
8596
ClusterDomain: "cluster.local",
8697
TopologySpreadConstraints: []corev1.TopologySpreadConstraint{{MaxSkew: 2, TopologyKey: "kubernetes.io/hostname", WhenUnsatisfiable: corev1.ScheduleAnyway}},
@@ -100,10 +111,16 @@ var _ = Describe("MarkLogicGroup controller", func() {
100111
Expect(createdCR.Name).Should(Equal(Name))
101112
Expect(createdCR.Spec.GroupConfig).Should(Equal(groupConfig))
102113
Expect(createdCR.Spec.EnableConverters).Should(Equal(true))
103-
Expect(createdCR.Spec.Resources.Limits.Cpu().Value()).Should(Equal(cpu))
104-
Expect(createdCR.Spec.Resources.Limits.Memory().Value()).Should(Equal(memory))
105-
Expect(createdCR.Spec.Resources.Requests.Cpu().Value()).Should(Equal(cpu))
106-
Expect(createdCR.Spec.Resources.Requests.Memory().Value()).Should(Equal(memory))
114+
Expect(createdCR.Spec.HugePages.Enabled).Should(Equal(true))
115+
Expect(createdCR.Spec.HugePages.MountPath).Should(Equal("/dev/hugepages"))
116+
Expect(createdCR.Spec.Resources.Limits.Cpu().Value()).Should(Equal(resourceCpuValue))
117+
Expect(createdCR.Spec.Resources.Limits.Memory().Value()).Should(Equal(resourceMemoryValue))
118+
hugepagesLimit := createdCR.Spec.Resources.Limits["hugepages-2Mi"]
119+
Expect(hugepagesLimit.Value()).Should(Equal(resourceHugepageValue))
120+
Expect(createdCR.Spec.Resources.Requests.Cpu().Value()).Should(Equal(resourceCpuValue))
121+
Expect(createdCR.Spec.Resources.Requests.Memory().Value()).Should(Equal(resourceMemoryValue))
122+
hugepagesRequest := createdCR.Spec.Resources.Requests["hugepages-2Mi"]
123+
Expect(hugepagesRequest.Value()).Should(Equal(resourceHugepageValue))
107124
Expect(createdCR.Spec.UpdateStrategy).Should(Equal(appsv1.OnDeleteStatefulSetStrategyType))
108125
Expect(createdCR.Spec.PriorityClassName).Should(Equal("high-priority"))
109126
Expect(createdCR.Spec.ClusterDomain).Should(Equal("cluster.local"))

pkg/k8sutil/statefulset.go

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@ import (
2121
type statefulSetParameters struct {
2222
Replicas *int32
2323
Name string
24-
Metadata metav1.ObjectMeta
2524
PersistentVolumeClaim corev1.PersistentVolumeClaim
2625
TerminationGracePeriodSeconds *int64
2726
UpdateStrategy appsv1.StatefulSetUpdateStrategyType
27+
NodeSelector map[string]string
28+
Affinity *corev1.Affinity
29+
TopologySpreadConstraints []corev1.TopologySpreadConstraint
30+
PriorityClassName string
2831
}
2932

3033
type containerParameters struct {
@@ -43,6 +46,8 @@ type containerParameters struct {
4346
LivenessProbe databasev1alpha1.ContainerProbe
4447
ReadinessProbe databasev1alpha1.ContainerProbe
4548
GroupConfig databasev1alpha1.GroupConfig
49+
EnableConverters bool
50+
HugePages *databasev1alpha1.HugePages
4651
}
4752

4853
func (oc *OperatorContext) ReconcileStatefulset() (reconcile.Result, error) {
@@ -188,7 +193,11 @@ func generateStatefulSetsDef(stsMeta metav1.ObjectMeta, params statefulSetParame
188193
Spec: corev1.PodSpec{
189194
Containers: generateContainerDef(stsMeta.GetName(), containerParams),
190195
TerminationGracePeriodSeconds: params.TerminationGracePeriodSeconds,
191-
Volumes: generateVolumes(stsMeta.Name),
196+
Volumes: generateVolumes(stsMeta.Name, containerParams),
197+
NodeSelector: params.NodeSelector,
198+
Affinity: params.Affinity,
199+
TopologySpreadConstraints: params.TopologySpreadConstraints,
200+
PriorityClassName: params.PriorityClassName,
192201
},
193202
},
194203
},
@@ -227,17 +236,18 @@ func generateContainerDef(name string, containerParams containerParameters) []co
227236
ImagePullPolicy: containerParams.ImagePullPolicy,
228237
Env: getEnvironmentVariables(containerParams),
229238
Lifecycle: getLifeCycle(),
230-
VolumeMounts: getVolumeMount(),
239+
VolumeMounts: getVolumeMount(containerParams),
231240
},
232241
}
233242
if containerParams.Resources != nil {
234243
containerDef[0].Resources = *containerParams.Resources
235244
}
236-
if containerParams.LivenessProbe.Enabled == true {
245+
246+
if containerParams.LivenessProbe.Enabled {
237247
containerDef[0].LivenessProbe = getLivenessProbe(containerParams.LivenessProbe)
238248
}
239249

240-
if containerParams.ReadinessProbe.Enabled == true {
250+
if containerParams.ReadinessProbe.Enabled {
241251
containerDef[0].ReadinessProbe = getReadinessProbe(containerParams.ReadinessProbe)
242252
}
243253

@@ -250,6 +260,10 @@ func generateStatefulSetsParams(cr *databasev1alpha1.MarklogicGroup) statefulSet
250260
Name: cr.Spec.Name,
251261
TerminationGracePeriodSeconds: cr.Spec.TerminationGracePeriodSeconds,
252262
UpdateStrategy: cr.Spec.UpdateStrategy,
263+
NodeSelector: cr.Spec.NodeSelector,
264+
Affinity: cr.Spec.Affinity,
265+
TopologySpreadConstraints: cr.Spec.TopologySpreadConstraints,
266+
PriorityClassName: cr.Spec.PriorityClassName,
253267
}
254268
if cr.Spec.Storage != nil {
255269
params.PersistentVolumeClaim = generatePVCTemplate(cr.Spec.Storage.Size)
@@ -260,15 +274,16 @@ func generateStatefulSetsParams(cr *databasev1alpha1.MarklogicGroup) statefulSet
260274
func generateContainerParams(cr *databasev1alpha1.MarklogicGroup) containerParameters {
261275
trueProperty := true
262276
containerParams := containerParameters{
263-
Image: cr.Spec.Image,
264-
Resources: cr.Spec.Resources,
265-
Name: cr.Spec.Name,
266-
Namespace: cr.Namespace,
267-
ClusterDomain: cr.Spec.ClusterDomain,
268-
BootstrapHost: cr.Spec.BootstrapHost,
269-
LivenessProbe: cr.Spec.LivenessProbe,
270-
ReadinessProbe: cr.Spec.ReadinessProbe,
271-
GroupConfig: cr.Spec.GroupConfig,
277+
Image: cr.Spec.Image,
278+
Resources: cr.Spec.Resources,
279+
Name: cr.Spec.Name,
280+
Namespace: cr.Namespace,
281+
ClusterDomain: cr.Spec.ClusterDomain,
282+
BootstrapHost: cr.Spec.BootstrapHost,
283+
LivenessProbe: cr.Spec.LivenessProbe,
284+
ReadinessProbe: cr.Spec.ReadinessProbe,
285+
GroupConfig: cr.Spec.GroupConfig,
286+
EnableConverters: cr.Spec.EnableConverters,
272287
}
273288

274289
if cr.Spec.Storage != nil {
@@ -283,6 +298,9 @@ func generateContainerParams(cr *databasev1alpha1.MarklogicGroup) containerParam
283298
containerParams.LicenseKey = cr.Spec.License.Key
284299
containerParams.Licensee = cr.Spec.License.Licensee
285300
}
301+
if cr.Spec.HugePages.Enabled {
302+
containerParams.HugePages = cr.Spec.HugePages
303+
}
286304

287305
return containerParams
288306
}
@@ -302,7 +320,7 @@ func getLifeCycle() *corev1.Lifecycle {
302320
}
303321
}
304322

305-
func generateVolumes(stsName string) []corev1.Volume {
323+
func generateVolumes(stsName string, containerParams containerParameters) []corev1.Volume {
306324
volumes := []corev1.Volume{}
307325
volumes = append(volumes, corev1.Volume{
308326
Name: "helm-scripts",
@@ -322,6 +340,17 @@ func generateVolumes(stsName string) []corev1.Volume {
322340
},
323341
},
324342
})
343+
if containerParams.HugePages.Enabled {
344+
volumes = append(volumes, corev1.Volume{
345+
Name: "huge-pages",
346+
VolumeSource: corev1.VolumeSource{
347+
EmptyDir: &corev1.EmptyDirVolumeSource{
348+
Medium: corev1.StorageMediumHugePages,
349+
},
350+
},
351+
})
352+
}
353+
325354
return volumes
326355
}
327356

@@ -364,6 +393,10 @@ func getEnvironmentVariables(containerParams containerParameters) []corev1.EnvVa
364393
Name: "MARKLOGIC_CLUSTER_TYPE",
365394
Value: "bootstrap",
366395
},
396+
corev1.EnvVar{
397+
Name: "INSTALL_CONVERTERS",
398+
Value: strconv.FormatBool(containerParams.EnableConverters),
399+
},
367400
)
368401
if containerParams.LicenseKey != "" {
369402
envVars = append(envVars, corev1.EnvVar{
@@ -390,7 +423,7 @@ func getEnvironmentVariables(containerParams containerParameters) []corev1.EnvVa
390423
return envVars
391424
}
392425

393-
func getVolumeMount() []corev1.VolumeMount {
426+
func getVolumeMount(containerParams containerParameters) []corev1.VolumeMount {
394427
var VolumeMounts []corev1.VolumeMount
395428

396429
// if persistenceEnabled != nil && *persistenceEnabled {
@@ -409,6 +442,14 @@ func getVolumeMount() []corev1.VolumeMount {
409442
ReadOnly: true,
410443
},
411444
)
445+
if containerParams.HugePages.Enabled {
446+
VolumeMounts = append(VolumeMounts,
447+
corev1.VolumeMount{
448+
Name: "huge-pages",
449+
MountPath: containerParams.HugePages.MountPath,
450+
},
451+
)
452+
}
412453
return VolumeMounts
413454
}
414455

0 commit comments

Comments
 (0)