Back to Notes

Notes

GitOps Source of Truth

GitOps를 Git 기반 desired state 운영 모델로 정리하고, DevOps와의 관계, 4가지 원칙, pull-based reconciliation, drift detection, rollback, Kubernetes 적용 방식을 설명한다.

Published
Updated
Area
Cloud Infrastructure
Type
concept
Series
DevOps Explained
Category
Notes
GitOpsDevOpsKubernetesArgo CDFluxCI/CDReconciliationDrift Detection

개요

GitOps는 Git을 단순한 source code 저장소가 아니라, 운영 환경의 desired state를 저장하는 source of truth로 사용하는 운영 방식이다.

일반적인 CI/CD에서는 pipeline이 build와 test를 수행한 뒤, 직접 cluster에 배포 명령을 실행하는 경우가 많다.

일반적인 CI/CD push 방식:
  code 변경
    -> CI pipeline 실행
    -> image build
    -> registry push
    -> kubectl apply 또는 helm upgrade
    -> production cluster 변경

GitOps에서는 관점이 달라진다.

GitOps 방식:
  Git repository에 원하는 상태를 선언
    -> GitOps controller가 Git을 감시
    -> cluster의 실제 상태와 Git의 desired state 비교
    -> 차이가 있으면 자동 reconcile

즉, GitOps는 단순히 Git을 사용하는 배포 방식이 아니다. Git에 저장된 선언적 configuration을 기준으로 실제 시스템 상태를 계속 맞추는 운영 모델이다.

핵심을 짧게 정리하면 다음과 같다.

GitOps = Git에 선언된 desired state를 기준으로
         cluster와 infrastructure의 실제 상태를 자동으로 맞추는 운영 방식

GitOps가 필요한 이유

Kubernetes 환경에서는 application 하나를 배포할 때도 여러 리소스가 함께 움직인다.

Deployment
Service
Ingress
ConfigMap
Secret
PersistentVolumeClaim
HorizontalPodAutoscaler
NetworkPolicy
ServiceAccount
Role / RoleBinding

작은 서비스 하나라면 사람이 직접 kubectl apply를 실행해도 관리할 수 있다. 하지만 서비스가 많아지고, cluster가 dev/staging/production으로 나뉘고, 여러 팀이 동시에 배포하기 시작하면 다음 질문이 중요해진다.

누가 production에 어떤 manifest를 적용했는가?
현재 cluster 상태가 Git에 있는 파일과 같은가?
긴급 수정으로 cluster에 직접 바꾼 값이 남아 있지 않은가?
rollback하려면 어떤 상태로 되돌려야 하는가?
dev/staging/prod 환경 차이가 의도된 것인가?

전통적인 push-based CD에서는 CI server가 cluster에 직접 명령을 내린다.

CI server:
  kubectl apply -f k8s/
  helm upgrade my-app ./chart

이 방식은 단순하고 직관적이다. 하지만 운영 관점에서는 다음 문제가 생길 수 있다.

문제설명
Cluster credential 노출CI server가 production cluster 접근 권한을 가져야 한다.
변경 추적 어려움실제 cluster에 적용된 상태와 Git 상태가 달라질 수 있다.
Drift 발생누군가 cluster에서 직접 수정하면 Git과 live state가 달라진다.
Rollback 기준 불명확이전에 어떤 manifest가 적용되었는지 추적이 어려울 수 있다.
Multi-cluster 확장 어려움여러 cluster에 같은 방식으로 push하려면 credential과 pipeline이 복잡해진다.
Audit 약함누가 어떤 desired state를 승인했는지 Git history와 분리될 수 있다.

GitOps는 이 문제를 다음 구조로 바꾼다.

Git repository:
  운영 환경의 desired state 저장

GitOps controller:
  Git을 감시하고 cluster 상태와 비교

Cluster:
  controller가 내부에서 desired state로 reconcile

이 구조에서는 CI server가 production cluster에 직접 접근하지 않아도 된다. CI는 image를 만들고 Git의 deployment repository를 갱신하는 데 집중하고, 실제 cluster 반영은 cluster 안의 GitOps controller가 수행한다.


GitOps와 DevOps의 관계

GitOps와 DevOps는 경쟁 개념이 아니다.

DevOps는 개발과 운영의 협업, CI/CD 자동화, feedback loop 단축, infrastructure automation, monitoring과 운영 개선을 포함하는 더 넓은 문화와 실천 방식이다.

DevOps:
  Development와 Operations의 협업
  CI/CD 자동화
  feedback loop 단축
  infrastructure automation
  monitoring과 운영 개선
  빠르고 안정적인 software delivery

GitOps는 그중에서도 특히 deployment와 operations를 Git 기반으로 선언적·자동화·감사 가능하게 만드는 방식이다.

GitOps:
  Git을 source of truth로 사용
  desired state를 선언적으로 저장
  controller가 actual state와 desired state를 비교
  drift가 있으면 reconcile
  변경 이력과 rollback을 Git history로 관리

관계를 표로 정리하면 다음과 같다.

