사전 GitOps
패턴

GitOps

gabury1고친 사람 github-actions[bot]

GitOps 는 서버와 서비스를 Git 저장소에 적힌 모습대로 맞춰 두는 운영 방식입니다. 사람은 시스템을 직접 만지지 않고 저장소의 파일만 고칩니다. 그러면 프로그램이 그 변경을 읽어 시스템에 반영합니다. 무엇이 언제 누구 손으로 바뀌었는지가 저장소 이력에 남습니다.

쉽고 빠른 이해

GitOps 는 운영을 코드 고치듯 하는 방식입니다. 웹 서버를 세 대에서 다섯 대로 늘리고 싶으면 설정 파일의 숫자 3 을 5 로 고쳐 올립니다. 서버에 접속해 명령을 치지 않습니다.

이렇게 하는 까닭은 손으로 한 변경이 흔적을 안 남기기 때문입니다. 누가 서버에서 설정을 바꾸면 무엇을 왜 바꿨는지 아무도 모릅니다. 저장소를 거치면 모든 변경이 리뷰를 받고 이력에 남습니다. 되돌릴 때도 같은 길을 씁니다. 지난 변경을 지우지 않습니다. 그 변경을 거꾸로 적은 변경을 하나 더 올립니다.

어떻게 도나:

  1. 사람이 설정 파일을 고쳐 변경 요청을 올립니다. 동료가 리뷰한 뒤 합칩니다
  2. 시스템 곁에 있는 프로그램이 저장소를 주기적으로 읽어 옵니다
  3. 저장소의 모습과 지금 시스템의 모습이 다르면 저장소 쪽으로 맞춥니다

대가도 있습니다. 급할 때 서버에서 바로 고친 것은 프로그램이 다시 저장소 모습으로 되돌려 버립니다. 비밀번호 같은 값은 저장소에 그냥 적을 수 없어 따로 다뤄야 합니다. 데이터베이스 안의 데이터처럼 파일로 적을 수 없는 것은 이 방식 밖에 남습니다. 그래서 시스템의 모습을 파일로 적을 수 있는 곳, 여러 사람이 함께 고치는 곳에 씁니다.

상세

이 절은 먼저 GitOps 를 이루는 네 약속을 봅니다. 그다음 변경 하나가 저장소에서 시스템까지 가는 길을 따라갑니다. 예로는 웹 서버 대수를 세 대에서 다섯 대로 늘리는 일 하나를 끝까지 씁니다. 마지막으로 이 방식이 무엇을 잃는지를 봅니다.

저장소가 정답인 운영

Git 은 파일의 변경 이력을 남기는 버전관리 도구입니다. 변경 하나하나를 커밋이라는 단위로 쌓습니다. 앞의 커밋에 적힌 모습은 언제든 다시 꺼내 볼 수 있습니다. 파일과 그 이력을 담아 두는 곳이 저장소입니다.

GitOps 에서는 이 저장소가 시스템의 정답지입니다. 「웹 서버는 세 대, 서버에 올릴 프로그램은 1.4 판」 같은 내용이 저장소의 파일에 적혀 있습니다. 시스템이 이 파일과 다르면 틀린 쪽은 시스템입니다. 이렇게 믿을 곳을 한 곳으로 정해 두는 것을 단일 진실 원천이라고 합니다.

이름은 Git 과 운영(Operations)을 붙여 지었습니다. 개발자가 코드를 다루던 방법을 그대로 운영에 가져온다는 뜻입니다.

네 가지 약속

GitOps 로 굴리는 시스템은 보통 네 가지를 갖춥니다. 넷은 차례로 앞의 것 위에 얹힙니다.

약속 뜻 없으면
선언적 순서가 아니라 끝났을 때의 모습을 적는다 저장소와 시스템을 비교할 기준이 없다
버전이 남고 안 바뀐다 적힌 모습은 이력으로 쌓이고 지난 기록을 고치지 않는다 무엇이 언제 바뀌었는지 못 따라간다
자동으로 끌어온다 시스템 쪽 프로그램이 저장소를 읽어 온다 누군가 밀어 넣어 줘야 반영된다
계속 맞춘다 시스템을 꾸준히 살펴 저장소 모습으로 되돌린다 한 번 맞춘 뒤 어긋나도 모른다

