From e26efe0c70ac93cd4cccb08adf3cf8439c811377 Mon Sep 17 00:00:00 2001 From: rock Date: Tue, 8 Sep 2026 09:15:37 -0700 Subject: [PATCH] fix(llm-serving): restrict ingress to api-gateway and monitoring Replace hand-applied llm-serving-default-deny NetworkPolicy that used llm-client=true pod label selector (any pod in any namespace could self-grant access) with a proper namespace-scoped policy. Ingress now restricted to: - api namespace (gateway) on ports 8080/80/8000/11434 - monitoring namespace (Prometheus) on ports 8080/9000 - intra-namespace (pod-to-pod within llm-serving) Tested live: - Gateway -> reasoning/ornith/embeddings/reranker: 200 OK - default namespace -> llm-serving: timeout (blocked) - portfolio namespace -> llm-serving: timeout (blocked) Closes #13 --- k8s/apps/llm-serving/kustomization.yaml | 1 + k8s/apps/llm-serving/networkpolicy.yaml | 62 +++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 k8s/apps/llm-serving/networkpolicy.yaml diff --git a/k8s/apps/llm-serving/kustomization.yaml b/k8s/apps/llm-serving/kustomization.yaml index d646e65..af1bb5a 100644 --- a/k8s/apps/llm-serving/kustomization.yaml +++ b/k8s/apps/llm-serving/kustomization.yaml @@ -14,5 +14,6 @@ resources: - ornith.yaml - reasoning.yaml - reranker.yaml + - networkpolicy.yaml # No namespace transformer: every file sets its own, and the transformer would # rewrite metadata.namespace on anything cross-namespace added later. diff --git a/k8s/apps/llm-serving/networkpolicy.yaml b/k8s/apps/llm-serving/networkpolicy.yaml new file mode 100644 index 0000000..7255782 --- /dev/null +++ b/k8s/apps/llm-serving/networkpolicy.yaml @@ -0,0 +1,62 @@ +# NetworkPolicy for LLM inference engines (llm-serving namespace). +# +# These pods have NO auth — vLLM, Ollama, and TEI accept any request. +# All access MUST go through the api-gateway, which validates JWTs and +# injects identity headers (X-Forwarded-User, X-Auth-Verified). +# +# Replaces the hand-applied llm-serving-default-deny policy that used +# `llm-client: "true"` pod label as a selector — any pod in any namespace +# could self-grant access by adding that label, which defeats the purpose. +# +# This policy restricts ingress to: +# 1. api namespace (gateway) — the sole entry point for inference +# 2. monitoring namespace — Prometheus scraping vLLM/TEI /metrics +# 3. intra-namespace — pod-to-pod (future: multi-replica comms) +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: llm-serving-ingress + namespace: llm-serving + labels: + app.kubernetes.io/part-of: llm-serving +spec: + podSelector: + matchLabels: + app.kubernetes.io/part-of: llm-serving + policyTypes: + - Ingress + ingress: + # Allow from api-gateway (namespace: api) + # Gateway proxies /v1/chat/completions, /v1/embeddings, /v1/rerank + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: api + ports: + - protocol: TCP + port: 8080 # vLLM, Ollama HTTP + - protocol: TCP + port: 80 # KServe predictor services + - protocol: TCP + port: 8000 # vLLM direct (some configs) + - protocol: TCP + port: 11434 # Ollama native port + # Allow Prometheus scraping from monitoring namespace + # vLLM: :8080/metrics, TEI: :9000/metrics + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: monitoring + ports: + - protocol: TCP + port: 8080 + - protocol: TCP + port: 9000 + # Allow intra-namespace (pod-to-pod within llm-serving) + - from: + - podSelector: + matchLabels: + app.kubernetes.io/part-of: llm-serving + ports: + - protocol: TCP + port: 8080