Repository navigation
Cilium policy refactor - #221
Merged
Merged
Conversation
wmajkowsEV
approved these changes
Sep 29, 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 free
to 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.
Description
Justification of changes:
The problem
Cilium enforces policy through a per-pod BPF map
(
cilium_policy_v2_<endpoint-id>, 16,384 entries) keyed on(identity, port, protocol, direction). A selector matching every pod in thecluster costs one entry per identity, per port.
The breaking line is
namespaceSelector: {}in the outside-world egress rule(
network-policy.yaml:105):Peers in a rule are OR'd and
ports:applies to all of them, so thatcluster-wide peer inherits all 12 port entries — which expand to 17 map
tokens, because
11000-11999is stored as 6 LPM prefixes, not 1.644 identities x 17 tokens = ~10,900 entriesfrom a single rule.This peer was added for the Cilium migration, following the Microsoft
guidance. That advice is correct for the port-less example in the doc, and
fatal when applied to a rule carrying 12 ports — the doc never states that
cost.
Measured on
aks-mgc-b-lab-aks01-weu-a99breaking-evtrekpod (endpoint 441)At 300 apps x 5 namespaces (1,500 identities) each selected pod's map reaches ~27,000 entries —
165% of the limit.
The fix
The single wide rule is split by destination type:
namespaceSelector: {}+ portsenvironment=<env>, port-lesstoEntities: world+ portsTwo independent levers: narrowing the peer, and removing the port list from it.
The second is the larger win — dropping
ports:takes the multiplier to 1regardless of how many identities the peer matches.
Result: ~12,400 -> ~600 entries per pod (20x), and no cluster-wide selector
remains, so it no longer grows with cluster size.
Note the format change is incidental. The same fix works in a plain
NetworkPolicy. OnlytoEntities: [host, remote-node]genuinely requires CNP,because Kubernetes
NetworkPolicycannot select a node.Net effect on pod access
Removed — traffic the old policy allowed and the new one does not:
ipBlock: 0.0.0.0/0matching pod IPs under NPMAdded — required for parity; without these Cilium is stricter than NPM:
toEntities: [host, remote-node]fromEntities: [host, remote-node]externalTrafficPolicy: ClusterSNATs the client to a node IP. Without this all LB ingress drops.kube-apiserverUnchanged: own-namespace, same-environment ingress, DNS, all external/PaaS
egress, prometheus scrape.
Summary: traffic within an environment is unchanged or slightly wider;
traffic across environments on those ports is now denied — which is what the
policy always intended, but NPM could not express.
Chart
Select the chart that you are modifying:
Checklist
${CHART}/tests/*.py