첫째 약속은 선언적 설정입니다. 「서버를 두 대 더 띄워라」가 아니라 「서버가 다섯 대 있어야 한다」라고 적는 방식입니다. 결과를 적어 두면 지금 몇 대인지와 상관없이 같은 파일로 같은 결과에 닿습니다.

적혀 있어야 할 모습을 원하는 상태라고 부릅니다. 지금 시스템이 실제로 놓인 모습은 실제 상태입니다. GitOps 의 일은 이 둘을 같게 만드는 것입니다.

끌어오는 프로그램과 조정 루프

셋째와 넷째 약속을 맡는 것은 시스템 곁에서 늘 도는 프로그램입니다. 이런 프로그램이 에이전트입니다. 사람 대신 정해진 일을 되풀이하는 프로그램이라는 뜻입니다.

에이전트는 같은 일을 끝없이 되풀이합니다. 한 바퀴는 세 단계입니다. 저장소에서 원하는 상태를 읽습니다. 시스템의 실제 상태를 살핍니다. 둘이 다른 만큼만 고칩니다. 이 되풀이를 조정 루프라고 부릅니다. 온도 조절기도 같은 모양입니다. 방 온도를 재어 설정 온도와 다르면 난방을 켭니다.

flowchart TD
    A["저장소에서 원하는 상태를 읽는다"] --> B["시스템의 실제 상태를 살핀다"]
    B --> C{"둘이 같은가"}
    C -->|같다| D["잠시 기다린다"]
    C -->|다르다| E["다른 만큼만 고친다"]
    E --> D
    D --> A

루프에는 끝이 없습니다. 변경을 반영한 뒤에도 에이전트는 계속 살핍니다. 그래서 누가 서버에 들어가 손으로 설정을 바꾸면, 다음 바퀴에서 그 변경이 저장소 모습으로 되돌아갑니다. 시스템이 적힌 모습에서 조금씩 벗어나는 일이 구성 드리프트입니다. 조정 루프가 이것을 계속 지웁니다.

변경 하나가 지나가는 길

웹 서버를 세 대에서 다섯 대로 늘리는 일로 따라가 보겠습니다. 사람과 에이전트가 각각 무엇을 하는지를 봅니다.

  1. 개발자가 설정 파일의 숫자를 고쳐 풀 리퀘스트를 올립니다. 풀 리퀘스트는 「이 변경을 합쳐 달라」는 요청입니다
  2. 동료가 변경을 읽고 코드 리뷰를 한 뒤 저장소의 기준 브랜치에 합칩니다. 브랜치는 커밋이 이어지는 한 갈래입니다. 기준 브랜치는 시스템에 반영할 모습을 담는 갈래입니다
  3. 에이전트가 다음 바퀴에 저장소를 읽습니다. 서버가 두 대 모자란 것을 알아챕니다
  4. 에이전트가 두 대를 더 띄웁니다. 이제 실제 상태와 원하는 상태가 같습니다

이 길에서 사람은 서버에 한 번도 접속하지 않았습니다. 사람이 한 일은 파일 한 줄을 고치고 리뷰를 받은 것뿐입니다.

되돌릴 때도 같은 길을 씁니다. 다섯 대가 문제였다면 그 커밋을 지우지 않습니다. 3 을 5 로 바꾼 것을 거꾸로 적은 커밋, 곧 되돌리는 커밋을 하나 더 합칩니다. 이력은 지워지지 않고 앞으로만 자랍니다. 에이전트는 저장소가 다시 세 대를 가리키는 것을 보고 두 대를 내립니다. 롤백이 새 절차가 아니라 평소의 변경과 같은 절차가 됩니다.

밀어 넣기와 끌어오기

GitOps 가 나오기 전에도 저장소에서 배포를 시작하는 방식은 있었습니다. 대개 지속적 통합(CI, Continuous Integration) 서버가 그 일을 했습니다. 지속적 통합은 커밋이 들어올 때마다 빌드와 테스트를 자동으로 돌리는 일입니다. 이 서버가 테스트 뒤에 운영 시스템에 접속해 변경을 밀어 넣었습니다.

GitOps 는 방향을 뒤집습니다. 바깥에서 밀어 넣지 않습니다. 시스템 곁의 에이전트가 저장소를 끌어옵니다. 두 방식은 누가 운영 시스템의 자격 증명을 쥐느냐에서 갈립니다. 자격 증명은 시스템에 들어가도 된다는 것을 증명하는 값입니다. 비밀번호나 접근 키가 그렇습니다.