구분DevOpsGitOps
범위개발·운영 협업 전체배포와 운영 상태 관리 방식
중심 도구CI/CD, IaC, monitoring, collaborationGit, declarative config, controller
핵심 목표빠르고 안정적인 deliveryauditable하고 reproducible한 deployment
상태 관리pipeline과 운영 도구마다 다를 수 있음Git desired state 중심
배포 방식push-based 또는 pull-based 모두 가능주로 pull-based reconciliation
Kubernetes와 관계Kubernetes 외 환경도 포함Kubernetes와 특히 잘 맞음

즉, DevOps가 목표와 문화라면, GitOps는 그 목표를 Kubernetes/cloud-native 환경에서 구현하는 delivery pattern에 가깝다.

DevOps가 목표와 문화라면,
GitOps는 그 목표를 Kubernetes/cloud-native 환경에서 구현하는 delivery pattern이다.

GitOps의 4가지 핵심 원칙

GitOps를 이해할 때는 다음 네 가지 원칙을 중심으로 보는 것이 좋다.

Declarative
Versioned and Immutable
Pulled Automatically
Continuously Reconciled

1. Declarative

GitOps에서 관리되는 시스템의 desired state는 declarative해야 한다.

Declarative하다는 것은 “어떤 명령을 어떤 순서로 실행하라”가 아니라, “최종적으로 어떤 상태가 되어야 한다”를 정의한다는 뜻이다.

Imperative 방식은 다음처럼 명령의 순서를 직접 나열한다.

kubectl create deployment web --image=nginx:1.27
kubectl scale deployment web --replicas=3
kubectl expose deployment web --port=80

반면 declarative 방식은 원하는 최종 상태를 YAML로 표현한다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:1.27
          ports:
            - containerPort: 80

GitOps에서는 Git에 이런 desired state를 저장한다.

Git에 저장되는 것:
  Kubernetes manifest
  Helm values
  Kustomize overlay
  policy
  environment-specific configuration

중요한 점은 GitOps가 단순히 Kubernetes YAML만 저장하는 방식은 아니라는 것이다. 선언적으로 표현 가능한 application configuration, infrastructure configuration, policy도 GitOps 대상이 될 수 있다.


2. Versioned and Immutable

GitOps에서 desired state는 versioned and immutable해야 한다. 즉, 현재 상태뿐 아니라 과거 상태도 추적 가능해야 한다.

Git commit A:
  image: app:v1

Git commit B:
  image: app:v2

Git commit C:
  replicas: 5

이 구조에서는 다음 질문에 답할 수 있다.

누가 변경했는가?
언제 변경했는가?
무엇이 변경되었는가?
왜 변경했는가?
어떤 commit으로 되돌리면 되는가?

GitOps에서 latest tag를 사용하는 것은 주의해야 한다.

image: my-app:latest

겉으로는 Git에 desired state가 저장된 것처럼 보이지만, latest가 가리키는 실제 image는 시간이 지나며 바뀔 수 있다. 그러면 Git commit만으로 정확히 어떤 artifact가 배포되었는지 알기 어렵다.

더 안전한 방식은 commit SHA나 immutable tag, 가능하면 image digest를 사용하는 것이다.

image: registry.example.com/my-app:a1b2c3d

또는 다음처럼 digest를 사용할 수 있다.

image: registry.example.com/my-app@sha256:...

GitOps에서 versioned and immutable은 단순히 Git을 쓴다는 뜻이 아니라, Git history만으로 desired state의 변경 이력을 신뢰할 수 있어야 한다는 뜻이다.


3. Pulled Automatically

GitOps에서는 software agent가 desired state를 자동으로 pull해야 한다.

전통적인 push 방식에서는 CI server가 cluster에 명령을 보낸다.

CI server
  -> kubectl apply
  -> cluster 변경

GitOps의 pull 방식에서는 cluster 안의 controller가 Git을 감시한다.

Git repository
  <- GitOps controller가 pull
  -> cluster state reconcile

이 차이는 보안과 운영에 큰 영향을 준다.

구분Push-based CDPull-based GitOps
실행 주체외부 CI servercluster 내부 controller
Cluster credential 위치CI server에 필요cluster 내부에 제한적으로 존재
변경 감지pipeline 실행 시점 중심controller가 지속적으로 Git 감시
Drift 대응별도 drift detection 필요controller가 지속적으로 비교 가능
Multi-clusterCI가 여러 cluster credential 관리각 cluster가 자기 Git 상태를 pull

Pull 방식의 장점은 production cluster credential을 외부 CI server에 넓게 배포하지 않아도 된다는 점이다. 각 cluster가 자기에게 필요한 Git repository를 읽고, 자기 cluster 상태를 맞춘다.

물론 pull 방식도 보안 설계가 필요하다. GitOps controller가 Git repository에 접근할 credential과 cluster 안에서 resource를 수정할 RBAC 권한을 갖기 때문이다.


4. Continuously Reconciled

GitOps에서 controller는 desired state와 actual state를 지속적으로 비교하고 reconcile한다.

desired state:
  Git에 선언된 상태

actual state:
  cluster에 실제 존재하는 상태

reconciliation:
  둘의 차이를 감지하고 desired state로 맞추는 과정

예를 들어 Git에는 replicas: 3이 선언되어 있는데, 누군가 cluster에서 직접 replicas: 5로 바꾸었다고 하자.

