The Istio service mesh comes with its own ingress, but we see customers with requirements to use a non-Istio ingress all the time. Previously, we’ve covered integrating NGINX with Istio. Recently we’ve been working with customers that are using Traefik ingress. With some slight adjustments to the approach we suggested previously, we at Tetrate learned how to implement Traefik as the ingress gateway to your Istio Service Mesh. This article will show you how.

The flow of traffic is shown on the diagram below. As soon as requests arrive at the service mesh from the Traefik ingress, Istio has the ability to apply security, observability and traffic steering rules to the request:

Incoming traffic bypasses the Istio sidecar and arrives directly at Traefik, so the requests terminate at the Traefik ingress.

Traefik uses the IngressRoute config to rewrite the “Host” header to match the destination, and forwards the request to the targeted service, which is a several step process:

  • Requests exiting Traefik Ingress are redirected to the Istio sidecar (by iptables).
  • The sidecar receives the request, encrypts it (because our Istio PeerAuthentication policy dictates STRICT mTLS), and forwards the request to a pod of the target service.

Below is an end-to-end walkthrough of an example deployment, using Istio’s bookinfo demo application but fronting the entire deployment with a Traefik ingress. In short, to get this to work in your own environment:

  • Deploy Traefik controller with an Istio sidecar, annotating the deployment so that inbound traffic bypasses the Istio Sidecar:
# Exclude the ports that Traefik receives traffic “80” 

 # Make sure Traefik controller can talk to the Kubernetes API server X.X.X.X/32 

  • Enable Istio sidecar injection in the application namespace and deploy any Istio-specific config you need.
  • Create IngressRoute with a Traefik Middleware object that rewrites the hostname to one recognized by the mesh (i.e. a service in the cluster; this is discussed below in the details with an example).

Bookinfo with Traefik Ingress

The rest of this post covers deploying Istio’s Bookinfo sample application, using Traefik as the ingress proxy for the deployment.

Setting up the Environment

To follow this example yourself:

1. Deploy a Kubernetes cluster of at least version 1.17 (minimal Istio 1.8 supported version). We use a Google Kubernetes Engine cluster created by:

gcloud container clusters create istio-traefik \
  --cluster-version=1.17 \
  --region  \
  --machine-type=e2-standard-4 \
  --project  \
  --num-nodes 1 \
  --node-locations  # i.e us-west2-b (otherwise 1 node per zone)

2. Download Istio 1.8.x.

curl -sL |\
 ISTIO_VERSION=1.8.1 sh -

3. Install it with enabled HTTP access logs.

./istio-1.8.1/bin/istioctl install \
  --set meshConfig.accessLogFile=/dev/stdout \

Deploying Bookinfo Application

With Istio installed, we can start deploying our application. We’ll use Istio’s Bookinfo application for our demonstration. This sample application is part of Istio distribution (in the ./istio-1.8.1/samples/ folder)

4. Create bookinfo namespace.

kubectl create ns bookinfo

5. Label it for the sidecar injection.

kubectl label namespace bookinfo istio-injection=enabled

6. Deploy bookinfo application in that namespace.

kubectl apply -f istio-1.8.1/samples/bookinfo/platform/kube/bookinfo.yaml -n bookinfo

Confirm that all the pods are started and have sidecars deployed with them.

Enable Istio mTLS for Service-to-Service Communications for the Application Namespace

cat <<EOF | kubectl apply -f - 
kind: PeerAuthentication
  name: default
  namespace: bookinfo
    mode: STRICT

Deploy Traefik Ingress

Now it’s time to deploy Traefik by following v2.3 documentation (The most recent version of Traefik as of this post is 2.3, but it’ll work with any version of Traefik if you adjust the IngressRoute and Middleware resources as required for your version). 7. Deploy Traefik constructs. Please note that there are some modifications to the documented deployment on the Traefik website (instead of default namespace in Traefik documentation, bookinfo namespace will be specified). The file can be accessed here and applied as follows:

$ kubectl apply -f created created created created created created created created created

8. Create a service for incoming requests. The service will receive the external IP address. (There are a few changes to the example from the Traefik website):

a. The Namespace needs to be specified.

b. Only two ports are published: 80 for the Bookinfo application and 8080 for Traefik management.

c. The service needs to point to Traefik with a label (traefik-ingress-lb) that is used here.

d. “Type: Loadbalancer” is added to tell GCP to assign an external IP to the service.

cat <<EOF | kubectl apply -f - 
apiVersion: v1
kind: Service
  name: traefik
  namespace: bookinfo
    - protocol: TCP
      name: web
      port: 80
    - protocol: TCP
      name: admin
      port: 8080
    app: traefik-ingress-lb
  type: LoadBalancer

9. Confirm that the service is created as expected:

$ kubectl get svc traefik -n bookinfo
NAME      TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                       AGE
traefik   LoadBalancer   35.236.XXX.XXX   80:31718/TCP,8080:31334/TCP   2m6s

10. As the Traefik website describes in detail, the Kubernetes Deployment with ServiceAccount needs to be applied. Besides the name and namespace, the following changes are introduced to the website example:

