Skip to content

Instantly share code, notes, and snippets.

@svx
Forked from ddtmachado/README.md
Created February 15, 2023 15:40
Show Gist options
  • Save svx/808578b6f98ab792c9dae57b1a4395f6 to your computer and use it in GitHub Desktop.
Save svx/808578b6f98ab792c9dae57b1a4395f6 to your computer and use it in GitHub Desktop.
Traefik v2 to v3 parallel CRD migration

For this test I used k3d with the following start options:

k3d cluster create \
    "trk" \
    --agents 2 \
    --port="80:80@loadbalancer" \
    --port="443:443@loadbalancer" \
    --k3s-arg="--disable=traefik@server:0" \
    --image "rancher/k3s:v1.20.15-k3s1-amd64"

Clone and build the CRD PR since its not merged yet, then import the built image into k3d

k3d image import --cluster trk traefik/traefik:latest

Create separate namespaces

kubectl create namespace traefik-v2
kubectl create namespace traefik-v3

Create the static configuration for each Traefik instance

kubectl apply -k configs -n traefik-v2
kubectl apply -k configs -n traefik-v3

Install both CRD versions

kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/${version}/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-${version}.yml

Deploy the stack

kubectl apply -f proxy-v2-and-v3.yaml

Create the dashboard and fallthrough rules

kubectl apply -f kubernetes/apps/dashboard-v2.yml   -n traefik-v2
kubectl apply -f kubernetes/apps/fallthrough.yml -n traefik-v2

At this point you should be able to access the dashboard of the Treaefik v2 instance while going through Traefik v3. Any application deployed with the old CRD API will be recognized and exposed in Traefik v2 but also acessible from v3 because of the fallthrough rule.

The easies way to validate that is to deploy a new dashboard CRD, this time with the new CRD API so it gets exposed in v3 and gets prioritized

kubectl apply -f kubernetes/apps/dashboard-v3.yml   -n traefik-v3

Now when accessing the dashboard you'll be presented with the v3 dashboard. The same principle can be applied for any exposed app, once you deploy the new CRD it will take precedence over any route with the same match on v2.

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: api
spec:
entryPoints:
- web
routes:
- match: Host(`traefik-dashboard.docker.localhost`)
kind: Rule
services:
- name: api@internal
kind: TraefikService
apiVersion: traefik.io/v1
kind: IngressRoute
metadata:
name: api
spec:
entryPoints:
- web
routes:
- kind: Rule
match: Host(`traefik-dashboard.docker.localhost`)
priority: 10
services:
- name: api@internal
kind: TraefikService
apiVersion: traefik.io/v1
kind: IngressRoute
metadata:
name: api
spec:
entryPoints:
- web
routes:
- kind: Rule
match: HostRegexp(`.+`)
priority: 1
services:
- name: traefik-v2
port: 80
# Saved into ./configs folder
configMapGenerator:
- name: traefik-config
files:
- static.yaml=static-config.yaml
generatorOptions:
disableNameSuffixHash: true
apiVersion: v1
kind: Service
metadata:
name: traefik-v2
namespace: traefik-v2
spec:
type: ClusterIP
ports:
- protocol: TCP
name: web
port: 80
- protocol: TCP
name: websecure
port: 443
selector:
app: traefik-v2
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: traefik-v2-cr
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses
- ingressclasses
verbs:
- get
- list
- watch
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- traefik.containo.us
resources:
- middlewares
- middlewaretcps
- ingressroutes
- traefikservices
- ingressroutetcps
- ingressrouteudps
- tlsoptions
- tlsstores
- serverstransports
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: traefik-v2-crb
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-v2-cr
subjects:
- kind: ServiceAccount
name: traefik-v2-sa
namespace: traefik-v2
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-v2-sa
namespace: traefik-v2
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: traefik-v2
namespace: traefik-v2
labels:
app: traefik-v2
spec:
replicas: 1
selector:
matchLabels:
app: traefik-v2
template:
metadata:
labels:
app: traefik-v2
spec:
serviceAccountName: traefik-v2-sa
containers:
- name: traefik
image: traefik:v2.9
imagePullPolicy: IfNotPresent
args:
- "--configfile=/configs/static.yaml"
- "--log.level=DEBUG"
ports:
- name: web
containerPort: 80
- name: websecure
containerPort: 443
volumeMounts:
- name: "traefik-config"
mountPath: "/configs"
volumes:
- name: traefik-config
configMap:
name: traefik-config
---
###### V2 ######
apiVersion: v1
kind: Service
metadata:
name: traefik-v3
namespace: traefik-v3
spec:
type: LoadBalancer
ports:
- protocol: TCP
name: web
port: 80
- protocol: TCP
name: websecure
port: 443
selector:
app: traefik-v3
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: traefik-v3-cr
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses
- ingressclasses
verbs:
- get
- list
- watch
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- traefik.io
resources:
- middlewares
- middlewaretcps
- ingressroutes
- traefikservices
- ingressroutetcps
- ingressrouteudps
- tlsoptions
- tlsstores
- serverstransports
- serverstransporttcps
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: traefik-v3-crb
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-v3-cr
subjects:
- kind: ServiceAccount
name: traefik-v3-sa
namespace: traefik-v3
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-v3-sa
namespace: traefik-v3
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: traefik-v3
namespace: traefik-v3
labels:
app: traefik-v3
spec:
replicas: 1
selector:
matchLabels:
app: traefik-v3
template:
metadata:
labels:
app: traefik-v3
spec:
serviceAccountName: traefik-v3-sa
containers:
- name: traefik
image: traefik/traefik:latest
imagePullPolicy: IfNotPresent
args:
- "--configfile=/configs/static.yaml"
- "--log.level=DEBUG"
ports:
- name: web
containerPort: 80
- name: websecure
containerPort: 443
volumeMounts:
- name: "traefik-config"
mountPath: "/configs"
volumes:
- name: traefik-config
configMap:
name: traefik-config
api:
dashboard: true
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
providers:
kubernetesCRD: {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment