GitOps — catálogo y troubleshooting¶
Parte de la guía de implementación
El recorrido paso a paso está en Fase 4 — GitOps. Ansible bootstrap (K3s, red): Fases 0–3.
Referencia de Applications Argo CD y resolución de problemas. Manifiestos en
gitops/.
Documentación relacionada:
- Opciones del playbook K3s — flags Ansible (kube-vip, ArgoCD controller, …)
- vCluster Platform — SSO (inicio de sesión único) Dex + kubeconfig web (K3s host + vclusters)
- Clúster Incus — UI (interfaz de usuario) web + OIDC (OpenID Connect) Dex
- Storage / Secretos
- Stack tecnológico
Dos repos, dos responsabilidades¶
| Repo | Qué instala | Herramienta |
|---|---|---|
homelab |
K3s binario, kube-vip CP, controller ArgoCD, red SO | Ansible |
gitops |
MetalLB, Gateway API, storage, vCluster, CAPN, … | Argo CD |
flowchart LR
A[Ansible bootstrap] --> B[ArgoCD controller]
B --> C[ApplicationSet homelab-root]
C --> D[Apps descomentadas, por olas -1 a 3]
D --> E[Apps manual]
Catálogo de componentes GitOps¶
Cada fila es una Application de ArgoCD (salvo manifiestos auxiliares).
Sync auto = la sincroniza homelab-root (si está descomentada en root-appset.yaml); manual = queda comentada hasta que la actives.
Bootstrap¶
| Manifiesto | Sync | Para qué sirve |
|---|---|---|
bootstrap/root-appset.yaml |
Una vez, a mano | ApplicationSet: genera la Application raíz homelab-root con las apps descomentadas de su lista, desplegadas por olas. Es el único kubectl apply GitOps tras tener el controller; ArgoCD no lo gestiona, así que se vuelve a aplicar con kubectl apply -f cada vez que cambia la lista. |
Wave 0 — Fundamentos (storage + LB controller)¶
| Application | Producto | Para qué sirve |
|---|---|---|
sealed-secrets |
Sealed Secrets | Controller que descifra SealedSecret en el clúster. |
openebs |
OpenEBS | Storage local por nodo (LocalPV). |
homelab-storage |
— | StorageClasses openebs-hostpath (default) y longhorn-mixto (trade-offs). |
metallb |
MetalLB | Controller LoadBalancer en LAN. No es kube-vip. |
gateway-api |
Gateway API | CRDs Gateway, HTTPRoute, etc. (canal standard). |
cert-manager |
cert-manager | Emisión de certificados TLS. |
Wave 1 — Red de servicios + storage HA¶
| Application | Producto | Para qué sirve |
|---|---|---|
metallb-config |
MetalLB | Pool L2 192.168.23.200–192.168.23.220 (reservado fuera del DHCP del router). |
cert-manager-config |
cert-manager | CA propia del HomeLab (ClusterIssuer homelab-ca). |
kong (o traefik, nginx-gateway) |
Kong Ingress Controller | Controlador de Gateway API y Gateway homelab (HTTP/HTTPS, *.homelab.local). Se activa solo uno; ver Cambiar el controlador de Gateway. |
longhorn |
Longhorn | Storage replicado cross-arch. |
Wave 2 — ArgoCD accesible + Dex¶
| Application / carpeta | Producto | Para qué sirve |
|---|---|---|
argocd-route |
Gateway API | HTTPRoute: UI en https://argocd.homelab.local. |
argocd/config/ (argocd) |
Dex | Connector GitHub + staticClients vCluster e Incus UI. |
argocd/secrets/ |
1Password SDK | OAuth desde app local |
Cómo se ve. La UI de ArgoCD en https://argocd.homelab.local pide iniciar sesión con GitHub (Dex):
Ver captura: inicio de sesión de Argo CD

La aplicación raíz homelab-root agrupa todas las demás: en su vista de árbol, cada recuadro «application» es una de las Application del catálogo.
Ver captura: árbol de homelab-root

