Skip to main content

Getting Started

For this tutorial, we deploy Traefik Hub API Gateway on a k3d cluster. It's possible to use alternatives such as kind, cloud providers, and others.

First, clone the GitHub repository dedicated to tutorials:

git clone https://github.com/traefik/hub.git
cd hub

Deploy Kubernetes

Using k3d

k3d cluster create traefik-hub --port 80:80@loadbalancer --port 443:443@loadbalancer --port 8000:8000@loadbalancer --k3s-arg "--disable=traefik@server:0"

Using Kind

kind requires some configuration to use an IngressController on localhost. See the following example:

Create the cluster

Ports need to be mapped for HTTP and HTTPS for kind with this config:

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: traefik-hub
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30000
hostPort: 80
protocol: TCP
- containerPort: 30001
hostPort: 443
protocol: TCP
kind create cluster --config=src/kind/config.yaml
kubectl cluster-info
kubectl wait --for=condition=ready nodes traefik-hub-control-plane

Now, add a load balancer (LB) to it:

kubectl apply -f src/kind/metallb-native.yaml
kubectl wait --namespace metallb-system --for=condition=ready pod --selector=app=metallb --timeout=90s
kubectl apply -f src/kind/metallb-config.yaml

Step 1: Install Traefik Hub

First, log in to the Traefik Hub Online Dashboard and open the page to create a new gateway.

⚠️ Do not install the gateway, but copy the token.

Then, open a terminal and run these commands to create the required secret:

export TRAEFIK_HUB_TOKEN=
kubectl create namespace traefik
kubectl create secret generic traefik-hub-license --namespace traefik --from-literal=token=$TRAEFIK_HUB_TOKEN

Now, install Traefik Hub with Helm:

# Add the Helm repository
helm repo add --force-update traefik https://traefik.github.io/charts
# Install the Helm chart
helm install traefik -n traefik --wait \
--version v33.1.0 \
--set hub.token=traefik-hub-license \
--set hub.apimanagement.enabled=true \
--set ingressClass.enabled=false \
--set ingressRoute.dashboard.enabled=true \
--set ingressRoute.dashboard.matchRule='Host(`dashboard.docker.localhost`)' \
--set ingressRoute.dashboard.entryPoints={web} \
--set image.registry=ghcr.io \
--set image.repository=traefik/traefik-hub \
--set image.tag=v3.8.0 \
--set ports.web.nodePort=30000 \
--set ports.websecure.nodePort=30001 \
traefik/traefik

If Traefik Hub is already installed, we can instead upgrade the Traefik Hub instance:

# Upgrade CRDs
kubectl apply --server-side --force-conflicts -k https://github.com/traefik/traefik-helm-chart/traefik/crds/
# Update the Helm repository
helm repo add --force-update traefik https://traefik.github.io/charts
# Upgrade the Helm chart
helm upgrade traefik -n traefik --wait \
--version v33.1.0 \
--set hub.token=traefik-hub-license \
--set hub.apimanagement.enabled=true \
--set ingressClass.enabled=false \
--set ingressRoute.dashboard.enabled=true \
--set ingressRoute.dashboard.matchRule='Host(`dashboard.docker.localhost`)' \
--set ingressRoute.dashboard.entryPoints={web} \
--set image.registry=ghcr.io \
--set image.repository=traefik/traefik-hub \
--set image.tag=v3.8.0 \
--set ports.web.nodePort=30000 \
--set ports.websecure.nodePort=30001 \
traefik/traefik

Now, we can access the local dashboard at http://dashboard.docker.localhost/.

Step 2: Deploy an API as an Ingress

ℹ️ This tutorial implements API using a JSON server in Go; check out the source code here.

First, let's deploy a weather app exposing an API:

kubectl apply -f src/manifests/apps-namespace.yaml
kubectl apply -f src/manifests/weather-app.yaml

It creates the weather app:

namespace/apps unchanged
configmap/weather-data unchanged
middleware.traefik.io/stripprefix-weather unchanged
deployment.apps/weather-app unchanged
service/weather-app unchanged
configmap/weather-app-openapispec unchanged

Then, expose the weather app using an IngressRoute:

---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: getting-started-apimanagement
namespace: apps
spec:
entryPoints:
- web
routes:
- match: Host(`getting-started.apimanagement.docker.localhost`)
kind: Rule
services:
- name: weather-app
port: 3000
middlewares:
- name: stripprefix-weather
kubectl apply -f api-management/1-getting-started/manifests/weather-app-ingressroute.yaml
ingressroute.traefik.io/getting-started-apimanagement created

At this moment, this API is exposed. It's possible to reach it using curl command:

curl -s http://getting-started.apimanagement.docker.localhost/weather | jq
[
{"city":"City of Gophers","id":"1","weather":"Sunny"},
{"city":"GopherRocks","id":"2","weather":"Cloudy"},
{"city":"GopherCity","id":"0","weather":"Moderate rain"}
]

