Skip to content

orchestratord: Make environmentd readiness, liveness and startup probes configurable - #40034

Merged
jubrad merged 4 commits into
MaterializeInc:mainfrom
jubrad:environmentd-probes
Oct 23, 2026
Merged

jubrad merged 4 commits into
MaterializeInc:mainfrom
jubrad:environmentd-probes

Conversation

@jubrad

@jubrad jubrad commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Motivation

The environmentd readiness and liveness probes are hardcoded in orchestratord: a TCP check against environmentd's SQL port (the internal one when configured, see #40036 and #40046) with initialDelaySeconds: 1 and failureThreshold: 12. Self-managed operators cannot tune them, and there is no startup probe, so the liveness probe has to be loose enough to cover a slow boot, which limits how quickly it can detect a stuck environmentd.

Description

The readiness and liveness probes can now be configured, and a startup probe can be added, at three layers:

  • Materialize CRD (v1alpha1 and v1): spec.environmentdReadinessProbe, spec.environmentdLivenessProbe and spec.environmentdStartupProbe, of type Probe.
  • orchestratord: --environmentd-default-readiness-probe, --environmentd-default-liveness-probe and --environmentd-default-startup-probe, as JSON, like --environmentd-default-resources.
  • Helm: environmentd.defaultReadinessProbe, environmentd.defaultLivenessProbe and environmentd.defaultStartupProbe (default {}), passed through to the flags above.

Each layer is overlaid onto the one below it, in this order: the built-in probe, then the operator default, then the CR. Only the fields a layer sets change, so environmentdLivenessProbe: {failureThreshold: 60} keeps the built-in TCP check without the CR author having to know the operator's port configuration. Setting any handler (exec, grpc, httpGet, tcpSocket) replaces the inherited handler as a unit, because Kubernetes rejects a probe with more than one.

There is no built-in startup probe, so none runs unless the operator default or the CR sets one. When one is set, it is overlaid onto the same built-in TCP check as the other two.

A probe that sets more than one handler is rejected: orchestratord fails to start if an operator-default flag has one, and reconciling a CR with one fails with an error naming the field. Each layer is checked, so the merged probe always has exactly one handler.

Rollout behavior:

  • On v1, the probe fields are part of the rollout hash, so changing them triggers a rollout, like environmentdResourceRequirements.
  • Unset probes are omitted from the serialized spec, so existing environments keep their hash and upgrading the operator does not trigger a rollout.
  • With nothing configured, the generated StatefulSet is unchanged.

The CRD description data under doc/user/data/self_managed/ is regenerated with crd-writer. The diff only adds the new fields.

Tests

  • generation.rs: unit tests for the probe overlay (no overrides, layered fields, replacing the handler as a unit) and for rejecting multiple handlers.
  • bin/orchestratord.rs: a test that the default probe flags reject a probe with two handlers.
  • materialize.rs: a test that unset probes keep the rollout hash, setting them changes it, and both full-object and partial-object v1/v1alpha1 conversions preserve them.
  • Helm unittest cases in tests/deployment_test.yaml for the three flags with probes set and unset.
  • An EnvironmentdProbes modification in test/orchestratord/mzcompose.py that checks the probes on the running environmentd pod, including that there is no startup probe unless one is configured.

Release notes

This release will allow configuring the environmentd readiness, liveness and startup probes through the Materialize CR (environmentdReadinessProbe, environmentdLivenessProbe, environmentdStartupProbe) and operator-wide through the helm chart (environmentd.defaultReadinessProbe, environmentd.defaultLivenessProbe, environmentd.defaultStartupProbe).

🤖 Generated with Claude Code

@jubrad
jubrad marked this pull request as ready for review October 20, 2026 18:33
@jubrad
jubrad requested review from a team as code owners October 20, 2026 18:33
volume_mounts: Some(volume_mounts),
liveness_probe: Some(probe.clone()),
readiness_probe: Some(probe),
liveness_probe: Some(liveness_probe),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we also desperately need a startup probe. This allows for much better granularity during early bootup vs lifecycle (we don't want the liveness probe to be useless in detecting actual issues).

termination_grace_period_seconds,
timeout_seconds,
} = overlay.clone();
let has_handler =

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like it won't reject if two probe options are set, which is very much required

@jubrad jubrad changed the title orchestratord: Make environmentd readiness and liveness probes configurable orchestratord: Make environmentd readiness, liveness and startup probes configurable Oct 20, 2026
@jubrad
jubrad force-pushed the environmentd-probes branch from 7924019 to 0c0ce48 Compare October 20, 2026 20:02
jubrad added a commit that referenced this pull request Oct 20, 2026
### Motivation

environmentd's readiness and liveness probes are TCP checks against the
external SQL port. environmentd binds that port before it boots but only
accepts connections once the coordinator is up, so connections made
during boot wait in the kernel accept queue (129 entries on Linux with
the current backlog).

balancerd and clients connect to the external SQL port. The TCP
readiness probe passes as soon as the port is bound, so the pod is
marked Ready during boot and receives that traffic. During a long boot,
client connections can fill the queue. Linux then drops new connection
attempts, TCP probes time out, and liveness kills environmentd after 12
consecutive failures. That restarts the boot, which can turn into a
crashloop.

### Description

Point both probes at the internal SQL port
(`--environmentd-internal-sql-port`, 6877 by default) instead.
orchestratord configures the internal SQL listener for every
environmentd version it manages, and client traffic does not use it, so
the probes' queue only fills from the probes themselves. Readiness and
liveness together make about 12 connections a minute, which fills 129
slots after roughly 10 minutes of boot. A larger listen backlog raises
that limit further.

This changes the generated environmentd StatefulSet. After upgrading the
operator, existing environments report pending changes and pick up the
new probe port on their next rollout. They are not restarted on their
own.

This conflicts with the probe configuration in #40034 on the same lines.
Whichever lands second rebases.

### Tests

No new tests. The orchestratord mzcompose tests already wait for
environmentd to become ready, which requires the readiness probe on the
new port to pass.

### Release notes

This release will make environmentd less likely to be restarted by its
liveness probe during a long startup.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <[email protected]>
jubrad and others added 4 commits October 22, 2026 22:25
…urable

Add `environmentdReadinessProbe` and `environmentdLivenessProbe` to both
versions of the Materialize CRD, matching
`--environmentd-default-{readiness,liveness}-probe` orchestratord flags,
and `environmentd.default{Readiness,Liveness}Probe` helm values.

Each layer is overlaid onto the built-in TCP probe against the SQL port,
then the operator default, then the CR. Only fields set in a layer
change, and a handler replaces the previous one as a unit.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…robes

Add `environmentdStartupProbe` to the Materialize CRD, with a matching
`--environmentd-default-startup-probe` flag and
`environmentd.defaultStartupProbe` helm value. No startup probe runs
unless one is configured.

Reject a probe that sets more than one handler, at orchestratord startup
for the operator defaults and at reconcile time for the CR fields.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
`validate_probe_handlers` is public, so its doc must not link to the
private `environmentd_probe`; the Doctests lint rejects that with
`-D warnings`.

The built-in probe targets the internal SQL port only when one is
configured, so describe it as environmentd's SQL port in the CRD and
helm docs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@jubrad
jubrad force-pushed the environmentd-probes branch from 0c0ce48 to 7cd0cd8 Compare October 23, 2026 03:27
@jubrad
jubrad merged commit 8b9ee08 into MaterializeInc:main Oct 23, 2026
87 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants