apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: {{ .Release.Name }}-egress namespace: {{ .Release.Namespace }} spec: podSelector: matchLabels: app: {{ .Release.Name }} policyTypes: [Egress] egress: # Forgejo — same cicd namespace (git push, registry push/pull) - to: - podSelector: {} # CoreDNS - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system ports: - protocol: UDP port: 53 - protocol: TCP port: 53 # Internet (action deps, base images) — never LAN or pod network - to: - ipBlock: cidr: 0.0.0.0/0 except: - 192.168.1.0/24 - 10.244.0.0/16 # ingress-nginx, which is how forgejo.riotpiao.com resolves (CoreDNS # rewrites that name to ingress-nginx-controller.ingress-nginx.svc). # Image pushes go to that name so the tag matches what containerd pulls # on the nodes; without this the whole /24 and pod CIDR are denied above # and `docker push`/`docker login` hang until they time out. # # Was an ipBlock pinned to the ingress-nginx LoadBalancer's LAN IP. That # stopped matching once DNS started resolving the name to the Service's # ClusterIP instead of the LB IP: Cilium enforces egress against the # post-DNAT pod IP, which falls inside the 10.244.0.0/16 exclusion above, # so every request silently hung rather than erroring. A namespaceSelector # follows the Service wherever it resolves and needs no IP to stay in # sync with -- same pattern as the kube-system DNS rule above. - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: ingress-nginx ports: - protocol: TCP port: 443