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

  1. What is a Service in OpenShift?
  2. Why shouldn't applications connect directly to Pods?
  3. What is the default Service type?
  4. What is the difference between ClusterIP and NodePort?
  5. What is the purpose of a Service selector?
  6. How does service discovery work?
  7. What is the difference between a Service and a Route?
  8. How does a Service load balance traffic?
  9. What happens when a Pod is recreated?
  10. Why are Services essential in microservice architectures?