349 lines
12 KiB
Markdown
349 lines
12 KiB
Markdown
# K3s Cluster Deployment
|
|
|
|
Aquest repositori conté les configuracions de Kubernetes per desplegar diverses aplicacions en un clúster K3s. Totes les aplicacions s'executen en l'entorn local amb accés a través del domini `rogi.casa`.
|
|
|
|
## 📋 Visió General
|
|
|
|
Aquest clúster K3s gestiona els següents serveis:
|
|
|
|
- **Glance** - Dashboard personal
|
|
- **Pi-hole** - Bloqueig de publicitat a nivell de xarxa
|
|
- **LiteLLM** - Proxy per a models de llenguatge
|
|
- **Gitea** - Servidor Git self-hosted
|
|
- **Home Assistant** - Automatització de la llar
|
|
- **Jellyfin** - Servidor multimèdia
|
|
- **n8n** - Automatització de fluxos de treball
|
|
- **OpenWebUI** - Interfície web per a LLMs
|
|
- **Phoenix** - Observabilitat per a aplicacions d'IA
|
|
- **Vaultwarden** - Gestor de contrasenyes
|
|
- **qBittorrent** - Client de torrents
|
|
- **Minecraft Server** - Servidor de Minecraft
|
|
- **Monitoring** - Prometheus i Grafana per a monitorització
|
|
|
|
## 🏗️ Estructura del Repositori
|
|
|
|
```
|
|
.
|
|
├── README.md # Aquest fitxer
|
|
├── argocd-bootstrap.yaml # App-of-apps: llavor per a ArgoCD (aplicar 1 cop)
|
|
├── <aplicació>/ # Cada aplicació té el seu directori
|
|
│ ├── deployment.yaml # Definició del Deployment
|
|
│ ├── service.yaml # Definició del Service
|
|
│ ├── ingress.yaml # Configuració d'Ingress de l'aplicació
|
|
│ ├── namespace.yaml # Namespace dedicat (opcional)
|
|
│ ├── configmap.yaml # ConfigMaps (opcional)
|
|
│ └── pvc.yaml # PersistentVolumeClaims (opcional)
|
|
├── argocd/ # ArgoCD
|
|
│ ├── ingress.yaml # Ingress d'ArgoCD
|
|
│ ├── apps/ # Applications + AppProject declaratius
|
|
│ └── gen-apps.sh # Genera argocd/apps/* i argocd-bootstrap.yaml
|
|
└── nas/ # Servei extern per al NAS
|
|
├── transport.yaml # ServersTransport de Traefik
|
|
└── ingress.yaml # Ingress del NAS
|
|
```
|
|
|
|
> **Nota**: Cada aplicació té el seu propi `ingress.yaml` dins del seu directori. Ja no hi ha cap `ingress.yaml` centralitzat a l'arrel.
|
|
|
|
## 🚀 Desplegament
|
|
|
|
### Prerequisits
|
|
|
|
1. **K3s instal·lat**: El clúster K3s ha d'estar funcionant
|
|
2. **kubectl configurat**: Accés al clúster amb `kubectl`
|
|
3. **cert-manager**: Per a certificats SSL (utilitza Cloudflare Origin Issuer)
|
|
4. **DNS configurat**: Els dominis `*.rogi.casa` han d'apuntar al clúster
|
|
|
|
### Desplegar una Aplicació
|
|
|
|
Per desplegar una aplicació específica:
|
|
|
|
```bash
|
|
# Desplegar una aplicació completa (tots els recursos del directori)
|
|
kubectl apply -f <aplicació>/
|
|
|
|
# Desplegar un recurs específic
|
|
kubectl apply -f <aplicació>/<fitxer>.yaml
|
|
```
|
|
|
|
### Desplegar Tot el Clúster
|
|
|
|
La forma recomanada és deixar que ArgoCD sincronitzi el repo (veure secció [ArgoCD (GitOps)](#-argocd-gitops)).
|
|
Per a un desplegament manual sense ArgoCD:
|
|
|
|
```bash
|
|
# Desplegar totes les aplicacions
|
|
for dir in */; do
|
|
kubectl apply -f "$dir"
|
|
done
|
|
|
|
# O aplicar recursos globals primer (opcional)
|
|
kubectl apply -f nas/
|
|
```
|
|
|
|
### Eliminar una Aplicació
|
|
|
|
```bash
|
|
# Eliminar tots els recursos d'una aplicació
|
|
kubectl delete -f <aplicació>/
|
|
|
|
# Eliminar un recurs específic
|
|
kubectl delete -f <aplicació>/<fitxer>.yaml
|
|
```
|
|
|
|
## 🌐 Ingress i Networking
|
|
|
|
### Configuració d'Ingress per Aplicació
|
|
|
|
Cada aplicació té el seu propi fitxer `ingress.yaml` dins del seu directori, seguint el model de [pihole/ingress.yaml](pihole/ingress.yaml). Característiques:
|
|
|
|
- **Traefik**: Controlador per defecte de K3s (`ingressClassName: traefik`)
|
|
- **TLS/SSL**: Certificats per host gestionats per cert-manager amb el cluster-issuer `letsencrypt-prod`
|
|
- **Secret per aplicació**: Cada ingress té el seu propi `<aplicació>-tls`
|
|
- **Namespace dedicat**: Cada ingress pertany al namespace de la seva aplicació
|
|
|
|
Exemple (`pihole/ingress.yaml`):
|
|
|
|
```yaml
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: pihole
|
|
namespace: pihole
|
|
annotations:
|
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
spec:
|
|
ingressClassName: traefik
|
|
tls:
|
|
- hosts:
|
|
- pihole.rogi.casa
|
|
secretName: pihole-tls
|
|
rules:
|
|
- host: pihole.rogi.casa
|
|
http:
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: pihole-web
|
|
port:
|
|
number: 80
|
|
```
|
|
|
|
## 🐙 ArgoCD (GitOps)
|
|
|
|
Totes les aplicacions del repo es despleguen de forma declarativa amb ArgoCD. Hi ha un `Application` per cada directori d'aplicació, agrupades sota un `AppProject` anomenat `k3s-cluster`.
|
|
|
|
### Estructura
|
|
|
|
- [`argocd/apps/project.yaml`](argocd/apps/project.yaml) — `AppProject` `k3s-cluster` (sync-wave -1).
|
|
- [`argocd/apps/<app>.yaml`](argocd/apps/) — un `Application` per aplicació (sync-wave 0), cadascun apunta al seu directori del repo.
|
|
- [`argocd-bootstrap.yaml`](argocd-bootstrap.yaml) — `Application` "app-of-apps" que sincronitza tot el directori `argocd/apps/`. És l'únic recurs que cal aplicar a mà.
|
|
- [`argocd/gen-apps.sh`](argocd/gen-apps.sh) — regenera tots els fitxers anteriors a partir d'una llista d'aplicacions.
|
|
|
|
### Flux
|
|
|
|
1. El `AppProject` i tots els `Application` estan versionats a `argocd/apps/`.
|
|
2. L'app `k3s-cluster-root` (a `argocd-bootstrap.yaml`) llegeix `argocd/apps/` i crea/actualitza el projecte i totes les applications.
|
|
3. Cada `Application` sincronitza el seu directori (ex: `pihole/`) cap al seu namespace, amb `prune` i `selfHeal` activats.
|
|
|
|
### Bootstrap (una sola vegada)
|
|
|
|
Prerequisits:
|
|
|
|
1. ArgoCD instal·lat al clúster (namespace `argocd`).
|
|
2. `cert-manager` instal·lat (veure [`cert-manager/install.sh`](cert-manager/install.sh)) — el `ClusterIssuer` depèn dels seus CRDs.
|
|
3. El repo registrat a ArgoCD (`Settings → Repositories`). Si el repo és públic a GitHub, l'HTTPS funciona sense credencials.
|
|
|
|
Llançar la llavor:
|
|
|
|
```bash
|
|
kubectl apply -f argocd-bootstrap.yaml
|
|
```
|
|
|
|
A partir d'aquí ArgoCD crea el projecte `k3s-cluster`, totes les `Application` i les sincronitza automàticament. Qualsevol canvi al repo es propaga sol (self-heal).
|
|
|
|
### Recrear el clúster des de zero
|
|
|
|
```bash
|
|
# 1. Instal·lar K3s
|
|
# 2. Instal·lar ArgoCD
|
|
# 3. Instal·lar cert-manager
|
|
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
|
|
kubectl wait --for=condition=available --timeout=120s deployment/cert-manager -n cert-manager
|
|
# 4. Registrar el repo a ArgoCD (o deixar-lo públic)
|
|
# 5. Llançar la llavor
|
|
kubectl apply -f argocd-bootstrap.yaml
|
|
```
|
|
|
|
### Afegir o treure una aplicació
|
|
|
|
1. Crea/esborra el directori de l'aplicació.
|
|
2. Afegeix/treu la línia corresponent a l'array `APPS` de [`argocd/gen-apps.sh`](argocd/gen-apps.sh) amb el format `name|namespace|path|recurse|validate`.
|
|
3. Executa `./argocd/gen-apps.sh` per regenerar els manifests.
|
|
4. Fes commit i push; ArgoCD ho sincronitza sol.
|
|
|
|
### Notes
|
|
|
|
- Els `Application`/`AppProject` pertanyen al namespace `argocd` (recursos propis d'ArgoCD).
|
|
- L'app `argocd` té `recurse: false` sobre el directori `argocd/` per gestionar només `ingress.yaml` i no els seus propis manifests sota `argocd/apps/`.
|
|
- L'app `phoenix` usa `Validate=false` per tolerar el CRD `ServiceMonitor` si el Prometheus Operator encara no és instal·lat.
|
|
- Els secrets que no estan al repo (ex: `gitea-registry` per a `gym-tracker`) s'han de crear manualment al seu namespace; Argo no els gestiona ni els esborra.
|
|
|
|
## 💾 Persistència de Dades
|
|
|
|
Les aplicacions que necessiten emmagatzematge persistent utilitzen:
|
|
|
|
- **PersistentVolumeClaims (PVC)**: Per a volums dinàmics
|
|
- **ConfigMaps**: Per a fitxers de configuració
|
|
- **StatefulSets**: Per a aplicacions que requereixen identitat persistent (ex: bases de dades)
|
|
|
|
Exemple: Minecraft utilitza `pvc.yaml` i `ss.yaml` (StatefulSet).
|
|
|
|
## 📊 Monitorització
|
|
|
|
El directori [monitoring/](monitoring/) conté un stack complet de monitorització:
|
|
|
|
- **Prometheus**: Recollida de mètriques
|
|
- **Grafana**: Visualització de dades
|
|
- **RBAC**: Permisos per a Prometheus
|
|
- **ServiceMonitors**: Descobriment automàtic de serveis (ex: Phoenix)
|
|
|
|
Accés:
|
|
- Grafana: Configurat a través de l'Ingress principal
|
|
- Datasources preconfigurats per connectar amb Prometheus
|
|
|
|
## 🔧 Gestió de Configuracions
|
|
|
|
### ConfigMaps
|
|
|
|
Les aplicacions utilitzen ConfigMaps per gestionar configuracions:
|
|
|
|
```bash
|
|
# Veure ConfigMaps
|
|
kubectl get configmaps -n <namespace>
|
|
|
|
# Editar un ConfigMap
|
|
kubectl edit configmap <nom> -n <namespace>
|
|
```
|
|
|
|
### Secrets
|
|
|
|
Els secrets es gestionen de forma segura:
|
|
|
|
```bash
|
|
# Crear un secret
|
|
kubectl create secret generic <nom> --from-literal=key=value -n <namespace>
|
|
|
|
# Veure secrets (encoded)
|
|
kubectl get secrets -n <namespace>
|
|
```
|
|
|
|
#### Secret per al Registre de Gitea
|
|
|
|
Per utilitzar imatges del registre privat de Gitea, cal crear un secret de tipus `docker-registry`:
|
|
|
|
```bash
|
|
# Crear el secret per al registre de Gitea (namespace default)
|
|
kubectl create secret docker-registry gitea-registry \
|
|
--docker-server=gitea.rogi.casa \
|
|
--docker-username=<teu-usuari-gitea> \
|
|
--docker-password=<teu-password-o-token> \
|
|
--docker-email=<teu-email>
|
|
|
|
# Si l'aplicació està en un namespace específic, afegeix -n <namespace>
|
|
kubectl create secret docker-registry gitea-registry \
|
|
--docker-server=gitea.rogi.casa \
|
|
--docker-username=<teu-usuari-gitea> \
|
|
--docker-password=<teu-password-o-token> \
|
|
--docker-email=<teu-email> \
|
|
-n <namespace>
|
|
```
|
|
|
|
**Nota**: És recomanable utilitzar un token d'accés personal de Gitea en lloc de la contrasenya. Pots generar-lo a: `Gitea > Settings > Applications > Generate New Token`.
|
|
|
|
Les aplicacions que utilitzen imatges del registre de Gitea (com `gym-tracker`) han d'incloure `imagePullSecrets` al seu deployment:
|
|
|
|
```yaml
|
|
spec:
|
|
imagePullSecrets:
|
|
- name: gitea-registry
|
|
containers:
|
|
- name: app
|
|
image: gitea.rogi.casa/user/repo/image:tag
|
|
```
|
|
|
|
## 🔍 Troubleshooting
|
|
|
|
### Verificar l'estat dels Pods
|
|
|
|
```bash
|
|
# Veure tots els pods
|
|
kubectl get pods --all-namespaces
|
|
|
|
# Descriure un pod amb problemes
|
|
kubectl describe pod <nom-pod> -n <namespace>
|
|
|
|
# Veure logs
|
|
kubectl logs <nom-pod> -n <namespace>
|
|
kubectl logs <nom-pod> -n <namespace> --previous # Logs del contenidor anterior
|
|
```
|
|
|
|
### Verificar Serveis i Ingress
|
|
|
|
```bash
|
|
# Veure serveis
|
|
kubectl get services --all-namespaces
|
|
|
|
# Veure configuració d'Ingress
|
|
kubectl get ingress --all-namespaces
|
|
kubectl describe ingress <nom> -n <namespace>
|
|
```
|
|
|
|
### Verificar Volums
|
|
|
|
```bash
|
|
# Veure PVCs
|
|
kubectl get pvc --all-namespaces
|
|
|
|
# Veure PVs
|
|
kubectl get pv
|
|
```
|
|
|
|
## 📝 Bones Pràctiques
|
|
|
|
1. **Namespaces**: Totes les aplicacions tenen un namespace dedicat; cap queda al namespace `default`
|
|
2. **Labels**: Tots els recursos utilitzen labels consistents per facilitar la gestió
|
|
3. **Resources Limits**: Configura limits de CPU/memòria per evitar overconsumption
|
|
4. **Health Checks**: Implementa liveness i readiness probes quan sigui possible
|
|
5. **Backup**: Fes còpies de seguretat regulars dels PVCs i ConfigMaps crítics
|
|
|
|
## 🔄 Actualitzacions
|
|
|
|
Per actualitzar una aplicació:
|
|
|
|
```bash
|
|
# Editar el fitxer YAML amb la nova versió de la imatge
|
|
vim <aplicació>/deployment.yaml
|
|
|
|
# Aplicar els canvis
|
|
kubectl apply -f <aplicació>/deployment.yaml
|
|
|
|
# Verificar el rollout
|
|
kubectl rollout status deployment/<nom> -n <namespace>
|
|
|
|
# Revertir si cal
|
|
kubectl rollout undo deployment/<nom> -n <namespace>
|
|
```
|
|
|
|
## 🌟 Serveis Externs
|
|
|
|
### NAS
|
|
El fitxer [nas/nas.yaml](nas/nas.yaml) configura un servei extern que apunta al NAS local (10.88.88.238:5000) sense desplegar pods dins del clúster. L'Ingress corresponent és a [nas/ingress.yaml](nas/ingress.yaml).
|
|
|
|
## 📚 Recursos Addicionals
|
|
|
|
- [Documentació de K3s](https://docs.k3s.io/)
|
|
- [Documentació de Kubernetes](https://kubernetes.io/docs/)
|
|
- [Traefik Ingress Controller](https://doc.traefik.io/traefik/providers/kubernetes-ingress/)
|
|
- [cert-manager](https://cert-manager.io/docs/) |