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
- 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
- Verify the ingress controller:
kubectl get pods -n ingress-nginx
Installing Traefik
- Install Traefik with Helm:
helm repo add traefik https://helm.traefik.io/traefik helm repo update helm install traefik traefik/traefik
- 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.
- Add your keystore to your Spring Boot project. Convert the
tls.crt
andtls.key
into a keystore (e.g., PKCS12 format):
openssl pkcs12 -export -in tls.crt -inkey tls.key \ -out keystore.p12 -name springboot-tls
- 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:
- 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
- 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:
- TLS Secrets: Certificates are valid, secure, and rotated frequently.
- Ingress Controller Health: Monitor ingress controllers for resource utilization and scaling needs.
- Automated SSL Rotation: Use tools like Cert-Manager to automate SSL certificate renewals.
- Rate Limiting and WAF: Apply ingress-level protections against malicious traffic with limits and firewalls.
- Health Probes: Ensure readiness and liveness probes are configured for services behind the ingress.
- 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.