03 - Networking, Services, Routes, NetworkPolicy¶
Cluster networking model¶
OpenShift 4 default SDN is OVN-Kubernetes. Older clusters may run OpenShift SDN.
Three networks:
- Cluster network (pods): default
10.128.0.0/14 - Service network (cluster IPs): default
172.30.0.0/16 - Machine network (nodes): cluster-specific
Each pod gets a unique IP. Pods can talk to all other pods (modulo NetworkPolicy).
Services¶
A Service is a stable virtual IP (and DNS name) for a set of pods.
Service types¶
| Type | Use case |
|---|---|
| ClusterIP | Default. Reachable inside cluster only. |
| NodePort | Exposed on every node's IP at a high port (30000-32767). |
| LoadBalancer | Cloud LB (in cloud-managed clusters). |
| ExternalName | DNS CNAME to external host. |
Headless (clusterIP: None) | No virtual IP; DNS returns pod IPs directly. |
Create¶
oc expose deploy/web --port=80 # creates ClusterIP Service
oc expose deploy/web --port=80 --type=NodePort
oc expose deploy/web --port=80 --type=LoadBalancer
YAML:
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector: { app: web }
ports:
- port: 80
targetPort: 8080 # container port
name: http
DNS for services¶
In-cluster DNS: <service>.<namespace>.svc.cluster.local. Short forms work within the same namespace.
Routes (OpenShift's external ingress)¶
Routes are OpenShift-specific; they sit on top of Services and expose them via the cluster's HAProxy ingress router.
Create routes¶
# Plain HTTP
oc expose svc/web --hostname=app.example.com
# TLS edge (router terminates TLS, plaintext to backend pod)
oc create route edge --service=web --hostname=app.example.com
# TLS passthrough (router passes through to backend; backend must serve TLS)
oc create route passthrough --service=web --hostname=app.example.com
# TLS reencrypt (router terminates TLS, re-encrypts to backend)
oc create route reencrypt --service=web --hostname=app.example.com \
--dest-ca-cert=ca.pem
Route YAML¶
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: web
spec:
host: app.example.com
to: { kind: Service, name: web }
port: { targetPort: http }
tls:
termination: edge
insecureEdgeTerminationPolicy: Redirect # Redirect | Allow | None
TLS certificates¶
For edge / reencrypt routes, you can supply cert and key:
oc create route edge --service=web \
--hostname=app.example.com \
--cert=fullchain.pem \
--key=privkey.pem \
--ca-cert=ca.pem
If omitted, the cluster wildcard cert is used.
Path-based routing¶
spec:
host: app.example.com
path: /api
to: { kind: Service, name: api }
Multiple Routes with the same host but different paths route to different services.
Route weighting (canary / blue-green)¶
spec:
to:
kind: Service
name: web-v1
weight: 90
alternateBackends:
- kind: Service
name: web-v2
weight: 10
10% of traffic goes to v2. Adjust weights to roll forward.
Ingress (Kubernetes-native)¶
OpenShift supports Ingress resources, which the Ingress Operator translates into Routes under the hood. Use Routes when in doubt - they're more idiomatic for OpenShift.
NetworkPolicy¶
NetworkPolicy controls pod-to-pod traffic. Default: all pods can talk to all pods. Once a NetworkPolicy selects a pod, only explicitly-allowed traffic is permitted.
Default deny¶
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: myapp
spec:
podSelector: {} # all pods in namespace
policyTypes: [Ingress, Egress]
# No ingress / egress rules = deny all
Allow from a specific pod¶
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
namespace: myapp
spec:
podSelector:
matchLabels: { app: backend }
policyTypes: [Ingress]
ingress:
- from:
- podSelector:
matchLabels: { app: frontend }
ports:
- protocol: TCP
port: 8080
Allow from another namespace¶
spec:
podSelector: { matchLabels: { app: api } }
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector:
matchLabels: { team: frontend }
ports:
- port: 80
Allow from outside cluster (router)¶
In OpenShift, ingress traffic from Routes comes through network.openshift.io/policy-group=ingress namespace label. To allow:
spec:
podSelector: { matchLabels: { app: web } }
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector:
matchLabels:
policy-group.network.openshift.io/ingress: ''
Common networking exam tasks¶
Expose a deployment to the cluster¶
oc expose deploy/web --port=80 # creates ClusterIP Service
Expose a service to public DNS¶
oc expose svc/web --hostname=app.example.com # plain HTTP route
oc create route edge --service=web --hostname=app.example.com # HTTPS edge
Force HTTPS on a route¶
Add insecureEdgeTerminationPolicy: Redirect to an edge route, OR:
oc patch route web -p '{"spec":{"tls":{"insecureEdgeTerminationPolicy":"Redirect"}}}'
Restrict app to only receive traffic from frontend¶
Apply the allow-frontend NetworkPolicy above.
Block all traffic to namespace except from one team¶
# 1. Default deny
spec:
podSelector: {}
policyTypes: [Ingress]
# 2. Allow team
spec:
podSelector: {}
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector:
matchLabels: { team: trusted }
Path-based routing on same host¶
Create two Routes with the same host but different path and different to services.
Canary 10% to v2¶
Use the route weighting YAML above.
Verification¶
After networking changes:
oc get svcshows expected servicesoc get routesshows expected routes with statusAdmittedcurl https://<route-host>/returns expected contentoc -n <ns> get networkpolicyshows expected policiesoc exec <client-pod> -- curl <target-svc>for in-cluster tests- For NetworkPolicy: test BOTH allowed AND denied paths to confirm policy works as intended