Skip to content

Network Policies

Configure network segmentation and traffic control in kMetal.

Platform Network Policies

Kamaji Control Plane Isolation

# kamaji-network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: kamaji-controller-policy
  namespace: kmetal-kamaji
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: kamaji
  policyTypes:

  - Ingress
  - Egress
  ingress:

  - from:
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:

    - protocol: TCP
      port: 8443

  - from:
    - namespaceSelector: {}
    ports:

    - protocol: TCP
      port: 9443  # Webhook
  egress:

  - to:
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:

    - protocol: TCP
      port: 443  # API server

    - protocol: TCP
      port: 2379  # etcd

  - to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          app.kubernetes.io/name: metallb

  - ports:
    - protocol: TCP
      port: 53

    - protocol: UDP
      port: 53

Control Plane Pod Network Policy

# control-plane-network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tenant-control-plane-policy
  namespace: kmetal-kamaji
spec:
  podSelector:
    matchLabels:
      kamaji.clastix.io/name: <tenant-control-plane-name>
  policyTypes:

  - Ingress
  - Egress
  ingress:

  - from:
    - namespaceSelector: {}  # Allow from all namespaces (tenant workloads)
    ports:

    - protocol: TCP
      port: 6443

  - from:
    - namespaceSelector:
        matchLabels:
          name: kmetal-metallb
  egress:

  - to:
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:

    - protocol: TCP
      port: 2379  # etcd

  - ports:
    - protocol: TCP
      port: 53

    - protocol: UDP
      port: 53

ETCD Network Policy

# etcd-network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: etcd-policy
  namespace: kmetal-kamaji
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: kamaji-etcd
  policyTypes:

  - Ingress
  - Egress
  ingress:

  - from:
    - podSelector:
        matchLabels:
          kamaji.clastix.io/name: <tenant-control-plane-name>
    ports:

    - protocol: TCP
      port: 2379

  - from:
    - podSelector:
        matchLabels:
          app.kubernetes.io/name: kamaji-etcd
    ports:

    - protocol: TCP
      port: 2379

    - protocol: TCP
      port: 2380  # Peer communication
  egress:

  - to:
    - podSelector:
        matchLabels:
          app.kubernetes.io/name: kamaji-etcd
    ports:

    - protocol: TCP
      port: 2379

    - protocol: TCP
      port: 2380

  - ports:
    - protocol: TCP
      port: 53

    - protocol: UDP
      port: 53

Tenant Network Policies

Default Deny All

# default-deny-all.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: tenant-namespace
spec:
  podSelector: {}
  policyTypes:

  - Ingress
  - Egress

Allow DNS

# allow-dns.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns
  namespace: tenant-namespace
spec:
  podSelector: {}
  policyTypes:

  - Egress
  egress:

  - to:
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:

    - protocol: TCP
      port: 53

    - protocol: UDP
      port: 53

Allow Control Plane Access

# allow-control-plane.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-control-plane
  namespace: tenant-namespace
spec:
  podSelector: {}
  policyTypes:

  - Egress
  egress:

  - to:
    - namespaceSelector:
        matchLabels:
          name: kmetal-kamaji
      podSelector:
        matchLabels:
          kamaji.clastix.io/name: tenant-cluster
    ports:

    - protocol: TCP
      port: 6443

Application Network Policies

Frontend to Backend

# frontend-backend-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: frontend-policy
  namespace: tenant-namespace
spec:
  podSelector:
    matchLabels:
      app: frontend
  policyTypes:

  - Egress
  egress:

  - to:
    - podSelector:
        matchLabels:
          app: backend
    ports:

    - protocol: TCP
      port: 8080
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-policy
  namespace: tenant-namespace
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:

  - Ingress
  - Egress
  ingress:

  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:

    - protocol: TCP
      port: 8080
  egress:

  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:

    - protocol: TCP
      port: 5432

Database Access

# database-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database-policy
  namespace: tenant-namespace
