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.yamldins del seu directori. Ja no hi ha capingress.yamlcentralitzat a l'arrel.
🚀 Desplegament
Prerequisits
- K3s instal·lat: El clúster K3s ha d'estar funcionant
- kubectl configurat: Accés al clúster amb
kubectl - cert-manager: Per a certificats SSL (utilitza Cloudflare Origin Issuer)
- DNS configurat: Els dominis
*.rogi.casahan d'apuntar al clúster
Desplegar una Aplicació
Per desplegar una aplicació específica:
# 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)). Per a un desplegament manual sense ArgoCD:
# 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ó
# 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. 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):
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—AppProjectk3s-cluster(sync-wave -1).argocd/apps/<app>.yaml— unApplicationper aplicació (sync-wave 0), cadascun apunta al seu directori del repo.argocd-bootstrap.yaml—Application"app-of-apps" que sincronitza tot el directoriargocd/apps/. És l'únic recurs que cal aplicar a mà.argocd/gen-apps.sh— regenera tots els fitxers anteriors a partir d'una llista d'aplicacions.
Flux
- El
AppProjecti tots elsApplicationestan versionats aargocd/apps/. - L'app
k3s-cluster-root(aargocd-bootstrap.yaml) llegeixargocd/apps/i crea/actualitza el projecte i totes les applications. - Cada
Applicationsincronitza el seu directori (ex:pihole/) cap al seu namespace, ambpruneiselfHealactivats.
Bootstrap (una sola vegada)
Prerequisits:
- ArgoCD instal·lat al clúster (namespace
argocd). cert-managerinstal·lat (veurecert-manager/install.sh) — elClusterIssuerdepèn dels seus CRDs.- El repo registrat a ArgoCD (
Settings → Repositories). Si el repo és públic a GitHub, l'HTTPS funciona sense credencials.
Llançar la llavor:
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
# 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ó
- Crea/esborra el directori de l'aplicació.
- Afegeix/treu la línia corresponent a l'array
APPSdeargocd/gen-apps.shamb el formatname|namespace|path|recurse|validate. - Executa
./argocd/gen-apps.shper regenerar els manifests. - Fes commit i push; ArgoCD ho sincronitza sol.
Notes
- Els
Application/AppProjectpertanyen al namespaceargocd(recursos propis d'ArgoCD). - L'app
argocdtérecurse: falsesobre el directoriargocd/per gestionar nomésingress.yamli no els seus propis manifests sotaargocd/apps/. - L'app
phoenixusaValidate=falseper tolerar el CRDServiceMonitorsi el Prometheus Operator encara no és instal·lat. - Els secrets que no estan al repo (ex:
gitea-registryper agym-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/ 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:
# Veure ConfigMaps
kubectl get configmaps -n <namespace>
# Editar un ConfigMap
kubectl edit configmap <nom> -n <namespace>
Secrets
Els secrets es gestionen de forma segura:
# 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:
# 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:
spec:
imagePullSecrets:
- name: gitea-registry
containers:
- name: app
image: gitea.rogi.casa/user/repo/image:tag
🔍 Troubleshooting
Verificar l'estat dels Pods
# 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
# Veure serveis
kubectl get services --all-namespaces
# Veure configuració d'Ingress
kubectl get ingress --all-namespaces
kubectl describe ingress <nom> -n <namespace>
Verificar Volums
# Veure PVCs
kubectl get pvc --all-namespaces
# Veure PVs
kubectl get pv
📝 Bones Pràctiques
- Namespaces: Totes les aplicacions tenen un namespace dedicat; cap queda al namespace
default - Labels: Tots els recursos utilitzen labels consistents per facilitar la gestió
- Resources Limits: Configura limits de CPU/memòria per evitar overconsumption
- Health Checks: Implementa liveness i readiness probes quan sigui possible
- Backup: Fes còpies de seguretat regulars dels PVCs i ConfigMaps crítics
🔄 Actualitzacions
Per actualitzar una aplicació:
# 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 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.