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