Git:
  replicas: 3

Cluster:
  replicas: 5

GitOps controller:
  drift 감지
  replicas를 다시 3으로 조정

이것이 GitOps의 핵심이다. 단순히 Git에 YAML을 저장하는 것이 아니라, 실제 환경이 Git에 선언된 상태와 계속 일치하도록 만드는 것이다.

이 개념은 Kubernetes controller의 reconciliation model과 잘 맞는다.

Kubernetes controller:
  Deployment desired state와 Pod actual state를 맞춤

GitOps controller:
  Git desired state와 cluster actual state를 맞춤

GitOps의 기본 Workflow

GitOps workflow를 단순화하면 다음과 같다.

1. 개발자가 code 변경
2. CI pipeline이 test/build 수행
3. container image 생성
4. image를 registry에 push
5. GitOps repository의 image tag 또는 manifest 변경
6. pull request 생성
7. review 후 merge
8. GitOps controller가 변경 감지
9. cluster에 desired state 반영
10. 상태와 health 확인

Kubernetes 관점에서는 다음처럼 표현할 수 있다.

Application repository:
  source code

CI:
  test
  build
  image push

Registry:
  container image 저장

GitOps repository:
  deployment manifest / Helm values / Kustomize overlay 저장

GitOps controller:
  Git repository 감시
  cluster actual state와 desired state 비교
  sync/reconcile 수행

Kubernetes cluster:
  실제 workload 실행

이 구조에서는 application source code repository와 deployment configuration repository를 분리할 수도 있고, 하나의 repository 안에서 디렉터리를 나눌 수도 있다.


GitOps Repository 구조

GitOps를 도입할 때 중요한 결정 중 하나가 repository 구조다.

Application repo와 GitOps repo 분리

app-repo:
  src/
  Dockerfile
  tests/
  package.json

gitops-repo:
  apps/my-app/base/
  apps/my-app/overlays/dev/
  apps/my-app/overlays/staging/
  apps/my-app/overlays/prod/

이 구조의 장점은 application code와 deployment state가 분리된다는 것이다.

장점설명
권한 분리개발자는 app repo, 운영자는 prod GitOps repo 관리 가능
배포 이력 명확deployment 변경만 별도 추적 가능
환경별 관리 쉬움dev/staging/prod overlay 분리 가능
GitOps controller 대상 명확controller가 deployment repo만 감시

단점도 있다.

단점:
  repository가 늘어남
  image tag update 자동화가 필요함
  code 변경과 deployment 변경의 연결을 추적해야 함

Monorepo 방식

repo:
  services/my-app/src/
  services/my-app/Dockerfile
  deploy/my-app/base/
  deploy/my-app/overlays/dev/
  deploy/my-app/overlays/prod/

이 구조는 한 repository 안에 application code와 deployment config를 함께 둔다.

장점은 다음과 같다.

장점:
  code와 manifest 변경을 한 PR에서 관리 가능
  작은 팀이나 단일 서비스에 단순함
  commit 단위 추적이 쉬움

단점은 다음과 같다.

단점:
  repository 권한 분리가 어려울 수 있음
  여러 팀이 함께 쓰면 복잡해짐
  GitOps controller가 감시할 path를 신중히 제한해야 함

조직 규모와 권한 모델에 따라 repository 구조 선택이 달라진다.


GitOps와 Kubernetes가 잘 맞는 이유

GitOps는 Kubernetes와 특히 잘 맞는다. 이유는 Kubernetes 자체가 declarative desired state model을 사용하기 때문이다.

Kubernetes에서는 사용자가 원하는 상태를 YAML로 선언한다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 3
  template:
    spec:
      containers:
        - name: api
          image: registry.example.com/api:a1b2c3d

Kubernetes controller는 이 desired state에 맞춰 실제 Pod를 생성하고 유지한다. GitOps controller는 한 단계 위에서 작동한다.

GitOps controller:
  Git에 있는 Kubernetes manifest를 cluster에 반영

Kubernetes controller:
  cluster에 반영된 manifest를 기준으로 Pod/Service 상태를 유지

즉, GitOps는 Kubernetes reconciliation model을 Git repository까지 확장한 것처럼 볼 수 있다.

Git desired state
  -> GitOps controller
  -> Kubernetes API object
  -> Kubernetes controller
  -> Pod/Service actual state

Argo CD와 Flux의 역할

GitOps를 구현하는 대표적인 도구는 Argo CDFlux다.

두 도구 모두 Git repository를 감시하고 Kubernetes cluster 상태를 desired state와 맞추는 역할을 한다.

도구특징
Argo CDUI가 강하고 Application 중심으로 상태를 확인하기 좋다.
FluxKubernetes controller 방식에 가깝고 Git/OCI source, Kustomize/Helm 연계가 강하다.

도구를 선택할 때는 다음을 봐야 한다.

기준확인할 점
UI 필요성운영자가 UI에서 sync 상태를 봐야 하는가?
Multi-cluster여러 cluster를 어떻게 관리할 것인가?
Helm/Kustomize어떤 manifest packaging 방식을 쓰는가?
권한 모델팀별 application 권한을 어떻게 나눌 것인가?
Drift 처리out-of-sync 상태를 어떻게 감지하고 복구할 것인가?
RollbackGit revert와 도구의 rollback model을 어떻게 사용할 것인가?
Secret 관리sealed secret, external secret, vault 연계를 어떻게 할 것인가?

