Uh oh!
There was an error while loading. Please reload this page.
NetworkPolicy locking down training-pod egress - #42
Merged
Conversation
Training pods run untrusted ML code uploaded by external data scientists.
This policy selects on the tracebloc.io/workload=training label (injected
by jobs-manager in the companion client-runtime PR) and:
- Denies all ingress (nothing should connect TO a training pod).
- Allows DNS to the cluster DNS service.
- Allows external TCP/443 only; blocks all pod-to-pod, ClusterIP, and
in-cluster pod traffic via ipBlock with cluster-CIDR exclusions.
Training pods can still reach tracebloc backend, Azure Service Bus, and
App Insights (external HTTPS). They can no longer reach mysql-client,
the K8s API server, the jobs-manager pod IP, or other training pods.
Per-platform defaults:
AKS: enabled=true (requires Azure NPM or Calico at cluster create)
EKS: enabled=false (AWS VPC CNI does not enforce NetworkPolicy; safer
to explicitly disable than silently have no effect)
BM: enabled=true (requires Calico / Cilium / kube-router)
OC: enabled=true (OVN-Kubernetes enforces by default; custom DNS
selector and OpenShift pod/service CIDRs)
The dnsSelector default is empty with a template-side fallback to
{k8s-app: kube-dns} to avoid Helm's map-merge semantics surprising
customers who override it (OpenShift's selector would otherwise be
unioned with the default rather than replacing it).
- templates/network-policy-training.yaml: new policy (gated on
networkPolicy.training.enabled)
- values.yaml + values.schema.json: new networkPolicy.training block
- ci/{aks,eks,bm,oc}-values.yaml: per-platform overrides with notes
- tests/network_policy_test.yaml: 8 helm-unittest cases covering
rendering, ingress denial, DNS allow, external HTTPS allow, cluster
CIDR blocking, and the OpenShift selector override
No effect until the companion client-runtime PR lands, which adds the
tracebloc.io/workload=training label to spawned training pods.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced Apr 21, 2026
This was referenced Jun 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a Helm-templated NetworkPolicy that denies ingress and restricts egress on training pods. Selects on the
tracebloc.io/workload=traininglabel injected by the jobs-manager in the companion PR: tracebloc/client-runtime#1.Training pods run untrusted Python code uploaded by external data scientists. This is the first kernel-level control on what that code can reach from inside the pod.
What the policy does
Ingress: denied entirely — nothing should connect TO a training pod.
Egress, allowed:
kube-system/openshift-dnsdepending on platform)Egress, blocked (the whole point):
Per-platform defaults
enabledtrue--network-policy azure) or Calico at cluster create. Documented inci/aks-values.yaml.falsetrue.truetrueDesign note: the map-merge footgun
Helm merges map values rather than replacing them. If I'd defaulted
dnsSelector: {k8s-app: kube-dns}invalues.yaml, the OpenShift override would add its label to that map rather than replacing it — producing a broken selector.So
dnsSelectordefaults to{}invalues.yaml, and the template falls back to{k8s-app: kube-dns}if empty. Each platform'sci/*-values.yamlsets the full intended selector. Documented in-line.Known limitations (intentional for this PR)
attacker.comon port 443 is still possible — this only closes in-cluster paths and non-443 egress. Closing external entirely requires routing all training-pod traffic through jobs-manager (architectural endgame, separate effort).clusterCidrs.Test plan
helm lint --strictpasses on all 4 platformshelm unittest— 8 new cases covering rendering toggle, podSelector, ingress denial, DNS allow, external HTTPS allow, cluster CIDR blocking, OpenShift selector override. 47/47 total across 6 suiteshelm templateinspection on AKS/EKS/BM/OC — EKS correctly produces no output (disabled), OC usesopenshift-dnsnamespace and the correct DNS daemon-set labelcurl https://api.tracebloc.io/✓curl mysql-client:3306blockedcurl kubernetes.default.svcblockedcurljobs-manager pod IP blockedDependency
Must land after tracebloc/client-runtime#1 has built a new jobs-manager image tag (
:devfirst). Otherwise the label doesn't exist and the policy selects nothing — not broken, just ineffective.CI note (not a blocker)
Existing helm-ci.yaml
paths:filter triggers onmainandopenshiftbranches but notdevelop. I validated locally (helm lint --strict,helm unittest, per-platformhelm template). Worth a follow-up to adddevelopto the trigger list.🤖 Generated with Claude Code