Skip to content

Commit e36ca3a

Browse files
committed
docs: recipe on readiness probes
Signed-off-by: Gabriele Bartolini <[email protected]>
1 parent 3a03cce commit e36ca3a

File tree

8 files changed

+285
-0
lines changed

8 files changed

+285
-0
lines changed
277 KB
Loading
98.1 KB
Loading
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
---
2+
title: "CNPG Recipe 20 – Finer Control of Postgres Clusters with Readiness Probes"
3+
date: 2025-06-25T08:04:00+02:00
4+
description: "how CloudNativePG leverages Kubernetes readiness probes to give users more reliable and configurable control over PostgreSQL in high-availability clusters"
5+
tags: ["postgresql", "postgres", "kubernetes", "k8s", "cloudnativepg", "cnpg", "postgresql", "postgres", "dok", "data on kubernetes", "probes", "cncf", "startup", "pg_isready", "readiness", "streaming", "maximumLag"]
6+
cover: cover.jpg
7+
thumb: thumb.jpg
8+
draft: false
9+
---
10+
11+
_Explore the new readiness probe introduced in CloudNativePG 1.26, which
12+
advances Kubernetes-native lifecycle management for PostgreSQL. Building on the
13+
improved probing infrastructure discussed in my previous article, this piece
14+
focuses on how readiness probes ensure that only fully synchronised and healthy
15+
instances—particularly replicas—are eligible to serve traffic or be promoted to
16+
primary. Special emphasis is placed on the `streaming` probe type and its
17+
integration with synchronous replication, giving administrators
18+
fine-grained control over failover behaviour and data consistency._
19+
20+
<!--more-->
21+
22+
---
23+
24+
In the previous article —
25+
[CNPG Recipe 19 - Finer Control Over Postgres Startup with Probes]({{< relref "../20250617-startup-probes/index.md" >}})
26+
— I covered the first set of enhancements to the
27+
[probing infrastructure in CloudNativePG 1.26](https://github.com/cloudnative-pg/cloudnative-pg/pull/6623),
28+
focusing on the startup process of a Postgres instance.
29+
30+
In this follow-up, I’ll continue the discussion with a closer look at
31+
CloudNativePG’s brand-new **readiness probe**.
32+
33+
---
34+
35+
## Understanding Readiness Probes
36+
37+
[Readiness probes](https://kubernetes.io/docs/concepts/configuration/liveness-readiness-startup-probes/#readiness-probe)
38+
have been part of Kubernetes since the beginning. Their purpose is to determine
39+
whether a running container is *ready* to accept traffic—for example, whether
40+
it should be included in a `Service`’s endpoints.
41+
42+
Unlike the startup probe, which runs only once at container start, the
43+
readiness probe kicks in *after* the startup probe succeeds and continues
44+
running for the entire lifetime of the container.
45+
46+
As mentioned in the previous article, readiness probes share the same
47+
configuration parameters as startup and liveness probes:
48+
49+
- `failureThreshold`
50+
- `periodSeconds`
51+
- `successThreshold`
52+
- `timeoutSeconds`
53+
54+
---
55+
56+
## Why Readiness Probes Matter for Postgres
57+
58+
Readiness probes play a critical role in ensuring that only Postgres instances
59+
fully prepared to handle client connections are exposed through Kubernetes
60+
Services.
61+
They prevent traffic from being routed to pods that may be technically running
62+
but are still recovering, replaying WAL files, or catching up as replicas.
63+
64+
Beyond traffic management, the concept of readiness can also be extended to
65+
evaluate a replica’s eligibility for promotion—a direction we’ve taken in
66+
CloudNativePG, as I’ll explain later in this article.
67+
68+
## How CloudNativePG Implements Readiness Probes
69+
70+
Unlike startup probes, CloudNativePG ships with a fixed default configuration
71+
for readiness probes:
72+
73+
```yaml
74+
failureThreshold: 3
75+
periodSeconds: 10
76+
successThreshold: 1
77+
timeoutSeconds: 5
78+
```
79+
80+
By default, the probe uses the `pg_isready` utility to determine whether the
81+
Postgres instance is ready—just like the startup probe; if `pg_isready` fails
82+
three consecutive times, with a 10-second interval between attempts, the
83+
`postgres` container is marked as *not ready*.
84+
85+
However, you can fully customise the readiness probe by defining the
86+
`.spec.probes.readiness` stanza in your cluster configuration—just like the
87+
[*Advanced mode* described in the startup probe article]({{< relref "../20250617-startup-probes/index.md#advanced-mode-full-probe-customisation" >}}).
88+
89+
## Full Probe Customisation
90+
91+
For scenarios that require finer control, CloudNativePG allows you to customise
92+
the readiness probe through the `.spec.probes.readiness` stanza. This lets you
93+
explicitly define the probe parameters introduced earlier in this article.
94+
95+
The following example configures Kubernetes to:
96+
97+
- Probe the container every 10 seconds (`periodSeconds`)
98+
- Tolerate up to 6 consecutive failures (`failureThreshold`)—equivalent to one
99+
minute—before marking the container as *not ready*
100+
101+
```yaml
102+
{{< include "yaml/freddie-custom.yaml" >}}
103+
```
104+
105+
This approach is particularly useful when the default settings don’t match your
106+
workload’s characteristics—especially when fine-tuning `failureThreshold`.
107+
108+
As you may have noticed, these settings apply uniformly to all PostgreSQL
109+
instance pods, regardless of whether they are primaries or standbys.
110+
111+
Now, let’s explore the rest of the capabilities—starting with my favourite:
112+
replica-specific configuration.
113+
114+
## Probe Strategies
115+
116+
Readiness probe strategies in CloudNativePG work just like those for startup
117+
probes, with the key difference being when they are executed and the parameter
118+
used: `.spec.probes.readiness.type`. For a detailed explanation of the
119+
different strategies, please refer to the previous article.
120+
121+
To summarise, the default type is `pg_isready`, but you can also choose from
122+
`query` and `streaming`.
123+
124+
For example, the following cluster configuration uses a `query`-based strategy
125+
for both the startup and readiness probes:
126+
127+
```yaml
128+
{{< include "yaml/freddie-query.yaml" >}}
129+
```
130+
131+
The rest of this article focuses on the `streaming` strategy and its impact on
132+
replicas within a CloudNativePG high-availability (HA) cluster.
133+
134+
## Readiness Probes on Replicas
135+
136+
While configuring a readiness probe on a primary is relatively
137+
straightforward—mostly a matter of tuning the right parameters and letting
138+
`pg_isready` do its job—it’s on replicas that CloudNativePG’s Kubernetes-native
139+
approach truly shines.
140+
141+
The key idea we’ve adopted is to extend the concept of *readiness* to also
142+
influence automated promotion decisions. In certain scenarios, you may want the
143+
cluster to remain without a leader temporarily, to preserve data integrity and
144+
prevent a lagging replica from being promoted prematurely.
145+
146+
By setting the probe `type` to `streaming`, a replica is considered *ready*
147+
only if it is actively streaming from the primary. This ensures that only
148+
healthy, up-to-date replicas are eligible for client traffic—and potentially
149+
for promotion.
150+
151+
In more advanced setups, you can further tighten promotion criteria by ensuring
152+
that any replica with non-zero lag—based on the most recent readiness probe—is
153+
excluded from promotion. This behaviour requires synchronous replication to be
154+
enabled. The following manifest demonstrates this configuration:
155+
156+
```yaml
157+
{{< include "yaml/freddie-streaming.yaml" >}}
158+
```
159+
160+
In this example, the readiness probe checks every 10 seconds and allows up to 6
161+
consecutive failures before marking the replica as *not ready*. The
162+
`maximumLag: 0` setting ensures that any replica consistently showing even
163+
minimal lag is excluded from being considered ready.
164+
165+
With synchronous replication enabled as shown above, PostgreSQL requires that
166+
each transaction be acknowledged by at least one standby before a successful
167+
`COMMIT` is returned to the application. Because PostgreSQL treats all eligible
168+
replicas equally when forming the synchronous quorum, even minimal replication
169+
lag can cause readiness probes to *flap*—frequently switching between ready and
170+
not ready states.
171+
172+
For instance, if a replica is located in an availability zone with slightly
173+
higher network latency, it may consistently fall just behind the primary enough
174+
to be marked as *not ready* by the probe.
175+
176+
This can lead to the replica being temporarily removed from read services and
177+
disqualified from promotion. While this behaviour might be acceptable or even
178+
desirable in some cases, it’s important to fully understand and account for the
179+
operational consequences. In any case, be sure to tune these probe settings
180+
carefully according to the specifics of your environment and your tolerance for
181+
lag before you use this setup in production.
182+
183+
## Key Takeaways
184+
185+
By default, readiness probes in CloudNativePG help ensure that PostgreSQL
186+
instances are functioning correctly and ready to serve traffic—writes for
187+
primaries, reads for Hot Standby replicas.
188+
189+
While the default `pg_isready`-based readiness probe is usually sufficient for
190+
primaries, replicas often benefit from stricter checks. As you've seen in this
191+
article, the `streaming` probe type—especially when combined with the
192+
`maximumLag` setting and synchronous replication— provides a powerful mechanism
193+
to enforce tighter consistency guarantees and to prevent *non-ready* replicas
194+
from being promoted. (And yes, I do recommend enabling synchronous replication
195+
in production, even if it comes with a slight performance cost.)
196+
197+
Now, if you're wondering, *“What’s the recommended setup for me?”*—the honest
198+
answer is: *It depends*. I know that’s not the clear-cut advice you might have
199+
hoped for, but there’s no one-size-fits-all solution. The goal of this article
200+
is to equip you with the knowledge and tools to make an informed choice that
201+
best suits your environment and requirements.
202+
203+
At the very least, you now have a rich set of options in CloudNativePG to
204+
design your PostgreSQL cluster’s readiness strategy with precision.
205+
206+
---
207+
208+
Stay tuned for the upcoming recipes! For the latest updates, consider
209+
subscribing to my [LinkedIn](https://www.linkedin.com/in/gbartolini/) and
210+
[Twitter](https://twitter.com/_GBartolini_) channels.
211+
212+
If you found this article informative, feel free to share it within your
213+
network on social media using the provided links below. Your support is
214+
immensely appreciated!
215+
216+
_Cover Picture: [“Tanzanian Elephant“](https://commons.wikimedia.org/wiki/File:Tanzanian_Elephant.jpg)._
217+
107 KB
Loading
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
apiVersion: postgresql.cnpg.io/v1
2+
kind: Cluster
3+
metadata:
4+
name: freddie
5+
spec:
6+
instances: 3
7+
8+
storage:
9+
size: 1Gi
10+
11+
probes:
12+
readiness:
13+
periodSeconds: 10
14+
failureThreshold: 6
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
apiVersion: postgresql.cnpg.io/v1
2+
kind: Cluster
3+
metadata:
4+
name: freddie
5+
spec:
6+
instances: 3
7+
8+
storage:
9+
size: 1Gi
10+
11+
probes:
12+
startup:
13+
type: query
14+
periodSeconds: 5
15+
failureThreshold: 120
16+
readiness:
17+
type: query
18+
periodSeconds: 10
19+
failureThreshold: 6
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
apiVersion: postgresql.cnpg.io/v1
2+
kind: Cluster
3+
metadata:
4+
name: freddie
5+
spec:
6+
instances: 3
7+
8+
storage:
9+
size: 1Gi
10+
11+
postgresql:
12+
synchronous:
13+
method: any
14+
number: 1
15+
16+
probes:
17+
startup:
18+
type: streaming
19+
maximumLag: 32Mi
20+
periodSeconds: 5
21+
failureThreshold: 120
22+
readiness:
23+
type: streaming
24+
maximumLag: 0
25+
periodSeconds: 10
26+
failureThreshold: 6
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
apiVersion: postgresql.cnpg.io/v1
2+
kind: Cluster
3+
metadata:
4+
name: freddie
5+
spec:
6+
instances: 3
7+
8+
storage:
9+
size: 1Gi

0 commit comments

Comments
 (0)