ApplicationSet отменяет ручные изменения Application: где редактировать шаблон
Оператор отключил автосинхронизацию Application, но она включилась снова. При этом Git приложения не менялся, а selfHeal выглядит выключенным. Вероятная причина находится уровнем выше: ApplicationSet генерирует само Application и восстанавливает его спецификацию. Нужно понять, какой контроллер управляет изменяемым объектом.
Прослеживаем владельца Application
kubectl -n argocd get application api-prod -o yaml
kubectl -n argocd get applicationset
kubectl -n argocd get applicationset api-environments -o yamlВ Application проверьте ownerReferences, labels и managedFields. Имя ApplicationSet возьмите из фактических данных, а не из примера. Затем найдите generator и template, из которых получаются имя, source, destination и syncPolicy. Сам ApplicationSet тоже может управляться GitOps-приложением; в этом случае изменение его live YAML также временно.
Здесь работают два разных согласования. ApplicationSet controller поддерживает набор Application и их спецификации. Application controller применяет workload этих Application в целевые кластеры. selfHeal относится ко второму уровню. Его выключение не запрещает первому контроллеру вернуть поле spec.syncPolicy у Application.
Меняем шаблон, из которого получается поле
Пример создаёт Application для двух namespace из одного chart-каталога. Адрес Git является заполнителем. Отсутствие automated означает ручную синхронизацию созданных приложений:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: api-environments
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- list:
elements:
- env: test
- env: prod
template:
metadata:
name: "api-{{.env}}"
spec:
project: api
source:
repoURL: https://git.example.com/team/platform.git
targetRevision: main
path: apps/api
destination:
server: https://kubernetes.default.svc
namespace: "{{.env}}"Значения generator становятся входом template. Если разные окружения должны иметь разные настройки, выразите это в исходных данных и шаблоне, а не серией ручных patch каждого Application. Сначала проверьте, какие имена и destinations получатся для всех элементов. Ошибка общего шаблона затрагивает сразу несколько окружений.
Временное исключение делаем узким
Для согласованного временного изменения можно настроить ignoreApplicationDifferences. Это поле ApplicationSet, оно относится к сравнению сгенерированных Application. Следующий фрагмент позволяет не возвращать только automated у api-prod:
ignoreApplicationDifferences:
- name: api-prod
jsonPointers:
- /spec/syncPolicy/automatedФрагмент добавляется в spec ApplicationSet. Он отличается от ignoreDifferences внутри Application, которое управляет сравнением workload. Исключение не создаёт новый ручной процесс управления само по себе: запишите, кто меняет поле, зачем и когда исключение будет убрано. После его удаления генератор снова становится владельцем настройки.
Для списков sources есть ограничения MergePatch: изменение одного элемента может привести к замене списка целиком и затронуть проигнорированные поля. Не переносите один JSON Pointer с single-source Application на multi-source без отдельной проверки. Прочитайте получившийся Application после очередного reconcile, а не только успешный apply ApplicationSet.
Не путаем две политики синхронизации
spec.syncPolicy.applicationsSync у ApplicationSet определяет создание, изменение и удаление Application контроллером набора. Это не то же самое, что template.spec.syncPolicy.automated, определяющее автоматическое применение workload. Режим create-only может запретить часть изменений Application, однако его действие зависит и от глобальной policy контроллера и разрешения override. Менять глобальный режим ради одного временного исключения обычно слишком широко.
Защита от удаления Application при изменении generator также не равна защите workload при удалении самого ApplicationSet. ownerReferences и finalizers имеют отдельный жизненный цикл. Не проверяйте такую гипотезу удалением рабочего набора: сначала разберите политику и протестируйте отдельный набор без данных.
После исправления дождитесь reconcile и повторно прочитайте api-prod. Затем проверьте, что другие сгенерированные Application сохранили ожидаемые поля. Результат должен объяснять цепочку «источник данных → template → Application → workload». Когда владелец каждого уровня известен, ручное изменение больше не выглядит исчезающим само по себе.
Ещё по теме
- Argo CD и Helm: где искать values, которые реально попали в релиз
- Prune и selfHeal в Argo CD: какие изменения они исправляют
Продолжить изучение
Хотите выстроить доставку изменений из Git в кластер? Синхронизация, окружения и восстановление после неудачного релиза — темы программы «Argo CD и GitOps: деплой в Kubernetes».
Продолжить на практике
- Argo CD и GitOps: деплой в Kubernetes ↗
Превратите Git в источник правды для Kubernetes. Настройте Argo CD, управляемую синхронизацию и окружения, научитесь находить drift и откатывать изменения через Git. Итог — воспроизводимый GitOps-процесс для приложения.