Step 3: Manage the API using Traefik Hub API Management

Let's manage the weather API with Traefik Hub using API and APIAccess resources:

---
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: getting-started-apimanagement-weather-api
namespace: apps
spec:
openApiSpec:
path: /openapi.yaml
override:
servers:
- url: http://api.getting-started.apimanagement.docker.localhost

---
apiVersion: hub.traefik.io/v1alpha1
kind: APIAccess
metadata:
name: getting-started-apimanagement-weather-api
namespace: apps
spec:
apis:
- name: getting-started-apimanagement-weather-api
everyone: true

First, reference the API in the IngressRoute using the dedicated annotation:

---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: getting-started-apimanagement-weather-api
namespace: apps
annotations:
hub.traefik.io/api: getting-started-apimanagement-weather-api # <=== Link to the API using its name
spec:
entryPoints:
- web
routes:
- match: Host(`api.getting-started.apimanagement.docker.localhost`) && PathPrefix(`/weather`)
kind: Rule
services:
- name: weather-app
port: 3000

Now, we can apply the above resources:

kubectl apply -f api-management/1-getting-started/manifests/api.yaml

It creates API, APIAccess, and links IngressRoute to the weather API:

api.hub.traefik.io/getting-started-apimanagement-weather-api created
apiaccess.hub.traefik.io/getting-started-apimanagement-weather-api created
ingressroute.traefik.io/getting-started-apimanagement-weather-api created

Now, the API is secured. When someone tries to access the API, it returns the expected 401 Unauthorized HTTP code:

curl -i http://api.getting-started.apimanagement.docker.localhost/weather
HTTP/1.1 401 Unauthorized
Date: Mon, 06 May 2024 12:09:56 GMT
Content-Length: 0

Step 4: Create a user for this API

We can create a user in the Traefik Hub Online Dashboard:

Create user admin

We can provide an API Portal to this user.

Step 5: Deploy the API Portal

An API Portal use the same logic as an API for the routing, using Ingress and dedicated annotation.

ℹ️ The portal enforces namespace boundaries and considers only APIAccess resources within the same namespace as the APIPortal.

---
apiVersion: hub.traefik.io/v1alpha1
kind: APIPortal
metadata:
name: getting-started-apimanagement-apiportal
namespace: apps
spec:
title: API Portal
description: "Apps Developer Portal"
trustedUrls:
- http://api.getting-started.apimanagement.docker.localhost

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: getting-started-apimanagement-apiportal
namespace: traefik
annotations:
# This annotation link this Ingress to the API Portal using <name>@<namespace> format.
hub.traefik.io/api-portal: getting-started-apimanagement-apiportal@apps
spec:
rules:
- host: api.getting-started.apimanagement.docker.localhost
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: apiportal
port:
number: 9903

ℹ️ This API Portal is routed with the internal ClusterIP Service named apiportal provided with the Helm Chart.

kubectl apply -f api-management/1-getting-started/manifests/api-portal.yaml
sleep 30
apiportal.hub.traefik.io/getting-started-apimanagement-apiportal created
ingress.networking.k8s.io/getting-started-apimanagement-apiportal created

The API Portal is reachable on http://api.getting-started.apimanagement.docker.localhost.

Now, we should be able to log in with the admin user and create a token for the user:

API Portal Log in

API Portal Create Token

export ADMIN_TOKEN=

The weather API is reachable with this token set as header 🎉 :

curl -s -H "Authorization: Bearer $ADMIN_TOKEN" http://api.getting-started.apimanagement.docker.localhost/weather | jq
[
{"city":"City of Gophers","id":"1","weather":"Sunny"},
{"city":"GopherRocks","id":"2","weather":"Cloudy"},
{"city":"GopherCity","id":"0","weather":"Moderate rain"}
]

ℹ️ If it fails with 401, wait a minute and try again. The token needs to be sync before it can be accepted by Traefik Hub.

We can see the API available in the apps namespace in the portal. We advise every API to come with an OpenAPI specification (OAS):

API Portal with OAS

However, it's still possible not setting an OAS, but it severely hurts getting started with API consumption. Let's deploy a forecast app without an OpenAPI specification:

kubectl apply -f src/manifests/weather-app-forecast.yaml

This time, we will specify how to get this openapi spec in API CRD:

---
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: getting-started-apimanagement-weather-api-forecast
namespace: apps
spec: {}

The other resources are built on the same model, as we can see in the complete file. Let's apply it:

kubectl apply -f api-management/1-getting-started/manifests/forecast.yaml
api.hub.traefik.io/getting-started-apimanagement-weather-api-forecast created
apiaccess.hub.traefik.io/getting-started-apimanagement-weather-api-forecast created
ingressroute.traefik.io/getting-started-apimanagement-weather-api-forecast created

And that's it! This time, we have documentation built from the OpenAPI specification, and we can also interactively try the API with the Try Out functionality.

API Portal without OAS