Wave 3 — Operaciones¶
| Application | Producto | Para qué sirve |
|---|---|---|
k3s-upgrade |
system-upgrade-controller | Upgrades K3s escalonados. |
Sync manual (tú decides cuándo)¶
| Application | Producto | Para qué sirve |
|---|---|---|
vcluster-platform |
vCluster Platform | UI: kubeconfig del host K3s (connected) + vclusters. |
capn-demo |
CAPN | Cluster API sobre Incus. |
calico-operator + calico-config |
Calico | CNI Calico (CRDs + operador + Installation). Activas: ArgoCD administra y actualiza Calico (v3.33.0); lo instaló Ansible al crear el clúster. Sync manual. Ver Calico con ArgoCD. |
canal |
Canal | CNI Canal (Flannel + políticas Calico). |
cilium |
Cilium | CNI Cilium vía Helm. |
CNI: Fase 3, no Fase 4
El CNI (Container Network Interface) se elige en Fase 3 — K3s (k3s_install.core.cni).
Por defecto Flannel embebido (Ansible, sin Application). Las apps anteriores
son alternativa GitOps si K3s (distribución ligera de Kubernetes) ya tiene --flannel-backend=none. Ver
playbook-options — CNI.
Manifiestos de soporte (no son Applications)¶
| Ruta | Para qué sirve |
|---|---|
storage/ |
StorageClasses vía homelab-storage. |
metallb/ |
Pool + L2Advertisement. |
k3s-upgrade/ |
CRs Plan SUC. |
vcluster/values/platform.yaml |
Helm values Platform + OIDC Dex. |
capn/clusters/ |
Clusters generados con clusterctl. |
cni/calico/ |
Installation CR Calico (calico-config Application). |
kube-vip (Ansible) vs MetalLB (GitOps)¶
| kube-vip | MetalLB | |
|---|---|---|
| Quién lo instala | Ansible (k3s_kube_vip) |
ArgoCD |
| Qué VIPea | Solo API server :6443 |
Services LoadBalancer |
| Config clave | svc_enable=false |
Pool 192.168.23.200–.220 |
Resolución de problemas rápida¶
| Síntoma | Revisar |
|---|---|
Application Degraded |
kubectl describe application -n argocd <nombre> |
arc-runners OutOfSync y el pod del listener se reinicia cada pocos minutos |
ArgoCD poda en bucle los recursos que crea el controlador de ARC (AutoscalingListener, Role, RoleBinding: copian la etiqueta app.kubernetes.io/instance). Se corrige con application.resourceTrackingMethod: annotation en argocd-cm (ya está en gitops/argocd/config). Comprueba: kubectl -n argocd get cm argocd-cm -o jsonpath='{.data.application\.resourceTrackingMethod}' → annotation; si no, sincroniza argocd y reinicia el controlador: kubectl -n argocd rollout restart statefulset argocd-application-controller |
openebs OutOfSync con el sync en Running |
El Job del hook pre-upgrade del chart no termina y Argo CD lo espera. En OpenEBS usa una imagen (bitnami/kubectl:1.25.15) que ya no existe en Docker Hub; el hook solo migra de v3 a v4 y está desactivado en argocd/apps/openebs.yaml (preUpgradeHook.enabled: false). Si el Job viejo sigue ahí con el finalizador argocd.argoproj.io/hook-finalizer, cancela la operación (status.operationState.phase: Terminating) y quítale el finalizador |
longhorn con el sync en Running: el Job longhorn-pre-upgrade no tiene pod (serviceaccount "longhorn-service-account" not found) |
En una instalación limpia con Argo CD ese Job corre antes que su ServiceAccount y el sync espera para siempre: desactívalo con preUpgradeChecker.jobEnabled: false (ya está así en argocd/apps/longhorn.yaml). Si cancelas la operación (status.operationState.phase: Terminating), quita el finalizador del Job y refresca. En una actualización el Job sí funciona y falla con razón si el salto no está soportado: lee kubectl logs -n longhorn-system job/longhorn-pre-upgrade antes de desactivarlo |
| Gateway sin dirección | metallb-config sync, pool libre en LAN |
| SSO vCluster falla | playbook-dex-oauth-secrets.yml --tags ensure,argocd,vcluster; restart Dex |
| Incus UI SSO falla | incus config get oidc.issuer / oidc.client.id en invincible; invincible debe confiar en la CA del HomeLab (--tags incus_ca); cliente incus-ui público en dex.config; restart Dex |
| Dex login sin GitHub | Secretos GitHub en argocd-secret; Redirect URIs de la OAuth App correcto |
| GitHub login rechazado | Usuario debe pertenecer al team devops de la org symintel |
| Longhorn pod pending | Etiquetas node.longhorn.io/create-default-disk (playbook labels) |
| Pods CNI no Ready | K3s con --flannel-backend=none antes de sync; solo una app CNI activa (CNI) |
Manifiestos fuente: gitops/argocd/apps/.
Guía ejecutable: Fase 4 — GitOps.