Skip to content

Exposing Services with Traefik on Kubernetes - Basic

This guide will help you get started with exposing your services through Traefik Proxy on Kubernetes. You'll learn the fundamentals of routing HTTP traffic, setting up path-based routing, and securing your services with TLS.

For routing, this guide gives you two options:

Feel free to choose the one that fits your needs best.

Prerequisites

  • A Kubernetes cluster with Traefik Proxy installed
  • kubectl configured to interact with your cluster
  • Traefik deployed using the Traefik Kubernetes Setup guide

Expose Your First HTTP Service

Let's expose a simple HTTP service using the whoami application. This will demonstrate basic routing to a backend service.

First, create the deployment and service:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
      - name: whoami
        image: traefik/whoami
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: whoami
  namespace: default
spec:
  selector:
    app: whoami
  ports:
  - port: 80

Save this as whoami.yaml and apply it:

kubectl apply -f whoami.yaml

Now, let's create routes using either Gateway API or IngressRoute.

Using Gateway API

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami
  namespace: default
spec:
  parentRefs:
  - name: traefik-gateway  # This Gateway is automatically created by Traefik
  hostnames:
  - "whoami.docker.localhost"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: whoami
      port: 80

Save this as whoami-route.yaml and apply it:

kubectl apply -f whoami-route.yaml

Using IngressRoute

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: whoami
  namespace: default
spec:
  entryPoints:
    - web
  routes:
  - match: Host(`whoami.docker.localhost`)
    kind: Rule
    services:
    - name: whoami
      port: 80

Save this as whoami-ingressroute.yaml and apply it:

kubectl apply -f whoami-ingressroute.yaml

Verify Your Service

Your service is now available at http://whoami.docker.localhost/. Test that it works:

curl -H "Host: whoami.docker.localhost" http://localhost/

Info

Make sure to remove the ports.web.redirections block from the values.yaml file if you followed the Kubernetes Setup Guide to install Traefik otherwise you will be redirected to the HTTPS entrypoint:

redirections:
  entryPoint:
    to: websecure

You should see output similar to:

Hostname: whoami-6d5d964cb-8pv4k
IP: 127.0.0.1
IP: ::1
IP: 10.42.0.18
IP: fe80::d4c0:3bff:fe20:b0a3
RemoteAddr: 10.42.0.17:39872
GET / HTTP/1.1
Host: whoami.docker.localhost
User-Agent: curl/7.68.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.42.0.1
X-Forwarded-Host: whoami.docker.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: traefik-76cbd5b89c-rx5xn
X-Real-Ip: 10.42.0.1

This confirms that Traefik is successfully routing requests to your whoami application.

Add Routing Rules

Now we'll enhance our routing by directing traffic to different services based on URL paths. This is useful for API versioning, frontend/backend separation, or organizing microservices.

First, deploy a second service to represent an API:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami-api
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: whoami-api
  template:
    metadata:
      labels:
        app: whoami-api
    spec:
      containers:
      - name: whoami
        image: traefik/whoami
        env:
        - name: WHOAMI_NAME
          value: "API Service"
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: whoami-api
  namespace: default
spec:
  selector:
    app: whoami-api
  ports:
  - port: 80

Save this as whoami-api.yaml and apply it:

kubectl apply -f whoami-api.yaml

Now set up path-based routing:

Gateway API with Path Rules

Update your existing HTTPRoute to include path-based routing:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami
  namespace: default
spec:
  parentRefs:
  - name: traefik-gateway
  hostnames:
  - "whoami.docker.localhost"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /api
    backendRefs:
    - name: whoami-api
      port: 80
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: whoami
      port: 80

Update the file whoami-route.yaml and apply it:

kubectl apply -f whoami-route.yaml

IngressRoute with Path Rules

Update your existing IngressRoute to include path-based routing:

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: whoami
  namespace: default
spec:
  entryPoints:
    - web
  routes:
  - match: Host(`whoami.docker.localhost`) && Path(`/api`)
    kind: Rule
    services:
    - name: whoami-api
      port: 80
  - match: Host(`whoami.docker.localhost`)
    kind: Rule
    services:
    - name: whoami
      port: 80

