You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# 🚀 Terraform Kubernetes — Starter Kit for Docker Desktop
3
+
# Terraform Kubernetes — Starter Kit for Docker Desktop
4
4
5
5
This starter kit is designed for local Kubernetes experimentation using Terraform. It provides a preconfigured setup with certificate management, ingress routing, and load balancing, making it easy to test, learn, and prototype cloud-native deployments.
6
6
7
-

7
+

8
8
9
-
## 👨💻 Who is it for?
9
+
## Who is it for?
10
10
- DevOps Engineers & SREs who want a sandbox for testing infrastructure automation.
11
11
- Developers exploring Kubernetes deployments without cloud costs.
12
12
- Teams learning Terraform and Kubernetes best practices in a safe, local environment.
13
13
14
-
## 📂 Project Structure
14
+
## Project Structure
15
15
16
16
### **Environments**
17
17
-`envs/local` - Local Environment. You can use Docker Desktop for local usage.
18
18
19
19
### **Modules**
20
20
Each service is managed as a separate module for better reusability and organization.
21
21
22
-
#### **📁 modules/metallb**
22
+
#### **modules/metallb**
23
23
- Deploys **MetalLB** via Helm.
24
24
- Configures **IP address pools** dynamically using `kubectl_manifest`.
25
25
26
-
#### **📁 modules/cert-manager**
26
+
#### **modules/cert-manager**
27
27
- Installs **Cert-Manager** using Helm.
28
28
29
-
#### **📁 modules/ingress-nginx**
29
+
#### **modules/ingress-nginx**
30
30
- Deploys **Ingress-Nginx** as a controller for managing ingress traffic.
31
31
32
-
#### **📁 modules/cluster-issuer-selfsigned**
32
+
#### **modules/cluster-issuer-selfsigned**
33
33
- Creates a **ClusterIssuer** and a self-signed CA certificate.
34
34
35
-
#### **📁 modules/cluster-issuer-production**
35
+
#### **modules/cluster-issuer-production**
36
36
- Creates a **ClusterIssuer** that uses letsencrypt .
37
37
38
-
#### **📁 modules/echo-server**
38
+
#### **modules/echo-server**
39
39
- Deploys **Echo Server** using Kubernetes manifests.
40
40
- Configures an **Ingress resource** with self-signed TLS issued by Cert-Manager.
41
41
@@ -47,7 +47,7 @@ brew install mkcert
47
47
mkcert -install
48
48
```
49
49
50
-
## 🛠️ Setup and Deployment
50
+
## Setup and Deployment
51
51
52
52
The best way is fork the repo. But it's up to you.
53
53
@@ -91,17 +91,40 @@ The best way is fork the repo. But it's up to you.
91
91
make tf-apply-approve
92
92
```
93
93
94
-
6.**Verify resources in Kubernetes:**
94
+
6.**Verify the deployment:**
95
+
96
+
Check that all pods are running:
95
97
```sh
96
98
kubectl get pods -A
99
+
```
100
+
All pods in `metallb-system`, `ingress-nginx`, `cert-manager`, and `demo` namespaces should be in `Running` status.
101
+
102
+
Check that services have received IP addresses:
103
+
```sh
97
104
kubectl get svc -A
105
+
```
106
+
The `ingress-nginx-controller` service should have an `EXTERNAL-IP` assigned by MetalLB.
107
+
108
+
Check that ingress is created:
109
+
```sh
98
110
kubectl get ingress -A
99
111
```
100
112
101
-
7.**Verify resources in Kubernetes:**
113
+
Check that the TLS certificate has been issued:
114
+
```sh
115
+
kubectl get certificates -A
116
+
```
117
+
The `READY` column should show `True`.
118
+
119
+
Send a request to the echo server:
102
120
```sh
103
121
curl https://echo.127.0.0.1.nip.io
104
122
```
123
+
If the certificate is not trusted by the system, use the `-k` flag:
124
+
```sh
125
+
curl -k https://echo.127.0.0.1.nip.io
126
+
```
127
+
A JSON response from the echo server confirms the entire stack is working correctly.
105
128
106
129
### **Destroying the Infrastructure**
107
130
To remove all deployed resources:
@@ -142,14 +165,190 @@ You can run basic validation for your Terraform configuration:
142
165
make tf-test
143
166
```
144
167
145
-
## 📌 Key Features
146
-
✅ Modular architecture with separate Terraform modules.
147
-
✅ Uses Helm for package management.
148
-
✅ Configures self-signed certificates with Cert-Manager.
149
-
✅ Supports MetalLB for LoadBalancer services in local Kubernetes environments.
150
-
✅ Ingress-Nginx handles application routing.
151
-
✅ Secure and automated TLS handling via ClusterIssuer.
168
+
## Troubleshooting
169
+
170
+
### Terraform asks for `cluster_issuer_selfsigned_ca_cert` interactively
171
+
172
+
Terraform requires two environment variables for the self-signed CA. If they are not set, it will prompt for input.
173
+
174
+
**Solution:** export the variables before running any Terraform command:
### Certificate is not trusted / `curl` returns SSL error
181
+
182
+
When using `curl https://echo.127.0.0.1.nip.io` you may see:
183
+
```
184
+
curl: (60) SSL certificate problem: unable to get local issuer certificate
185
+
```
186
+
187
+
**Cause:** the mkcert root CA is not installed in the system trust store.
188
+
189
+
**Solution:**
190
+
```sh
191
+
mkcert -install
192
+
```
193
+
This adds the mkcert CA to the system trust store. After that, `curl` and browsers will trust the certificate. As a quick workaround, use `curl -k` to skip verification.
194
+
195
+
### Kubernetes is not running / `kubectl` cannot connect
196
+
197
+
```
198
+
The connection to the server localhost:6443 was refused
199
+
```
200
+
201
+
**Solution:** make sure Docker Desktop is running and Kubernetes is enabled in Docker Desktop settings (Settings > Kubernetes > Enable Kubernetes).
202
+
203
+
### Ingress controller has no EXTERNAL-IP (shows `<pending>`)
204
+
205
+
```sh
206
+
kubectl get svc -n ingress-nginx
207
+
# EXTERNAL-IP shows <pending>
208
+
```
209
+
210
+
**Cause:** MetalLB is not ready or the IP address pool is not configured.
211
+
212
+
**Solution:**
213
+
1. Check that MetalLB pods are running: `kubectl get pods -n metallb-system`
214
+
2. Check the IPAddressPool resource: `kubectl get ipaddresspool -n metallb-system`
215
+
3. Try redeploying: `make tf-recreate`
216
+
217
+
### Certificate is not issued (READY is False)
218
+
219
+
```sh
220
+
kubectl get certificates -A
221
+
# READY shows False
222
+
```
223
+
224
+
**Solution:** check the certificate request status and cert-manager logs:
Common cause: cert-manager pods are not ready yet. Wait a minute and check again.
230
+
231
+
### ClusterIssuer is not ready
232
+
233
+
```sh
234
+
kubectl get clusterissuer
235
+
# READY shows False
236
+
```
237
+
238
+
**Cause:** the CA secret is missing or contains invalid data. This usually happens when `TF_VAR_cluster_issuer_selfsigned_ca_cert` or `TF_VAR_cluster_issuer_selfsigned_ca_key` were set with incorrect values (e.g. double base64 encoding, empty string, or wrong file path).
239
+
240
+
**Diagnosis:**
241
+
```sh
242
+
kubectl describe clusterissuer selfsigned
243
+
kubectl get secret selfsigned-ca -n cert-manager -o yaml
244
+
```
245
+
246
+
**Solution:** make sure the variables contain a single base64-encoded value:
### Certificate issued but browser still shows "Not Secure"
260
+
261
+
The certificate is valid inside the cluster (`kubectl get certificates` shows `True`), but the browser shows a security warning.
262
+
263
+
**Cause:** the CA that signed the certificate is not trusted by your OS/browser. The cluster uses mkcert's root CA, which must be installed locally.
264
+
265
+
**Solution:**
266
+
```sh
267
+
# Install mkcert CA into system trust store
268
+
mkcert -install
269
+
270
+
# Verify it's installed
271
+
mkcert -CAROOT
272
+
```
273
+
After this, restart the browser. On macOS, you can also verify in Keychain Access — look for "mkcert" in the System keychain.
274
+
275
+
### Certificate error only in specific namespace
276
+
277
+
If the certificate works in one namespace but not another, the issue is likely a missing or misconfigured Ingress annotation.
278
+
279
+
**Check** that your Ingress has the correct annotation:
280
+
```yaml
281
+
annotations:
282
+
cert-manager.io/cluster-issuer: selfsigned
283
+
```
284
+
285
+
**Verify** the certificate and secret exist in the correct namespace:
286
+
```sh
287
+
kubectl get certificates -n <namespace>
288
+
kubectl get secrets -n <namespace> | grep tls
289
+
```
290
+
291
+
### Wrong certificate served / `SSL: no alternative certificate subject name matches`
292
+
293
+
```
294
+
curl: (60) SSL: no alternative certificate subject name matches target host name 'echo.127.0.0.1.nip.io'
295
+
```
296
+
297
+
The certificate inside Kubernetes is correct, but `curl` receives a different one.
298
+
299
+
**Cause:** another Docker container or service is occupying ports 80/443 on the host, intercepting traffic before it reaches the Kubernetes ingress controller.
300
+
301
+
**Diagnosis:**
302
+
```sh
303
+
docker ps | grep -E "0.0.0.0:(80|443)"
304
+
```
305
+
306
+
**Solution:** stop the conflicting container and restart the ingress controller:
**Solution:** make sure you have Terraform >= 1.5.0 installed:
315
+
```sh
316
+
terraform version
317
+
```
318
+
Then retry with:
319
+
```sh
320
+
make tf-init
321
+
```
322
+
323
+
### Pods stuck in `ContainerCreating` or `CrashLoopBackOff`
324
+
325
+
**Solution:** inspect the pod events:
326
+
```sh
327
+
kubectl describe pod <pod-name> -n <namespace>
328
+
kubectl logs <pod-name> -n <namespace>
329
+
```
330
+
Common causes: image pull issues (check internet connection), resource limits exceeded in Docker Desktop (increase memory/CPU in Docker Desktop settings).
331
+
332
+
### Need a completely fresh start
333
+
334
+
If nothing helps, do a full reset — this destroys all resources, deletes state, and recreates everything from scratch:
335
+
```sh
336
+
make tf-reset
337
+
```
338
+
339
+
> For a detailed step-by-step guide, see [docs/getting-started.md](docs/getting-started.md).
340
+
341
+
## Key Features
342
+
- Modular architecture with separate Terraform modules.
343
+
- Uses Helm for package management.
344
+
- Configures self-signed certificates with Cert-Manager.
345
+
- Supports MetalLB for LoadBalancer services in local Kubernetes environments.
346
+
- Ingress-Nginx handles application routing.
347
+
- Secure and automated TLS handling via ClusterIssuer.
348
+
349
+
---
350
+
**Contributions & Issues**
351
+
If you encounter any issues or have suggestions for improvements, feel free to contribute or raise an issue!
152
352
153
353
---
154
-
📢 **Contributions & Issues**
155
-
If you encounter any issues or have suggestions for improvements, feel free to contribute or raise an issue! 🚀
0 commit comments