ArgoCD: another operation is already in progress — deadlock operacji
Naprawa deadlocku operacji w ArgoCD, gdy stuck operation blokuje synchronizację z błędem another operation is already in progress.
Ten runbook jest częścią serii o blokadach synchronizacji ArgoCD. Zobacz też: etcd request too large i HPA OutOfSync loop. Jeśli interesuje Cię szerszy kontekst GitOps i ArgoCD, przeczytaj nasz post o GitOps i ArgoCD.
Objaw
ArgoCD odmawia synchronizacji — każda próba kończy się komunikatem:
# ArgoCD refuses to sync — operation lock is stuck
argocd app sync <APP_NAME>
# FATA[0001] rpc error: code = FailedPrecondition
# desc = another operation is already in progress
# Check the stuck operation
kubectl get application <APP_NAME> -n argocd \
-o jsonpath='{.status.operationState.phase}'
# Output: "Running" (but nothing is actually running)
Application jest zablokowana — nie można uruchomić nowej synchronizacji ani ręcznie, ani automatycznie. W ArgoCD UI widoczny jest „spinning” icon bez rzeczywistego postępu.
Przyczyna
ArgoCD implementuje pesymistyczny locking — jedna Application może mieć tylko jedną aktywną operację sync w danym momencie. Stan operacji jest zapisywany w .status.operationState w Application CRD. Jeśli controller ulegnie awarii (restart poda, OOMKill, preemption node’a) podczas sync, operacja pozostaje w stanie Running mimo że żaden proces jej nie obsługuje.
To deadlock — ArgoCD nie może rozpocząć nowej operacji, bo „stara” operacja nigdy się nie zakończyła. Problem jest częsty w klastrach z agresywnym autoscalingiem node’ów lub przy ograniczonych zasobach dla application-controller (zbyt mały memory limit prowadzi do OOMKill).
Rozwiązanie
A) Usuń stan operacji (najszybszy fix):
# Remove the operation state that's causing the lock
kubectl patch application <APP_NAME> -n argocd --type json -p '[
{"op": "remove", "path": "/status/operationState"}
]'
# Alternative: remove via annotation if patch fails
kubectl annotate application <APP_NAME> -n argocd \
argocd.argoproj.io/refresh- \
argocd.argoproj.io/operation-
B) Wymuś zakończenie operacji przez ArgoCD CLI:
# Terminate the stuck operation
argocd app terminate-op <APP_NAME>
# Wait 10 seconds, then force a fresh sync
sleep 10
argocd app sync <APP_NAME> --force --replace
C) Restart application-controller (opcja nuklearna):
Jeśli problem dotyczy wielu Applications jednocześnie lub powyższe rozwiązania nie działają:
# If individual app fixes don't work, restart the controller
# This clears ALL in-flight operations across all Applications
kubectl rollout restart statefulset argocd-application-controller -n argocd
# Monitor controller startup
kubectl logs -f statefulset/argocd-application-controller -n argocd | \
grep -i "sync\|operation"
# Verify all apps recover
argocd app list --output json | \
jq '.[] | select(.status.sync.status != "Synced") | .metadata.name'
Po restarcie controller automatycznie przeprowadzi reconciliation loop dla wszystkich Applications i podejmie zablokowane operacje. Należy monitorować logi przez kilka minut, aby upewnić się, że żadna Application nie wróciła do stanu deadlock.
Prewencja: Aby unikać deadlocków w przyszłości, upewnij się, że application-controller ma wystarczające zasoby (rekomendowane minimum to 512 Mi memory limit dla klastrów z <50 Applications, 1-2 Gi dla większych). Rozważ też ustawienie --operation-processors i --status-processors w argumencie controllera, aby kontrolować liczbę równoległych operacji synchronizacji.
Walidacja
# 1. Verify no stuck operations
argocd app get <APP_NAME> --output json | jq '.status.operationState.phase'
# Expected: "Succeeded" or null
# 2. Verify sync status is Synced
argocd app get <APP_NAME> --output json | jq '.status.sync.status'
# Expected: "Synced"
# 3. Verify health status
argocd app get <APP_NAME> --output json | jq '.status.health.status'
# Expected: "Healthy"
# 4. Try a manual sync to confirm lock is cleared
argocd app sync <APP_NAME>
# Expected: sync completes without "another operation" error
# 5. Check controller logs for recurring errors
kubectl logs statefulset/argocd-application-controller -n argocd \
--since=5m | grep -c "error"
# Expected: 0 or minimal
Jeśli sync przechodzi bez błędu „another operation is already in progress”, deadlock jest rozwiązany. Monitoruj przez kilka minut, aby upewnić się, że problem nie wraca (co może wskazywać na powtarzające się OOMKill controllera).
Pipeline CI/CD blokuje Twój zespół?
Umów bezpłatną 30-minutową rozmowę. Przejrzymy konfigurację ArgoCD i wskażemy, co naprawić od razu.