spec:
  podSelector:
    matchLabels:
      app: database
  policyTypes:

  - Ingress
  ingress:

  - from:
    - podSelector:
        matchLabels:
          app: backend
    ports:

    - protocol: TCP
      port: 5432

External Access Policies

Allow Internet Egress

# allow-internet-egress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-internet-egress
  namespace: tenant-namespace
spec:
  podSelector:
    matchLabels:
      internet-access: "true"
  policyTypes:

  - Egress
  egress:

  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:

        - 10.0.0.0/8
        - 172.16.0.0/12
        - 192.168.0.0/16

Ingress Traffic

# allow-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-ingress
  namespace: tenant-namespace
spec:
  podSelector:
    matchLabels:
      app: frontend
  policyTypes:

  - Ingress
  ingress:

  - from:
    - namespaceSelector:
        matchLabels:
          name: ingress-controller
    ports:

    - protocol: TCP
      port: 8080

Monitoring Network Policies

Verify Network Policies

# List all network policies
kubectl get networkpolicies --all-namespaces

# Describe specific policy
kubectl describe networkpolicy kamaji-controller-policy -n kmetal-kamaji

# Check policies in tenant namespace
kubectl get networkpolicy -n tenant-namespace -o yaml

Test Network Connectivity

# Test connectivity from pod
kubectl run test-pod --rm -it --image=nicolaka/netshoot -- /bin/bash

# Inside pod, test connections
curl -v http://backend-service:8080
nc -zv database-service 5432
dig kubernetes.default.svc.cluster.local

Network Policy Auditing

# network-policy-alert.yaml
groups:

- name: network-policy
  rules:

  - alert: NetworkPolicyViolation
    expr: |
      rate(cilium_drop_count_total{reason="Policy denied"}[5m]) > 10
    labels:
      severity: warning
    annotations:
      summary: "High rate of network policy violations"

  - alert: MissingNetworkPolicy
    expr: |
      count(kube_pod_info) by (namespace)
      unless
      count(kube_networkpolicy_labels) by (namespace)
    labels:
      severity: info
    annotations:
      summary: "Namespace {{ $labels.namespace }} has no network policies"

Calico / Cilium Network Policies (tenant-side)

Tenant-side examples

kMetal's under cluster uses Flannel (primary) and Kube-OVN (secondary). The Calico / Cilium policies below apply only inside tenant clusters that have chosen those CNIs for tenant workloads.

Global Network Policy

# global-network-policy.yaml
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: deny-all-ingress
spec:
  selector: all()
  types:

  - Ingress
  ingress:

  - action: Deny
    source:
      notSelector: has(cluster-internal)

Namespace Network Sets

# namespace-network-set.yaml
apiVersion: projectcalico.org/v3
kind: NetworkSet
metadata:
  name: trusted-networks
  namespace: tenant-namespace
spec:
  nets:

  - 10.0.0.0/8
  - 192.168.1.0/24
---
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
  name: allow-trusted-networks
  namespace: tenant-namespace
spec:
  selector: app == "backend"
  ingress:

  - action: Allow
    source:
      nets:

      - 10.0.0.0/8
      - 192.168.1.0/24

Cilium Network Policies

Layer 7 HTTP Policy

# l7-http-policy.yaml
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: l7-http-policy
  namespace: tenant-namespace
spec:
  endpointSelector:
    matchLabels:
      app: backend
  ingress:

  - fromEndpoints:
    - matchLabels:
        app: frontend
    toPorts:

    - ports:
      - port: "8080"
        protocol: TCP
      rules:
        http:

        - method: "GET"
          path: "/api/.*"

        - method: "POST"
          path: "/api/users"

DNS-Based Policy

# dns-policy.yaml
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-external-api
  namespace: tenant-namespace
spec:
  endpointSelector:
    matchLabels:
      app: backend
  egress:

  - toFQDNs:
    - matchName: "api.github.com"
    - matchPattern: "*.googleapis.com"
    toPorts:

    - ports:
      - port: "443"
        protocol: TCP