Egress
v4.20
Egress IP
This example shows how to configure egress IP addresses on OpenShift so that traffic from selected namespaces uses a fixed source IP. That makes it easy to whitelist cluster workloads in firewalls or identify traffic in logs (e.g., from a specific app or team).
Official documentation: Chapter 9. Configuring an egress IP address
Tested with:
Component
Version
OpenShift
v4.20.1
Overview
Two OpenShift clusters are used:
Cluster: ocp6
Source cluster — here we configure egress IPs and run a pod that sends HTTP requests (via curl) to the web server on ocp7 .
Cluster: ocp7
Target cluster — hosts a simple web server so we can see the sender IP in the server logs and verify egress IP behavior.
Deploy simple-nginx on ocp7
Deploy the target web server on ocp7 (target cluster):
oc new-project egress-target
oc apply -k 'git@github.com:openshift-examples/kustomize/components/simple-nginx?ref=2026-02-12'
Get the route hostname:
% oc get route simple-nginx -o jsonpath = '{.spec.host}'
simple-nginx-egress-target.apps.ocp7.stormshift.coe.muc.redhat.com
Call the web server from your machine (or any client):
% curl -I https://simple-nginx-egress-target.apps.ocp7.stormshift.coe.muc.redhat.com
HTTP/1.1 200 OK
server: nginx/1.26.3
date: Thu, 12 Feb 2026 15 :19:17 GMT
content-type: text/html
content-length: 45
last-modified: Thu, 12 Feb 2026 15 :17:31 GMT
etag: "698def0b-2d"
accept-ranges: bytes
set-cookie: 5386f97f58871214bc079b41bd88c1cd = 43357b3d3312239cb10b42b1c3d17138; path = /; HttpOnly; Secure; SameSite = None
cache-control: private
Check the pod logs to see the client IP that nginx recorded:
% oc logs -f deployment/simple-nginx | grep curl
10 .130.0.2 - - [ 12 /Feb/2026:15:26:45 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/8.12.1" "10.32.96.62"
10.130.0.2 — cluster-internal IP of the ingress/router pod
10.32.96.62 — real client IP (your machine or the pod making the request)
Label worker nodes so they can be assigned egress IPs:
% oc label node -l node-role.kubernetes.io/worker k8s.ovn.org/egress-assignable= ""
node/ocp6-worker-0 labeled
node/ocp6-worker-1 labeled
node/ocp6-worker-2 labeled
Create an EgressIP object with the IPs to use and which namespaces (via label) will use them. Use IPs that are valid on your cluster’s egress network and not in use by nodes or other services:
oc apply -f - <<EOF
apiVersion: k8s.ovn.org/v1
kind: EgressIP
metadata:
name: egress-coe
spec:
egressIPs:
- 10.32.105.72
- 10.32.105.73
namespaceSelector:
matchLabels:
egress: coe
EOF
Deploy a curl pod in a new project — first without the egress label so traffic uses the node IP:
oc new-project curl
oc apply -k 'git@github.com:openshift-examples/kustomize/components/rhel-support-tools?rev=2026-02-12'
From inside the pod, run curl against the ocp7 route. The pod is on ocp6-worker-2 (node IP 10.32.105.97):
% oc rsh deployment.apps/rhel-support-tools
sh-5.1$ echo $NODE_NAME $NODE_IP
ocp6-worker-2 10 .32.105.97
sh-5.1$ curl -Ik https://simple-nginx-egress-target.apps.ocp7.stormshift.coe.muc.redhat.com
HTTP/1.1 200 OK
server: nginx/1.26.3
date: Thu, 12 Feb 2026 15 :42:30 GMT
content-type: text/html
content-length: 45
last-modified: Thu, 12 Feb 2026 15 :31:00 GMT
etag: "698df234-2d"
accept-ranges: bytes
set-cookie: 5386f97f58871214bc079b41bd88c1cd = 7fbe3d3d6235cc5431656b0f57361872; path = /; HttpOnly; Secure; SameSite = None
cache-control: private
sh-5.1$
On ocp7 , check the simple-nginx logs. The client IP should be the node IP (10.32.105.97), because the namespace does not use egress IP yet:
10 .130.0.2 - - [ 12 /Feb/2026:15:42:30 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.76.1" "10.32.105.97"
Enable egress IP for the curl namespace by adding the label that matches the EgressIP namespaceSelector:
oc label namespace/curl egress = coe
Run curl again from the same pod (still on the same node):
% oc rsh deployment.apps/rhel-support-tools
sh-5.1$ echo $NODE_NAME $NODE_IP
ocp6-worker-2 10 .32.105.97
sh-5.1$ curl -Ik https://simple-nginx-egress-target.apps.ocp7.stormshift.coe.muc.redhat.com
HTTP/1.1 200 OK
server: nginx/1.26.3
date: Thu, 12 Feb 2026 15 :48:38 GMT
content-type: text/html
content-length: 45
last-modified: Thu, 12 Feb 2026 15 :31:00 GMT
etag: "698df234-2d"
accept-ranges: bytes
set-cookie: 5386f97f58871214bc079b41bd88c1cd = 7fbe3d3d6235cc5431656b0f57361872; path = /; HttpOnly; Secure; SameSite = None
cache-control: private
sh-5.1$
On ocp7 , check the simple-nginx logs again. The client IP should now be 10.32.105.72 — one of the egress IPs — instead of the node IP:
10 .130.0.2 - - [ 12 /Feb/2026:15:48:38 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.76.1" "10.32.105.72"
Source IP is now the egress IP.
2026-02-12
2025-08-31
Contributors: