Berserk Docs

Network Policies

Securing inter-service communication with Kubernetes NetworkPolicies

Berserk includes optional Kubernetes NetworkPolicies that restrict both ingress and egress traffic for each service. When enabled, only known communication paths are allowed -- blocking unauthorized pod-to-pod traffic and outbound connections.

The model is built around a single public edge. The gateway is the only service meant to take traffic from outside the cluster: it authenticates requests and proxies them on to the rest of the stack (UI over HTTP, plus gRPC to meta, query, and ingest). ingest is the one other externally reachable service, accepting OTLP/Loki telemetry from external agents. Every other service accepts connections only from the specific in-cluster peers it talks to.

NetworkPolicy enforcement requires a CNI plugin. On EKS, use the VPC CNI v1.14+ with ENABLE_NETWORK_POLICY=true on the aws-node DaemonSet, or install Calico. Without a compatible CNI, the NetworkPolicy resources are created but have no effect.

Enabling

Network policies are disabled by default. Enable them in your values file:

values.yaml
global:
  networkPolicy:
    enabled: true

Service Communication Map

When network policies are enabled, only the gateway and ingest accept ingress from outside the cluster. Everything else is reachable only from the listed in-cluster peers:

ServiceAccepts ingress from (peers)Connects out to (peers)External ingress
gatewaypublic edgeui, permissions, meta, query, ingestYes
ingestexternal telemetry sourcesmetaYes
metagateway, query, ingest, janitor, ui, nursery--No
queryui, janitormeta, nurseryYes (exception)
nurseryquerymetaNo
janitor--meta, queryNo
uigatewaygateway, query, meta, permissionsNo
permissionsgateway, ui--No

query is a known exception: it still sets allowExternal: true, so external clients (and the gateway's gRPC proxy) reach query:9510 through that open door rather than an explicit peer rule, and the customer post-rollout validation probe can connect directly. Moving query fully behind the gateway -- adding gateway to its ingressFrom and dropping allowExternal -- is a planned follow-up.

Beyond the peers above, every service also gets:

  • DNS egress (port 53 UDP/TCP), always.
  • External egress to the CIDR allowlist (S3 on 443, PostgreSQL on 5432 by default) when allowExternalEgress is set -- the default for every service. See External Egress.
  • OTLP egress to ingest:4317 when observability is enabled. See OTLP Telemetry.

A couple of services carry extra in-cluster rules not shown above: query pods accept and make cross-pod connections on port 9520 (the QWS worker-sibling lane), and meta additionally accepts connections from one-off setup / admin operator pods (e.g. kubectl run bzrk-cli) used for token and table creation.

External Egress

Services that need to reach external endpoints (S3, PostgreSQL) use a configurable CIDR allowlist. By default, HTTPS (443) and PostgreSQL (5432) are open to all IPs. Tighten these for production:

values.yaml
global:
  networkPolicy:
    enabled: true
    externalEgress:
      # S3 VPC endpoint
      - cidr: 10.0.0.0/16
        ports:
          - port: 443
            protocol: TCP
      # RDS PostgreSQL
      - cidr: 10.1.0.0/24
        ports:
          - port: 5432
            protocol: TCP

OTLP Telemetry

When global.observability.otlpEnabled is true, all services automatically get egress to the OTLP endpoint. Two cases are handled:

Default endpoint (ingest:4317): Egress to the ingest pod is added automatically via pod selector. The ingest service also gets an ingress rule allowing all namespace pods to send telemetry on port 4317.

External collector: If global.observability.otlpEndpoint points outside the namespace, configure global.networkPolicy.otlpEgress with the appropriate CIDR rules:

values.yaml
global:
  observability:
    otlpEnabled: true
    otlpEndpoint: "otel-collector.monitoring:4317"
  networkPolicy:
    enabled: true
    otlpEgress:
      - cidr: 10.2.0.0/16
        ports:
          - port: 4317
            protocol: TCP

Helm prints a warning during install/upgrade if OTLP is enabled with a non-default endpoint but no otlpEgress rules are configured.

Custom Rules

Add custom ingress or egress rules for all services via the global values, or per-service via the sub-chart values.

Global (applied to all services):

values.yaml
global:
  networkPolicy:
    additionalIngress:
      - from:
          - namespaceSelector:
              matchLabels:
                name: monitoring
        ports:
          - port: 9090
            protocol: TCP

Per-service (e.g., allow a specific namespace to reach query):

values.yaml
query:
  networkPolicy:
    additionalIngress:
      - from:
          - namespaceSelector:
              matchLabels:
                name: data-team
        ports:
          - port: 9510
            protocol: TCP

Per-Service Configuration

Each service supports these networkPolicy values:

ValueTypeDescription
allowExternalboolAllow ingress from any source on service ports
allowExternalEgressboolAllow egress to global.networkPolicy.externalEgress CIDRs
ingressFromlistBerserk peers allowed to connect ([{app, ports}])
egressTolistBerserk peers this service connects to ([{app, ports}])
additionalIngresslistExtra raw NetworkPolicy ingress rules
additionalEgresslistExtra raw NetworkPolicy egress rules

On this page