Ingress Configuration
Ingress provides a flexible way to route HTTP and HTTPS traffic inside a Kubernetes cluster. While NodePort and LoadBalancer services are useful for exposing applications, they generally operate at the transport layer and offer limited control over hostnames, URL paths, and TLS termination. An Ingress resource adds layer 7 routing by matching incoming requests to Kubernetes Services based on domains, paths, and other HTTP attributes.
An Ingress object is only a declarative set of routing rules. An Ingress Controller must be running in the cluster to watch these resources and translate them into the configuration of an actual proxy or load balancer. Popular choices include NGINX Ingress Controller, Traefik, and HAProxy.
A typical request follows this path:
- A client sends an HTTP or HTTPS request to the cluster’s external endpoint.
- The request reaches the Ingress Controller, which is usually exposed through a
LoadBalancer,NodePort, or cloud-managed load-balancer service. - The controller evaluates the Ingress rules and selects the appropriate backend.
- The selected Kubernetes
Serviceforwards the request to one of its readyPodendpoints.
This design separates application routing rules from the implementation of the underlying load balancer. The same Ingress resource can therefore be used with different controllers, although controller-specific annotations and behavior may vary.
Prerequisites
Before creating an Ingress, make sure the following components are available:
- A functioning Kubernetes cluster.
- An installed and running Ingress Controller.
- A DNS record or another method for directing traffic to the controller.
- A backend application deployed behind a Kubernetes
Service. - TLS certificates if the application must be served over HTTPS.
For the examples below, assume that a service named my-web-service exposes port 80 and connects to a deployment with ready replicas.
You can confirm that the controller is available with:
kubectl get ingressclass
kubectl get pods -n ingress-nginx
The namespace and controller name depend on how Ingress was installed.
Creating a Basic Ingress
Create a file named ingress-basic.yaml with the following content:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-web-service
port:
number: 80
This configuration sends requests for app.example.com to the my-web-service service on port 80.
Depending on the controller installation, the Ingress class may instead be selected with spec.ingressClassName. The kubernetes.io/ingress.class annotation remains widely supported, but it should not be confused with the controller-specific annotations used for features such as path rewriting.
Important Fields
metadata.nameidentifies the Ingress resource within its namespace.metadata.annotationscontains optional configuration understood by a particular controller.spec.rulesdefines the host and path routing rules.hostmatches the hostname requested by the client. If it is omitted, the rule can match requests regardless of the requested domain.http.pathsmaps URL paths to backend services.pathTypecontrols how paths are matched. Common values include:Prefix: Matches a URL path prefix. Path segments are handled in a segment-aware manner by modern Kubernetes implementations.Exact: Matches the complete URL path exactly.ImplementationSpecific: Leaves the matching behavior to the Ingress Controller.
backend.serviceidentifies the Kubernetes Service that should receive matching traffic.
A Prefix path of / commonly acts as a catch-all route. When several paths overlap, controller implementations may prioritize the most specific match.
Applying and Validating the Configuration
Apply the resource with kubectl:
kubectl apply -f ingress-basic.yaml
Then inspect its status and assigned address:
kubectl get ingress example-ingress -o wide
kubectl describe ingress example-ingress
The ADDRESS column may contain an IP address, a hostname, or both. The exact value depends on how the Ingress Controller is exposed.
For local testing, map the hostname to the controller’s address. On Linux or macOS, add an entry such as the following to /etc/hosts:
<INGRESS_CONTROLLER_IP> app.example.com
Alternatively, curl can set the Host header directly:
curl -H "Host: app.example.com" http://<INGRESS_CONTROLLER_IP>
A successful request should return a response from the backend application. If it does not, check that the Service has ready endpoints:
kubectl get service my-web-service
kubectl get endpointslices \
-l kubernetes.io/service-name=my-web-service
Configuring TLS and HTTPS
Production applications should normally be served over HTTPS. Kubernetes stores TLS credentials in a Secret, while the Ingress resource specifies which hosts should use that certificate.
Creating the TLS Secret
If the certificate and private key are stored in tls.crt and tls.key, create the Secret with:
kubectl create secret tls example-tls-secret \
--cert=path/to/tls.crt \
--key=path/to/tls.key
The Secret must exist in the same namespace as the Ingress resource that references it. The certificate should include the complete certificate chain expected by clients.
Referencing the Secret
Create an Ingress configuration with a tls section:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress-tls
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- hosts:
- app.example.com
secretName: example-tls-secret
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-web-service
port:
number: 80
Apply it and verify the endpoint:
kubectl apply -f ingress-tls.yaml
curl -I https://app.example.com
Once the controller loads the Secret, it will normally terminate TLS on port 443 and forward decrypted HTTP traffic to the backend service. TLS termination protects traffic between the client and controller; traffic between the controller and application pods may still be unencrypted. For end-to-end encryption, configure application-level TLS or a service mesh.
Useful Routing Patterns
An Ingress can direct different paths to different services:
spec:
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /web
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
Annotations can add controller-specific behavior. For example, the following NGINX annotation rewrites the request path before forwarding it:
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
Because annotation behavior is controller-specific, it should be tested carefully. Rewriting can affect redirects, static assets, and APIs that expect the original URL path.
Common Troubleshooting Steps
If requests return 404, 503, or the wrong application, inspect the resource and controller events:
kubectl describe ingress example-ingress
kubectl get events --sort-by=.lastTimestamp
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller
Common causes include:
- The requested hostname does not match
spec.rules[].host. - The request path does not match the configured
pathType. - The backend Service has no ready endpoints.
- The Ingress class points to a controller that is not running.
- DNS resolves to the wrong address.
- The TLS Secret is missing, invalid, or located in another namespace.
- A rewrite annotation changes the path expected by the application.
Ingress is a central part of exposing Kubernetes workloads, but it works best as part of a larger routing setup. Combining precise host and path rules, TLS termination, controller-specific annotations, and thorough endpoint validation enables a reliable path from external traffic to application pods.