Setup Traefik with MetalLB
Requirements
- Kubernetes
- MetalLB
- Traefik
- Helm
Install Traefik using Helm
bash
helm repo add traefik https://helm.traefik.io/traefik
helm repo update
helm install traefik traefik/traefik
1
2
3
2
3
To install crds go here Copy and execute commands in IngressRoute Definition
.
Install metallb
sh
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.9/config/manifests/metallb-native.yaml
1
MetallB setup
metallb-pool.yml
yml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: traefik-pool-public
namespace: metallb-system
spec:
addresses:
- 192.168.1.201/32 # Exclude this IP from DHCP and NAT it to WAN
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: traefik
namespace: metallb-system
spec:
ipAddressPools:
- traefik-pool-public
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Traefik with MetalLB example setup
namespace.yml
yml
apiVersion: v1
kind: Namespace
metadata:
name: traefik
1
2
3
4
2
3
4
account.yml
yml
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-account
namespace: traefik
1
2
3
4
5
2
3
4
5
role.yml
yml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: traefik-role
namespace: traefik
rules:
- apiGroups:
- ""
resources:
- services
- secrets
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- discovery.k8s.io
resources:
- endpointslices
verbs:
- 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
cluster-role-binding.yml
yml
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: traefik-role-binding
namespace: traefik
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-role
subjects:
- kind: ServiceAccount
name: traefik-account
namespace: traefik
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
traefik-deployment.yml
yml
kind: Deployment
apiVersion: apps/v1
metadata:
name: traefik-deployment
labels:
app: traefik
namespace: traefik
spec:
replicas: 1
selector:
matchLabels:
app: traefik
template:
metadata:
labels:
app: traefik
namespace: traefik
spec:
serviceAccountName: traefik-account
containers:
- name: traefik
image: traefik:v3.4
args:
- --api.insecure
- --providers.kubernetesingress
ports:
- name: web
containerPort: 80
- name: dashboard
containerPort: 8080
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
traefik-service.yml
yml
apiVersion: v1
kind: Service
metadata:
name: traefik-web-service
annotations:
metallb.io/address-pool: traefik-pool-public
spec:
type: LoadBalancer
ports:
- protocol: TCP
name: web
port: 80
- protocol: TCP
name: admin
port: 8080
- protocol: TCP
name: websecure
port: 443
selector:
app: traefik
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Whoami app example
whoami-deployment.yml
yml
kind: Deployment
apiVersion: apps/v1
metadata:
name: whoami
labels:
app: whoami
spec:
replicas: 1
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- name: whoami
image: traefik/whoami
ports:
- name: web
containerPort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
whoami-ingress.yml
yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: whoami-ingress
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: whoami
port:
name: web
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
whoami-service.yml
yml
apiVersion: v1
kind: Service
metadata:
name: whoami
spec:
ports:
- name: web
port: 80
targetPort: web
selector:
app: whoami
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
You can use the dashboard of Traefik to see the status of your services and routes. You need to access it using a port forward to the Traefik pod. Because we don't expose the dashboard to our public metalLB IP.
HTTPS setup
yaml
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: default
name: traefik-ingress-controller
---
kind: Deployment
apiVersion: apps/v1
metadata:
namespace: default
name: traefik
labels:
app: traefik
spec:
replicas: 1
selector:
matchLabels:
app: traefik
template:
metadata:
labels:
app: traefik
spec:
nodeSelector:
node-type: storage
spec:
serviceAccountName: traefik-ingress-controller
initContainers:
- name: init-acme
image: busybox
command: ["/bin/sh", "-c"]
args:
- touch /data/acme.json && chmod 600 /data/acme.json
volumeMounts:
- name: acme-storage
mountPath: /data
containers:
- name: traefik
image: traefik:v3.4
args:
- --api.insecure=true
- --accesslog
- --entryPoints.web.address=:80
- --entryPoints.websecure.address=:443
- --providers.kubernetescrd
- --certificatesresolvers.myresolver.acme.httpchallenge=true
- --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web
- --certificatesresolvers.myresolver.acme.email=olivierargentieri@gmail.com
- --certificatesresolvers.myresolver.acme.storage=/data/acme.json
ports:
- name: web
containerPort: 80
- name: websecure
containerPort: 4443
- name: admin
containerPort: 8080
volumeMounts:
- name: acme-storage
mountPath: /data
volumes:
- name: acme-storage
persistentVolumeClaim:
claimName: acme-pvc
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: traefik-retain-storage
provisioner: kubernetes.io/no-provisioner
reclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: acme-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: traefik-retain-storage
hostPath:
path: "/mnt/traefik/acme"
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: node-type
operator: In
values:
- storage
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: acme-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: traefik-retain-storage
crds ingress route tls/notls.
```yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: simpleingressroute
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`olivierargentieri.ddns.net`) && PathPrefix(`/notls`)
kind: Rule
services:
- name: whoami
port: 80
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: ingressroutetls
namespace: default
spec:
entryPoints:
- websecure
routes:
- match: Host(`olivierargentieri.ddns.net`) && PathPrefix(`/tls`)
kind: Rule
services:
- name: whoami
port: 80
tls:
certResolver: myresolver # This is the resolver we defined in the Traefik deployment arguments.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
To set up HTTPS, you can use Let's Encrypt with Traefik. You need to add the following arguments to the Traefik deployment:
References
Bonus setup new app
Becareful to use the correct selector and matchLabels in the deployment and service. For securirty reasons, trafik can't redirect connections to other namespaces.
yml
apiVersion: v1
kind: Secret
metadata:
name: ghcr-secret
data:
.dockerconfigjson: <base64_hash> # see https://docs.olivierargentieri.fr/it/kubernetes/githubcredential.html#create-a-github-token
type: kubernetes.io/dockerconfigjson
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-iptv
labels:
app: iptv
spec:
replicas: 1
selector:
matchLabels:
app: iptv
template:
metadata:
labels:
app: iptv
spec:
containers:
- name: app-iptv
image: ghcr.io/olivierargentieri/agiptv:latest
ports:
- name: web
containerPort: 80
protocol: TCP
resources:
limits:
cpu: 200m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
imagePullPolicy: Always
restartPolicy: Always
imagePullSecrets:
- name: ghcr-secret
---
apiVersion: v1
kind: Service
metadata:
name: svc-iptv
spec:
ports:
- name: web
port: 80
targetPort: web
selector:
app: iptv
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: ingressroute-iptv
spec:
entryPoints:
- websecure # this is important to use the correct entry point for HTTPS.
routes:
- match: Host(`olivierargentieri.ddns.net`) && PathPrefix(`/iptv`)
kind: Rule
services:
- name: svc-iptv
port: 80
tls:
certResolver: myresolver
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70