From 4aa065fa92d4c50ab7fe080c8bbaa42e3bb1ead1 Mon Sep 17 00:00:00 2001 From: micheleRP Date: Mon, 15 Sep 2025 13:27:41 -0600 Subject: [PATCH 01/17] DOC-1643 single source client connections in docs --- .../configure-availability.adoc | 24 ++++++++++++++++++- .../pages/properties/cluster-properties.adoc | 11 +++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/modules/manage/pages/cluster-maintenance/configure-availability.adoc b/modules/manage/pages/cluster-maintenance/configure-availability.adoc index b0d6da05d..89db71596 100644 --- a/modules/manage/pages/cluster-maintenance/configure-availability.adoc +++ b/modules/manage/pages/cluster-maintenance/configure-availability.adoc @@ -1,6 +1,7 @@ = Configure Client Connections :description: Guidelines for configuring Redpanda clusters for optimal availability. :page-categories: Management, Networking +// tag::single-source[] Optimize the availability of your clusters by configuring and tuning properties. @@ -10,14 +11,16 @@ A malicious Kafka client application may create many network connections to exec The following Redpanda cluster properties limit the number of connections: -* xref:reference:cluster-properties.adoc#kafka_connections_max[`kafka_connections_max`]: Similar to Kafka's `max.connections`, this sets the maximum number of connections per broker. * xref:reference:cluster-properties.adoc#kafka_connections_max_per_ip[`kafka_connections_max_per_ip`]: Similar to Kafka's `max.connections.per.ip`, this sets the maximum number of connections accepted per IP address by a broker. * xref:reference:cluster-properties.adoc#kafka_connections_max_overrides[`kafka_connections_max_overrides`]: A list of IP addresses for which `kafka_connections_max_per_ip` is overridden and doesn't apply. +ifndef::env-cloud[] +* xref:reference:cluster-properties.adoc#kafka_connections_max[`kafka_connections_max`]: Similar to Kafka's `max.connections`, this sets the maximum number of connections per broker. Redpanda also provides properties to manage the rate of connection creation: * xref:reference:cluster-properties.adoc#kafka_connection_rate_limit[`kafka_connection_rate_limit`]: This property limits the maximum rate of connections created per second. It applies to each CPU core. * xref:reference:cluster-properties.adoc#kafka_connection_rate_limit_overrides[`kafka_connection_rate_limit_overrides`]: A list of IP addresses for which `kafka_connection_rate_limit` is overridden and doesn't apply. +endif::[] [NOTE] ==== @@ -46,10 +49,21 @@ See also: xref:develop:produce-data/configure-producers.adoc[Configure Producers A Redpanda broker may create log segments at startup. If a broker crashes after startup, and if it gets stuck in a crash loop, it could produce progressively more stored state that uses more disk space and takes more time for each restart to process. +ifndef::env-cloud[] To prevent infinite crash loops, the Redpanda broker property xref:reference:node-properties.adoc#crash_loop_limit[`crash_loop_limit`] sets an upper limit on the number of consecutive crashes that can happen within one hour of each other. After it reaches the limit, a broker cannot restart until its internal consecutive crash counter is reset to zero by one of the following conditions: +endif::[] + +ifdef::env-cloud[] +To prevent infinite crash loops, the Redpanda broker property [`crash_loop_limit`] sets an upper limit on the number of consecutive crashes that can happen within one hour of each other. After it reaches the limit, a broker cannot restart until its internal consecutive crash counter is reset to zero by one of the following conditions: +endif::[] * The `redpanda.yaml` configuration file is updated. +ifndef::env-cloud[] * The `startup_log` file in the broker's xref:reference:node-properties.adoc#data_directory[data_directory] is manually deleted. +endif::[] +ifdef::env-cloud[] +* The `startup_log` file in the broker's `data_directory` is manually deleted. +endif::[] * One hour has elapsed since the last crash. * The broker is properly shut down. (This is not possible after `crash_loop_limit` has been reached and the broker cannot be restarted.) @@ -59,4 +73,12 @@ To prevent infinite crash loops, the Redpanda broker property xref:reference:nod * If the limit is less than two, the broker is blocked from restarting after every crash, until one of the reset conditions is met. ==== +ifndef::env-cloud[] To facilitate debugging in environments where a broker is stuck in a crash loop, set the xref:reference:properties/broker-properties.adoc#crash_loop_sleep_sec[`crash_loop_sleep_sec` configuration]. This setting determines how long the broker sleeps before terminating the process after reaching the crash loop limit. The window during which the broker remains available allows you to troubleshoot the issue. This setting is most useful when xref:troubleshoot:errors-solutions/k-resolve-errors.adoc[troubleshooting in Kubernetes environments]. +endif::[] + +ifdef::env-cloud[] +To facilitate debugging in environments where a broker is stuck in a crash loop, set the `crash_loop_sleep_sec` configuration. This setting determines how long the broker sleeps before terminating the process after reaching the crash loop limit. The window during which the broker remains available allows you to troubleshoot the issue. +endif::[] + +// end::single-source[] diff --git a/modules/reference/pages/properties/cluster-properties.adoc b/modules/reference/pages/properties/cluster-properties.adoc index 54b421f0b..9c40eee32 100644 --- a/modules/reference/pages/properties/cluster-properties.adoc +++ b/modules/reference/pages/properties/cluster-properties.adoc @@ -2862,6 +2862,7 @@ Maximum number of Kafka client connections per broker. If `null`, the property i --- +// tag::kafka_connections_max_overrides[] === kafka_connections_max_overrides A list of IP addresses for which Kafka client connection limits are overridden and don't apply. For example, `(['127.0.0.1:90', '50.20.1.1:40']).`. @@ -2872,7 +2873,9 @@ A list of IP addresses for which Kafka client connection limits are overridden a *Type:* array +ifndef::env-cloud[] *Default*: `{}` (empty list) +endif::[] *Related topics*: @@ -2880,6 +2883,10 @@ A list of IP addresses for which Kafka client connection limits are overridden a --- + +// end::kafka_connections_max_overrides[] + +// tag::kafka_connections_max_per_ip[] === kafka_connections_max_per_ip Maximum number of Kafka client connections per IP address, per broker. If `null`, the property is disabled. @@ -2892,7 +2899,9 @@ Maximum number of Kafka client connections per IP address, per broker. If `null` *Accepted values:* [`0`, `4294967295`] +ifndef::env-cloud[] *Default:* `null` +endif::[] *Related topics*: @@ -2900,6 +2909,8 @@ Maximum number of Kafka client connections per IP address, per broker. If `null` --- +// end::kafka_connections_max_per_ip[] + === kafka_enable_authorization Flag to require authorization for Kafka connections. If `null`, the property is disabled, and authorization is instead enabled by <>. From 25bdef4761f0431bdaa9aa33a63214472036562d Mon Sep 17 00:00:00 2001 From: micheleRP Date: Mon, 15 Sep 2025 13:35:37 -0600 Subject: [PATCH 02/17] update playbook for linking PR previews --- local-antora-playbook.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-antora-playbook.yml b/local-antora-playbook.yml index 955308112..8552bd422 100644 --- a/local-antora-playbook.yml +++ b/local-antora-playbook.yml @@ -17,7 +17,7 @@ content: - url: https://github.com/redpanda-data/docs branches: [v/*, shared, site-search,'!v-end-of-life/*'] - url: https://github.com/redpanda-data/cloud-docs - branches: 'main' + branches: 'DOC-1673-single-source-client-connections-in-cloud-docs' - url: https://github.com/redpanda-data/redpanda-labs branches: main start_paths: [docs,'*/docs'] From 29e45496d28c931336e6199d7162b59f8c6d7817 Mon Sep 17 00:00:00 2001 From: micheleRP Date: Mon, 15 Sep 2025 13:49:01 -0600 Subject: [PATCH 03/17] minor edits for Cloud --- .../pages/cluster-maintenance/configure-availability.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/manage/pages/cluster-maintenance/configure-availability.adoc b/modules/manage/pages/cluster-maintenance/configure-availability.adoc index 89db71596..f03067e50 100644 --- a/modules/manage/pages/cluster-maintenance/configure-availability.adoc +++ b/modules/manage/pages/cluster-maintenance/configure-availability.adoc @@ -54,7 +54,7 @@ To prevent infinite crash loops, the Redpanda broker property xref:reference:nod endif::[] ifdef::env-cloud[] -To prevent infinite crash loops, the Redpanda broker property [`crash_loop_limit`] sets an upper limit on the number of consecutive crashes that can happen within one hour of each other. After it reaches the limit, a broker cannot restart until its internal consecutive crash counter is reset to zero by one of the following conditions: +To prevent infinite crash loops, the Redpanda broker property `crash_loop_limit` sets an upper limit on the number of consecutive crashes that can happen within one hour of each other. After it reaches the limit, a broker cannot restart until its internal consecutive crash counter is reset to zero by one of the following conditions: endif::[] * The `redpanda.yaml` configuration file is updated. @@ -74,11 +74,11 @@ endif::[] ==== ifndef::env-cloud[] -To facilitate debugging in environments where a broker is stuck in a crash loop, set the xref:reference:properties/broker-properties.adoc#crash_loop_sleep_sec[`crash_loop_sleep_sec` configuration]. This setting determines how long the broker sleeps before terminating the process after reaching the crash loop limit. The window during which the broker remains available allows you to troubleshoot the issue. This setting is most useful when xref:troubleshoot:errors-solutions/k-resolve-errors.adoc[troubleshooting in Kubernetes environments]. +To facilitate debugging in environments where a broker is stuck in a crash loop, set the xref:reference:properties/broker-properties.adoc#crash_loop_sleep_sec[`crash_loop_sleep_sec`] broker property. This setting determines how long the broker sleeps before terminating the process after reaching the crash loop limit. The window during which the broker remains available allows you to troubleshoot the issue. This setting is most useful when xref:troubleshoot:errors-solutions/k-resolve-errors.adoc[troubleshooting in Kubernetes environments]. endif::[] ifdef::env-cloud[] -To facilitate debugging in environments where a broker is stuck in a crash loop, set the `crash_loop_sleep_sec` configuration. This setting determines how long the broker sleeps before terminating the process after reaching the crash loop limit. The window during which the broker remains available allows you to troubleshoot the issue. +To facilitate debugging in environments where a broker is stuck in a crash loop, set the `crash_loop_sleep_sec` broker property. This setting determines how long the broker sleeps before terminating the process after reaching the crash loop limit. The window during which the broker remains available allows you to troubleshoot the issue. endif::[] // end::single-source[] From 67472465e7ebd2f911385ec7abb4e861c78036c2 Mon Sep 17 00:00:00 2001 From: micheleRP Date: Mon, 15 Sep 2025 13:58:35 -0600 Subject: [PATCH 04/17] fix links --- .../pages/cluster-maintenance/configure-availability.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/manage/pages/cluster-maintenance/configure-availability.adoc b/modules/manage/pages/cluster-maintenance/configure-availability.adoc index f03067e50..51915a01d 100644 --- a/modules/manage/pages/cluster-maintenance/configure-availability.adoc +++ b/modules/manage/pages/cluster-maintenance/configure-availability.adoc @@ -11,10 +11,10 @@ A malicious Kafka client application may create many network connections to exec The following Redpanda cluster properties limit the number of connections: -* xref:reference:cluster-properties.adoc#kafka_connections_max_per_ip[`kafka_connections_max_per_ip`]: Similar to Kafka's `max.connections.per.ip`, this sets the maximum number of connections accepted per IP address by a broker. -* xref:reference:cluster-properties.adoc#kafka_connections_max_overrides[`kafka_connections_max_overrides`]: A list of IP addresses for which `kafka_connections_max_per_ip` is overridden and doesn't apply. +* xref:reference:properties/cluster-properties.adoc#kafka_connections_max_per_ip[`kafka_connections_max_per_ip`]: Similar to Kafka's `max.connections.per.ip`, this sets the maximum number of connections accepted per IP address by a broker. +* xref:reference:properties/cluster-properties.adoc#kafka_connections_max_overrides[`kafka_connections_max_overrides`]: A list of IP addresses for which `kafka_connections_max_per_ip` is overridden and doesn't apply. ifndef::env-cloud[] -* xref:reference:cluster-properties.adoc#kafka_connections_max[`kafka_connections_max`]: Similar to Kafka's `max.connections`, this sets the maximum number of connections per broker. +* xref:reference:properties/cluster-properties.adoc#kafka_connections_max[`kafka_connections_max`]: Similar to Kafka's `max.connections`, this sets the maximum number of connections per broker. Redpanda also provides properties to manage the rate of connection creation: From a8115cbb63f7b7656240896f7c8a896dafb454f0 Mon Sep 17 00:00:00 2001 From: micheleRP Date: Mon, 15 Sep 2025 14:19:25 -0600 Subject: [PATCH 05/17] minor edits --- .../pages/cluster-maintenance/configure-availability.adoc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/manage/pages/cluster-maintenance/configure-availability.adoc b/modules/manage/pages/cluster-maintenance/configure-availability.adoc index 51915a01d..2d9b90560 100644 --- a/modules/manage/pages/cluster-maintenance/configure-availability.adoc +++ b/modules/manage/pages/cluster-maintenance/configure-availability.adoc @@ -1,5 +1,5 @@ = Configure Client Connections -:description: Guidelines for configuring Redpanda clusters for optimal availability. +:description: Learn about guidelines for configuring client connections in Redpanda clusters for optimal availability. :page-categories: Management, Networking // tag::single-source[] @@ -16,6 +16,10 @@ The following Redpanda cluster properties limit the number of connections: ifndef::env-cloud[] * xref:reference:properties/cluster-properties.adoc#kafka_connections_max[`kafka_connections_max`]: Similar to Kafka's `max.connections`, this sets the maximum number of connections per broker. +ifdef::env-cloud[] +IMPORTANT: Per-IP connection controls require Redpanda to see individual client IPs. If clients connect through PrivateLink endpoints, NAT gateways, or other shared-IP egress, the per-IP limit applies to the shared IP, affecting all clients behind it and preventing isolation of a single offending client. +endif::[] + Redpanda also provides properties to manage the rate of connection creation: * xref:reference:cluster-properties.adoc#kafka_connection_rate_limit[`kafka_connection_rate_limit`]: This property limits the maximum rate of connections created per second. It applies to each CPU core. From 20513655747b25e8b3660eb4873f04e4ea56410c Mon Sep 17 00:00:00 2001 From: micheleRP Date: Mon, 15 Sep 2025 14:28:05 -0600 Subject: [PATCH 06/17] fix ifdef --- .../cluster-maintenance/configure-availability.adoc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/manage/pages/cluster-maintenance/configure-availability.adoc b/modules/manage/pages/cluster-maintenance/configure-availability.adoc index 2d9b90560..100c9c546 100644 --- a/modules/manage/pages/cluster-maintenance/configure-availability.adoc +++ b/modules/manage/pages/cluster-maintenance/configure-availability.adoc @@ -16,14 +16,14 @@ The following Redpanda cluster properties limit the number of connections: ifndef::env-cloud[] * xref:reference:properties/cluster-properties.adoc#kafka_connections_max[`kafka_connections_max`]: Similar to Kafka's `max.connections`, this sets the maximum number of connections per broker. -ifdef::env-cloud[] -IMPORTANT: Per-IP connection controls require Redpanda to see individual client IPs. If clients connect through PrivateLink endpoints, NAT gateways, or other shared-IP egress, the per-IP limit applies to the shared IP, affecting all clients behind it and preventing isolation of a single offending client. -endif::[] - Redpanda also provides properties to manage the rate of connection creation: -* xref:reference:cluster-properties.adoc#kafka_connection_rate_limit[`kafka_connection_rate_limit`]: This property limits the maximum rate of connections created per second. It applies to each CPU core. -* xref:reference:cluster-properties.adoc#kafka_connection_rate_limit_overrides[`kafka_connection_rate_limit_overrides`]: A list of IP addresses for which `kafka_connection_rate_limit` is overridden and doesn't apply. +* xref:reference:properties/cluster-properties.adoc#kafka_connection_rate_limit[`kafka_connection_rate_limit`]: This property limits the maximum rate of connections created per second. It applies to each CPU core. +* xref:reference:properties/cluster-properties.adoc#kafka_connection_rate_limit_overrides[`kafka_connection_rate_limit_overrides`]: A list of IP addresses for which `kafka_connection_rate_limit` is overridden and doesn't apply. +endif::[] + +ifdef::env-cloud[] +IMPORTANT: Per-IP connection controls require Redpanda to see individual client IPs. If clients connect through PrivateLink endpoints, NAT gateways, or other shared-IP egress, the per-IP limit applies to the shared IP, affecting all clients behind it and preventing isolation of a single offending client. endif::[] [NOTE] From 4ef6a9d493913426f7b5191130297a73c0b72d3e Mon Sep 17 00:00:00 2001 From: micheleRP Date: Mon, 15 Sep 2025 14:42:59 -0600 Subject: [PATCH 07/17] minor nav update --- modules/ROOT/nav.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ROOT/nav.adoc b/modules/ROOT/nav.adoc index 4c3727305..8ee0ddafb 100644 --- a/modules/ROOT/nav.adoc +++ b/modules/ROOT/nav.adoc @@ -161,7 +161,7 @@ *** xref:manage:cluster-maintenance/disk-utilization.adoc[] *** xref:manage:cluster-maintenance/manage-throughput.adoc[Manage Throughput] *** xref:manage:cluster-maintenance/compaction-settings.adoc[Compaction Settings] -*** xref:manage:cluster-maintenance/configure-availability.adoc[Configure Availability] +*** xref:manage:cluster-maintenance/configure-availability.adoc[] *** xref:manage:cluster-maintenance/partition-recovery.adoc[Forced Partition Recovery] *** xref:manage:cluster-maintenance/nodewise-partition-recovery.adoc[Node-wise Partition Recovery] ** xref:manage:security/index.adoc[Security] From 890694600da63d82c76189e8866d4e9d6fdfa78f Mon Sep 17 00:00:00 2001 From: micheleRP Date: Mon, 15 Sep 2025 17:06:57 -0600 Subject: [PATCH 08/17] conditionalize out crash loops for Cloud --- .../configure-availability.adoc | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/modules/manage/pages/cluster-maintenance/configure-availability.adoc b/modules/manage/pages/cluster-maintenance/configure-availability.adoc index 100c9c546..d3a70d63a 100644 --- a/modules/manage/pages/cluster-maintenance/configure-availability.adoc +++ b/modules/manage/pages/cluster-maintenance/configure-availability.adoc @@ -49,25 +49,15 @@ Additionally, you can use Kafka properties to control message retry behavior. De See also: xref:develop:produce-data/configure-producers.adoc[Configure Producers] +ifndef::env-cloud[] == Prevent crash loops A Redpanda broker may create log segments at startup. If a broker crashes after startup, and if it gets stuck in a crash loop, it could produce progressively more stored state that uses more disk space and takes more time for each restart to process. -ifndef::env-cloud[] To prevent infinite crash loops, the Redpanda broker property xref:reference:node-properties.adoc#crash_loop_limit[`crash_loop_limit`] sets an upper limit on the number of consecutive crashes that can happen within one hour of each other. After it reaches the limit, a broker cannot restart until its internal consecutive crash counter is reset to zero by one of the following conditions: -endif::[] - -ifdef::env-cloud[] -To prevent infinite crash loops, the Redpanda broker property `crash_loop_limit` sets an upper limit on the number of consecutive crashes that can happen within one hour of each other. After it reaches the limit, a broker cannot restart until its internal consecutive crash counter is reset to zero by one of the following conditions: -endif::[] * The `redpanda.yaml` configuration file is updated. -ifndef::env-cloud[] * The `startup_log` file in the broker's xref:reference:node-properties.adoc#data_directory[data_directory] is manually deleted. -endif::[] -ifdef::env-cloud[] -* The `startup_log` file in the broker's `data_directory` is manually deleted. -endif::[] * One hour has elapsed since the last crash. * The broker is properly shut down. (This is not possible after `crash_loop_limit` has been reached and the broker cannot be restarted.) @@ -77,12 +67,7 @@ endif::[] * If the limit is less than two, the broker is blocked from restarting after every crash, until one of the reset conditions is met. ==== -ifndef::env-cloud[] To facilitate debugging in environments where a broker is stuck in a crash loop, set the xref:reference:properties/broker-properties.adoc#crash_loop_sleep_sec[`crash_loop_sleep_sec`] broker property. This setting determines how long the broker sleeps before terminating the process after reaching the crash loop limit. The window during which the broker remains available allows you to troubleshoot the issue. This setting is most useful when xref:troubleshoot:errors-solutions/k-resolve-errors.adoc[troubleshooting in Kubernetes environments]. endif::[] -ifdef::env-cloud[] -To facilitate debugging in environments where a broker is stuck in a crash loop, set the `crash_loop_sleep_sec` broker property. This setting determines how long the broker sleeps before terminating the process after reaching the crash loop limit. The window during which the broker remains available allows you to troubleshoot the issue. -endif::[] - // end::single-source[] From 6e1f9aa4439d69c668c9646b3e9966a2ddd37aca Mon Sep 17 00:00:00 2001 From: micheleRP Date: Mon, 15 Sep 2025 17:22:41 -0600 Subject: [PATCH 09/17] clarification about Kafka client properties --- .../pages/cluster-maintenance/configure-availability.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/manage/pages/cluster-maintenance/configure-availability.adoc b/modules/manage/pages/cluster-maintenance/configure-availability.adoc index d3a70d63a..e4a8f03fe 100644 --- a/modules/manage/pages/cluster-maintenance/configure-availability.adoc +++ b/modules/manage/pages/cluster-maintenance/configure-availability.adoc @@ -36,7 +36,7 @@ endif::[] You can configure the Kafka client backoff and retry properties to change the default behavior of the clients to suit your failure requirements. -The following Kafka properties let you manage client reconnections: +Set the following Kafka client properties on your application's producer or consumer to manage client reconnections: * `reconnect.backoff.ms`: Amount of time to wait before attempting to reconnect to the broker. The default is 50 milliseconds. * `reconnect.backoff.max.ms`: Maximum amount of time in milliseconds to wait when reconnecting to a broker. The backoff increases exponentially for each consecutive connection failure, up to this maximum. The default is 1000 milliseconds (1 second). From 548245ac369fe983b506618103dac4a9ff9372a1 Mon Sep 17 00:00:00 2001 From: micheleRP Date: Mon, 15 Sep 2025 19:06:19 -0600 Subject: [PATCH 10/17] add config specific to cloud, with limitations --- .../configure-availability.adoc | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/modules/manage/pages/cluster-maintenance/configure-availability.adoc b/modules/manage/pages/cluster-maintenance/configure-availability.adoc index e4a8f03fe..d7cdf5737 100644 --- a/modules/manage/pages/cluster-maintenance/configure-availability.adoc +++ b/modules/manage/pages/cluster-maintenance/configure-availability.adoc @@ -22,16 +22,54 @@ Redpanda also provides properties to manage the rate of connection creation: * xref:reference:properties/cluster-properties.adoc#kafka_connection_rate_limit_overrides[`kafka_connection_rate_limit_overrides`]: A list of IP addresses for which `kafka_connection_rate_limit` is overridden and doesn't apply. endif::[] -ifdef::env-cloud[] -IMPORTANT: Per-IP connection controls require Redpanda to see individual client IPs. If clients connect through PrivateLink endpoints, NAT gateways, or other shared-IP egress, the per-IP limit applies to the shared IP, affecting all clients behind it and preventing isolation of a single offending client. -endif::[] - [NOTE] ==== * These connection limit properties are disabled by default. You must manually enable them. * Typically, a client opens two or three connections, so the total number of connections is not equal to the number of clients. For example, to support 100 clients, you might set your connection limit to 300. ==== +ifdef::env-cloud[] +=== Configure connection count limit by client IP + +Use the `kafka_connections_max_per_ip` property to limit the number of connections from each client IP address. + +IMPORTANT: Per-IP connection controls require Redpanda to see individual client IPs. If clients connect through PrivateLink endpoints, NAT gateways, or other shared-IP egress, the per-IP limit applies to the shared IP, affecting all clients behind it and preventing isolation of a single offending client. + +==== Configure the limit + +To configure `kafka_connections_max_per_ip` safely without disrupting legitimate clients, follow these steps: + +. Set up metrics scraping into your monitoring stack for the relevant cluster. See xref:manage:monitor-cloud.adoc[]. + +. Monitor current connection patterns using the `redpanda_rpc_active_connections` metric with the `redpanda_server="kafka"` filter: ++ +``` +redpanda_rpc_active_connections{redpanda_id="CLOUD_CLUSTER_ID", redpanda_server="kafka"} +``` + +. Analyze the connection data to identify the normal range of connections per IP address during typical traffic cycles. + +. Set the `kafka_connections_max_per_ip` value based on your analysis: +** Use the upper bound of normal connections from step 3, OR +** Use a lower value if you know the expected connections per client (typically 2-3 connections per client) + +. Continue monitoring the connection metrics after applying the limit to ensure: +** Legitimate clients are not affected +** The problematic client is properly controlled + +==== Limitations + +* Decreasing the limit does not terminate any currently open Kafka API connections. +* This limit does not apply to Kafka HTTP Proxy connections. +* The limit may negatively affect tail latencies across all client connections. +* Clients behind NAT gateways or private links share the same IP address as seen by Redpanda brokers. +* All clients behind the shared IP are collectively subject to the single `kafka_connections_max_per_ip` limit. +* Connection rejections occur randomly among clients once the limit is reached. For example: If `kafka_connections_max_per_ip` is set to 100, but clients behind a NAT gateway collectively need 150 connections, whichever client attempts the 101st connection gets rejected. +* Redpanda may modify this property during internal operations. +* Availability incidents caused by misconfiguring this feature are excluded from the Redpanda Cloud SLA. + +endif::env-cloud[] + == Configure client reconnections You can configure the Kafka client backoff and retry properties to change the default behavior of the clients to suit your failure requirements. From d15e72eee37dd930737364d3690b1052365bf2d9 Mon Sep 17 00:00:00 2001 From: micheleRP Date: Tue, 16 Sep 2025 11:44:32 -0600 Subject: [PATCH 11/17] remove Prevent crash loops section from this page --- .../configure-availability.adoc | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/modules/manage/pages/cluster-maintenance/configure-availability.adoc b/modules/manage/pages/cluster-maintenance/configure-availability.adoc index d7cdf5737..200752f09 100644 --- a/modules/manage/pages/cluster-maintenance/configure-availability.adoc +++ b/modules/manage/pages/cluster-maintenance/configure-availability.adoc @@ -87,25 +87,4 @@ Additionally, you can use Kafka properties to control message retry behavior. De See also: xref:develop:produce-data/configure-producers.adoc[Configure Producers] -ifndef::env-cloud[] -== Prevent crash loops - -A Redpanda broker may create log segments at startup. If a broker crashes after startup, and if it gets stuck in a crash loop, it could produce progressively more stored state that uses more disk space and takes more time for each restart to process. - -To prevent infinite crash loops, the Redpanda broker property xref:reference:node-properties.adoc#crash_loop_limit[`crash_loop_limit`] sets an upper limit on the number of consecutive crashes that can happen within one hour of each other. After it reaches the limit, a broker cannot restart until its internal consecutive crash counter is reset to zero by one of the following conditions: - -* The `redpanda.yaml` configuration file is updated. -* The `startup_log` file in the broker's xref:reference:node-properties.adoc#data_directory[data_directory] is manually deleted. -* One hour has elapsed since the last crash. -* The broker is properly shut down. (This is not possible after `crash_loop_limit` has been reached and the broker cannot be restarted.) - -[NOTE] -==== -* The `crash_loop_limit` property is disabled by default. You must manually enable it by setting it to a non-zero value. -* If the limit is less than two, the broker is blocked from restarting after every crash, until one of the reset conditions is met. -==== - -To facilitate debugging in environments where a broker is stuck in a crash loop, set the xref:reference:properties/broker-properties.adoc#crash_loop_sleep_sec[`crash_loop_sleep_sec`] broker property. This setting determines how long the broker sleeps before terminating the process after reaching the crash loop limit. The window during which the broker remains available allows you to troubleshoot the issue. This setting is most useful when xref:troubleshoot:errors-solutions/k-resolve-errors.adoc[troubleshooting in Kubernetes environments]. -endif::[] - // end::single-source[] From 674fb6a2b6b38388b94de5059406eb73bccce320 Mon Sep 17 00:00:00 2001 From: micheleRP Date: Tue, 16 Sep 2025 11:47:55 -0600 Subject: [PATCH 12/17] incorporate Camilo's feedback --- .../pages/cluster-maintenance/configure-availability.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/manage/pages/cluster-maintenance/configure-availability.adoc b/modules/manage/pages/cluster-maintenance/configure-availability.adoc index 200752f09..43cee4bce 100644 --- a/modules/manage/pages/cluster-maintenance/configure-availability.adoc +++ b/modules/manage/pages/cluster-maintenance/configure-availability.adoc @@ -47,7 +47,7 @@ To configure `kafka_connections_max_per_ip` safely without disrupting legitimate redpanda_rpc_active_connections{redpanda_id="CLOUD_CLUSTER_ID", redpanda_server="kafka"} ``` -. Analyze the connection data to identify the normal range of connections per IP address during typical traffic cycles. +. Analyze the connection data to identify the normal range of connections for each broker during typical traffic cycles. . Set the `kafka_connections_max_per_ip` value based on your analysis: ** Use the upper bound of normal connections from step 3, OR From 2b6963afe4760270fabe41e78502a2b85a126f2e Mon Sep 17 00:00:00 2001 From: micheleRP Date: Tue, 16 Sep 2025 16:04:21 -0600 Subject: [PATCH 13/17] incorporate doc review --- .../cluster-maintenance/configure-availability.adoc | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/modules/manage/pages/cluster-maintenance/configure-availability.adoc b/modules/manage/pages/cluster-maintenance/configure-availability.adoc index 43cee4bce..739a97d03 100644 --- a/modules/manage/pages/cluster-maintenance/configure-availability.adoc +++ b/modules/manage/pages/cluster-maintenance/configure-availability.adoc @@ -39,7 +39,7 @@ IMPORTANT: Per-IP connection controls require Redpanda to see individual client To configure `kafka_connections_max_per_ip` safely without disrupting legitimate clients, follow these steps: -. Set up metrics scraping into your monitoring stack for the relevant cluster. See xref:manage:monitor-cloud.adoc[]. +. Set up your monitoring stack for your cluster. See xref:manage:monitor-cloud.adoc[]. . Monitor current connection patterns using the `redpanda_rpc_active_connections` metric with the `redpanda_server="kafka"` filter: + @@ -49,20 +49,15 @@ redpanda_rpc_active_connections{redpanda_id="CLOUD_CLUSTER_ID", redpanda_server= . Analyze the connection data to identify the normal range of connections for each broker during typical traffic cycles. -. Set the `kafka_connections_max_per_ip` value based on your analysis: -** Use the upper bound of normal connections from step 3, OR -** Use a lower value if you know the expected connections per client (typically 2-3 connections per client) +. Set the `kafka_connections_max_per_ip` value based on your analysis. Use the upper bound of normal connections from step 3, or use a lower value if you know how many connections per client are being opened. -. Continue monitoring the connection metrics after applying the limit to ensure: -** Legitimate clients are not affected -** The problematic client is properly controlled +. Continue monitoring the connection metrics after applying the limit to ensure that legitimate clients are not affected and that the problematic client is properly controlled. ==== Limitations * Decreasing the limit does not terminate any currently open Kafka API connections. -* This limit does not apply to Kafka HTTP Proxy connections. +* This limit does not apply to HTTP Proxy connections. * The limit may negatively affect tail latencies across all client connections. -* Clients behind NAT gateways or private links share the same IP address as seen by Redpanda brokers. * All clients behind the shared IP are collectively subject to the single `kafka_connections_max_per_ip` limit. * Connection rejections occur randomly among clients once the limit is reached. For example: If `kafka_connections_max_per_ip` is set to 100, but clients behind a NAT gateway collectively need 150 connections, whichever client attempts the 101st connection gets rejected. * Redpanda may modify this property during internal operations. From 235b6a9f85d6c135f0320818148d80a0979e6dd1 Mon Sep 17 00:00:00 2001 From: micheleRP Date: Tue, 16 Sep 2025 17:04:03 -0600 Subject: [PATCH 14/17] incorporate review feedback --- .../configure-availability.adoc | 9 ++++++--- modules/shared/images/monitor_connections.png | Bin 0 -> 67006 bytes 2 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 modules/shared/images/monitor_connections.png diff --git a/modules/manage/pages/cluster-maintenance/configure-availability.adoc b/modules/manage/pages/cluster-maintenance/configure-availability.adoc index 739a97d03..002ad2549 100644 --- a/modules/manage/pages/cluster-maintenance/configure-availability.adoc +++ b/modules/manage/pages/cluster-maintenance/configure-availability.adoc @@ -47,16 +47,19 @@ To configure `kafka_connections_max_per_ip` safely without disrupting legitimate redpanda_rpc_active_connections{redpanda_id="CLOUD_CLUSTER_ID", redpanda_server="kafka"} ``` -. Analyze the connection data to identify the normal range of connections for each broker during typical traffic cycles. +. Analyze the connection data to identify the normal range of connections for each broker during typical traffic cycles. For example, in the following screenshot, the normal pattern per broker is around 200-300 connections: ++ +image::shared:monitor_connections.png[Range of active connections over time] -. Set the `kafka_connections_max_per_ip` value based on your analysis. Use the upper bound of normal connections from step 3, or use a lower value if you know how many connections per client are being opened. +. Set the `kafka_connections_max_per_ip` value based on your analysis. Use the upper bound of normal connections from step 3, or use a lower value if you know how many connections per client IP are being opened. . Continue monitoring the connection metrics after applying the limit to ensure that legitimate clients are not affected and that the problematic client is properly controlled. ==== Limitations * Decreasing the limit does not terminate any currently open Kafka API connections. -* This limit does not apply to HTTP Proxy connections. +* This limit does not apply to Kafka HTTP Proxy connections. +* Clients behind NAT gateways or private links share the same IP address as seen by Redpanda brokers. * The limit may negatively affect tail latencies across all client connections. * All clients behind the shared IP are collectively subject to the single `kafka_connections_max_per_ip` limit. * Connection rejections occur randomly among clients once the limit is reached. For example: If `kafka_connections_max_per_ip` is set to 100, but clients behind a NAT gateway collectively need 150 connections, whichever client attempts the 101st connection gets rejected. diff --git a/modules/shared/images/monitor_connections.png b/modules/shared/images/monitor_connections.png new file mode 100644 index 0000000000000000000000000000000000000000..ee56efd6aee230728a648ba0f90688159b95bd97 GIT binary patch literal 67006 zcmeFZ2Ut@}w=ldB5y65WC;}1{5Tq(aI#H1>ARTEDk={g#fRG@FbP!NbP>>E%a%cu= zkq%0c-lX@QPy=cI)}tQZd(XM|-1ocpe*gD8?}pi#%$~hwR+%+x)~pG6fIJQyQ&m(^ z1Slu~KpFf4$P>U71y5Tm08m#4cmV)72v7vs0{g)nSOs7K69DXcv+qX4{AgY*@&A; zy?6EI%^P1~{`mX`|L1MH?_1x2Zh^0`v{|{PsYjnX7#+3Bcz^b$!Ov=co}s;K>1qK! zB7lk4;@*8XkPtjz{^kR>dtdXOV4m?l*eNg{{xxs?d;ZPW{GH$PCEx1kYRiLln!)@r z3mfyhV15A1^WXWU-1?Wiql5d`cE4U7EmQc-;sJ_=v(Ik2Ceis9^~s|Sv2 znNy#0VHAE8opO-lT44>7b|;2Y75*9vA=OWkPCNdPZhecFx

