Skip to main content

Standard Kubernetes Ingress with Traefik

The simplest way to expose your application is using a standard Kubernetes Ingress resource with ingressClassName: public-traefik. This uses the Helm chart's built-in ingress configuration — no customResources needed.

Basic Hostname Routing​

Route all traffic for a hostname to your service.

base/base-values.yaml

image:
registry: docker.io
repository: traefik/whoami
tag: latest
port: 80

envs/prod/values.yaml

deployment:
enabled: true
replicas: 1

service:
enabled: true

ingress:
enabled: true
ingressClassName: public-traefik
entries:
- name: public
hosts:
- hostname: '{{ include "app.name" . }}.apps.{{ .Values.captain_domain }}'

Verify​

curl https://my-app-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-uat).

info

{{ include "app.name" . }} resolves to <folder-name>-<env> — for example, if your app folder is apps/my-app and your environment folder is envs/prod, the hostname becomes my-app-prod.apps.nonprod.antoniostacos.onglueops.com. All examples on this page assume the app folder is named my-app.


Sticky Sessions​

Pin a user to the same backend pod using cookies. Useful when running multiple replicas and your app maintains session state.

envs/prod/values.yaml

deployment:
enabled: true
replicas: 2

service:
enabled: true
annotations:
traefik.ingress.kubernetes.io/service.sticky.cookie: "true"
traefik.ingress.kubernetes.io/service.sticky.cookie.name: "my-sticky-cookie"
traefik.ingress.kubernetes.io/service.sticky.cookie.maxage: "3600"

ingress:
enabled: true
ingressClassName: public-traefik
entries:
- name: public
hosts:
- hostname: '{{ include "app.name" . }}.apps.{{ .Values.captain_domain }}'

Verify​

# First request sets a cookie
curl -v https://my-app-prod.apps.nonprod.antoniostacos.onglueops.com 2>&1 | grep set-cookie
# Output should include: set-cookie: my-sticky-cookie=<hash>; ...

# Subsequent requests with the cookie go to the same pod
curl -b "my-sticky-cookie=<hash>" https://my-app-prod.apps.nonprod.antoniostacos.onglueops.com

Path-Based Routing​

Route different URL paths to the same (or different) services.

envs/prod/values.yaml

deployment:
enabled: true
replicas: 1

service:
enabled: true

ingress:
enabled: true
ingressClassName: public-traefik
entries:
- name: public
hosts:
- hostname: '{{ include "app.name" . }}.apps.{{ .Values.captain_domain }}'
paths:
- path: /api
pathType: Prefix
- path: /health
pathType: Prefix
info

When you specify explicit paths, only those paths will be routed. Requests to other paths (e.g., /) will return a 404. To add a catch-all, add a path entry with path: /.

Verify​

curl https://my-app-prod.apps.nonprod.antoniostacos.onglueops.com/api
curl https://my-app-prod.apps.nonprod.antoniostacos.onglueops.com/health

Multiple Hostnames​

Serve the same application from multiple domain names.

envs/prod/values.yaml

deployment:
enabled: true
replicas: 1

service:
enabled: true

ingress:
enabled: true
ingressClassName: public-traefik
entries:
- name: public
hosts:
- hostname: '{{ include "app.name" . }}.apps.{{ .Values.captain_domain }}'
- hostname: 'my-app-alt.apps.{{ .Values.captain_domain }}'

Verify​

# Both hostnames route to the same service
curl https://my-app-prod.apps.nonprod.antoniostacos.onglueops.com
curl https://my-app-alt.apps.nonprod.antoniostacos.onglueops.com

Referencing Traefik Middleware from a Standard Ingress​

You can use standard Ingress for routing while attaching Traefik Middleware CRDs via annotations. The middleware is created via customResources and referenced using the traefik.ingress.kubernetes.io/router.middlewares annotation.

warning

Standard Ingress annotations are not processed through Helm's tpl function. The namespace prefix in middleware references (e.g., nonprod-) must be hardcoded to your actual deployment namespace. If your apps deploy to a different namespace, replace nonprod accordingly. IngressRoute CRDs do not have this limitation — middleware references there are resolved by namespace automatically.

envs/prod/values.yaml

deployment:
enabled: true
replicas: 1

service:
enabled: true

ingress:
enabled: true
ingressClassName: public-traefik
annotations:
traefik.ingress.kubernetes.io/router.middlewares: nonprod-my-headers-mw@kubernetescrd
entries:
- name: public
hosts:
- hostname: '{{ include "app.name" . }}.apps.{{ .Values.captain_domain }}'

customResources:
- |
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: my-headers-mw
spec:
headers:
frameDeny: true
contentTypeNosniff: true
browserXssFilter: true
caution

The middleware reference format is <namespace>-<middleware-name>@kubernetescrd. Since all apps deploy to the nonprod namespace, the format is nonprod-<middleware-name>@kubernetescrd.

Verify​

curl -I https://my-app-prod.apps.nonprod.antoniostacos.onglueops.com
# Response headers should include:
# X-Frame-Options: DENY
# X-Content-Type-Options: nosniff
# X-XSS-Protection: 1; mode=block

TLS / HTTPS Redirect​

Force HTTP traffic to redirect to HTTPS using a Traefik redirectScheme middleware combined with a standard Ingress.

envs/prod/values.yaml

deployment:
enabled: true
replicas: 1

service:
enabled: true

ingress:
enabled: true
ingressClassName: public-traefik
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
traefik.ingress.kubernetes.io/router.middlewares: nonprod-my-app-tls-redirect@kubernetescrd
entries:
- name: public
hosts:
- hostname: '{{ include "app.name" . }}.apps.{{ .Values.captain_domain }}'

customResources:
- |
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: my-app-tls-redirect
spec:
redirectScheme:
scheme: https
permanent: true

The middleware reference format is <namespace>-<middleware-name>@kubernetescrd.

Verify​

# HTTP → should redirect to HTTPS (301)
curl -D- -o /dev/null http://my-app-prod.apps.nonprod.antoniostacos.onglueops.com
# HTTP/1.1 301 Moved Permanently
# Location: https://my-app-prod.apps.nonprod.antoniostacos.onglueops.com/

# HTTPS → serves the app
curl https://my-app-prod.apps.nonprod.antoniostacos.onglueops.com

Common Traefik Annotations for Standard Ingress​

AnnotationDescriptionExample Value
traefik.ingress.kubernetes.io/router.tlsEnable TLS on the router"true"
traefik.ingress.kubernetes.io/router.entrypointsRestrict to specific entrypointswebsecure
traefik.ingress.kubernetes.io/router.middlewaresAttach middleware(s)nonprod-mw-name@kubernetescrd
traefik.ingress.kubernetes.io/service.sticky.cookieEnable sticky sessions"true"
traefik.ingress.kubernetes.io/service.sticky.cookie.nameCookie name for sticky sessions"my-cookie"
traefik.ingress.kubernetes.io/service.sticky.cookie.maxageCookie max age in seconds"3600"
traefik.ingress.kubernetes.io/router.prioritySet router priority"100"