Troubleshooting¶
An AI assistant can run these checks with kubectl or a Kubernetes MCP server. Do not paste kubeconfig or Secret data into the chat.
Argo cannot clone the GitOps repo¶
Private repo and no repo-creds Secret yet. Wave 2 cannot fix the first clone — that YAML is in the repo Argo cannot read. Create the Secret, then prove the clone in the UI (Settings → Repositories must be Successful) before you apply or refresh: bootstrap.
Symptoms: ComparisonError, authentication required, Repository not accessible, empty applications after apply.
GitHub webhook to Argo returns 401 / 404 / timeout¶
The UI stays on the LAN. Only /api/webhook is public. Full setup: wave 7.
- 401:
webhook.github.secretinargocd-secret≠ the GitHub webhook secret, orargocd-serverwas not restarted after the key appeared. - 404: wrong path (must be Exact
/api/webhook), or GitHub is hitting the LAN hostname / the UI Ingress. - timeout: public DNS is not the WAN address, or WAN 80/443 is not forwarded to the ingress VIP (
.30). - Certificate stays Issuing: missing
http01-edit-in-placeonargocd-webhook, or Argo self-healed/spec/rules(that ignoreDifferences is already onapplications/argocd.yaml).
Cannot log in to Argo or Grafana after rotating admin¶
- Argo: extra account missing from
configs.cm/ RBAC, or you setadmin.enabled: "false"before the sealed bcrypt landed.argocd login --corestill works. Wave 7. - Argo UI dead after a SealedSecret sync: you replaced
argocd-secretinstead of patching it (sealedsecrets.bitnami.com/patch: "true"). Redis / server keys are gone — restore from backup or let the chart recreate, then re-seal the patch only. - Grafana still wants
admin/prom-operator:adminPasswordis still in values, or Secretgrafana-adminwas not mounted. Observability.
Argo Application stuck OutOfSync¶
- Large CRDs: set
ServerSideApply=true(already on Argo CD, CNPG, kube-prometheus-stack). - Webhook CA: MetalLB and cert-manager mutate
caBundle.ignoreDifferencesis already set where we have seen this. - Deployment
.status: Kubernetes 1.35+ adds fields older Argo schemas do not know. Applications that need it haveServerSideDiff=falseor ignore.status. - Wrong
repoURL: you leftYOUR_GITHUBin the Application.
kubectl dies when one control plane reboots¶
- kubeconfig
serveris a node IP (https://10.0.0.11:6443) instead of the API VIP (https://10.0.0.20:6443). See API VIP. - VIP never came up:
ping 10.0.0.20fails after bootstrap. Checkvip.ipis on all three CP configs and on no worker.talosctl get addresseson each CP. .20is also in a MetalLB pool or a DHCP lease — two owners fighting ARP.- You pointed
talosctl config endpointat the VIP and now cannot recover etcd. Point it at.11.12.13.
MetalLB has no EXTERNAL-IP¶
- Nodes and the pool must share L2 (same VLAN/bridge).
- PSA:
metallb-systemmust beenforce=privileged. - Speaker DaemonSet not Ready:
kubectl -n metallb-system describe ds. - Address already used on the LAN (another VM, Unraid, a reservation), or you reused the API VIP
.20in a pool.
Longhorn will not start on Talos¶
- Image Factory image missing
iscsi-tools/util-linux-tools. kubelet.extraMountsfor/var/lib/longhornmissing.- Kernel modules
iscsi_tcp/nbdnot in machine config. - Namespace not privileged.
defaultReplicaCount: 3on one worker — volumes stay degraded.
Ingress 502 / Service has no endpoints (LAN backend)¶
- You created
kind: Endpoints. On 1.35 that API is deprecated. Use an EndpointSlice withkubernetes.io/service-nameand matching port names. - Service has a
selector. Delete it; otherwise the control plane owns the slices. - LAN host firewall does not allow the worker node IPs. Flannel SNATs to
.21–.29, not the ingress VIP. - Endpoint IP is wrong, DHCP moved it, or you used a ClusterIP /
127.0.0.1. - LAN hop is HTTPS but Ingress is missing
nginx.org/ssl-services: "<service-name>"(F5 annotation, not ingress-nginx).
ACME HTTP-01 fails¶
- Missing
acme.cert-manager.io/http01-edit-in-place: "true"on the Ingress. On this L2 + F5 + pinned/32setup the default solver Ingress never shares the ingress VIP. See day-2. - Ingress VIP not reachable on port 80 from the internet. WAN 80/443 must DNAT to the ingress VIP (
.30in the examples), not a worker, not a CP, and not the API VIP (.20). - You used a
*.k8s.home.example.comname. Let's Encrypt cannot see those. Use Step-CA. - Public DNS does not point at that VIP yet (chicken and egg: create the record once, then let external-dns or Cloudflare own it).
- Production LE rate limits — use staging.
Laptop cannot resolve *.k8s.home.example.com¶
Work top-down. Full map: local DNS.
dig grafana.k8s.home.example.com @<BIND-IP> +norecurse— if this fails, the zone or record is wrong (BIND, wildcard, or external-dns never wrote the A).dig grafana.k8s.home.example.com @<router-or-pihole>— if only this fails, the domain override / forward is missing. DHCP clients never talk to BIND directly in topology A.dig grafana.k8s.home.example.comwith no@— if this fails, the laptop is not using the LAN resolver (VPN DNS, hardcoded1.1.1.1, phone on LTE).- Talos nodes:
machine.network.nameserversmust be the LAN resolver, not only public DNS, or in-cluster lookups of home names fail.
RFC2136 / TSIG¶
- Secret
tsigmissing → external-dns CrashLoop. --rfc2136-tsig-keyname≠ BINDkeyname.--rfc2136-zone≠--domain-filter≠ the actual zone innamed.conf.- Clock skew more than a few minutes.
- BIND logs
REFUSED: TSIG not sent, orupdate-policytoo tight. - Source IP in the BIND log is a node IP (masquerade), not a pod IP. Allow that plus the key; do not open the zone to the whole internet.
Step-CA / certificates stay Issuing¶
Full procedure: Step-CA.
- Ingress used
cert-manager.io/cluster-issuer: step-issuer. That looks for a cert-manager ClusterIssuer. Useissuer+issuer-kind: StepClusterIssuer+issuer-group: certmanager.step.sm. caBundleis not the current root, or is not raw base64 of the PEM.kid/ provisioner name / password mismatch (step ca provisioner list).- Pods cannot reach
https://<ca-host>:9005(Unraid firewall, wrong IP). duration: 24hexceedsmaxTLSCertDurationinca.json.- Browser warns but Certificate is Ready: root not in that device's trust store (Firefox has its own). Hitting the VIP by IP also fails SAN checks.
SealedSecret stays Error¶
- Sealed with another cluster’s cert. Restore the sealing-key backup or re-seal everything.
- Wrong namespace in the SealedSecret vs the target Secret.
Longhorn backup target Unavailable¶
- Secret
longhorn-backup-s3missing keysAWS_ENDPOINTS/ access key, or wrong namespace (longhorn). defaultBackupStore.backupTargetnots3://bucket@region/form. Wave 9.- Workers cannot reach MinIO (Unraid firewall). Unraid extras.
CNPG backup / plugin not archiving¶
- Wave 9 plugin Application not Healthy.
ObjectStorebarmanObjectName≠ Clusterplugins.parameters.barmanObjectName.- Secret keys must be
ACCESS_KEY_ID/ACCESS_SECRET_KEYas in day-2.
kubectl top empty¶
- metrics-server not Ready; kubelet TLS skip flags are in
values/metrics-server/values.yaml.
Still stuck after a Validation check, and the docs look wrong: Get help — open an issue on the public repo. Do not paste secrets.