밀어 넣기 끌어오기
반영을 시작하는 쪽 바깥의 지속적 통합 서버 시스템 곁의 에이전트
운영 시스템의 자격 증명을 쥐는 쪽 바깥의 서버 시스템 안쪽의 에이전트
반영 뒤에 생긴 어긋남 다음 배포 때까지 모른다 다음 바퀴에 되돌린다

끌어오기에서는 자격 증명이 운영 시스템 밖으로 나가지 않습니다. 바깥 서버가 뚫려도 운영 시스템에 들어갈 열쇠는 거기 없습니다. 아래 그림은 두 방식에서 자격 증명이 어느 쪽에 있는지, 누가 경계를 넘어 일을 시작하는지를 보입니다.

flowchart TD
    subgraph PUSH["밀어 넣기"]
        P1["저장소"] --> P2["지속적 통합 서버<br/>자격 증명을 쥔다"]
        P2 -->|"바깥에서 경계를 넘어 들어간다"| P3
        subgraph SYS1["운영 시스템"]
            P3["서버들"]
        end
    end
    subgraph PULL["끌어오기"]
        Q1["저장소"]
        subgraph SYS2["운영 시스템"]
            Q2["에이전트<br/>자격 증명을 쥔다"] --> Q3["서버들"]
        end
        Q1 -->|"안쪽 에이전트가 요청해 읽어 온다"| Q2
    end
    P3 ~~~ Q1

이 방식이 잃는 것

GitOps 는 모든 변경을 저장소로 모읍니다. 그 대가는 저장소를 거치지 않는 일이 불편해지는 것입니다.

첫째, 급한 손 수정이 살아남지 못합니다. 장애 중에 서버에서 설정을 바로 고쳐도 에이전트가 다음 바퀴에 되돌립니다. 급한 수정도 저장소를 거쳐야 하므로 리뷰와 반영 시간만큼 늦어집니다.

둘째, 비밀 정보를 저장소에 그냥 적을 수 없습니다. 비밀번호를 평문으로 커밋하면 저장소를 읽을 수 있는 사람 모두가 봅니다. 이력은 지우지 않는 것이 원칙이라 나중에 지우기도 어렵습니다. 그래서 암호화해 적거나 바깥 보관소를 가리키는 방법을 따로 붙여야 합니다.

셋째, 파일로 적을 수 없는 상태는 이 방식 밖에 남습니다. 데이터베이스에 쌓인 데이터가 그렇습니다. 테이블 모양을 바꾸는 스키마 마이그레이션처럼 정해진 순서로 한 번만 해야 하는 일도 결과만 적는 방식에 잘 안 맞습니다.

넷째, 반영이 즉시 일어나지 않습니다. 에이전트가 다음 바퀴에 저장소를 읽을 때까지 변경은 기다립니다. 합친 뒤 반영까지 틈이 생깁니다. 그 사이에는 저장소와 시스템이 다릅니다.

그래서 GitOps 는 두 조건이 갖춰진 곳에 맞습니다. 시스템의 모습을 파일로 적을 수 있어야 합니다. 여러 사람이 같은 시스템을 고쳐야 합니다. 손 수정이 잦거나 지켜야 할 상태 대부분이 데이터인 시스템에는 덜 맞습니다.

관련 항목

GitOps 가 바탕으로 삼는 운영 원칙

코드형 인프라 · 선언적 설정 · 단일 진실 원천 · 불변 인프라 · 멱등성 · 설정 관리

GitOps 가 맞추는 두 상태와 그 어긋남

원하는 상태 · 실제 상태 · 구성 드리프트 · 드리프트 탐지 · 조정 루프

GitOps 의 변경이 거치는 개발 도구

Git · 버전관리 · 저장소 · 커밋 · 브랜치 · 풀 리퀘스트 · 코드 리뷰 · 감사 로그

GitOps 가 속하는 배포 흐름

지속적 통합 · 지속적 전달 · 지속적 배포 · 커밋에서 배포까지 · 부분 배포 · 롤백 · 자동 롤백

GitOps 를 구현한 도구와 그 발판

Argo CD · Flux · Kubernetes · 테라폼 · 컨테이너 이미지 · 에이전트

GitOps 를 굴리며 따로 챙기는 보안 대상

비밀 정보 · 자격증명 · 접근 제어 · 공급망 공격

다른 이름: 깃옵스 · Git Ops · 깃 옵스