FluxCD 무한 reconcile — spec.ignore로 필드 제외

CI·CD3분조회 –

클러스터에 올라가는 리소스를 Git 에 두고 FluxCD 가 맞춰 놓습니다. FluxCD 는 Kustomization 단위로 Git 의 한 경로를 지켜보다가, 클러스터 상태가 거기 적힌 것과 달라지면 Git 쪽으로 되돌립니다.

사람이 손으로 고쳐 놓은 게 다음 배포 때 슬그머니 사라지는 걸 막으려는 것이라 평소에는 이게 하는 일이 눈에 안 보입니다. Git 과 클러스터가 같으면 비교만 하고 아무것도 안 하니, 로그도 주기마다 한 줄씩 조용히 남고 맙니다.

그런데 어느 날부터 Kustomization 하나가 몇 초 간격으로 계속 reconcile 로그를 남기기 시작했습니다. 되돌리고 또 되돌리고, 멈추지를 않습니다.

두 컨트롤러의 같은 필드 경합

FluxCD 는 클러스터가 Git 과 달라지면 되돌립니다(drift 교정). 되돌린 값을 다른 쪽이 또 바꾸면 그대로 반복되고, 사람이 kubectl edit 으로 고쳐 놓은 경우가 그렇습니다.

더 흔한 건 다른 컨트롤러와 겹치는 경우입니다. HPA 는 부하에 따라 spec.replicas 를 바꾸고 FluxCD 는 Git 에 적힌 값으로 되돌리니, HPA 가 3으로 올리면 FluxCD 가 2로 내리고 HPA 가 다시 3으로 올립니다. 둘 다 자기 일을 제대로 하지만 같은 필드에 주인이 둘이라 생기는 문제입니다.

그 필드를 빼기 전에 — Git 에서 빼는 쪽이 먼저

HPA 가 붙은 Deployment 라면 매니페스트에서 replicas 를 아예 지우는 게 먼저고, Git 에 그 값이 없으면 FluxCD 가 되돌릴 값도 없습니다.

매니페스트에서 뺄 수 없는 경우도 있습니다. 차트가 replicas 를 기본값으로 밀어 넣거나 값이 있어야 첫 배포가 되는 구조가 그런데, 그때 쓰는 게 spec.ignore 입니다.

spec.ignore로 drift 교정에서 제외

Kustomization 의 spec.ignore 는 특정 경로를 drift 감지와 교정에서 빼는 목록입니다. 경로는 JSON Pointer 로 적고, target 으로 어느 리소스에 적용할지 좁힙니다.

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: app
  namespace: flux-system
spec:
  ignore:
    - paths:
        - /spec/replicas   # HPA가 관리하는 필드
      target:
        kind: Deployment

Argo CD 의 ignoreDifferences 와 헷갈리기 쉽습니다. 이름도 하위 필드 이름도 다르고, Argo CD 문법을 그대로 넣으면 Kustomization 이 검증에서 거부됩니다.

replicas 를 HPA 에 맡기고 FluxCD 는 나머지만 Git 에 맞추니 두 컨트롤러의 관리 범위가 안 겹칩니다.

어느 필드를 뺄지는 “누가 이 필드를 정하는 쪽인가” 로 갈립니다. 부하에 따라 바뀌어야 하는 값은 HPA 가 정하는 것이라 Git 에 고정할 값이 아닙니다.

급할 땐 flux suspend

무한 reconcile 이 도는 중에 원인을 파악하려면 먼저 멈추는 게 낫습니다.

flux suspend kustomization <name>

suspend 하면 FluxCD 가 되돌리기를 멈추니 그 상태에서 무엇이 충돌하는지 보고 고친 뒤 다시 resume 합니다. 돌아가는 중에 들여다보면 상태가 계속 바뀌어서 어느 필드가 문제인지 짚기 어렵습니다.

필드마다 주인은 하나

무한 reconcile 은 버그가 아니라 관리 범위가 겹쳐서 생기는 일이라, 고치는 방향도 어느 쪽을 이기게 할지가 아니라 그 필드의 주인을 정하고 나머지를 물러나게 하는 쪽입니다.

reconcile 이 계속 돌면 먼저 suspend 로 멈추고 어떤 필드가 되돌려지고 있는지 봅니다. 그 필드를 바꾸는 다른 컨트롤러가 있으면 매니페스트에서 지우거나 spec.ignore 로 빼면 되고, 없으면 사람이 손으로 고친 것이니 Git 쪽을 맞추면 됩니다.

참고

  1. 불러오는 중