Skip to content

Commit 396e5c6

Browse files
authored
Add rabbit memory limit (#403)
* Set RabbitMQ memory override when memory resource limit provided. * Include headroom for Erlang VM in RabbitMQ memory override to avoid being OOM killed.
1 parent 73233e7 commit 396e5c6

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

api/v1beta1/rabbitmqcluster_types.go

+4
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,10 @@ func (cluster *RabbitmqCluster) MutualTLSEnabled() bool {
314314
return cluster.TLSEnabled() && cluster.Spec.TLS.CaSecretName != ""
315315
}
316316

317+
func (cluster *RabbitmqCluster) MemoryLimited() bool {
318+
return cluster.Spec.Resources != nil && cluster.Spec.Resources.Limits != nil && !cluster.Spec.Resources.Limits.Memory().IsZero()
319+
}
320+
317321
func (cluster *RabbitmqCluster) SingleTLSSecret() bool {
318322
return cluster.MutualTLSEnabled() && cluster.Spec.TLS.CaSecretName == cluster.Spec.TLS.SecretName
319323
}

api/v1beta1/rabbitmqcluster_types_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,16 @@ var _ = Describe("RabbitmqCluster", func() {
113113
Expect(created.MutualTLSEnabled()).To(BeTrue())
114114
})
115115

116+
It("can be queried if memory limits are provided", func() {
117+
created := generateRabbitmqClusterObject("rabbit-mem-limit")
118+
Expect(created.MemoryLimited()).To(BeTrue())
119+
120+
created.Spec.Resources = &corev1.ResourceRequirements{
121+
Limits: map[corev1.ResourceName]resource.Quantity{},
122+
}
123+
Expect(created.MemoryLimited()).To(BeFalse())
124+
})
125+
116126
It("is validated", func() {
117127
By("checking the replica count", func() {
118128
nOne := int32(-1)

internal/resource/configmap.go

+17
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ package resource
1212
import (
1313
"bytes"
1414
"fmt"
15+
1516
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
1617

1718
"gopkg.in/ini.v1"
@@ -83,6 +84,12 @@ func (builder *ServerConfigMapBuilder) Update(object runtime.Object) error {
8384
}
8485
}
8586

87+
if builder.Instance.MemoryLimited() {
88+
if _, err := defaultSection.NewKey("total_memory_available_override_value", fmt.Sprintf("%d", removeHeadroom(builder.Instance.Spec.Resources.Limits.Memory().Value()))); err != nil {
89+
return err
90+
}
91+
}
92+
8693
rmqProperties := builder.Instance.Spec.Rabbitmq
8794
if err := cfg.Append([]byte(rmqProperties.AdditionalConfig)); err != nil {
8895
return fmt.Errorf("failed to append spec.rabbitmq.additionalConfig: %w", err)
@@ -125,3 +132,13 @@ func updateProperty(configMapData map[string]string, key string, value string) {
125132
configMapData[key] = value
126133
}
127134
}
135+
136+
// The Erlang VM needs headroom above Rabbit to avoid being OOM killed
137+
// We set the headroom to be the smaller amount of 20% memory or 2GiB
138+
func removeHeadroom(memLimit int64) int64 {
139+
const GiB int64 = 1073741824
140+
if memLimit/5 > 2*GiB {
141+
return memLimit - 2*GiB
142+
}
143+
return memLimit - memLimit/5
144+
}

internal/resource/configmap_test.go

+24
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@
1010
package resource_test
1111

1212
import (
13+
"fmt"
14+
1315
. "github.com/onsi/ginkgo"
1416
. "github.com/onsi/gomega"
1517
rabbitmqv1beta1 "github.com/rabbitmq/cluster-operator/api/v1beta1"
1618
"github.com/rabbitmq/cluster-operator/internal/resource"
1719
corev1 "k8s.io/api/core/v1"
20+
k8sresource "k8s.io/apimachinery/pkg/api/resource"
1821
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1922
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2023
"k8s.io/apimachinery/pkg/runtime"
@@ -249,6 +252,27 @@ ssl_options.verify = verify_peer`)))
249252
})
250253
})
251254

255+
Context("Memory Limits", func() {
256+
It("sets a RabbitMQ memory limit with headroom when memory limits are specified", func() {
257+
const GiB int64 = 1073741824
258+
instance = rabbitmqv1beta1.RabbitmqCluster{
259+
ObjectMeta: metav1.ObjectMeta{
260+
Name: "rabbit-mem-limit",
261+
},
262+
Spec: rabbitmqv1beta1.RabbitmqClusterSpec{
263+
Resources: &corev1.ResourceRequirements{
264+
Limits: map[corev1.ResourceName]k8sresource.Quantity{
265+
corev1.ResourceMemory: k8sresource.MustParse("10Gi"),
266+
},
267+
},
268+
},
269+
}
270+
271+
Expect(configMapBuilder.Update(configMap)).To(Succeed())
272+
Expect(configMap.Data).To(HaveKeyWithValue("rabbitmq.conf", ContainSubstring(fmt.Sprintf("total_memory_available_override_value = %d", 8*GiB))))
273+
})
274+
})
275+
252276
Context("labels", func() {
253277
BeforeEach(func() {
254278
instance = rabbitmqv1beta1.RabbitmqCluster{

0 commit comments

Comments
 (0)