a. Secure endpoint removed for simplicity.

b.Accesslog – added “=true” as it didn’t work without the value.

c. Log.level set to DEBUG will help us to see what’s happening.

d. Added annotations (For more details please refer to the previously mentioned Tetrate NGINX article).

KUBERNETES_SVC_IP=$( kubectl get svc kubernetes -n default -o jsonpath='{.spec.clusterIP}’ )

cat <<EOF | kubectl apply -f - 
apiVersion: v1
kind: ServiceAccount
  namespace: bookinfo
  name: traefik-ingress-lb

kind: Deployment
apiVersion: apps/v1
  namespace: bookinfo
  name: traefik-ingress-lb
    app: traefik-ingress-lb
  replicas: 1
      app: traefik-ingress-lb
        app: traefik-ingress-lb
      annotations: "80" ${KUBERNETES_SVC_IP}/32
      serviceAccountName: traefik-ingress-lb
        - name: traefik-ingress-lb
          image: traefik:v2.3
            - --api.insecure
            - --accesslog=true
            - --providers.kubernetescrd
            - --entrypoints.web.address=:80
            - --log.level=DEBUG
            - name: web
              containerPort: 80
            - name: admin
              containerPort: 8080

11. Confirm the deployment of Traefik in the Bookinfo Namespace:

$  kubectl get pods -n bookinfo -l app=traefik-ingress-lb
NAME                                  READY   STATUS    RESTARTS   AGE
traefik-ingress-lb-669fc4b77d-74mpx   2/2     Running   0          2m35s

12. Get the service IP and record BOOKINFO_IP variable value.

BOOKINFO_IP=$(kubectl -n bookinfo get service traefik -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

13. Test response from the Ingress port 80 and see that it doesn’t have route to the application.


Make sure it returns “404 Not Found” — not-200 response is expected as the ingress rules are not implemented yet.

Configure Traefik Ingress Rules

1. Traefik’s Middleware header rewrite functionality will allow Istio Service mesh to function correctly. In this example, the host needs to be defined as “productpage.bookinfo.svc”. The header can be defined according to the Traefik documentation:

cat <<EOF | kubectl apply -f - 
kind: Middleware
  name: productpage-header
  namespace: bookinfo
      Host: productpage.bookinfo.svc

2. The final step is to specify the routing logic for the ingress requests, since the focus of this article is Service Mesh integration. The definition is very simple and forwards all incoming requests arriving on port 80 to the fronting bookinfo application service called ProductPage (serving traffic on port 9080). It also uses the middleware object created in the previous step:

cat <
kind: IngressRoute
  name: productpage
  namespace: bookinfo
    - web
  - match: PathPrefix(\`/\`)
    kind: Rule
    - name: productpage-header
    - name: productpage
      port: 9080

Validate Your Deployment Functionality

1. Retest the application response:


We’ll receive “200 OK” response. It can also be tested via the browser using https://<BOOKINFO_IP value from above>/productpage:

2. If /productpage is added to the url https://<BOOKINFO_IP value>/productpage, it will return the application response:

3. By querying the Traefik pod logs in the bookinfo namespace of the istio-proxy container, the outgoing request to the application can be seen in istio-proxy logs. There are no incoming requests, since they reach the Traefik Ingress directly.

TRAEFIK_POD=$( kubectl -n bookinfo get pods -l app=traefik-ingress-lb -o jsonpath='{.items[0]}' )

kubectl -n bookinfo logs ${TRAEFIK_POD} -c istio-proxy

Please note that the logs take a few seconds to be displayed after the request is processed. Logs are only available if the Istio install was done with the “meshConfig.accessLogFile=/dev/stdout” flag:

[2021-01-05T20:13:55.015Z] "GET /productpage HTTP/1.1" 200 - "-" 0 5179 1069 1069 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36" "4bd443e9-1a2e-4d30-b1e3-398a5005f240" "productpage.bookinfo.svc" "" outbound|9080||productpage.bookinfo.svc.cluster.local - default
[2021-01-05T20:13:56.301Z] "GET /static/bootstrap/fonts/glyphicons-halflings-regular.woff2 HTTP/1.1" 200 - "-" 0 18028 3 3 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36" "8cb44552-c3c8-45dd-8674-4af207ce1648" "productpage.bookinfo.svc" "" outbound|9080||productpage.bookinfo.svc.cluster.local - default


This article demonstrates how Traefik Ingress can be implemented as an entry point to an Istio service mesh. The basic approach applied here should be applicable even if your environment is different from the one used in our example. The Traefik / Service Mesh integration can be successfully implemented in different clouds with brand-new or existing (a.k.a. brownfield) deployments of Traefik, when the service mesh is introduced during Day Two implementations stage. In the end, you’re getting the best of two worlds: Istio Service Mesh integrating with the Ingress controller of your choice!

This article was originally published in The New Stack. 

Peter McAllister is a Tetrate engineer. Tetrate makes it easier for enterprises to adopt a service mesh and offers a service mesh management platform designed for multi-cluster and multi-cloud.