GitOps의 핵심은 특정 도구가 아니라 Git desired state와 continuous reconciliation이다. 도구는 이 원칙을 구현하는 수단이다.


Push-based CD와 Pull-based GitOps 비교

GitOps를 이해할 때 가장 중요한 비교가 push와 pull이다.

Push-based CD

CI/CD pipeline:
  cluster credential 보유
  kubectl apply 실행
  cluster에 직접 변경 push

장점은 다음과 같다.

- 구조가 단순함
- 기존 CI/CD 도구와 익숙함
- 즉시 명령 실행 가능
- 초기 도입이 쉬움

단점은 다음과 같다.

- CI server에 cluster credential이 필요함
- cluster drift를 계속 감지하기 어려움
- 여러 cluster로 확장 시 credential 관리가 복잡함
- 실제 cluster 상태가 Git과 달라질 수 있음

Pull-based GitOps

GitOps controller:
  cluster 내부에서 Git repository 감시
  desired state를 pull
  actual state와 비교
  reconcile 수행

장점은 다음과 같다.

- Git이 source of truth가 됨
- cluster credential을 외부 CI에 넓게 배포하지 않아도 됨
- drift detection과 reconciliation이 자연스러움
- rollback이 Git revert 중심으로 단순해짐
- multi-cluster 운영에 적합함

단점도 있다.

- GitOps controller 운영이 필요함
- Git repository 구조 설계가 필요함
- Secret 관리 방식이 중요해짐
- 자동 reconcile이 원하지 않는 변경을 되돌릴 수 있음
- stateful workload와 migration은 별도 전략이 필요함

비교하면 다음과 같다.

구분Push-based CDPull-based GitOps
배포 실행 위치CI/CD serverCluster 내부 controller
Source of truthPipeline 실행 결과 또는 GitGit repository
CredentialCI server가 cluster credential 보유Controller가 제한된 권한으로 cluster 내부에서 동작
Drift 감지별도 구현 필요기본 모델에 포함
Rollbackpipeline 재실행 또는 수동 rollbackGit revert 중심
Multi-clusterpipeline이 여러 cluster에 push각 cluster가 Git에서 pull
운영 복잡도초기 단순controller/repo 설계 필요

GitOps와 CI/CD의 역할 분리

GitOps를 도입하면 CI와 CD의 역할이 더 명확해진다.

CI:
  source code 검증
  unit/integration test
  container image build
  image scan
  registry push
  SBOM/provenance 생성

GitOps CD:
  deployment config 변경 감시
  cluster sync
  drift detection
  health check
  rollback 지원

예를 들어 Tekton과 Argo CD를 함께 쓴다면 다음 구조가 자연스럽다.

Tekton:
  Git clone
  test
  image build
  image push
  GitOps repo image tag update

Argo CD:
  GitOps repo 감시
  cluster와 desired state 비교
  sync
  health 확인

이렇게 역할을 나누면 CI pipeline이 production cluster에 직접 접근하지 않아도 된다.

CI의 책임:
  artifact를 안전하게 만들기

GitOps controller의 책임:
  선언된 desired state를 cluster에 반영하기

이 분리는 보안과 운영 측면에서 중요하다.


Image Tag 업데이트 방식

GitOps workflow에서 자주 고민되는 지점이 image tag 업데이트다.

CI가 image를 만들면 GitOps repository의 manifest나 Helm values를 갱신해야 한다.

예를 들어 CI가 다음 image를 만들었다고 하자.

registry.example.com/my-app:a1b2c3d

그러면 GitOps repo의 manifest가 바뀐다.

image:
  repository: registry.example.com/my-app
  tag: a1b2c3d

또는 Deployment manifest가 직접 바뀔 수 있다.

containers:
  - name: my-app
    image: registry.example.com/my-app:a1b2c3d

이 변경을 자동 commit할 수도 있고, PR로 만들 수도 있다.

자동 commit 방식:
  CI가 GitOps repo에 바로 commit
  GitOps controller가 sync

PR 방식:
  CI가 image tag update PR 생성
  reviewer 승인
  merge 후 sync

각 방식의 차이는 다음과 같다.

방식장점주의점
자동 commit빠름, 완전 자동화에 적합production까지 자동 반영될 수 있음
PR 방식review와 승인 가능lead time이 늘 수 있음
환경별 promotiondev→staging→prod 단계 관리 쉬움promotion workflow 설계 필요

Production에는 PR 기반 promotion을 두고, dev에는 자동 commit을 두는 식으로 환경별 정책을 나눌 수 있다.


Environment 분리와 Promotion

GitOps에서는 dev, staging, production 환경을 어떻게 나눌지가 중요하다.

대표적인 구조는 다음과 같다.

apps/
  my-app/
    base/
      deployment.yaml
      service.yaml
    overlays/
      dev/
        kustomization.yaml
        values.yaml
      staging/
        kustomization.yaml
        values.yaml
      prod/
        kustomization.yaml
        values.yaml

base에는 공통 설정을 두고, 환경별 차이는 overlays에서 관리한다.

