Files
seaweedfs/.github/workflows
09da5f634f helm: optional NetworkPolicy per component (#10479)
* helm: optional NetworkPolicy per component

In a namespace with a default-deny policy the chart cannot be installed:
the components never reach each other, and the post-install bucket hook
waits on the master and filer until it gives up.

networkPolicy.enabled renders one policy per component, selecting its
pods by the standard app.kubernetes.io labels and admitting the other
pods of the release on the ports that component listens on. The port
lists come from the same values as the containerPorts, and CI asserts
the two agree. Restricting egress is a second opt-in with extraEgress
for the filer store and notification sinks, which the chart cannot
know about.

Closes #10421

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* helm: say "changed" instead of "retuned" in the policy comments

codespell reads "retuned" as a misspelling of "returned" and fails the
spelling job.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* helm: refuse empty port and DNS peer lists instead of widening

In a NetworkPolicy an empty ports list means every port and a missing peer
selector means every pod, so `kubeApiServer.ports: []` silently opened the
API server CIDRs on all ports, and nulling a DNS selector rendered
`podSelector: null`, which is every pod in kube-system. Both now fail the
render, and the DNS rule emits only the selectors that are set.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* helm: gate the bucket hook Job and its policy on one helper

Both were deriving the same condition from the same values, kept in step by
a comment. seaweedfs.bucketHookEnabled makes it one definition, so adding an
S3 mode cannot leave the Job running without its policy - which under
default-deny means the hook hangs. CI pins the pairing across the eleven
modes that decide it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* helm: say that an egress default-deny needs both toggles

networkPolicy.enabled on its own only covers a default-deny that restricts
ingress. Where Egress is in its policyTypes as well, which is the usual
baseline, the components still cannot resolve DNS and egress.enabled is
required too. Both values and the README said the first half of that.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* helm: quote the label values the policies emit

The same int-coercion the hook templates were fixed for, in the file this PR
adds: unquoted, a release named 123 renders app.kubernetes.io/instance as a
YAML integer in the metadata, the podSelector and both peer selectors, and
the API server rejects the object - a policy that silently never applies.
CI now renders the chart as release "123" and fails if any policy label
comes out as a non-string.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* helm: gate the resize hook policy on the same lookup as its Job

The policy rendered whenever the hook was enabled, which is the default, so
every release carrying networkPolicy got one - as a pre-install hook that
Helm never collects, left in the namespace after uninstall. It also made
egress.kubeApiServer.cidrs mandatory for every release, since the policy
claims the API server, for a Job that only runs on an upgrade that grows a
PVC.

Move the command computation the Job is gated on into a helper and read it
from both.

* helm: drop the API server rule from the admin policy

No seaweedfs binary talks to the Kubernetes API - there is no client-go in
go.mod - so the rule granted admin an egress path it never uses, and forced
anyone running admin with egress on to name an API server address for it.
The pod-RW ClusterRole the comment was reasoning from is a leftover from a
migration and is not read by any component.

* helm: reject a networkPolicy.components key that names no component

The component names are not guessable - objectstorage-provisioner,
seaweedfs-all-in-one, volume-<name> - and a typo silently dropped the rules
it was carrying. Check against every component the chart can produce, not
the enabled ones, so a values file shared across releases can still hold
overrides for a component this one leaves off.

* helm: name the all-in-one policy after the workload

componentName prefixes the release fullname onto the suffix it is given, and
the component label already starts with seaweedfs-, so the policy came out as
<release>-seaweedfs-seaweedfs-all-in-one.

* helm ci: assert the denied probe failed rather than that it did not succeed

kubectl run's "pod/x created" was captured alongside the pod log, so an
empty log would still not match exit=0 and the denial would pass without
anything having been tested.

* helm: document what turning the network policies on costs

Three things the values did not say: a Prometheus outside the release stops
scraping and nothing reports it, the resize hook's policy is a hook resource
that uninstall leaves behind, and the DNS selectors are wrong on OpenShift.

* helm: spell out the managed distributions codespell reads as a typo

codespell has AKS in its dictionary as a misspelling of ASK, so the DNS
selector note failed the spelling job.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* helm ci: read the probe verdict from the marker line, not the whole log

The default-deny step decides both probes from the pod log, but kubectl logs
returns stderr as well, and busybox wget reports "download timed out" there
even under -q. The denied probe therefore produced two lines beginning with
wget:, which matches neither exit=0 nor exit=*, so a correct denial landed in
the arm meant for a probe that produced no result at all and failed the job.

The earlier form hid this behind a catch-all that treated anything without
exit=0 as a denial; tightening that assertion made the stray line fatal
without narrowing the input it reads.

Pick the marker line out instead. The trailing || true is required: the step
runs under bash -e, so a grep that matches nothing would abort it rather than
reach the arm that reports an empty result, which is the case that assertion
exists to catch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Sebastian Preisner <preisner@puzzle-itc.de>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Chris Lu <chris.lu@gmail.com>
2026-07-30 12:04:30 -07:00
..