19S=jIm{vFjU~TiZLh-Mz1PQ2>;` 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 Lb|GZ&UmyPq)5Z;f literal 0 HcmV?d00001 From 1d4d557fe73c3bb3341f28a6e9d8bb7759ee0976 Mon Sep 17 00:00:00 2001 From: micheleRP Date: Tue, 16 Sep 2025 17:20:54 -0600 Subject: [PATCH 15/17] minor edit --- .../pages/cluster-maintenance/configure-availability.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/manage/pages/cluster-maintenance/configure-availability.adoc b/modules/manage/pages/cluster-maintenance/configure-availability.adoc index 002ad2549..2b1bd366b 100644 --- a/modules/manage/pages/cluster-maintenance/configure-availability.adoc +++ b/modules/manage/pages/cluster-maintenance/configure-availability.adoc @@ -47,7 +47,7 @@ To configure `kafka_connections_max_per_ip` safely without disrupting legitimate redpanda_rpc_active_connections{redpanda_id="CLOUD_CLUSTER_ID", redpanda_server="kafka"} ``` -. Analyze the connection data to identify the normal range of connections for each broker during typical traffic cycles. For example, in the following screenshot, the normal pattern per broker is around 200-300 connections: +. Analyze the connection data to identify the normal range of connections for each broker during typical traffic cycles. For example, in the following Grafana screenshot, the normal range is around 200-300 connections: + image::shared:monitor_connections.png[Range of active connections over time] From a14a75ce279d26f0209a3a028606e01824d0da04 Mon Sep 17 00:00:00 2001 From: micheleRP Date: Wed, 17 Sep 2025 09:34:04 -0600 Subject: [PATCH 16/17] incorporate feedback from Travis --- .../pages/cluster-maintenance/configure-availability.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/manage/pages/cluster-maintenance/configure-availability.adoc b/modules/manage/pages/cluster-maintenance/configure-availability.adoc index 2b1bd366b..09330e34a 100644 --- a/modules/manage/pages/cluster-maintenance/configure-availability.adoc +++ b/modules/manage/pages/cluster-maintenance/configure-availability.adoc @@ -25,7 +25,7 @@ endif::[] [NOTE] ==== * These connection limit properties are disabled by default. You must manually enable them. -* Typically, a client opens two or three connections, so the total number of connections is not equal to the number of clients. For example, to support 100 clients, you might set your connection limit to 300. +* The total number of connections is not equal to the number of clients, because a client can open multiple connections. As a conservative estimate, for a cluster with N brokers, plan for N + 2 connections per client. ==== ifdef::env-cloud[] @@ -33,7 +33,7 @@ ifdef::env-cloud[] Use the `kafka_connections_max_per_ip` property to limit the number of connections from each client IP address. -IMPORTANT: Per-IP connection controls require Redpanda to see individual client IPs. If clients connect through PrivateLink endpoints, NAT gateways, or other shared-IP egress, the per-IP limit applies to the shared IP, affecting all clients behind it and preventing isolation of a single offending client. +IMPORTANT: Per-IP connection controls require Redpanda to see individual client IPs. If clients connect through private link endpoints, NAT gateways, or other shared-IP egress, the per-IP limit applies to the shared IP, affecting all clients behind it and preventing isolation of a single offending client. Similarly, multiple clients running on the same host will share the same IP address, and the limit applies collectively to all those clients. ==== Configure the limit @@ -62,7 +62,7 @@ image::shared:monitor_connections.png[Range of active connections over time] * Clients behind NAT gateways or private links share the same IP address as seen by Redpanda brokers. * The limit may negatively affect tail latencies across all client connections. * All clients behind the shared IP are collectively subject to the single `kafka_connections_max_per_ip` limit. -* Connection rejections occur randomly among clients once the limit is reached. For example: If `kafka_connections_max_per_ip` is set to 100, but clients behind a NAT gateway collectively need 150 connections, whichever client attempts the 101st connection gets rejected. +* Connection rejections occur randomly among clients when the limit is reached. For example, suppose `kafka_connections_max_per_ip` is set to 100, but clients behind a NAT gateway collectively need 150 connections. When the limit is reached, clients can make only some of the connections while others get rejected, leaving the client in a not-working state. * Redpanda may modify this property during internal operations. * Availability incidents caused by misconfiguring this feature are excluded from the Redpanda Cloud SLA. From c712d099a202526aef523d98e232cb5ec0190349 Mon Sep 17 00:00:00 2001 From: micheleRP Date: Wed, 17 Sep 2025 13:08:02 -0600 Subject: [PATCH 17/17] revert playbook --- local-antora-playbook.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local-antora-playbook.yml b/local-antora-playbook.yml index 8552bd422..955308112 100644 --- a/local-antora-playbook.yml +++ b/local-antora-playbook.yml @@ -17,7 +17,7 @@ content: - url: https://github.com/redpanda-data/docs branches: [v/*, shared, site-search,'!v-end-of-life/*'] - url: https://github.com/redpanda-data/cloud-docs - branches: 'DOC-1673-single-source-client-connections-in-cloud-docs' + branches: 'main' - url: https://github.com/redpanda-data/redpanda-labs branches: main start_paths: [docs,'*/docs']