Skip to content

ci: Hardening and Improving chart/Graylog CI - #178

Draft
alix-graylog wants to merge 8 commits into
mainfrom
wave-4-ci-hardening
Draft

ci: Hardening and Improving chart/Graylog CI#178
alix-graylog wants to merge 8 commits into
mainfrom
wave-4-ci-hardening

Conversation

@alix-graylog

Copy link
Copy Markdown
Collaborator

Summary

Short description of the change.

Details

  • List of meaningful technical changes

Linked issues

This fixes #??

PR Checklist

Please check the items that apply to your change.

  • Tests added/updated
  • Documentation updated
  • This PR includes a new feature
  • This PR includes a bugfix
  • This PR includes a refactor

Testing Checklist

Static Validation

  • Linter check passes: helm lint ./charts/graylog
  • Helm renders local template sucessfully: helm template graylog ./charts/graylog --validate

Installation

  • Fresh installation completes successfully: helm install graylog ./charts/graylog
  • All pods reach Running state: kubectl rollout status statefulset/graylog
  • Helm tests pass: helm test graylog

Functional (if applicable)

  • Web UI accessible and login works
  • DataNodes visible in System > Cluster Configuration
  • Inputs can be created and receive data

Upgrade (if applicable)

  • Upgrade from previous release succeeds
  • Scaling up/down works correctly
  • Configuration changes apply correctly

Specific to this PR

  • describe what was specifically tested

Notes for reviewers

  • Verify all applicable tests above pass
  • Validate that the linked issues are no longer reproducible, if applicable
  • Sync up with the author before merging
  • The commit history should be preserved - use rebase-merge or standard merge options when applicable

@alix-graylog alix-graylog changed the title Wave 4 ci hardening ci: Hardening and Improving chart/Graylog CI Aug 21, 2026
The operator owns the pod template of the StatefulSet it manages and injects
its own resource defaults of 500m CPU and 500M memory per container and per
init container. mongo-rs.yaml overrode serviceAccountName and affinity but
never containers or initContainers, so nothing in the chart - no value, no
--set - could change what a MongoDB pod requested.

The init containers matter as much as the containers: a pod reserves
max(max(initContainer), sum(containers)), so each merely copying a binary into
a shared volume at 500m sets the pod's effective floor whenever the containers
ask for less. Overriding only the containers is not enough.

Adds mongodb.resources, mongodb.agentResources and mongodb.initResources,
patched onto the operator-owned template by container name, with defaults sized
for a production replica set rather than inherited from the operator. mongod
gets 2Gi: WiredTiger sizes its cache from the container limit and an idle
3-member replica set already sits at ~340Mi, so the operator's 500M limit left
almost nothing before an OOMKill. CPU goes the other way, since the same
replica set idles under 50m per member.

A MongoDB pod's reservation therefore moves from 1000m/800M to 300m/1152Mi, and
ci/ci-values.yaml shrinks all three blocks to 150m/640Mi for CI. Existing
installs get a rolling restart of the replica set on upgrade.
helm-ct-install had no timeout, so a wedged install could burn the default
360-minute ceiling on every leg of the matrix. helm-extra-args --timeout=900s
bounds the install itself, not namespace termination hanging on a finalizer.

The step was also silent: helm --wait prints nothing until it succeeds or times
out, so a stuck install looked exactly like a slow one for fifteen minutes. A
watcher now streams not-yet-Running pods and recent warning events every 20s,
and node capacity plus reservations are printed after the cluster comes up,
which turns "Insufficient cpu" into a one-line diagnosis.

Sizing moves entirely into charts/graylog/ci/ci-values.yaml, which ct discovers
on its own. It was duplicated as --set flags, and those take precedence over the
values file: the graylog memory request in ci-values.yaml was silently
overridden and the two disagreed. Only the generated rootPassword is passed as a
flag now, because it cannot be committed.

The MongoDB operator is shrunk to 100m: its chart asks for 500m to reconcile a
single one-member replica set.

ci-values.yaml also sets graylog.terminationGracePeriodSeconds to 30. The chart
default of 300s exists to let the preStop drain flush the journal, and ct pays
it on every leg when it deletes the namespace, but nothing in CI holds data
worth draining. The chart default is unchanged.
Answering "what happened in CI" meant opening a job and reading log output.
Every job now writes what it learned to the run summary instead.

- changes: which jobs run, which are skipped and why, plus the changed file
  list. A skipped run is now self-explanatory rather than suspicious.
- lint: the ct lint verdict and a per-example table - rendered object count for
  each values overlay, and for a failure the offending key rather than Helm's
  generic schema error. Runs even when ct lint fails, so the table is not lost
  with it.
- unittest: suite and test counts lifted from helm-unittest's own output, the
  two behaviour-script verdicts, and failing suites when something breaks.
- install: per matrix leg, the result, how long the install took, node
  allocatable CPU and memory, and the pod requests as last observed. On failure
  it adds the matching error lines from the ct log, the pods that never reached
  Running, and recent warning events.

The pod-request snapshot is taken by the watcher loop rather than at summary
time: ct deletes its namespace when it finishes, so by then the workloads under
test are gone and cannot be queried.
ct discovers charts/graylog/ci/ci-values.yaml on its own and the workflow passes
no sizing flags, so nothing in a run said what the chart was linted or installed
with. Both ct jobs now report it.

The report comes from rendering the chart with that overlay, not from printing
the overlay file. The overlay mentions only a handful of keys, so only the
rendered result accounts for chart defaults - MongoDB most of all, where the
container names being patched belong to the operator and the pod's reservation
is max(max(initContainer), sum(containers)) rather than a number written down
anywhere.

Per workload it reports replicas, the pod's request, per-container limits and
the grace period, then the whole stack's total request, which is the figure that
decides whether the install fits on the runner at all.

It lives in .github/scripts/ci_values_summary.py because two jobs need it and
the quantity arithmetic is worth having in one testable place. In the install
job it runs before ct install, so the summary says what was attempted even when
the install times out. Both calls are continue-on-error: a step that only
describes the run must never fail it.
Reviewing a chart change meant rendering it locally to see what actually
changed. The lint job now renders the chart six ways - chart defaults, the CI
overlay, and each values-overlay example - and uploads them as
rendered-manifests-helm-<version>, kept for 14 days. Reviewing a change becomes
downloading that and the same artifact from main, and diffing the two.

It lives in the lint job because rendering needs no cluster, so the artifact
exists even for a change that skips the install matrix. The bundle is 232K.

Secret values are redacted before upload. helm template generates a root
password, the password_secret pepper and both MongoDB passwords for every value
left empty, which is the default, and artifacts on a public repository are
world-downloadable: those would read as leaked credentials to anyone who found
them, and to a secret scanner. Keys are kept so a diff still shows one appearing
or disappearing, and the placeholder is valid base64 so the manifests stay
loadable.

The step then proves the redaction worked and discards the bundle rather than
uploading it if any value survived. A failed redaction must not become a
published credential.
@alix-graylog alix-graylog added the infrastructure Internal code infrastructure. label Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

infrastructure Internal code infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant