{{- if .Values.networkPolicy.enabled }} # NetworkPolicy mínima del shape: bajo deny-all-default del namespace, permite: # - Ingress: Traefik Proxy (web-backend público) + Prometheus (scrape de /metrics). # - Egress: DNS, Harbor (pull en startup), ns-addons del tenant (BD). # Nota: el cluster tenant usa Traefik Proxy + Gateway API en ns traefik-system # (ADR-060 Fase 1; reemplaza rke2-ingress-nginx que corría en kube-system). # Materializada como Helm hook (pre-install/pre-upgrade, weight "-8") para que # este disponible ANTES de que el Job Alembic (hook weight 0) ejecute su # InitContainer wait-for-secret — el InitContainer hace REST API call al # kube-apiserver y necesita egress DNS + API permitidos. Sin esto, el chicken- # and-egg con default-deny del namespace `apps` (entregado por stack-deployer) # bloquea el hook → curl falla DNS → Job timeout → helm install fail → la # NetworkPolicy nunca se aplica en la fase principal. # # Weight ordering (mas chico = antes): # -8 NetworkPolicy -> -7 Role/RoleBinding -> -5 SA -> 0 Job Alembic # (El AddonClaim vive FUERA del chart desde 0.3.0 — ADR-066. Lo aplica el # workflow del tenant ANTES de `helm upgrade --install`, asi que en la fase # de hooks ya existe y addon-provisioner ya esta reconciliando.) # # delete-policy: before-hook-creation (NO hook-succeeded): la fase principal del # Deployment necesita la NetworkPolicy viva en runtime; solo se borra/recrea al # inicio del proximo hook (idempotente entre upgrades). apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: {{ .Release.Name }} labels: {{- include "app.labels" . | nindent 4 }} annotations: "helm.sh/hook": pre-install,pre-upgrade "helm.sh/hook-weight": "-8" "helm.sh/hook-delete-policy": before-hook-creation spec: podSelector: matchLabels: {{- include "app.selectorLabels" . | nindent 6 }} policyTypes: [Ingress, Egress] ingress: # Tráfico HTTP desde Traefik Proxy (Gateway API, ADR-060 Fase 1). # El controller corre en ns traefik-system (lo instala el bundle traefik-bootstrap). - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: {{ .Values.networkPolicy.ingressControllerNamespace | default "traefik-system" }} ports: - protocol: TCP port: 8000 # Scrape de métricas Prometheus - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: cattle-monitoring-system podSelector: matchLabels: app.kubernetes.io/name: prometheus ports: - protocol: TCP port: 8000 egress: # DNS - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system ports: - protocol: UDP port: 53 - protocol: TCP port: 53 # ns-addons del tenant: MariaDB primary + pool - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: {{ .Values.networkPolicy.addonsNamespace }} ports: - protocol: TCP port: 3306 - protocol: TCP port: 6033 # kube-apiserver + Harbor pull (registro externo). # # NOTA RKE2/DO: el Service `kubernetes` (ns default) tiene endpoint hacia # la IP PUBLICA del Droplet en port 6443 (no ClusterIP intra-cluster). Por # eso namespaceSelector "default" NO funciona — kube-proxy DNATea # 10.43.0.1:443 a la public IP:6443 del nodo. Calico aplica la regla NP # contra la IP de destino post-DNAT, asi que requiere ipBlock que cubra # la public IP. # # ipBlock 0.0.0.0/0 cubre ambos: apiserver public IP:6443 + Harbor:443. # El InitContainer wait-for-secret del Job Alembic necesita esto para # REST API call. - to: - ipBlock: cidr: 0.0.0.0/0 ports: - protocol: TCP port: 443 - protocol: TCP port: 6443 {{- end }}