Save this as whoami-ingressroute.yaml and apply it:

kubectl apply -f whoami-ingressroute.yaml

Test the Path-Based Routing

Verify that different paths route to different services:

# Root path should go to the main whoami service
curl -H "Host: whoami.docker.localhost" http://localhost/

# /api path should go to the whoami-api service
curl -H "Host: whoami.docker.localhost" http://localhost/api

For the /api requests, you should see the response showing "API Service" in the environment variables section, confirming that your path-based routing is working correctly:

{"hostname":"whoami-api-67d97b4868-dvvll","ip":["127.0.0.1","::1","10.42.0.9","fe80::10aa:37ff:fe74:31f2"],"headers":{"Accept":["*/*"],"Accept-Encoding":["gzip"],"User-Agent":["curl/8.7.1"],"X-Forwarded-For":["10.42.0.1"],"X-Forwarded-Host":["whoami.docker.localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["traefik-669c479df8-vkj22"],"X-Real-Ip":["10.42.0.1"]},"url":"/api","host":"whoami.docker.localhost","method":"GET","name":"API Service","remoteAddr":"10.42.0.13:36592"}

Enable TLS

Let's secure our service with HTTPS by adding TLS. We'll start with a self-signed certificate for local development.

Create a Self-Signed Certificate

Generate a self-signed certificate:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt \
  -subj "/CN=whoami.docker.localhost"

Create a TLS secret in Kubernetes:

kubectl create secret tls whoami-tls --cert=tls.crt --key=tls.key

Prerequisite for Gateway API with TLS

Before using the Gateway API with TLS, you must define the websecure listener in your Traefik installation. This is typically done in your Helm values.

Example configuration in values.yaml:

gateway:
  listeners:
    web:
      port: 80
      protocol: HTTP
      namespacePolicy:
        from: All
    websecure:
      port: 443
      protocol: HTTPS
      namespacePolicy:
        from: All
      mode: Terminate
      certificateRefs:
        - kind: Secret
          name: local-selfsigned-tls
          group: ""

See the Traefik Kubernetes Setup Guide for complete installation details.

Gateway API with TLS

Update your existing HTTPRoute to use the secured gateway listener:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami
  namespace: default
spec:
  parentRefs:
  - name: traefik-gateway
    sectionName: websecure  # The HTTPS listener
  hostnames:
  - "whoami.docker.localhost"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /api
    backendRefs:
    - name: whoami-api
      port: 80
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: whoami
      port: 80

Update the file whoami-route.yaml and apply it:

kubectl apply -f whoami-route.yaml

IngressRoute with TLS

Update your existing IngressRoute to use TLS:

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: whoami
  namespace: default
spec:
  entryPoints:
    - websecure  # Changed from 'web' to 'websecure'
  routes:
  - match: Host(`whoami.docker.localhost`) && Path(`/api`)
    kind: Rule
    services:
    - name: whoami-api
      port: 80
  - match: Host(`whoami.docker.localhost`)
    kind: Rule
    services:
    - name: whoami
      port: 80
  tls:
    secretName: whoami-tls  # Added TLS configuration

Update the file whoami-ingressroute.yaml and apply it:

kubectl apply -f whoami-ingressroute.yaml

Verify HTTPS Access

Now you can access your service securely. Since we're using a self-signed certificate, you'll need to skip certificate verification:

curl -k -H "Host: whoami.docker.localhost" https://localhost/

Your browser can also access https://whoami.docker.localhost/ (you'll need to accept the security warning for the self-signed certificate).

Next Steps

Now that you've mastered the basics of exposing services with Traefik on Kubernetes, you're ready to explore more advanced features like middlewares, Let's Encrypt certificates, sticky sessions, and multi-layer routing.

Continue to the Advanced Guide to learn about:

  • Adding middlewares for security and access control
  • Generating certificates with Let's Encrypt (IngressRoute) or cert-manager (Gateway API)
  • Configuring sticky sessions for stateful applications
  • Setting up multi-layer routing for authentication-based routing with IngressRoute