환경차이 예시
devreplica 1, 작은 resource request, debug logging
stagingproduction-like config, test database
prodreplica 3+, stricter resource, production secret, HPA

주의할 점은 환경 차이가 너무 커지면 staging이 production 검증 역할을 하지 못한다는 것이다.

나쁜 구조:
  dev/staging/prod가 거의 다른 시스템처럼 동작

좋은 구조:
  공통 base를 유지하고, 필요한 차이만 overlay로 분리

GitOps에서는 환경 차이도 Git diff로 확인할 수 있어야 한다.


Drift Detection

GitOps의 큰 장점 중 하나가 drift detection이다.

Drift는 Git에 선언된 desired state와 실제 cluster 상태가 달라진 상태다.

예를 들어 Git에는 다음이 있다.

replicas: 3

그런데 누군가 cluster에서 직접 수정한다.

kubectl scale deployment api --replicas=5

그러면 상태는 다음과 같다.

Git desired state:
  replicas = 3

Cluster actual state:
  replicas = 5

결과:
  drift 발생

GitOps controller는 이를 감지하고 다시 Git 상태로 맞출 수 있다.

drift 감지
  -> out-of-sync 표시
  -> 자동 sync 또는 수동 sync
  -> replicas = 3으로 복구

이 기능은 운영 안정성에 중요하다.

장점:
  cluster 수동 변경을 감지
  Git을 source of truth로 유지
  audit되지 않은 변경을 줄임
  환경 재현성을 높임

다만 모든 drift를 즉시 자동으로 되돌리는 것이 항상 좋은 것은 아니다. 긴급 장애 대응 중 수동 scaling을 했는데 GitOps controller가 바로 되돌리면 운영자가 의도한 임시 대응이 실패할 수 있다.

따라서 auto-sync 정책은 환경별로 다르게 설계해야 한다.

환경권장 정책 예시
devauto-sync 적극 사용
stagingauto-sync + pruning 가능
productionauto-sync 여부 신중히 결정, manual approval 또는 sync window 고려
incident 중auto-sync 일시 중단 절차 필요

Rollback

GitOps에서 rollback은 보통 Git revert로 표현된다.

문제 발생:
  commit C에서 production 장애

대응:
  Git revert commit C
  GitOps controller가 이전 desired state로 sync

이 방식의 장점은 rollback도 Git history에 남는다는 것이다.

누가 rollback했는가?
어떤 commit을 revert했는가?
언제 rollback했는가?
rollback 이후 cluster 상태는 어떤가?

하지만 주의할 점이 있다. 모든 장애가 Git revert만으로 해결되지는 않는다.

다음 변경은 rollback이 어렵다.

database schema migration
data format 변경
message queue event schema 변경
cache key format 변경
external API contract 변경
stateful workload 변경

예를 들어 application image만 이전으로 되돌려도 database schema가 이미 바뀌었다면 이전 version이 동작하지 않을 수 있다.

따라서 GitOps에서도 backward compatibility가 중요하다.

안전한 migration 예:
  1. 새 column 추가
  2. app이 old/new schema 모두 읽도록 배포
  3. data backfill
  4. app이 new schema 사용
  5. old column 제거

GitOps rollback은 강력하지만, application과 data compatibility가 함께 설계되어야 한다.


GitOps와 보안

GitOps는 보안 측면에서 장점이 많지만, 잘못 설계하면 새로운 위험도 생긴다.

장점

장점설명
변경 이력모든 desired state 변경이 Git history에 남는다.
Reviewproduction 변경을 PR review로 검토할 수 있다.
권한 분리CI가 production cluster credential을 직접 갖지 않아도 된다.
Drift 감지수동 변경과 비인가 변경을 탐지할 수 있다.
Audit누가 어떤 상태를 승인했는지 추적 가능하다.
RollbackGit revert로 desired state 복구 가능하다.

주의할 점

GitOps repo에는 민감 정보를 그대로 넣으면 안 된다.

절대 직접 넣지 말아야 할 것:
  password
  token
  private key
  kubeconfig
  database credential
  cloud access key

Kubernetes Secret manifest도 base64 encoding일 뿐 암호화가 아니다.

apiVersion: v1
kind: Secret
data:
  password: cGFzc3dvcmQ=

이 값은 쉽게 decode할 수 있다.

따라서 GitOps에서는 secret 관리 전략이 필요하다.

방식설명
External Secretsexternal secret manager에서 cluster로 secret 동기화
Sealed Secretsencrypted Secret을 Git에 저장하고 cluster에서 복호화
SOPSYAML secret을 암호화하여 Git에 저장
Vault 연동runtime에 secret manager에서 주입
CI/CD secret storepipeline 단계에서 필요한 credential만 사용

또한 GitOps controller의 권한도 최소화해야 한다.

나쁜 예:
  Argo CD/Flux controller가 cluster-admin
  모든 namespace와 secret에 접근 가능

좋은 방향:
  application별 namespace 권한 제한
  project별 repository scope 제한
  production sync 권한 제한
  Git repository write 권한 최소화

Policy as Code와 GitOps

GitOps는 Policy as Code와 잘 맞는다.

