OpenShift Services Explained
Learn everything about OpenShift Services, including ClusterIP, NodePort, LoadBalancer, service discovery, networking, Spring Boot integration, load balancing, and real-world enterprise architectures.
Introduction
When a Spring Boot application is deployed on OpenShift, it runs inside one or more Pods.
However, Pods are temporary:
- Pods can restart.
- Pods can be recreated.
- Pod IP addresses change.
- Pods can be scaled up or down.
If clients communicate directly with Pod IPs, applications will eventually fail.
OpenShift solves this problem using Services.
A Service provides a stable network endpoint that always points to the correct Pods, regardless of how many Pods exist or whether they are recreated.
Learning Objectives
By the end of this article, you will understand:
- What is an OpenShift Service?
- Why Services are required
- Service architecture
- Service discovery
- ClusterIP
- NodePort
- LoadBalancer
- Service selectors
- Spring Boot networking
- Enterprise networking best practices
Why Do We Need Services?
Imagine a Spring Boot application with three Pods.
flowchart TD
Pod1["Payment Pod 1<br/>10.10.1.5"]
Pod2["Payment Pod 2<br/>10.10.1.8"]
Pod3["Payment Pod 3<br/>10.10.1.12"]
Tomorrow Pod 2 crashes.
OpenShift creates a replacement.
flowchart TD
Pod1["Payment Pod 1"]
Pod2["❌ Failed"]
NewPod["Payment Pod 4"]
Its IP address changes.
Applications cannot rely on Pod IPs.
Solution
Use a Service.
flowchart LR
Client
--> Service
Service
--> Pod1
Service
--> Pod2
Service
--> Pod3
Clients always communicate with the Service instead of individual Pods.
What is a Service?
A Service is a Kubernetes/OpenShift resource that provides:
- Stable IP Address
- Stable DNS Name
- Load Balancing
- Service Discovery
- Pod Abstraction
Think of it as a load balancer inside the cluster.
Service Architecture
flowchart TD
Client
--> Service
Service
--> Pod1
Service
--> Pod2
Service
--> Pod3
The Service automatically distributes traffic.
Spring Boot Architecture
flowchart LR
USER["Browser"]
ROUTE["OpenShift Route"]
SERVICE["ClusterIP Service"]
subgraph APP["Spring Boot Application"]
POD1["Pod 1"]
POD2["Pod 2"]
POD3["Pod 3"]
end
USER --> ROUTE
ROUTE --> SERVICE
SERVICE --> POD1
SERVICE --> POD2
SERVICE --> POD3
Users never communicate directly with Pods.
How Services Work
Every Service has:
- Name
- Selector
- Port
- Target Port
Example:
selector:
app: payment-api
OpenShift automatically connects the Service to Pods having the same label.
Service Selector
flowchart LR
SVC["OpenShift Service"]
subgraph LABELS["Label Selector"]
SEL["app=payment"]
end
subgraph PODS["Matching Pods"]
P1["Payment Pod 1"]
P2["Payment Pod 2"]
P3["Payment Pod 3"]
end
SVC --> SEL
SEL --> P1
SEL --> P2
SEL --> P3
If labels don't match, the Service cannot find any Pods.
Request Flow
sequenceDiagram
participant User
participant Route
participant Service
participant Pod
participant SpringBoot
User->>Route: HTTP Request
Route->>Service: Forward Request
Service->>Pod: Load Balance
Pod->>SpringBoot: Process Request
SpringBoot-->>Pod: Response
Pod-->>Service: Response
Service-->>Route: Response
Route-->>User: HTTP Response
Types of Services
OpenShift supports several Service types.
| Type | Purpose |
|---|---|
| ClusterIP | Internal communication |
| NodePort | External access through node port |
| LoadBalancer | Cloud load balancer |
| ExternalName | External DNS mapping |
ClusterIP
ClusterIP is the default Service type.
flowchart LR
ORDER["Order Service Pod"]
CLUSTERIP["ClusterIP Service"]
subgraph PAYMENT["Payment Application"]
POD1["Payment Pod 1"]
POD2["Payment Pod 2"]
POD3["Payment Pod 3"]
end
ORDER --> CLUSTERIP
CLUSTERIP --> POD1
CLUSTERIP --> POD2
CLUSTERIP --> POD3
Characteristics:
- Internal only
- Most common
- Used for Microservices
- Not accessible from outside
ClusterIP Example
apiVersion: v1
kind: Service
metadata:
name: payment-service
spec:
type: ClusterIP
selector:
app: payment
ports:
- port: 80
targetPort: 8080
NodePort
NodePort exposes the Service through every Worker Node.
flowchart LR
USER["Internet User"]
NODE["Kubernetes Worker Node"]
NP["NodePort (30080)"]
subgraph APP["Payment Application"]
POD1["Payment Pod 1"]
POD2["Payment Pod 2"]
end
USER --> NODE
NODE --> NP
NP --> POD1
NP --> POD2
Usually used for testing.
NodePort Example
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
nodePort: 30080
Access:
http://NodeIP:30080
LoadBalancer
Cloud providers create an external load balancer.
flowchart LR
USER["Internet"]
ALB["AWS Application Load Balancer"]
SVC["OpenShift Service"]
subgraph APP["Application Pods"]
POD1["Pod 1"]
POD2["Pod 2"]
POD3["Pod 3"]
end
USER --> ALB
ALB --> SVC
SVC --> POD1
SVC --> POD2
SVC --> POD3
Supported on:
- AWS
- Azure
- Google Cloud
LoadBalancer Example
spec:
type: LoadBalancer
Cloud platforms automatically provision the load balancer.
ExternalName
Maps a Service to an external DNS.
flowchart LR
APP["Spring Boot Application"]
EXT["ExternalName Service"]
DNS["database.company.com"]
DB["Managed Database"]
APP --> EXT
EXT --> DNS
DNS --> DB
Useful for:
- External APIs
- External Databases
Service Discovery
Every Service automatically receives a DNS name.
Example:
payment-service.default.svc.cluster.local
Applications communicate using DNS instead of IP addresses.
Banking Microservices Example
flowchart TD
CLIENT["Customer"]
GW["API Gateway"]
subgraph SERVICES["Banking Services"]
PAY["Payment Service"]
CUST["Customer Service"]
LOAN["Loan Service"]
end
CLIENT --> GW
GW --> PAY
GW --> CUST
GW --> LOAN
Each microservice exposes its own Service.
Spring Boot Communication
Instead of:
http://10.10.10.25
Applications call:
http://payment-service
DNS automatically resolves to the correct Pods.
Service YAML
apiVersion: v1
kind: Service
metadata:
name: payment-service
spec:
selector:
app: payment
ports:
- protocol: TCP
port: 80
targetPort: 8080
Deploy:
oc apply -f service.yaml
Verify Service
oc get services
Example:
NAME TYPE
payment-service ClusterIP
Describe Service
oc describe service payment-service
Displays:
- Selector
- Endpoints
- Ports
- Labels
Service Endpoints
graph LR
SVC["Service"]
P1["Pod 1"]
P2["Pod 2"]
P3["Pod 3"]
SVC --> P1
SVC --> P2
SVC --> P3
OpenShift automatically updates endpoints whenever Pods change.
Scaling Example
Initially:
flowchart LR
Service
--> Pod1
Service
--> Pod2
After scaling:
flowchart LR
Service
--> Pod1
Service
--> Pod2
Service
--> Pod3
Service
--> Pod4
Service
--> Pod5
The Service automatically starts distributing traffic to the new Pods.
OpenShift Route vs Service
| Service | Route |
|---|---|
| Internal networking | External access |
| Cluster communication | Internet access |
| Stable DNS | Public URL |
| Load balancing | HTTP/HTTPS exposure |
Typically:
Browser
↓
Route
↓
Service
↓
Pods
Enterprise Architecture
flowchart LR
CUSTOMERS["Customers"]
ROUTE["Route"]
API["API Gateway Service"]
PAYMENT["Payment Service"]
ACCOUNT["Account Service"]
CUSTOMER["Customer Service"]
PAYPODS["Payment Pods"]
ACCPODS["Account Pods"]
CUSPODS["Customer Pods"]
CUSTOMERS --> ROUTE
ROUTE --> API
API --> PAYMENT
API --> ACCOUNT
API --> CUSTOMER
PAYMENT --> PAYPODS
ACCOUNT --> ACCPODS
CUSTOMER --> CUSPODS
This architecture is commonly used in banking and insurance platforms.
Common Issues
Service Has No Endpoints
Cause:
Labels don't match.
Verify:
oc get pods --show-labels
Connection Refused
Check:
- Container Port
- Target Port
- Spring Boot server.port
DNS Resolution Failure
Verify:
oc get svc
Ensure the Service exists in the correct Project.
Best Practices
- Use meaningful Service names.
- Always use labels and selectors consistently.
- Prefer ClusterIP for internal communication.
- Use Routes instead of NodePort in OpenShift.
- Keep Service definitions in Git.
- Monitor Service endpoints.
- Use health probes with Services.
- Separate Services by business capability.
Advantages
- Stable networking
- Automatic load balancing
- Built-in service discovery
- Pod abstraction
- High availability
- Easy scaling
- Microservice communication
- Cloud-native networking
Summary
OpenShift Services provide a stable networking layer between clients and application Pods.
Key takeaways:
- Services hide changing Pod IP addresses.
- ClusterIP is the default and most commonly used Service type.
- Services automatically load balance traffic across healthy Pods.
- DNS-based service discovery simplifies microservice communication.
- Routes expose Services externally to users.
- Services are fundamental building blocks of every production OpenShift application.
Interview Questions
- What is a Service in OpenShift?
- Why shouldn't applications connect directly to Pods?
- What is the default Service type?
- What is the difference between ClusterIP and NodePort?
- What is the purpose of a Service selector?
- How does service discovery work?
- What is the difference between a Service and a Route?
- How does a Service load balance traffic?
- What happens when a Pod is recreated?
- Why are Services essential in microservice architectures?