# 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) ├── / # 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 / # Desplegar un recurs específic kubectl apply -f /.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 / # Eliminar un recurs específic kubectl delete -f /.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 `-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/.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 # Editar un ConfigMap kubectl edit configmap -n ``` ### Secrets Els secrets es gestionen de forma segura: ```bash # Crear un secret kubectl create secret generic --from-literal=key=value -n # Veure secrets (encoded) kubectl get secrets -n ``` #### 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= \ --docker-password= \ --docker-email= # Si l'aplicació està en un namespace específic, afegeix -n kubectl create secret docker-registry gitea-registry \ --docker-server=gitea.rogi.casa \ --docker-username= \ --docker-password= \ --docker-email= \ -n ``` **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 -n # Veure logs kubectl logs -n kubectl logs -n --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 -n ``` ### 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 /deployment.yaml # Aplicar els canvis kubectl apply -f /deployment.yaml # Verificar el rollout kubectl rollout status deployment/ -n # Revertir si cal kubectl rollout undo deployment/ -n ``` ## 🌟 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/)