Skip to content

Commit f1e0141

Browse files
authored
Update README.md
1 parent 9637787 commit f1e0141

File tree

1 file changed

+114
-48
lines changed

1 file changed

+114
-48
lines changed

README.md

Lines changed: 114 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,90 @@
11
# k8s-dotnet-aks
22

3-
Proyecto de ejemplo para aprender Kubernetes en Azure (AKS) con una API .NET 8 + SQLite, Docker, Terraform (backend remoto en Azure Storage), Azure Container Registry (ACR) y CI/CD con GitHub Actions. Incluye workflows para **crear** y **destruir** la infraestructura automáticamente.
3+
Sample project to learn how to deploy a .NET 8 + SQLite API to **Azure Kubernetes Service (AKS)** using Docker, Terraform (with Azure remote backend), Azure Container Registry (ACR), and CI/CD pipelines with GitHub Actions. Includes automated workflows to **create** and **destroy** the infrastructure.
44

5+
<div align="center">
6+
<img width="512" height="768" alt="Azure K8S Architecture Diagram" src="https://github.com/user-attachments/assets/7ddcd16b-88bf-449d-9fe9-e0463e477283" />
7+
<p align="center">Architecture Diagram</p>
8+
</div>
59
---
610

7-
## 🧱 Estructura del Proyecto
11+
## 📚 Table of Contents
12+
13+
- [📁 Project Structure](#-project-structure)
14+
- [🔐 Requirements](#-requirements)
15+
- [🚀 GitHub Actions Workflows](#-github-actions-workflows)
16+
- [🌐 Automated Deployment Flow](#-automated-deployment-flow)
17+
- [☁️ Terraform Remote Backend](#-terraform-remote-backend)
18+
- [▶️ Run API Locally](#-run-api-locally)
19+
- [🐳 Build Local Docker Image](#-build-local-docker-image)
20+
- [☸️ Useful Kubernetes Commands](#-useful-kubernetes-commands)
21+
- [⚠️ Important Notes](#-important-notes)
22+
- [🧹 Cleanup](#-cleanup)
23+
24+
---
25+
26+
## 📁 Project Structure
827

928
```
1029
k8s-dotnet-aks/
1130
├── src/
12-
│ ├── K8sDotnetApi/ # API .NET 8 Minimal + EF Core + SQLite CRUD
13-
│ └── k8s/ # Manifiestos Kubernetes (PVC, Deployment, Service)
31+
│ ├── K8sDotnetApi/ # .NET 8 Minimal API + EF Core + SQLite CRUD
32+
│ └── k8s/ # Kubernetes manifests (PVC, Deployment, Service)
1433
├── infra/ # Terraform: RG, ACR, AKS
1534
├── .github/workflows/ # Workflows: terraform-create, terraform-destroy, ci, cd
16-
└── K8sDotnetApi.sln # Solución Visual Studio
35+
└── K8sDotnetApi.sln # Visual Studio solution
1736
```
1837

1938
---
2039

21-
## 🔐 Requisitos
40+
## 🔐 Requirements
2241

23-
- Azure Subscription con Service Principal
24-
- GitHub repo con estos **Secrets** configurados:
42+
- Azure subscription with a Service Principal
43+
- GitHub repo with the following **Secrets**:
2544

26-
| Secret | Descripción |
27-
|---------------------|------------------------------------------------------------------|
28-
| `AZURE_CREDENTIALS` | Credenciales JSON generadas con `az ad sp create-for-rbac --sdk-auth` |
29-
| `VM_SSH_PUB_KEY` | Clave pública SSH para nodos AKS |
30-
| `VM_SSH_KEY` | (Opcional) Clave privada SSH para acceso manual a nodos |
45+
| Secret | Description |
46+
| ------------------- | ------------------------------------------------------------------- |
47+
| `AZURE_CREDENTIALS` | JSON credentials created with `az ad sp create-for-rbac --sdk-auth` |
48+
| `VM_SSH_PUB_KEY` | Public SSH key for AKS node authentication |
49+
| `VM_SSH_KEY` | (Optional) Private SSH key for manual access to AKS nodes |
3150

3251
---
3352

34-
## 🚀 Workflows de GitHub Actions
53+
## 🚀 GitHub Actions Workflows
3554

36-
| Archivo | Propósito | Cuándo se ejecuta |
37-
|---------------------------|------------------------------------------|----------------------------------------------|
38-
| `terraform-create.yml` | Provisiona la infraestructura (AKS, ACR) | `push` a `main` o manual desde GitHub |
39-
| `terraform-destroy.yml` | Elimina toda la infraestructura | Manual desde la UI de GitHub Actions |
40-
| `ci.yml` | Compila y testea la API (.NET) | `push` o `pull_request` hacia `main` |
41-
| `cd.yml` | Construye imagen Docker y despliega a AKS| `push` a `main` |
55+
| File | Purpose | Trigger |
56+
| ----------------------- | ------------------------------------------ | -------------------------------------- |
57+
| `terraform-create.yml` | Provisions infrastructure (AKS, ACR, etc.) | On `push` to `main` or manual dispatch |
58+
| `terraform-destroy.yml` | Destroys all infrastructure | Manual dispatch from GitHub UI |
59+
| `ci.yml` | Builds and tests the .NET API | On `push` or `pull_request` to `main` |
60+
| `cd.yml` | Builds Docker image and deploys to AKS | On `push` to `main` |
4261

4362
---
4463

45-
## 🌐 Flujo de Trabajo Automatizado
64+
## 🌐 Automated Deployment Flow
4665

47-
1. **Push a `main`**corre *Terraform Create Infra* (crea RG, ACR, AKS).
48-
2. Cuando finaliza, corre **CI Build & Push**:
49-
- Obtiene nombre del ACR desde Terraform outputs.
50-
- Construye imagen Docker de la API.
51-
- Publica imagen en ACR.
52-
3. Cuando finaliza, corre **CD Deploy to AKS**:
53-
- Obtiene credenciales AKS desde Terraform outputs.
54-
- Aplica pvc.yaml, deployment.yaml (parcheando el nombre de imagen), service.yaml.
55-
- La app queda expuesta con un LoadBalancer público.
56-
4. Cuando quieras limpiar costos, ejecuta manualmente **Terraform Destroy Infra** (workflow_dispatch).
66+
1. **Push to** `main`triggers *Terraform Create Infra*.
67+
2. When finished, **CI Build & Push** runs:
68+
- Fetches ACR login server from Terraform output.
69+
- Builds Docker image of the API.
70+
- Pushes image to ACR.
71+
3. Then, **CD Deploy to AKS** runs:
72+
- Gets AKS credentials from Terraform output.
73+
- Applies PVC, Deployment (with ACR image), and Service manifests.
74+
- Exposes the app via a public LoadBalancer.
75+
4. To clean up, manually run **Terraform Destroy Infra** to avoid cost.
5776

5877
---
5978

60-
## ☁️ Backend Remoto de Terraform
79+
## ☁️ Terraform Remote Backend
6180

62-
Los workflows crean automáticamente (idempotente) estos recursos para almacenar el estado remoto:
81+
Terraform stores state remotely in an Azure Storage Account. The following resources are created:
6382

6483
- Resource Group: `tfstate-rg`
6584
- Storage Account: `tfstatek8sstore`
6685
- Container: `tfstate`
6786

68-
O puedes crearlos manualmente con:
87+
You can also create them manually:
6988

7089
```bash
7190
az group create -n tfstate-rg -l eastus
@@ -75,25 +94,28 @@ az storage container create -n tfstate --account-name tfstatek8sstore
7594

7695
---
7796

78-
## ▶️ Ejecutar API Localmente
97+
## ▶️ Run API Locally
7998

8099
```bash
81100
cd src/K8sDotnetApi
82101
dotnet restore
83102
dotnet run
84-
# http://localhost:5164/
103+
# Access via: http://localhost:5164/
85104
```
86105

87-
### Probar CRUD
106+
### Test CRUD
88107

89108
```bash
90109
curl http://localhost:5164/movies
91110
curl -X POST http://localhost:5164/movies -H "Content-Type: application/json" -d '{"title":"Matrix","year":1999}'
92111
```
93-
112+
<div align="center">
113+
<img width="1178" height="786" alt="K8S API Get Movies" src="https://github.com/user-attachments/assets/e01df3f4-f642-4856-811a-b88825a68a4f" />
114+
<p align="center">K8S API Get Movies</p>
115+
</div>
94116
---
95117

96-
## 🐳 Construir Imagen Docker Local
118+
## 🐳 Build Local Docker Image
97119

98120
```bash
99121
cd src/K8sDotnetApi
@@ -103,24 +125,68 @@ docker run -p 8080:8080 holamundo-dotnet:local
103125

104126
---
105127

106-
## ⚠️ Notas Importantes
128+
## ☸️ Useful Kubernetes Commands
129+
130+
```bash
131+
# Get AKS credentials locally
132+
az aks get-credentials --name <aks-name> --resource-group <rg-name>
133+
134+
# View Pods
135+
kubectl get pods
136+
137+
# View Services (check External IP)
138+
kubectl get svc
139+
140+
# Apply manifests
141+
kubectl apply -f src/k8s/deployment.yaml
142+
kubectl apply -f src/k8s/service.yaml
143+
144+
# Get logs
145+
kubectl logs <pod-name>
146+
147+
# Test container port is open (inside pod)
148+
kubectl exec -it <pod-name> -- curl localhost:8080/movies
149+
150+
# Delete everything
151+
kubectl delete -f src/k8s/
152+
```
153+
154+
---
155+
156+
## ⚠️ Important Notes
107157

108-
- El nombre del ACR en Terraform está configurado como `k8sdotnetacr` (debe ser único globalmente).
109-
- El `deployment.yaml` usa el marcador `<ACR_LOGIN_SERVER>` que es sustituido por el workflow `cd.yml` automáticamente.
110-
- SQLite se monta en `/app/data/movies.db` mediante un PVC con Azure Disk. Para escalar horizontalmente, deberías usar una base de datos externa como Azure SQL.
158+
- The ACR name in Terraform is `k8sdotnetacr` (must be globally unique).
159+
- The `deployment.yaml` uses `containerPort: 8080`, so service must map `targetPort: 8080`.
160+
- `cd.yml` replaces the image reference dynamically with the one from ACR.
161+
- SQLite is persisted in `/app/data/movies.db` using a PVC backed by Azure Disk.
162+
- For production or horizontal scaling, switch to an external database like Azure SQL.
111163

112164
---
113165

114-
## 🧹 Limpieza
166+
## 🧹 Cleanup
115167

116-
Para evitar costos innecesarios, ejecuta el workflow manual:
168+
To avoid unwanted Azure costs, go to GitHub → **Actions** tab → manually trigger:
117169

118170
```
119171
Terraform Destroy Infra
120172
```
121173

122-
Desde la pestaña **Actions** en GitHub.
123-
124174
---
125175

126-
¡Disfruta aprendiendo AKS! 💪
176+
Enjoy learning AKS and GitHub Actions! 🚀
177+
178+
## 📦 Sample Data
179+
180+
Once deployed, you can test the API with some sample movie records:
181+
182+
```bash
183+
curl -X POST http://<EXTERNAL-IP>/movies -H "Content-Type: application/json" -d '{"title":"Matrix","year":1999}'
184+
curl -X POST http://<EXTERNAL-IP>/movies -H "Content-Type: application/json" -d '{"title":"Inception","year":2010}'
185+
curl -X POST http://<EXTERNAL-IP>/movies -H "Content-Type: application/json" -d '{"title":"Interstellar","year":2014}'
186+
curl -X POST http://<EXTERNAL-IP>/movies -H "Content-Type: application/json" -d '{"title":"The Dark Knight","year":2008}'
187+
curl -X POST http://<EXTERNAL-IP>/movies -H "Content-Type: application/json" -d '{"title":"The Matrix Reloaded","year":2003}'
188+
```
189+
190+
Replace `<EXTERNAL-IP>` with the public IP of your `hola-mundo-dotnet-svc` LoadBalancer.
191+
192+
---

0 commit comments

Comments
 (0)