Skip to content

Let a deployment state its own probes, and fix CRD generation - #13

Merged
wasabii merged 1 commit into
mainfrom
fix/probes-and-crd-generation
Sep 6, 2026
Merged

wasabii merged 1 commit into
mainfrom
fix/probes-and-crd-generation

Conversation

@wasabii

@wasabii wasabii commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

What this changes

Probes are settable. spec.deployment gains livenessProbe, readinessProbe and startupProbe. The operator hardcodes timeoutSeconds: 1 on all three and the CRD exposed no probe fields, so an instance that answers /health slowly is killed 30s later — seq-server-0 carries 346 restarts on one cluster and 282 on another, all exit 143.

A probe given on the deployment replaces the operator's outright rather than merging. Merging would let a caller set one field, inherit the rest, and read back a probe that is neither what they wrote nor what was chosen for them — and gives no way to clear a field the operator sets. Unset keeps today's probes byte for byte.

CRD generation works again. The pinned kubeops.cli 9.1.6-alethic.5 resolves from no configured feed, and KubeOps.Operator.targets probes the CLI with IgnoreExitCode then invokes generation with ContinueOnError — so generation was skipped and the build still reported success. Now pinned to stock 9.11.8, matching the KubeOps.Operator / KubeOps.Generator references already in the project.

spec.deployment.resources becomes usable. 9.1.x transpiled ResourceQuantity as an object {format, value}; Kubernetes quantities are strings, so cpu: 250m never matched the schema. That is why Seq has been running BestEffort. env[].valueFrom.resourceFieldRef.divisor had the same fault. Stock 9.11.8 emits type: string.

Namespaces are declared via EntityRbac. An Instance's permissions are evaluated against the namespace object, but nothing inferred that, so the rule was hand-patched wherever the generated role was copied. The chart's ClusterRole is now a straight copy of the generated role.

On dropping the fork

Regenerating on stock leaves four of the five CRDs byte-identical apart from nullable annotations, and every enum identical. The fork's transpiler patch is JsonStringEnumMemberNameAttribute handling, which nothing in this repo declares — so it costs this operator nothing to drop, and the fork's v9.1.5 base is what carried the ResourceQuantity bug.

Worth noting: the fork is still based on v9.1.5, so any other operator generated with it has the same resources fault.

Reviewer note — one grant you may want to reject

Adding [EntityRbac(typeof(V1Namespace), ...)] with Get | List | Watch also makes the generator emit a namespaces/status rule with get, update, patch. The operator never writes namespace status, so that is privilege it does not need. The alternative is to drop the attribute and keep patching the namespaces rule in by hand on every regeneration. Happy to revert if you would rather not carry the extra grant.

Follow-up, not in this PR

This needs a release before it does anything: sweep-appdev-env pins the operator at 0.1.0-pre.132 in the seq-operator OCIRepository, and crds: CreateReplace will replace the CRD when a new chart version lands. The matching spec.deployment.resources change for the Seq instance is held back until then — against the currently deployed CRD it will not validate.

The operator hardcodes timeoutSeconds: 1 on all three probes and the CRD
exposed no probe fields at all, so an instance that answers /health slowly is
killed by the kubelet 30 seconds later. Under CPU contention Seq's own log
reports a /api response taking 12.7 seconds; seq-server-0 carries 346 restarts
on one cluster and 282 on another, every one of them exit 143 rather than a
fault in Seq.

spec.deployment now carries livenessProbe, readinessProbe and startupProbe. A
probe given there replaces the operator's outright rather than merging into it:
merging would let a caller set one field, inherit the rest, and read back a
probe that is neither what they wrote nor what was chosen for them, and it
offers no way to clear a field the operator sets. Left unset, the emitted
probes are exactly what they are today.

None of that could reach the CRD, because the pinned kubeops.cli
9.1.6-alethic.5 resolves from no configured feed, and KubeOps.Operator.targets
probes the CLI with IgnoreExitCode and invokes generation with ContinueOnError
-- so generation was skipped and the build still reported success. The tool is
pinned to the stock 9.11.8, matching the KubeOps.Operator and KubeOps.Generator
references the project already carries.

Regenerating on stock leaves four of the five CRDs byte-identical apart from
nullable annotations, and every enum identical -- the fork's patch is
JsonStringEnumMemberNameAttribute handling, which nothing here declares. What
it does change is ResourceQuantity, which 9.1.x transpiled as an object of
{format, value}. Kubernetes quantities are strings, so spec.deployment.resources
could not be given an ordinary value like 250m, which is why Seq has run
BestEffort; env[].valueFrom.resourceFieldRef.divisor carried the same fault.

Namespaces are declared through EntityRbac. An Instance's permissions are
evaluated against the namespace object itself, but nothing inferred that from
the controller's entity types, so the rule was patched in by hand wherever the
generated role was copied. The chart's ClusterRole is now a straight copy of
the generated role with nothing added to it.
@wasabii
wasabii merged commit 2823b76 into main Sep 6, 2026
2 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.

1 participant