Migrating Spring Cloud to Kubernetes: A Guide to Native Components
oussama-el-amrani@portfolio ~/blog/spring-cloud-to-kubernetes
$ cat spring-cloud-to-kubernetes.md
Migrating Spring Cloud to Kubernetes: A Guide to Native Components Migrating Spring Cloud to Kubernetes: A Guide to Native Components

Migrating Spring Cloud to Kubernetes: A Guide to Native Components

Created: 11/29/2025 at 2:30:00 PM / Updated: 11/29/2025 at 3:45:00 PM / 6 minutes to read / Tags: spring, kubernetes, microservices, cloud, guide

When moving a Spring Cloud application to Kubernetes, a common question arises: should I continue using Spring Cloud components, or should I use the native Kubernetes equivalents?

In this post, we’ll explore this question by comparing three key components:

  • Config Server vs. ConfigMaps/Secrets
  • Discovery Server (Eureka) vs. Services
  • Spring Cloud Gateway vs. Ingress

Let’s see why using the built-in Kubernetes components is often the simpler, more powerful choice.

Configuration: Spring Cloud Config vs. Kubernetes ConfigMaps

In a traditional Spring Cloud architecture, the Spring Cloud Config Server provides a central place to manage properties for all microservices. Typically, these configurations are stored in a Git repository. This is a great way to centralize configuration.

However, Kubernetes has its own powerful, built-in solution: ConfigMaps and Secrets.

  • ConfigMaps are used for storing non-sensitive configuration data (like API URLs, feature flags, etc.)
  • Secrets are used for sensitive data (like passwords and API keys)

These objects are managed directly by the Kubernetes API and stored securely in its etcd database.

apiVersion: v1
kind: ConfigMap
metadata:
name: conference-service
data:
# These properties will be available as environment variables
# or mounted as files inside the pod.
KEYNOTE_API_URL: http://keynote-service:8080

Hot Reloading with Configuration Watcher

“But what about hot reloading?” you might ask. This is one of the most powerful features of the Spring Cloud Config Server. When a change is made, the server can notify clients, which then call their /actuator/refresh endpoint to reload only the necessary configuration beans without restarting the pod.

We can achieve this exact same behavior in Kubernetes by using the official Spring Cloud Kubernetes Configuration Watcher.

Instead of a generic tool that just restarts the pod (like stakater/Reloader), the Configuration Watcher is designed specifically for Spring applications. Here’s how it works:

  1. You deploy the Configuration Watcher into your cluster
  2. It monitors any ConfigMap or Secret that your application is using
  3. When it detects a change, it doesn’t just kill the pod. Instead, it makes a POST request to that pod’s /actuator/refresh endpoint

This gives you the best of both worlds:

  • You use simple, native Kubernetes ConfigMaps to store your properties
  • You get true, application-aware hot reloading at runtime, just as you would with the Spring Cloud Config Server

Service Discovery: Netflix Eureka vs. Kubernetes Services

In a microservice architecture, services need to find and talk to each other. Netflix Eureka solves this by acting as a registry. When a microservice starts, it “registers” itself with Eureka (e.g., keynote-service is at 192.168.1.10:8080). When another service wants to talk to it, it first asks Eureka for the address.

In Kubernetes, this entire discovery process is handled automatically by Services and CoreDNS.

When you create a Deployment for your microservice, you also create a Service object to expose it. This Service gets a stable, internal IP address and a DNS name (like conference-service) that never changes, even when the pods behind it are created or destroyed.

apiVersion: v1
kind: Service
metadata:
name: conference-service
spec:
# This selector finds all pods with the label "app: conference-service"
selector:
app: conference-service
ports:
- protocol: TCP
port: 8081 # The port the Service is available on
targetPort: 8081 # The port the container is listening on

Now, when your keynote-service wants to talk to conference-service, it doesn’t need Eureka. It simply makes a request to the hostname conference-service (or http://conference-service:8081).

Here’s what happens automatically:

  1. Kubernetes’s internal DNS (CoreDNS) resolves the name conference-service to the Service’s stable IP address
  2. The Service acts as a load balancer. It knows the actual IPs of all healthy conference-service pods
  3. It forwards the request to one of the healthy pods

The creation and deletion of pods is completely abstracted. Your application only ever needs to know the static Service name.

API Gateway: Spring Cloud Gateway vs. Kubernetes Ingress

Finally, we need a single entry point for our application to route external traffic (from end-users) to our various microservices.

The Spring Cloud Gateway is an application-aware facade. It’s smart: it can integrate with the discovery server (Eureka) to find microservices, and you can write complex routing rules and filters in Java.

The Kubernetes equivalent is an Ingress. An Ingress is a set of rules that tells an Ingress Controller (like NGINX, Traefik, or HAProxy) how to route traffic. The Ingress Controller is the public entry point to your cluster.

The Ingress object is a simple, declarative way to define routing:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: conference-microservice-ingress
spec:
# This assumes you have the NGINX Ingress Controller installed
ingressClassName: nginx
rules:
# All traffic for "super.app" comes here
- host: super.app
http:
paths:
# If the path is /api/conferences...
- path: /api/conferences
pathType: Prefix
backend:
service:
# ...send it to the "conference-service" Service
name: conference-service
port:
number: 8081
# If the path is /api/keynotes...
- path: /api/keynotes
pathType: Prefix
backend:
service:
# ...send it to the "keynote-service" Service
name: keynote-service
port:
number: 8080

When a user browses to super.app/api/conferences, the Ingress Controller sees this rule and automatically forwards the request to the conference-service Service, which in turn load-balances the request to a healthy pod.

Conclusion

While Spring Cloud provides a fantastic suite of tools, Kubernetes provides native, declarative, and powerful alternatives for configuration, service discovery, and routing. By replacing these Spring Cloud components, you can:

  • Simplify your application by removing additional dependencies
  • Reduce overhead by leveraging platform capabilities
  • Fully embrace the power of the Kubernetes platform

The migration doesn’t have to be all-or-nothing. You can gradually replace these components one by one, starting with the one that provides the most immediate benefit for you

$ cd ../
j/k: navigate
Enter: activate
/: search
n/N: next/prev
🐳
☸️
☁️
🔧
📊
🔒