Skip to main content

Getting Started

For this tutorial, we will deploy Traefik Hub API Gateway on a k3d cluster. It is 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:30000@loadbalancer --port 443:30001@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 configuration:

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

Step 1: Install Traefik Hub

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

warning

Copy the token from the gateway creation page. We'll use our own configuration steps instead of the ones shown on that page.

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 v35.4.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=latest-v3 \
--set service.type=NodePort \
--set ports.web.nodePort=30000 \
--set ports.websecure.nodePort=30001 \
traefik/traefik

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

# 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 v35.4.0 \
--reset-then-reuse-values \
--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=latest-v3 \
--set service.type=NodePort \
--set ports.web.nodePort=30000 \
--set ports.websecure.nodePort=30001 \
--set image.pullPolicy=Always
traefik/traefik

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

Step 2: Deploy an API as an Ingress

info

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

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

kubectl create namespace apps
kubectl apply -f https://raw.githubusercontent.com/traefik/hub/main/src/manifests/weather-app.yaml

It creates the weather app:

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

Then, expose the weather app using an IngressRoute:

cat <<'EOF' | kubectl apply -f -
---
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
EOF
ingressroute.traefik.io/getting-started-apimanagement created

At this point, the API is exposed. It is possible to reach it using the 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 the API resource:

cat <<'EOF' | kubectl apply -f -
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
EOF

Next, reference the API resource in the IngressRoute using the dedicated annotation:

cat <<'EOF' | kubectl apply -f -
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
EOF

After applying the resources, it creates API and links IngressRoute to the weather API:

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

Next, we need to configure visibility and authorization for our API. Traefik Hub separates API visibility from authorization:

ResourcePurpose
APICatalogItemMakes an API visible in the Portal to one or more user groups.
APIPlanDefines the available plans that users can subscribe to when accessing an API.
ManagedSubscriptionGrants an application access to that API with an APIPlan.

For the APIPlan feature to work, we need to deploy and configure Redis in the cluster and the Traefik Hub deployment. We can do this by following these steps:

info

These commands install Redis for demo purposes. For production deployments, refer to the Redis production installation guide: https://doc.traefik.io/traefik-hub/api-gateway/expose/middleware/distributed-rate-limit

Install the Redis via the Helm chart:

helm install redis oci://registry-1.docker.io/bitnamicharts/redis -n traefik --wait
info

The installation process can take a few seconds.

Export the Redis instance password:

export REDIS_PASSWORD=$(kubectl get secret --namespace traefik redis -o jsonpath="{.data.redis-password}" | base64 -d)

Finally, upgrade the Traefik Hub deployment to include Redis:

helm upgrade traefik -n traefik --wait \
--version v35.4.0 \
--reset-then-reuse-values \
--set hub.redis.endpoints=redis-master.traefik.svc.cluster.local:6379 \
--set hub.redis.password=${REDIS_PASSWORD} \
traefik/traefik

We'll make the weather API visible to the admin group in the portal using an APICatalogItem and grant the weather-app application access to consume it through a specific API plan.

cat <<'EOF' | kubectl apply -f -
---
apiVersion: hub.traefik.io/v1alpha1
kind: APIPlan
metadata:
name: weather-api-basic-plan
namespace: apps
spec:
title: Basic
description: "Basic API Plan"
rateLimit:
limit: 5
period: 1s
quota:
limit: 500
period: 24h
---
apiVersion: hub.traefik.io/v1alpha1
kind: APICatalogItem
metadata:
name: getting-started-weather-catalog
namespace: apps
spec:
groups:
- admin # Users in this group can **see** the API
apis:
- name: getting-started-apimanagement-weather-api
apiPlan:
name: weather-api-basic-plan
---
apiVersion: hub.traefik.io/v1alpha1
kind: ManagedSubscription
metadata:
name: weather-api-subscription
namespace: apps
spec:
applications:
- appId: weather-app # Will be created in the Portal (Step 5)
apis:
- name: getting-started-apimanagement-weather-api
apiPlan:
name: weather-api-basic-plan
EOF

After applying the resources, it creates APICatalogItem, APIPlan, and ManagedSubscription resources:

apicatalogitem.hub.traefik.io/getting-started-weather-catalog created
apiplan.hub.traefik.io/weather-api-plan created
managedsubscription.hub.traefik.io/weather-api-subscription created
note

We'll use weather-app as the application ID for the ManagedSubscription resource for now but we'll update it with an actual application ID in the next steps.

Now, the API is secured. When we try to access the API without an API key, 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 the API

Next, create an Admin user in the Traefik Hub Online Dashboard:

Create user admin

info

Ensure that the admin group is created in the Traefik Hub Online Dashboard and the admin user is added to the admin group.

After creating a new user, you'll be prompted to set a password. Select the link displayed and paste it in your browser to set a new password. Remember these credentials as they will be used to access the API Portal.

Create user admin

Now, we can provide an API Portal to the admin user.

Step 5: Deploy the API Portal

An API Portal uses the same logic as an API for routing, employing an Ingress resource and a dedicated annotation.

info

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

cat <<'EOF' | kubectl apply -f -
---
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
EOF
info

This API Portal is routed using the internal ClusterIP service named apiportal provided with the Helm chart.

Why use an Ingress and not an IngressRoute?

The API Portal is fronted by the built-in ClusterIP service apiportal that ships with the Helm chart. Using a plain Ingress maintains straightforward routing and works across namespaces without additional configuration. An IngressRoute would require cross-namespace RBAC permissions without providing additional benefits for this use case. See the API Portal documentation for details.

