Secure Spring Boot Microservices in Kubernetes with TLS and Ingress

Securing microservices in Kubernetes requires a robust approach, especially when these services communicate over the public internet. TLS (Transport Layer Security) ensures data confidentiality and integrity, while Kubernetes’ Ingress resource simplifies application routing and load balancing. This post explores how to secure Spring Boot microservices using TLS and an Ingress controller, and explains critical configurations and considerations for a production-grade setup.

Why Use Ingress Over LoadBalancer?

Kubernetes provides multiple options for exposing applications, including NodePort, LoadBalancer, and Ingress. While LoadBalancer provisions cloud provider-driven load balancers automatically, Ingress offers a more flexible, cost-efficient solution with the following advantages:

  • Centralized Management – Manage routing for multiple services through a single resource using simple rules.
  • TLS Termination – Terminate SSL/TLS at the ingress point, reducing the complexity of managing certificates across individual pods and services.
  • Custom Routing – Enable advanced routing mechanisms, such as path-based or host-based rules, to direct traffic.
  • Cost Efficiency – Avoid the creation of a separate load balancer instance for every service in your cluster.

By utilizing an ingress controller, you create a consolidated and efficient entry point for your microservices.

Installing an Ingress Controller (NGINX or Traefik)

Ingress requires an ingress controller to operate. Popular options include NGINX and Traefik.

Installing NGINX

  1. Use Helm to install the NGINX ingress controller:
   helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
   helm repo update
   helm install ingress-nginx ingress-nginx/ingress-nginx
  1. Verify the ingress controller:
   kubectl get pods -n ingress-nginx

Installing Traefik

  1. Install Traefik with Helm:
   helm repo add traefik https://helm.traefik.io/traefik
   helm repo update
   helm install traefik traefik/traefik
  1. Verify Traefik installation:
   kubectl get pods -n kube-system

The ingress controller is now ready to manage your service routing.

Creating TLS Secrets and Certificates

TLS enables secure communication between clients and your Kubernetes cluster. Follow these steps to configure TLS secrets:

Step 1. Generate a Certificate

Use tools like OpenSSL or Let’s Encrypt to generate a certificate and private key:

   openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
       -keyout tls.key -out tls.crt \
       -subj "/CN=mydomain.com/O=myorganization"

Step 2. Create a Kubernetes Secret

Store the certificate and key in a Kubernetes secret:

   kubectl create secret tls my-tls-secret --key tls.key --cert tls.crt

Verify the secret’s existence:

   kubectl get secrets | grep my-tls-secret

Configuring Spring Boot for HTTPS

Spring Boot applications can be configured to serve HTTPS traffic directly using the TLS secrets.

  1. Add your keystore to your Spring Boot project. Convert the tls.crt and tls.key into a keystore (e.g., PKCS12 format):
   openssl pkcs12 -export -in tls.crt -inkey tls.key \
       -out keystore.p12 -name springboot-tls
  1. Configure application.properties:
   server.ssl.enabled=true
   server.ssl.key-store=classpath:keystore.p12
   server.ssl.key-store-password=password
   server.ssl.key-store-type=PKCS12

Alternatively, allow TLS termination at the ingress controller to reduce configuration overhead within Spring Boot.

Defining Ingress Rules to Route to Services

Ingress rules specify how traffic is routed to services based on paths or hosts.

Example of Path-Based Routing

For distinguishing between API and frontend requests:

   apiVersion: networking.k8s.io/v1
   kind: Ingress
   metadata:
     name: springboot-ingress
     annotations:
       nginx.ingress.kubernetes.io/rewrite-target: /
   spec:
     rules:
     - http:
         paths:
         - path: /api
           pathType: Prefix
           backend:
             service:
               name: springboot-service
               port:
                 number: 8080

Example of Host-Based Routing

For applications served on multiple subdomains:

   spec:
     rules:
     - host: api.mydomain.com
       http:
         paths:
         - pathType: Prefix
           backend:
             service:
               name: springboot-service
               port:
                 number: 8080
     - host: www.mydomain.com
       http:
         paths:
         - pathType: Prefix
           backend:
             service:
               name: frontend-service
               port:
                 number: 80

Redirecting HTTP to HTTPS

To enforce secure communication and redirect HTTP traffic to HTTPS, annotate the ingress resource:

   metadata:
     annotations:
       nginx.ingress.kubernetes.io/force-ssl-redirect: "true"

NGINX will automatically redirect all HTTP requests to HTTPS.

Using Auth Headers and JWT with Ingress

Authentication is crucial when exposing microservices to external clients. Use auth headers or JWTs (JSON Web Tokens) with NGINX ingress:

  1. Add a JWT authentication annotation:
   metadata:
     annotations:
       nginx.ingress.kubernetes.io/auth-type: jwt
       nginx.ingress.kubernetes.io/auth-secret-name: jwt-secret
       nginx.ingress.kubernetes.io/auth-signin-url: https://auth.example.com/signin
  1. Configure your service to validate the JWT payload on each request.

Rate Limiting with Annotations

Rate limiting protects your services from excessive or abusive requests. Annotate your ingress resource to implement a rate limit:

   metadata:
     annotations:
       nginx.ingress.kubernetes.io/limit-connections: "20"
       nginx.ingress.kubernetes.io/limit-rps: "10"

Here, the example limits clients to 10 requests per second and a maximum of 20 concurrent connections.

Production Checklist for Ingress and SSL

Before moving to production, ensure:

  1. TLS Secrets: Certificates are valid, secure, and rotated frequently.
  2. Ingress Controller Health: Monitor ingress controllers for resource utilization and scaling needs.
  3. Automated SSL Rotation: Use tools like Cert-Manager to automate SSL certificate renewals.
  4. Rate Limiting and WAF: Apply ingress-level protections against malicious traffic with limits and firewalls.
  5. Health Probes: Ensure readiness and liveness probes are configured for services behind the ingress.
  6. Error Pages: Configure custom error pages for smoother user experience during unhandled scenarios.

FAQ

Why choose an ingress over a load balancer?

Ingress reduces costs by consolidating traffic routing into a single resource, whereas load balancers require individual cloud-provided instances for each service.

What’s the difference between path-based and host-based routing?

Path-based routing directs requests based on URL paths, while host-based routing relies on domain names or subdomains.

Can I use self-signed certificates in Kubernetes?

Yes, but it’s recommended only for non-production environments. Always use certificates from trusted authorities in production.

How does ingress handle authentication?

Ingress supports JWT authentication and header-based authentication out-of-the-box via annotations.

What happens if the TLS secret is missing?

Ingress will fail to serve traffic over HTTPS and may block requests entirely.

By following this guide, you can create a secure and scalable architecture for Spring Boot microservices in Kubernetes, ensuring robustness and reliability in production.

Similar Posts