Utilize GitOps with FluxCD in Kubernetes Part 2
Managing Kubernetes with GitOps using Flux CD Part 2
Now that cert-manager is configured, we’ll deploy Traefik as our ingress controller by first creating its namespace, Helm repository configuration, and dashboard authentication secret. We’ll add the helm-repo.yaml
to access the official Traefik Helm charts, and then update the secret with our actual dashboard password using kubectl. This will establish the foundational resources needed before deploying Traefik itself.
Create the Traefik namespace and secret
1
2
fluxcd/clusters/home on main
mkdir traefik
namespace.yaml
1
2
3
4
apiVersion: v1
kind: Namespace
metadata:
name: traefik
helm-repo.yaml
1
2
3
4
5
6
7
8
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: HelmRepository
metadata:
name: traefik
namespace: flux-system
spec:
interval: 1m
url: https://helm.traefik.io/traefik
traefik-secrets.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: v1
kind: Secret
metadata:
name: traefik-dashboard-auth-secret
namespace: traefik
annotations:
kustomize.toolkit.fluxcd.io/reconcile: disabled
type: kubernetes.io/basic-auth
stringData:
username: admin
password: "RANDOM_PASSWORD"
# Update password with:
# kubectl create secret generic traefik-dashboard-auth-secret --namespace traefik \
# --from-literal=username=admin \
# --from-literal=password=YOUR_NEW_PASSWORD \
# --type=kubernetes.io/basic-auth \
# --dry-run=client -o yaml | kubectl apply -f -
kubectl create secret generic traefik-dashboard-auth-secret -n traefik \
--from-literal=username=admin \
--from-literal=password=YOUR_NEW_PASSWORD \
--type=kubernetes.io/basic-auth \
--dry-run=client -o yaml | kubectl apply -f -
Create the Traefik deployment
This HelmRelease configuration sets up Traefik with automatic HTTPS redirection, security headers, basic authentication for the dashboard, and proper resource management. You’ll need to replace all instances of schenk.tech with your own domain name to ensure the dashboard and security configurations work correctly for your environment.
helm-release.yaml
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: traefik
namespace: traefik
spec:
interval: 1m
timeout: 20m
install:
crds: CreateReplace
upgrade:
crds: CreateReplace
chart:
spec:
chart: traefik
version: 24.0.0
sourceRef:
kind: HelmRepository
name: traefik
namespace: flux-system
values:
autoscaling:
enabled: true
minReplicas: 1
maxReplicas: 3
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 80
resources:
requests:
cpu: 500m
memory: 150Mi
limits:
cpu: 1
memory: 500Mi
deployment:
replicas: null
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
# logs:
# access:
# enabled: true
# format: json
metrics:
prometheus:
enabled: true
addEntryPointsLabels: true
addServicesLabels: true
ingressClass:
enabled: true
fallbackApiVersion: v1
isDefaultClass: true
ssl:
enabled: true
certManager:
enabled: true
enforced: true
tlsStore: # Enable once certificates are created
default:
defaultCertificate:
secretName: wildcard-schenk-tech
ports:
metrics:
expose: true
port: 9100
web:
redirectTo: websecure
websecure:
tls:
enabled: true
traefik:
expose: true
service:
spec:
externalTrafficPolicy: Local
providers:
kubernetesCRD:
enabled: true # This is so certificates work
allowCrossNamespace: true
allowExternalNameServices: true
kubernetesIngress:
enabled: false
ingressRoute:
dashboard:
enabled: false # We set up a manual ingress route below - do not enable this!!
entryPoints:
metrics:
expose: true
port: 9100
web:
http:
redirections:
entryPoint:
to: https
scheme: https
websecure:
# address: ":443"
forwardedHeaders:
insecure: true
trustedIPs:
- "127.0.0.1/32"
- "10.0.0.0/8"
- "192.168.0.0/16"
- "172.16.0.0/12"
http:
middlewares:
# - www-redir@kubernetescrd
- traefik-security@kubernetescrd
additionalArguments:
- "--api.insecure=false"
extraObjects:
- apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: security
spec:
headers:
accessControlAllowMethods:
- "*"
accessControlAllowHeaders:
- "*"
accessControlAllowOriginListRegex:
- "https://(.*)?.schenk\\.tech"
accessControlMaxAge: 100
addVaryHeader: true
accessControlAllowCredentials: true
frameDeny: false
referrerPolicy: "same-origin"
contentSecurityPolicy: "*"
customResponseHeaders:
x-aspnet-version: ""
X-Powered-By: ""
Server: ""
- apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: dashboard-auth
namespace: traefik
spec:
basicAuth:
secret: traefik-dashboard-auth-secret
- apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard
namespace: traefik
spec:
entryPoints:
- websecure
routes:
- match: Host(`traefik.schenk.tech`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`))
kind: Rule
middlewares:
- name: dashboard-auth
namespace: traefik
services:
- name: api@internal
kind: TraefikService
The kustomization.yaml
file ties together all our Traefik components - the namespace, HelmRelease, and secrets - ensuring they’re deployed in the correct order and maintaining the complete desired state of our ingress controller configuration.
kustomization.yaml
1
2
3
4
5
6
7
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- traefik-secrets.yaml
- helm-repo.yaml
- helm-release.yaml
- namespace.yaml
After committing and pushing these configuration files to your Git repository, FluxCD will automatically detect the changes and begin deploying Traefik. You can force an immediate reconciliation using flux reconcile source git flux-system
if you don’t want to wait for the next sync interval.
You can now check if all the resources have been deployed using:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
flux get all -A
NAMESPACE NAME REVISION SUSPENDED READY MESSAGE
flux-system gitrepository/flux-system main@sha1:d373c323 False True stored artifact for revision 'main@sha1:d373c323'
NAMESPACE NAME REVISION SUSPENDED READY MESSAGE
flux-system helmrepository/cert-manager sha256:c10b5e02 False True stored artifact: revision 'sha256:c10b5e02'
flux-system helmrepository/traefik sha256:62a21791 False True stored artifact: revision 'sha256:62a21791'
NAMESPACE NAME REVISION SUSPENDED READY MESSAGE
flux-system helmchart/cert-manager-cert-manager v1.17.2 False True pulled 'cert-manager' chart with version 'v1.17.2'
flux-system helmchart/traefik-traefik 24.0.0 False True pulled 'traefik' chart with version '24.0.0'
NAMESPACE NAME REVISION SUSPENDED READY MESSAGE
cert-manager helmrelease/cert-manager v1.17.2 False True Helm install succeeded for release cert-manager/cert-manager.v1 with chart cert-manager@v1.17.2
traefik helmrelease/traefik 24.0.0 False True Helm upgrade succeeded for release traefik/traefik.v3 with chart traefik@24.0.0
NAMESPACE NAME REVISION SUSPENDED READY MESSAGE
flux-system kustomization/flux-system main@sha1:d373c323 False True Applied revision: main@sha1:d373c323
Verifying the Traefik Deployment
Let’s verify that Traefik has been deployed correctly. First, check if the Traefik pods are running in the correct namespace:
1
2
3
kubectl get pods -n traefik
NAME READY STATUS RESTARTS AGE
traefik-5f48b964d5-h7mlh 1/1 Running 0 21h
Let’s verify the Traefik service and endpoints:
1
2
3
4
5
6
7
8
9
# Check if the Traefik service is properly configured
kubectl get svc -n traefik
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
traefik LoadBalancer 10.43.58.137 192.168.10.200 9100:30340/TCP,9000:32058/TCP,80:32666/TCP,443:32273/TCP 21h
# Verify the endpoints are correctly set up
kubectl get endpoints -n traefik
NAME ENDPOINTS AGE
traefik 10.42.3.102:9000,10.42.3.102:8000,10.42.3.102:8443 + 1 more... 21h
Finally, you can test the dashboard access by visiting https://traefik.your-domain.com/dashboard/ in your browser. You’ll be prompted for the basic authentication credentials we configured earlier.
Connect to Traefik Dashboard
In this part, we’ve successfully deployed Traefik as our ingress controller using FluxCD, setting up automatic HTTPS redirection, security headers, and a protected dashboard interface. This deployment not only gives us a robust way to manage incoming traffic to our services but also serves as a practical example of how to deploy and configure services in our GitOps-driven homelab. With both cert-manager and Traefik now in place, we have a solid foundation for deploying additional services with automatic SSL/TLS certificate management and secure ingress routing. In the next part, we’ll migrate our AWX instance to this Kubernetes cluster, demonstrating how to move existing services into our new GitOps infrastructure while maintaining their functionality and security.