After applying the resources, it creates APIPortal and Ingress resources:

apiportal.hub.traefik.io/getting-started-apimanagement-apiportal created
ingress.networking.k8s.io/getting-started-apimanagement-apiportal created

The API Portal is reachable at http://api.getting-started.apimanagement.docker.localhost (its creation can take up to a minute).

Now, we can log in with the [email protected] as our username and the set password and create an application that can subscribe to the weather API plan and consume the API:

API Portal Log in

Step 6 : Create an Application in the API Portal

Next, we can create a new application by navigating to the Applications (at the top left of the portal) section and clicking on Create application:

API Portal Create Application

info
  • You can choose any name for the application but we recommend using a meaningful name like weather-app and in kebab case.
  • You can either generate the application ID manually or let the API Portal generate it for you by clicking icon beside the application ID input field.

After creating the application, we need to update our ManagedSubscription with the new application ID. We can do that by running the command below:

# Set this variable with the appId generated in the API portal
export APP_ID=
# Use the APP_IP exported variable to generate ManagedSubscription for this specific application
cat <<EOF | kubectl apply -f -
apiVersion: hub.traefik.io/v1alpha1
kind: ManagedSubscription
metadata:
name: weather-api-subscription
namespace: apps
spec:
applications:
- appId: $APP_ID
apis:
- name: getting-started-apimanagement-weather-api
apiPlan:
name: weather-api-basic-plan
EOF
managedsubscription.hub.traefik.io/weather-api-subscription configured

Step 7: Testing the API & Navigating the API Portal

Now, if we navigate to the API Catalog section of the API portal, we can see the OpenAPI specification for the weather API:

API Portal - OAS

Next, let's create an API key for our application and verify if we can now make requests to the weather API. We can do this by navigating to the Applications section of the portal, selecting the application just created, and clicking on Create API key.

API Portal - Create API Key

info
  • You can choose any name for the API key but we recommend using a meaningful name and it should be in kebab case.

After creating the API key, export it:

export API_KEY=

Making a request to the weather API now allows access:

curl -s -H "Authorization: Bearer $API_KEY" 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"}
]

To view the subscription details, navigate back to the API Catalog section in the API portal and click the gear-like icon on the API's OAS page:

We can also see the API endpoints available in the apps namespace within the portal and make requests directly from the portal because of the OpenAPI specification attached to the API. It is advisable that every API includes an OpenAPI specification (OAS):

API Portal with OAS

However, it is still possible to use the API portal without setting an OAS, but this significantly hinders the process of getting started with API consumption.

Let's deploy a forecast app without an OpenAPI specification:

cat <<'EOF' | kubectl apply -f -    
---
apiVersion: v1
kind: ConfigMap
metadata:
name: weather-app-forecast-data
namespace: apps
data:
api.json: |
{
"weather": {
"1": { "city": "GopherCity", "weather": "Cloudy", "dt": "3128231402" },
"2": { "city": "City of Gopher", "weather": "Rainy", "dt": "3128231402" },
"3": { "code": "GopherCentral", "weather": "Shiny", "dt": "3128231402" }
}
}

---
apiVersion: apps/v1
kind: Deployment
metadata:
name: weather-app-forecast
namespace: apps
spec:
replicas: 1
selector:
matchLabels:
app: weather-app-forecast
template:
metadata:
labels:
app: weather-app-forecast
spec:
containers:
- name: api
image: ghcr.io/traefik/api-server:v1.2.0
args: ["-data", "/api/api.json", "-errorrate", "2"]
imagePullPolicy: IfNotPresent
volumeMounts:
- name: api-data
mountPath: /api
volumes:
- name: api-data
configMap:
name: weather-app-forecast-data
---
apiVersion: v1
kind: Service
metadata:
name: weather-app-forecast
namespace: apps
labels:
app: weather-app-forecast
spec:
type: ClusterIP
ports:
- port: 3000
name: api
selector:
app: weather-app-forecast
EOF

This time, we will not specify how to retrieve the OpenAPI specification in the API CRD:

cat <<'EOF' | kubectl apply -f -
---
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: getting-started-apimanagement-weather-api-forecast
namespace: apps
spec: {}
EOF

The other resources are structured similarly. Let's apply it:

cat <<'EOF' | kubectl apply -f -
---
apiVersion: hub.traefik.io/v1alpha1
kind: APICatalogItem
metadata:
name: getting-started-forecast-catalog
namespace: apps
spec:
apis:
- name: getting-started-apimanagement-weather-api-forecast
everyone: true

---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: getting-started-apimanagement-weather-api-forecast
namespace: apps
annotations:
hub.traefik.io/api: getting-started-apimanagement-weather-api-forecast
spec:
entryPoints:
- web
routes:
- match: Host(`api.getting-started.apimanagement.docker.localhost`) && Path(`/forecast`)
kind: Rule
services:
- name: weather-app-forecast
port: 3000
EOF
api.hub.traefik.io/getting-started-apimanagement-weather-api-forecast created
apicatalogitem.hub.traefik.io/getting-started-apimanagement-weather-api-forecast created
ingressroute.traefik.io/getting-started-apimanagement-weather-api-forecast created

If you navigate to the API portal, you should see the API displayed without an OpenAPI specification:

API Portal without OAS

And that's it! You have successfully deployed and managed your first API with Traefik Hub API management.

Next Steps

To deepen your understanding of the concepts introduced in this guide, explore the documentation for the relevant resources:

Familiarizing yourself with these resources will provide a solid foundation for leveraging Traefik Hub's API Management features.