GitOps repo에 들어오는 변경을 PR 단계에서 검사할 수 있고, cluster admission 단계에서도 검사할 수 있다.

예를 들어 다음 정책을 둘 수 있다.

- privileged container 금지
- hostPath volume 제한
- container는 root로 실행 금지
- production namespace에는 resource requests/limits 필수
- LoadBalancer service는 승인된 namespace에서만 허용
- image는 승인된 registry에서만 허용
- latest tag 사용 금지
- Secret plaintext commit 금지

GitOps workflow에서 policy check는 다음 지점에 들어갈 수 있다.

Pull Request:
  manifest lint
  schema validation
  policy-as-code check

Merge:
  GitOps controller sync

Admission:
  Kubernetes admission controller가 최종 정책 검증

Runtime:
  drift와 policy violation 관찰

이렇게 하면 잘못된 desired state가 Git에 들어가기 전에 막고, 혹시 들어가더라도 cluster에서 다시 막을 수 있다.


Progressive Delivery와 GitOps

GitOps는 progressive delivery와도 결합할 수 있다.

Progressive delivery는 새 version을 한 번에 전체 사용자에게 배포하지 않고, canary, blue-green, feature flag 등을 통해 점진적으로 노출하는 방식이다.

GitOps + Canary:
  Git에 새 version 선언
  canary controller가 5% traffic에 먼저 배포
  metrics 확인
  정상이라면 25%, 50%, 100%로 확대
  비정상이라면 rollback

GitOps는 desired state 변경을 관리하고, progressive delivery controller는 rollout 전략과 metric 검증을 담당한다.

확인할 metric은 다음과 같다.

Metric목적
HTTP 5xx rateserver error 증가 여부
p95/p99 latency지연 악화 여부
request success rate요청 성공률
pod restart countcrash 여부
business transaction success실제 user journey 성공 여부
SLO burn ratereliability 목표 영향

GitOps가 있다고 해서 배포가 자동으로 안전해지는 것은 아니다. GitOps는 원하는 상태를 안정적으로 반영하는 방식이고, 새 version이 application-level로 안전한지는 test, canary, observability가 함께 판단해야 한다.


GitOps와 Observability

GitOps를 운영하려면 observability가 필요하다.

GitOps controller가 sync에 성공했다고 해서 application이 정상이라는 뜻은 아니다.

Sync 성공:
  manifest가 cluster에 적용됨

Health 정상:
  Kubernetes resource가 기대한 상태임

Application 정상:
  실제 사용자 요청이 성공하고 latency가 정상임

이 세 가지는 다르다.

GitOps에서 확인해야 할 상태는 다음과 같다.

상태의미
Sync statusGit desired state와 cluster actual state가 일치하는가
Health statusKubernetes resource가 정상 상태인가
Drift statusGit과 다른 수동 변경이 있는가
Rollout status새 version 배포가 완료되었는가
Application metricerror rate, latency, throughput이 정상인가
Business metric핵심 사용자 journey가 정상인가

GitOps controller의 UI나 CLI는 sync와 health를 보여줄 수 있지만, SLO나 user impact는 Prometheus, Grafana, Alertmanager, tracing, logging 같은 observability stack과 함께 봐야 한다.


Multi-cluster GitOps

GitOps는 multi-cluster 운영에 특히 유용하다.

여러 cluster가 있을 때 push-based CD는 CI server가 각 cluster credential을 관리해야 한다.

CI server:
  dev kubeconfig
  staging kubeconfig
  prod kubeconfig
  region-a kubeconfig
  region-b kubeconfig

GitOps에서는 각 cluster가 자기 Git repository 또는 path를 pull하도록 구성할 수 있다.

cluster-dev:
  Git path: clusters/dev

cluster-staging:
  Git path: clusters/staging

cluster-prod:
  Git path: clusters/prod

이 구조의 장점은 다음과 같다.

- cluster별 desired state 분리
- cluster credential 외부 노출 감소
- cluster가 자기 상태를 스스로 reconcile
- 신규 cluster bootstrap 자동화 가능
- Git diff로 cluster 간 차이 확인 가능

Multi-cluster GitOps에서는 repo structure와 controller 배치 방식이 중요하다.

방식설명
cluster별 controller각 cluster 안에 GitOps controller 설치
hub-and-spoke중앙 cluster의 controller가 여러 cluster 관리
environment path 분리Git path로 dev/staging/prod 분리
app-of-apps pattern상위 application이 여러 하위 app 관리
bootstrap repocluster 초기 설치 상태를 Git으로 관리

어떤 구조가 맞는지는 cluster 수, 보안 정책, 네트워크 접근성, 운영팀 구조에 따라 달라진다.


GitOps와 Infrastructure as Code의 차이

GitOps와 IaC는 겹치지만 같은 말은 아니다.

IaC는 infrastructure를 code로 정의하는 방식이다.

IaC:
  Terraform
  CloudFormation
  Pulumi
  Ansible
  Kubernetes YAML

GitOps는 Git에 저장된 desired state를 controller가 자동으로 pull하고 reconcile하는 운영 방식이다.

