diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index ba353b83b..118868610 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -5,7 +5,7 @@ on: branches: [ main ] env: - GO_VERSION: 1.19.1 + GO_VERSION: 1.19.2 K8S_VERSION: v1.24.1 jobs: diff --git a/.github/workflows/prometheus-rules.yml b/.github/workflows/prometheus-rules.yml index 9638ed0bb..7fb322486 100644 --- a/.github/workflows/prometheus-rules.yml +++ b/.github/workflows/prometheus-rules.yml @@ -7,7 +7,7 @@ on: - observability/prometheus/rules/**/*.y*ml env: - GO_VERSION: 1.19.1 + GO_VERSION: 1.19.2 jobs: rules: diff --git a/api/v1beta1/rabbitmqcluster_types.go b/api/v1beta1/rabbitmqcluster_types.go index 7a11744ff..627cf76d8 100644 --- a/api/v1beta1/rabbitmqcluster_types.go +++ b/api/v1beta1/rabbitmqcluster_types.go @@ -84,6 +84,16 @@ type RabbitmqClusterSpec struct { // +kubebuilder:validation:Minimum:=0 // +kubebuilder:default:=604800 TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"` + // DelayStartSeconds is the time the init container (`setup-container`) will sleep before terminating. + // This effectively delays the time between starting the Pod and starting the `rabbitmq` container. + // RabbitMQ relies on up-to-date DNS entries early during peer discovery. + // The purpose of this artificial delay is to ensure that DNS entries are up-to-date when booting RabbitMQ. + // For more information, see https://github.com/kubernetes/kubernetes/issues/92559 + // If your Kubernetes DNS backend is configured with a low DNS cache value or publishes not ready addresses + // promptly, you can decrase this value or set it to 0. + // +kubebuilder:validation:Minimum:=0 + // +kubebuilder:default:=30 + DelayStartSeconds *int32 `json:"delayStartSeconds,omitempty"` // Secret backend configuration for the RabbitmqCluster. // Enables to fetch default user credentials and certificates from K8s external secret stores. SecretBackend SecretBackend `json:"secretBackend,omitempty"` diff --git a/api/v1beta1/rabbitmqcluster_types_test.go b/api/v1beta1/rabbitmqcluster_types_test.go index fcdd26ead..71293f9df 100644 --- a/api/v1beta1/rabbitmqcluster_types_test.go +++ b/api/v1beta1/rabbitmqcluster_types_test.go @@ -512,6 +512,7 @@ func generateRabbitmqClusterObject(clusterName string) *RabbitmqCluster { Spec: RabbitmqClusterSpec{ Replicas: pointer.Int32Ptr(1), TerminationGracePeriodSeconds: pointer.Int64Ptr(604800), + DelayStartSeconds: pointer.Int32Ptr(30), Service: RabbitmqClusterServiceSpec{ Type: "ClusterIP", }, diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 4e89d32da..73eea12a4 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -377,6 +377,11 @@ func (in *RabbitmqClusterSpec) DeepCopyInto(out *RabbitmqClusterSpec) { *out = new(int64) **out = **in } + if in.DelayStartSeconds != nil { + in, out := &in.DelayStartSeconds, &out.DelayStartSeconds + *out = new(int32) + **out = **in + } in.SecretBackend.DeepCopyInto(&out.SecretBackend) } diff --git a/config/crd/bases/rabbitmq.com_rabbitmqclusters.yaml b/config/crd/bases/rabbitmq.com_rabbitmqclusters.yaml index 32e8f70e3..783e03c1b 100644 --- a/config/crd/bases/rabbitmq.com_rabbitmqclusters.yaml +++ b/config/crd/bases/rabbitmq.com_rabbitmqclusters.yaml @@ -10,7 +10,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.9.2 + controller-gen.kubebuilder.io/version: v0.10.0 creationTimestamp: null name: rabbitmqclusters.rabbitmq.com spec: @@ -525,6 +525,12 @@ spec: type: array type: object type: object + delayStartSeconds: + default: 30 + description: DelayStartSeconds is the time the init container (`setup-container`) will sleep before terminating. This effectively delays the time between starting the Pod and starting the `rabbitmq` container. RabbitMQ relies on up-to-date DNS entries early during peer discovery. The purpose of this artificial delay is to ensure that DNS entries are up-to-date when booting RabbitMQ. For more information, see https://github.com/kubernetes/kubernetes/issues/92559 If your Kubernetes DNS backend is configured with a low DNS cache value or publishes not ready addresses promptly, you can decrase this value or set it to 0. + format: int32 + minimum: 0 + type: integer image: description: Image is the name of the RabbitMQ docker image to use for RabbitMQ nodes in the RabbitmqCluster. Must be provided together with ImagePullSecrets in order to use an image in a private registry. type: string diff --git a/docs/api/rabbitmq.com.ref.asciidoc b/docs/api/rabbitmq.com.ref.asciidoc index 2c52fab49..04919eb70 100644 --- a/docs/api/rabbitmq.com.ref.asciidoc +++ b/docs/api/rabbitmq.com.ref.asciidoc @@ -309,6 +309,7 @@ Spec is the desired state of the RabbitmqCluster Custom Resource. | *`override`* __xref:{anchor_prefix}-github-com-rabbitmq-cluster-operator-api-v1beta1-rabbitmqclusteroverridespec[$$RabbitmqClusterOverrideSpec$$]__ | Provides the ability to override the generated manifest of several child resources. | *`skipPostDeploySteps`* __boolean__ | If unset, or set to false, the cluster will run `rabbitmq-queues rebalance all` whenever the cluster is updated. Set to true to prevent the operator rebalancing queue leaders after a cluster update. Has no effect if the cluster only consists of one node. For more information, see https://www.rabbitmq.com/rabbitmq-queues.8.html#rebalance | *`terminationGracePeriodSeconds`* __integer__ | TerminationGracePeriodSeconds is the timeout that each rabbitmqcluster pod will have to terminate gracefully. It defaults to 604800 seconds ( a week long) to ensure that the container preStop lifecycle hook can finish running. For more information, see: https://github.com/rabbitmq/cluster-operator/blob/main/docs/design/20200520-graceful-pod-termination.md +| *`delayStartSeconds`* __integer__ | DelayStartSeconds is the time the init container (`setup-container`) will sleep before terminating. This effectively delays the time between starting the Pod and starting the `rabbitmq` container. RabbitMQ relies on up-to-date DNS entries early during peer discovery. The purpose of this artificial delay is to ensure that DNS entries are up-to-date when booting RabbitMQ. For more information, see https://github.com/kubernetes/kubernetes/issues/92559 If your Kubernetes DNS backend is configured with a low DNS cache value or publishes not ready addresses promptly, you can decrase this value or set it to 0. | *`secretBackend`* __xref:{anchor_prefix}-github-com-rabbitmq-cluster-operator-api-v1beta1-secretbackend[$$SecretBackend$$]__ | Secret backend configuration for the RabbitmqCluster. Enables to fetch default user credentials and certificates from K8s external secret stores. |=== diff --git a/internal/resource/statefulset.go b/internal/resource/statefulset.go index 14a8dffe9..11430bddb 100644 --- a/internal/resource/statefulset.go +++ b/internal/resource/statefulset.go @@ -13,6 +13,7 @@ import ( "encoding/json" "fmt" "reflect" + "strconv" "strings" "sigs.k8s.io/controller-runtime/pkg/client" @@ -711,19 +712,20 @@ func setupContainer(instance *rabbitmqv1beta1.RabbitmqCluster) corev1.Container //Init Container resources cpuRequest := k8sresource.MustParse(initContainerCPU) memoryRequest := k8sresource.MustParse(initContainerMemory) - + command := []string{ + "sh", "-c", + "cp /tmp/erlang-cookie-secret/.erlang.cookie /var/lib/rabbitmq/.erlang.cookie " + + "&& chmod 600 /var/lib/rabbitmq/.erlang.cookie ; " + + "cp /tmp/rabbitmq-plugins/enabled_plugins /operator/enabled_plugins ; " + + "echo '[default]' > /var/lib/rabbitmq/.rabbitmqadmin.conf " + + "&& sed -e 's/default_user/username/' -e 's/default_pass/password/' %s >> /var/lib/rabbitmq/.rabbitmqadmin.conf " + + "&& chmod 600 /var/lib/rabbitmq/.rabbitmqadmin.conf ; " + + "sleep " + strconv.Itoa(int(pointer.Int32Deref(instance.Spec.DelayStartSeconds, 30))), + } setupContainer := corev1.Container{ - Name: "setup-container", - Image: instance.Spec.Image, - Command: []string{ - "sh", "-c", - "cp /tmp/erlang-cookie-secret/.erlang.cookie /var/lib/rabbitmq/.erlang.cookie " + - "&& chmod 600 /var/lib/rabbitmq/.erlang.cookie ; " + - "cp /tmp/rabbitmq-plugins/enabled_plugins /operator/enabled_plugins ; " + - "echo '[default]' > /var/lib/rabbitmq/.rabbitmqadmin.conf " + - "&& sed -e 's/default_user/username/' -e 's/default_pass/password/' %s >> /var/lib/rabbitmq/.rabbitmqadmin.conf " + - "&& chmod 600 /var/lib/rabbitmq/.rabbitmqadmin.conf", - }, + Name: "setup-container", + Image: instance.Spec.Image, + Command: command, Resources: corev1.ResourceRequirements{ Limits: corev1.ResourceList{ "cpu": cpuRequest, diff --git a/internal/resource/statefulset_test.go b/internal/resource/statefulset_test.go index 3e099e1aa..6f9af5189 100644 --- a/internal/resource/statefulset_test.go +++ b/internal/resource/statefulset_test.go @@ -936,7 +936,7 @@ default_pass = {{ .Data.data.password }} "cp /tmp/rabbitmq-plugins/enabled_plugins /operator/enabled_plugins ; "+ "echo '[default]' > /var/lib/rabbitmq/.rabbitmqadmin.conf "+ "&& sed -e 's/default_user/username/' -e 's/default_pass/password/' /etc/rabbitmq/conf.d/11-default_user.conf >> /var/lib/rabbitmq/.rabbitmqadmin.conf "+ - "&& chmod 600 /var/lib/rabbitmq/.rabbitmqadmin.conf", + "&& chmod 600 /var/lib/rabbitmq/.rabbitmqadmin.conf ; sleep 30", ), "VolumeMounts": Not(ContainElement([]corev1.VolumeMount{ { @@ -1334,7 +1334,7 @@ default_pass = {{ .Data.data.password }} "cp /tmp/rabbitmq-plugins/enabled_plugins /operator/enabled_plugins ; "+ "echo '[default]' > /var/lib/rabbitmq/.rabbitmqadmin.conf "+ "&& sed -e 's/default_user/username/' -e 's/default_pass/password/' /tmp/default_user.conf >> /var/lib/rabbitmq/.rabbitmqadmin.conf "+ - "&& chmod 600 /var/lib/rabbitmq/.rabbitmqadmin.conf", + "&& chmod 600 /var/lib/rabbitmq/.rabbitmqadmin.conf ; sleep 30", ), "VolumeMounts": ConsistOf([]corev1.VolumeMount{ { @@ -2282,6 +2282,7 @@ func generateRabbitmqCluster() rabbitmqv1beta1.RabbitmqCluster { Image: "rabbitmq-image-from-cr", ImagePullSecrets: []corev1.LocalObjectReference{{Name: "my-super-secret"}}, TerminationGracePeriodSeconds: pointer.Int64Ptr(604800), + DelayStartSeconds: pointer.Int32Ptr(30), Service: rabbitmqv1beta1.RabbitmqClusterServiceSpec{ Type: "this-is-a-service", Annotations: map[string]string{},