Multiple IngressRoutes for One App
Create multiple IngressRoutes to expose the same service under different subdomains — for example, an API endpoint and a web frontend endpoint.
Prerequisites
base/base-values.yaml
image:
registry: docker.io
repository: traefik/whoami
tag: latest
port: 80
Configuration
- customResources (list)
- customResourcesMap (map)
envs/prod/values.yaml
deployment:
enabled: true
replicas: 1
service:
enabled: true
customResources:
- |
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: my-app-api-prod
annotations:
kubernetes.io/ingress.class: public-traefik
external-dns.alpha.kubernetes.io/target: public-v2.{{ .Values.captain_domain }}
spec:
entryPoints:
- web
- websecure
routes:
- match: Host(`my-app-api-prod.apps.{{ .Values.captain_domain }}`)
kind: Rule
services:
- name: '{{ include "app.name" . }}'
namespace: '{{ include "app.namespace" . }}'
port: 80
- |
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: my-app-web-prod
annotations:
kubernetes.io/ingress.class: public-traefik
external-dns.alpha.kubernetes.io/target: public-v2.{{ .Values.captain_domain }}
spec:
entryPoints:
- web
- websecure
routes:
- match: Host(`my-app-web-prod.apps.{{ .Values.captain_domain }}`)
kind: Rule
services:
- name: '{{ include "app.name" . }}'
namespace: '{{ include "app.namespace" . }}'
port: 80
envs/prod/values.yaml
deployment:
enabled: true
replicas: 1
service:
enabled: true
customResourcesMap:
api-route: |
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: my-app-api-prod
annotations:
kubernetes.io/ingress.class: public-traefik
external-dns.alpha.kubernetes.io/target: public-v2.{{ .Values.captain_domain }}
spec:
entryPoints:
- web
- websecure
routes:
- match: Host(`my-app-api-prod.apps.{{ .Values.captain_domain }}`)
kind: Rule
services:
- name: '{{ include "app.name" . }}'
namespace: '{{ include "app.namespace" . }}'
port: 80
web-route: |
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: my-app-web-prod
annotations:
kubernetes.io/ingress.class: public-traefik
external-dns.alpha.kubernetes.io/target: public-v2.{{ .Values.captain_domain }}
spec:
entryPoints:
- web
- websecure
routes:
- match: Host(`my-app-web-prod.apps.{{ .Values.captain_domain }}`)
kind: Rule
services:
- name: '{{ include "app.name" . }}'
namespace: '{{ include "app.namespace" . }}'
port: 80
tip
Using customResourcesMap here makes it easy to add or remove routes per environment. For example, you could define the API route in base-values.yaml and add the web route only in envs/prod/values.yaml.
What Gets Created
| Resource | Name | Hostname |
|---|---|---|
| IngressRoute | my-app-api-prod | my-app-api-prod.apps.nonprod.antoniostacos.onglueops.com |
| IngressRoute | my-app-web-prod | my-app-web-prod.apps.nonprod.antoniostacos.onglueops.com |
Both route to the same my-app-prod service.
Verify
# Both hostnames should resolve (after ~2 min for DNS)
curl https://my-app-api-prod.apps.nonprod.antoniostacos.onglueops.com
curl https://my-app-web-prod.apps.nonprod.antoniostacos.onglueops.com
note
The -prod suffix matches your environment folder name (envs/prod/). If you deploy to a different environment like envs/uat/, the suffix changes accordingly (e.g., my-app-api-uat).
Key Points
- Each IngressRoute must have a unique
metadata.namewithin the namespace - Both IngressRoutes need their own
external-dnsannotation so DNS records are created for each hostname - You can attach different middlewares to each IngressRoute (e.g., rate limiting on the API, different headers on the web route)