OpenShift Service Discovery for Microservices

Learn how Service Discovery works in OpenShift, understand Kubernetes DNS, internal networking, Spring Boot microservice communication, and enterprise service discovery patterns.


Introduction

Modern enterprise applications rarely consist of a single application. Instead, they are built using dozens or even hundreds of microservices.

For example, an online banking platform may have separate microservices for:

  • Authentication
  • Customer Management
  • Accounts
  • Payments
  • Transactions
  • Notifications
  • Fraud Detection

These services constantly communicate with each other.

A common question is:

How does one microservice locate another inside OpenShift without knowing its IP address?

The answer is Service Discovery.

OpenShift automatically provides service discovery through Kubernetes DNS, allowing applications to communicate using stable service names instead of changing Pod IP addresses.


Learning Objectives

By the end of this article, you will understand:

  • What is Service Discovery?
  • Why Service Discovery is required
  • Kubernetes DNS
  • Internal DNS resolution
  • ClusterIP Services
  • Spring Boot communication
  • Cross-namespace communication
  • Enterprise architecture
  • Best practices

Microservices Without Service Discovery

Imagine three microservices communicating directly.

flowchart LR
    A[Order Service]
    --> B[10.10.2.15]

    B --> C[Payment Pod]

Problem:

  • Pod IP changes
  • Scaling breaks communication
  • Failed Pods receive new IPs

Applications become unreliable.


Microservices With Service Discovery

flowchart LR
    A[Order Service]

    --> B[payment-service]

    --> C[Payment Pods]

Applications communicate using Service names, not Pod IPs.


What is Service Discovery?

Service Discovery is the process of automatically locating services running inside a cluster.

Instead of:

http://10.20.15.18

Applications use:

http://payment-service

OpenShift automatically resolves the service name to healthy Pods.


Service Discovery Architecture

flowchart TD

Order[Order Service]

DNS[CoreDNS]

PaymentService[Payment Service]

Pod1[Payment Pod 1]

Pod2[Payment Pod 2]

Order --> DNS

DNS --> PaymentService

PaymentService --> Pod1

PaymentService --> Pod2

CoreDNS is responsible for DNS resolution inside the cluster.


Complete Request Flow

sequenceDiagram

participant Order

participant DNS

participant Service

participant Pod

participant PaymentAPI

Order->>DNS: Resolve payment-service

DNS-->>Order: Cluster IP

Order->>Service: HTTP Request

Service->>Pod: Load Balance

Pod->>PaymentAPI: Execute

PaymentAPI-->>Order: JSON Response

Kubernetes DNS

Every Service automatically receives a DNS name.

Example:

payment-service

Fully Qualified Domain Name (FQDN):

payment-service.default.svc.cluster.local

DNS is automatically maintained by OpenShift.


DNS Hierarchy

flowchart TD

Cluster

--> Namespace

Namespace

--> Service

Service

--> Pods

Internal DNS

Applications communicate internally without exposing APIs externally.

flowchart LR
    ORDER["Order Service"]
    DNS["payment-service.default.svc.cluster.local"]
    SVC["Payment Service"]
    PODS["Payment Pods"]

    ORDER --> DNS
    DNS --> SVC
    SVC --> PODS

No Route required.


Why Not Use Pod IP?

Pod IPs are temporary.

flowchart LR

OldPod[Payment Pod]

--> IP1[10.10.5.8]

Crash[Pod Restart]

--> NewPod[Payment Pod]

--> IP2[10.10.8.15]

Service Discovery hides these changes.


ClusterIP Service

Every Service has a stable virtual IP.

flowchart LR
    ORDER["Order Service"]

    SERVICE["ClusterIP Service"]

    subgraph APP["Payment Application"]
        POD1["Payment Pod 1"]
        POD2["Payment Pod 2"]
        POD3["Payment Pod 3"]
    end

    ORDER --> SERVICE
    SERVICE --> POD1
    SERVICE --> POD2
    SERVICE --> POD3

Applications always connect to the ClusterIP.


Banking Example

flowchart LR
    API["API Gateway"]

    CUSTOMER["Customer Service"]
    PAYMENT["Payment Service"]
    LOAN["Loan Service"]

    FRAUD["Fraud Service"]
    NOTIFY["Notification Service"]

    API --> CUSTOMER
    API --> PAYMENT
    API --> LOAN

    PAYMENT --> FRAUD
    PAYMENT --> NOTIFY

Each service communicates using DNS names.


Spring Boot Example

Payment Service URL

payment.service.url=http://payment-service

Order Service

@RestController
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/orders")
    public String placeOrder() {

        return restTemplate.getForObject(
            "http://payment-service/api/pay",
            String.class);
    }

}

No IP addresses are required.


Using Spring WebClient

WebClient.builder()
.baseUrl("http://payment-service")
.build();

WebClient works seamlessly with OpenShift DNS.


Multi-Service Architecture