구분IaCGitOps
핵심infrastructure를 code로 정의Git desired state와 actual state를 reconcile
범위provisioning, configurationdeployment, operations, cluster state management
실행 방식plan/apply, script, pipeline 등 다양controller 기반 pull/reconcile 중심
Source of truth보통 GitGit 또는 versioned desired state store
Drift 대응별도 plan/drift detection 필요continuous reconciliation에 포함
예시Terraform으로 VPC 생성Argo CD/Flux로 Kubernetes app sync

즉, IaC는 GitOps의 재료가 될 수 있다. 하지만 Git에 Terraform code를 저장했다고 자동으로 GitOps가 되는 것은 아니다.

Git에 IaC 저장:
  version control은 됨

GitOps:
  agent가 desired state를 pull하고
  actual state를 계속 reconcile해야 함

Kubernetes Homelab에서 GitOps 적용하기

개인 k3s나 homelab 환경에서도 GitOps는 유용하다.

k3s, Traefik, Longhorn, Nexus, MetalLB, registry 같은 구성 요소를 운영한다면, GitOps는 “서버가 날아가도 다시 만들 수 있는 상태”를 만드는 데 도움이 된다.

예를 들어 다음을 GitOps로 관리할 수 있다.

영역GitOps 관리 대상
Namespace서비스별 namespace
IngressTraefik IngressRoute, TLS 설정
StorageLonghorn StorageClass, backup 설정
RegistryNexus/Harbor deployment, PVC, ingress
ObservabilityPrometheus, Grafana, Loki values
AppDeployment, Service, ConfigMap, HPA
NetworkMetalLB IPAddressPool, L2Advertisement
SecurityRBAC, NetworkPolicy, ServiceAccount

작은 homelab에서는 다음부터 시작하는 것이 현실적이다.

1. Kubernetes manifest와 Helm values를 Git에 저장
2. Argo CD 또는 Flux 설치
3. dev/internal service부터 GitOps로 관리
4. Secret은 Git에 평문으로 넣지 않음
5. 수동 변경이 생기면 Git에 반영
6. cluster 재구축 절차를 README로 정리

예시 구조는 다음과 같다.

homelab-gitops/
  clusters/
    k3s-main/
      apps/
        traefik/
        longhorn/
        nexus/
        prometheus/
        grafana/
      infrastructure/
        metallb/
        storageclass/
        namespaces/

Homelab에서 GitOps의 장점은 다음이다.

- 어떤 서비스가 어떤 values로 설치되었는지 Git에 남음
- 장애 후 복구가 쉬워짐
- 수동 변경과 drift를 줄일 수 있음
- ingress, storage, registry 구성을 문서화할 수 있음
- 새 node나 새 cluster로 이관할 때 재현성이 좋아짐

주의할 점도 있다.

- secret을 Git에 그대로 넣지 말 것
- auto-sync가 storage나 database workload에 미치는 영향 검토
- Longhorn, database, registry처럼 stateful workload는 backup/restore 전략 필요
- GitOps controller 자체 복구 절차도 필요
- bootstrap dependency를 고려해야 함

특히 GitOps controller도 cluster 안에서 동작하므로, cluster 자체가 완전히 망가졌을 때 controller를 어떻게 다시 설치할지 bootstrap 절차가 필요하다.


Bootstrap 문제

GitOps를 쓰다 보면 중요한 질문이 생긴다.

GitOps controller도 cluster 안에 있는데,
cluster가 새로 만들어졌을 때 GitOps controller는 누가 설치하는가?

이를 bootstrap 문제라고 볼 수 있다.

일반적인 흐름은 다음과 같다.

1. Kubernetes cluster 생성
2. 최소한의 bootstrap command 실행
3. GitOps controller 설치
4. GitOps controller가 Git repo를 바라보도록 설정
5. 나머지 platform component를 GitOps로 설치

즉, GitOps가 모든 것을 처음부터 자동으로 해결하는 것은 아니다. 최소 bootstrap 단계는 필요하다.

Homelab에서도 다음처럼 나눌 수 있다.

Manual/bootstrap:
  k3s 설치
  kubeconfig 확보
  GitOps controller 설치
  Git repository 연결

GitOps-managed:
  namespace
  ingress
  storage
  monitoring
  registry
  application

이 경계를 명확히 해야 복구 절차가 단순해진다.


자칫 실수하기 쉬운 부분

Git에 YAML을 저장하면 GitOps라고 생각하는 경우

Git에 Kubernetes manifest를 저장하는 것은 GitOps의 일부일 수 있다. 하지만 controller가 actual state를 continuously reconcile하지 않는다면 완전한 GitOps라고 보기 어렵다.

Git에 YAML 저장:
  version control

GitOps:
  version control
  + pull-based automation
  + continuous reconciliation
  + drift detection

CI가 계속 kubectl apply하면서 GitOps라고 부르는 경우

CI가 Git에서 manifest를 읽고 kubectl apply를 실행하는 구조는 Git-based deployment일 수는 있지만, GitOps의 pull/reconcile model과는 다르다.

CI:
  Git read
  kubectl apply

이 구조:
  Git을 사용하지만 push-based CD에 가까움

GitOps에서는 cluster 내부 agent가 Git을 pull하고 상태를 맞춘다.

Secret을 Git에 그대로 넣는 경우

