Kubernetes 선언형 운영: GitOps reconciliation을 kind로 이해하기

반응형

Kubernetes와 GitOps는 둘 다 desired state를 다루지만 같은 제어 루프는 아니다. Kubernetes controller는 API server에 저장된 desired state를 지키고, GitOps agent는 외부 source의 선언을 읽어 cluster state와 계속 비교한다. Kubernetes GitOps를 이해하려면 이 두 reconciliation 경계를 먼저 나눠 보는 편이 좋다.

기존 kind 실습의 목적도 도구를 많이 설치하는 데 있지 않다. Pod를 지우고 replica 수를 바꿔 보면서 누가 어떤 desired state를 복구하는지 확인하는 데 있다.

Kubernetes와 GitOps는 desired state의 위치가 다르다

Deployment를 API server에 적용하면 Deployment controller는 spec.replicas에 맞는 ReplicaSet과 Pod를 유지한다. Pod 하나를 지우면 controller가 새 Pod를 만든다. 이것은 Kubernetes reconciliation이다.

GitOps는 그 위에 source reconciliation을 더한다.

Git·OCI 등의 desired state source
  → GitOps agent가 pull·render·compare
  → Kubernetes API의 desired state
  → Kubernetes controller가 workload를 reconcile
  → 실제 Pod·Service·Volume

kubectl apply -f도 선언형 object를 API server에 전달하지만, 명령을 한 번 실행한 뒤 Git을 계속 관찰하지는 않는다. YAML을 Git에 넣는 것만으로도 software agent가 생기지 않는다. 따라서 선언형 Kubernetes 사용과 GitOps 운영은 겹치지만 동의어는 아니다.

OpenGitOps 네 원칙을 확인한다

OpenGitOps v1.0.0은 GitOps-managed system에 네 원칙을 제시한다.

원칙 운영 질문
Declarative 원하는 상태가 선언으로 표현되는가
Versioned and Immutable desired state의 전체 version history가 남는가
Pulled Automatically software agent가 source에서 선언을 자동으로 가져오는가
Continuously Reconciled agent가 actual state를 관찰하고 desired state 적용을 계속 시도하는가

PR review와 commit history는 중요한 workflow지만 네 원칙 전체를 대신하지 않는다. 반대로 agent가 자동 적용하더라도 source revision, 권한, drift policy가 불명확하면 안전한 GitOps가 되지 않는다.

kind에서 Kubernetes reconciliation을 확인한다

아래 실습은 web application이 아니라 controller 동작만 보기 위해 pause image를 사용한다. local cluster가 외부에 노출되지 않도록 kind의 기본 loopback 설정을 유지한다.

kind create cluster --name reconcile-lab

deployment.yaml을 만든다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: reconcile-lab
spec:
  replicas: 2
  selector:
    matchLabels:
      app: reconcile-lab
  template:
    metadata:
      labels:
        app: reconcile-lab
    spec:
      containers:
        - name: pause
          image: registry.k8s.io/pause:3.10
kubectl apply -f deployment.yaml
kubectl rollout status deployment/reconcile-lab
kubectl get deployment,pod -l app=reconcile-lab

Pod 하나를 지우고 다시 센다.

pod_name=$(kubectl get pod -l app=reconcile-lab \
  -o jsonpath='{.items[0].metadata.name}')
kubectl delete pod "$pod_name"
kubectl wait --for=condition=Ready pod \
  -l app=reconcile-lab --timeout=120s
kubectl get pod -l app=reconcile-lab

새 Pod가 만들어지는 이유는 Git 파일을 다시 읽었기 때문이 아니다. API server의 Deployment가 replica 2개를 원하고 Deployment·ReplicaSet controller가 그 상태를 유지했기 때문이다.

수동 scale로 GitOps가 없는 상태를 확인한다

이번에는 API server의 desired state 자체를 바꾼다.

kubectl scale deployment reconcile-lab --replicas=3
kubectl get deployment reconcile-lab

local file에는 여전히 replicas: 2가 적혀 있어도 cluster는 3개를 유지한다. Kubernetes controller 관점에서는 API server에 저장된 3이 올바른 desired state이기 때문이다. file이나 Git을 지속적으로 보는 GitOps agent가 없으므로 자동으로 2개로 돌아가지 않는다.

사람이 다시 선언을 적용하면 2개로 복구된다.

kubectl apply -f deployment.yaml
kubectl rollout status deployment/reconcile-lab

Argo CD나 Flux를 붙이면 agent가 source의 2와 live 3의 차이를 OutOfSync로 감지할 수 있다. 실제로 되돌릴지는 Manual sync, automated sync, self-heal 정책에 따라 달라진다.

실습을 마치면 disposable cluster를 정리한다.

kind delete cluster --name reconcile-lab

Git이 담지 않는 상태도 명시한다

“Git의 상태가 시스템의 모든 상태”라고 말하면 복구 범위를 과장할 수 있다. 보통 Git이 잘 담는 것은 manifest와 policy 같은 desired configuration이다. 다음은 별도 system of record가 필요하다.

  • database와 PersistentVolume의 사용자 데이터
  • secret manager에 보관한 secret value와 암호화 key
  • cloud provider의 실제 resource와 provider-side default
  • runtime status, event, metric, log
  • Git 밖에서 관리하는 identity·DNS·certificate

Git repository에는 이 dependency를 생성하거나 참조하는 선언과 version은 남길 수 있다. 하지만 실제 data backup과 credential 복구까지 Git commit 하나가 해결하지는 않는다.

운영 전에는 reconciliation 정책을 쓴다

GitOps controller를 붙이기 전에 다음을 정한다.

  1. authoritative source와 revision은 무엇인가
  2. source 변경을 누가 review·merge하는가
  3. agent가 접근할 repository·cluster·namespace 범위는 어디까지인가
  4. drift를 알리기만 할지 자동으로 되돌릴지
  5. prune으로 삭제할 수 있는 resource와 보호 대상은 무엇인가
  6. emergency change를 Git으로 되돌려 기록하는 절차는 무엇인가

GitOps 개념 자체는 OpenGitOps 원칙과 CI/CD 차이, Argo CD 첫 적용은 Argo CD 설치와 첫 Application에서 이어진다.

참고 자료

반응형
KEEP READING
카테고리 전체 보기 →

댓글