flowchart LR
    BROWSER["Browser"]
    ROUTE["OpenShift Route"]
    GATEWAY["API Gateway"]

    CUSTOMER["Customer Service"]
    ORDER["Order Service"]
    PAYMENT["Payment Service"]

    INVENTORY["Inventory Service"]
    FRAUD["Fraud Service"]

    BROWSER --> ROUTE
    ROUTE --> GATEWAY

    GATEWAY --> CUSTOMER
    GATEWAY --> ORDER
    GATEWAY --> PAYMENT

    ORDER --> INVENTORY
    PAYMENT --> FRAUD

Only the API Gateway is exposed externally.


Cross-Namespace Communication

Suppose:

Payment Service

Namespace:

payments

Order Service

Namespace:

orders

Use:

payment-service.payments.svc.cluster.local

instead of:

payment-service

Cross-Namespace Architecture

flowchart LR
    ORDERS["Orders Namespace"]
    DNS["payment-service.payments.svc.cluster.local"]
    PAYMENTS["Payments Namespace"]
    PODS["Payment Pods"]

    ORDERS --> DNS
    DNS --> PAYMENTS
    PAYMENTS --> PODS

Verify DNS

Open terminal:

oc rsh payment-pod

Test DNS:

nslookup payment-service

or

curl http://payment-service

List Services

oc get svc

Example:

payment-service

customer-service

loan-service

Service Endpoints

oc get endpoints

Output:

payment-service

10.10.1.4

10.10.1.5

10.10.1.8

Scaling Example

Before Scaling

flowchart LR

Service

--> Pod1

Service

--> Pod2

After Scaling

flowchart LR

Service

--> Pod1

Service

--> Pod2

Service

--> Pod3

Service

--> Pod4

Service

--> Pod5

Applications continue using the same DNS name.


Service Discovery During Deployment

flowchart LR
    ORDER["Order Service"]
    DNS["payment-service"]
    OLD["Old Pods"]
    NEW["New Pods"]

    ORDER --> DNS
    DNS --> OLD
    DNS --> NEW

Rolling deployments happen transparently.


Enterprise Banking Architecture

flowchart TD
    CUSTOMER["Customer"]
    ROUTE["OpenShift Route"]
    API["API Gateway"]

    AUTH["Authentication Service"]
    ACCOUNT["Account Service"]
    PAYMENT["Payment Service"]
    FRAUD["Fraud Detection"]
    ORACLE[("Oracle Database")]
    KAFKA[("Kafka")]
    NOTIFY["Notification Service"]

    CUSTOMER --> ROUTE
    ROUTE --> API

    API --> AUTH
    API --> ACCOUNT
    API --> PAYMENT

    PAYMENT --> FRAUD
    FRAUD --> ORACLE

    PAYMENT --> KAFKA
    KAFKA --> NOTIFY

Every service communicates using internal DNS.


Common Problems

Service Not Found

Verify:

oc get svc

DNS Resolution Failed

Verify:

nslookup payment-service

No Endpoints

oc get endpoints

If empty:

  • Labels mismatch
  • Pods not running

Connection Refused

Check:

  • Service Port
  • Target Port
  • Spring Boot server.port

Best Practices

  • Never use Pod IPs.
  • Always communicate using Service names.
  • Expose only API Gateway externally.
  • Keep backend services internal.
  • Use ClusterIP for microservices.
  • Use FQDN for cross-namespace communication.
  • Monitor DNS resolution.
  • Configure health probes.

Common Mistakes

❌ Hardcoding Pod IPs.

❌ Exposing every microservice.

❌ Using NodePort internally.

❌ Forgetting namespace names.

❌ Calling Pods directly.


Advantages

  • Automatic discovery
  • Stable networking
  • Dynamic scaling
  • Built-in DNS
  • High availability
  • Zero configuration
  • Better resilience
  • Enterprise ready

Summary

Service Discovery is one of the core capabilities that enables microservices to communicate reliably inside OpenShift.

Key takeaways:

  • OpenShift automatically provides DNS-based Service Discovery.
  • Applications communicate using Service names instead of Pod IP addresses.
  • ClusterIP Services provide stable endpoints while Pods can scale or restart transparently.
  • CoreDNS resolves service names within the cluster.
  • Cross-namespace communication uses fully qualified domain names (FQDNs).
  • Service Discovery enables scalable, resilient, and loosely coupled Spring Boot microservices.

Interview Questions

  1. What is Service Discovery?
  2. Why shouldn't applications use Pod IP addresses?
  3. What is CoreDNS?
  4. What is the default Service type used for Service Discovery?
  5. How does OpenShift resolve service names?
  6. What is the FQDN format of a Service?
  7. How do microservices communicate across namespaces?
  8. What happens to Service Discovery when Pods are scaled?
  9. How do you verify Service endpoints?
  10. Why is Service Discovery essential in microservice architectures?