GitOps는 Git을 source of truth로 삼지만, secret을 평문으로 저장하라는 뜻이 아니다.

주의:
  Kubernetes Secret의 base64는 암호화가 아님
  Git history에 secret이 남으면 제거가 어려움
  secret은 별도 암호화 또는 external secret manager로 관리해야 함

Auto-sync를 무조건 켜는 경우

Auto-sync는 편리하지만 production에서는 신중해야 한다.

위험:
  잘못된 commit이 merge되면 즉시 production 반영
  incident 중 수동 조치를 GitOps가 되돌릴 수 있음
  대규모 변경이 자동으로 적용될 수 있음

Production에서는 approval, sync window, policy check, progressive delivery를 함께 고려해야 한다.

GitOps가 모든 배포 문제를 해결한다고 생각하는 경우

GitOps는 desired state 관리와 reconciliation에 강하다. 하지만 다음 문제는 별도로 설계해야 한다.

- database migration
- schema compatibility
- feature flag
- canary analysis
- SLO monitoring
- rollback safety
- secret rotation
- multi-cluster ownership

GitOps는 배포의 기반을 안정화하지만, application release engineering 전체를 자동으로 해결하지는 않는다.


실무 검증 포인트

GitOps를 운영할 때는 다음 질문을 확인해야 한다.

검증 포인트확인 질문
Source of truth운영 환경의 desired state가 Git에 있는가?
Declarative config배포 상태가 명령이 아니라 선언형으로 표현되는가?
Versioningimage tag, Helm chart, config가 versioned/immutable한가?
Pull modelcluster 내부 controller가 Git을 pull하는가?
Reconciliationactual state와 desired state 차이를 감지하고 복구하는가?
Secret 관리secret이 Git에 평문으로 저장되지 않는가?
RBACGitOps controller 권한이 최소화되어 있는가?
Drift policymanual change를 어떻게 감지하고 처리하는가?
RollbackGit revert로 안전하게 되돌릴 수 있는가?
Migrationdatabase/schema 변경이 rollback과 호환되는가?
Observabilitysync status와 application health를 모두 확인하는가?
Promotiondev→staging→prod 승격 workflow가 명확한가?
Bootstrapcluster 재구축 시 GitOps controller를 다시 설치할 절차가 있는가?
Multi-clustercluster별 repo/path/권한 구조가 명확한가?

Mental Model

GitOps는 다음 mental model로 이해하면 좋다.

Git:
  운영 환경의 desired state를 저장하는 source of truth

CI:
  source code를 test/build하고 image를 registry에 push

Registry:
  versioned artifact 저장소

GitOps repository:
  image tag, manifest, Helm values, Kustomize overlay 저장

GitOps controller:
  Git desired state와 cluster actual state를 비교

Kubernetes:
  실제 workload 실행

Observability:
  sync 성공 이후 application health와 user impact 확인

더 짧게 정리하면 다음과 같다.

GitOps = Git에 선언하고, controller가 맞춘다.

정리

GitOps는 Git을 운영 환경의 desired state를 저장하는 source of truth로 삼고, cluster 내부의 controller가 Git 상태를 자동으로 pull하여 실제 시스템 상태와 지속적으로 reconcile하는 DevOps 운영 방식이다.

핵심은 다음과 같다.

  • GitOps는 Git에 선언된 desired state와 실제 cluster 상태를 맞추는 운영 모델이다.
  • DevOps와 GitOps는 경쟁 개념이 아니다. GitOps는 DevOps를 구현하는 구체적인 deployment/operation pattern이다.
  • GitOps의 핵심 원칙은 declarative, versioned and immutable, pulled automatically, continuously reconciled이다.
  • Push-based CD는 CI server가 cluster에 직접 변경을 push하고, pull-based GitOps는 cluster 내부 controller가 Git을 pull한다.
  • GitOps는 drift detection과 rollback을 Git history 중심으로 단순화한다.
  • GitOps repository 구조는 application repo 분리 방식과 monorepo 방식 중 조직의 권한 모델과 규모에 맞게 선택해야 한다.
  • Kubernetes는 declarative desired state와 controller reconciliation model을 사용하므로 GitOps와 잘 맞는다.
  • Argo CD와 Flux는 GitOps를 구현하는 대표적인 controller다.
  • Secret은 Git에 평문으로 저장하면 안 되며, External Secrets, Sealed Secrets, SOPS, Vault 같은 전략이 필요하다.
  • Auto-sync는 편리하지만 production에서는 approval, sync window, policy check, progressive delivery와 함께 설계해야 한다.
  • GitOps controller 자체를 설치하는 bootstrap 절차도 필요하다.

GitOps의 본질은 다음 네 가지로 압축된다.

Declarative:
  원하는 상태를 선언한다.

Versioned and Immutable:
  원하는 상태의 변경 이력을 Git에 남긴다.

Pulled Automatically:
  cluster의 controller가 Git 상태를 자동으로 가져온다.

Continuously Reconciled:
  실제 상태와 원하는 상태가 달라지면 계속 맞춘다.

결국 GitOps는 단순한 배포 자동화 도구가 아니라, 운영 환경의 상태를 Git에 선언하고 실제 시스템이 그 선언과 계속 일치하도록 만드는 운영 모델이다.