구성 드리프트
고친 사람 github-actions[bot]
구성 드리프트는 서버의 실제 설정이 적어 둔 설정과 조금씩 어긋나는 일입니다. 누군가 손으로 고친 한 줄이 기록 없이 남는 데서 시작됩니다. 같아야 할 서버끼리도 서로 달라집니다. 대개 서버를 새로 만들거나 설정을 다시 적용할 때에야 드러납니다.
쉽고 빠른 이해
구성 드리프트는 서버의 실제 설정이 파일에 적어 둔 설정과 달라져 가는 일입니다. 장애가 난 밤에 서버 한 대에 들어가 타임아웃을 30초에서 60초로 늘렸다고 해 봅시다. 설정을 적어 둔 파일에는 여전히 30초가 남아 있습니다.
이런 어긋남에 이름까지 붙은 까닭은 아무 오류도 내지 않기 때문입니다. 서버는 멀쩡히 돕니다. 파일을 읽는 사람은 그 파일이 지금 서버의 모습이라고 믿습니다.
어떻게 쌓이나:
- 파일대로 서버를 만듭니다. 이때는 둘이 같습니다
- 급한 일로 파일을 거치지 않고 서버를 고칩니다
- 고친 내용을 파일에 다시 적지 않습니다. 이런 일이 몇 달 쌓입니다
대가는 나중에 치릅니다. 파일대로 설정을 다시 적용하면 고친 것이 사라집니다. 서버를 몇 대 늘리면 새 서버에서만 장애가 나기도 합니다.
상세
먼저 구성 드리프트가 무엇과 무엇 사이의 어긋남인지 정합니다. 이어서 타임아웃 값 하나가 어긋나는 이야기를 따라갑니다. 어긋남이 어디서 생기고 무엇을 망가뜨리는지 봅니다.
원하는 상태와 실제 상태
서버가 갖춰야 할 모습을 파일에 적어 두는 팀이 많습니다. 깔려 있어야 할 프로그램, 설정 값, 열어 둘 포트 같은 것을 적습니다. 이렇게 적어 둔 모습을 원하는 상태라 합니다.
원하는 상태를 적은 파일을 선언형 설정 파일이라 합니다. 할 일의 순서가 아니라 결과를 적기 때문에 선언형이라는 이름이 붙었습니다.
선언형 설정 파일은 보통 Git 같은 버전관리 도구에 넣어 둡니다. 그러면 누가 언제 무엇을 바꿨는지가 남습니다. 서버 설정을 이렇게 코드처럼 다루는 방식이 코드형 인프라입니다.
이 파일을 서버에 적용하는 프로그램이 있습니다. 파일을 읽고 서버를 둘러본 뒤 다른 곳만 파일대로 고칩니다. 이런 도구로 서버를 맞추는 일을 설정 관리라 합니다. 그 도구는 설정 관리 도구라 부릅니다.
파일에 적힌 모습과 별개로, 서버가 지금 돌고 있는 모습을 실제 상태라 합니다. 도구가 서버를 파일대로 막 맞춘 직후에는 두 상태가 같습니다.
구성 드리프트는 실제 상태가 원하는 상태에서 벌어지는 일입니다. 드리프트(drift)는 물결에 떠밀려 조금씩 흘러간다는 뜻입니다. 큰 변경 한 번이 아니라 작은 변경이 쌓여 멀어진다는 데서 온 이름입니다. 설정 드리프트라고도 부릅니다.
견주는 기준이 파일 하나만은 아닙니다. 같은 역할로 나란히 도는 서버들이 서로 달라지는 것도 드리프트라 부릅니다. 아래 표는 같아야 할 서버 세 대를 선언형 설정 파일과 견준 모습입니다.
| 설정 | 파일 | 서버 A | 서버 B | 서버 C |
|---|---|---|---|---|
| 요청 타임아웃 | 30초 | 30초 | 60초 | 30초 |
| 로그 수준 | 경고 | 경고 | 경고 | 디버그 |
| 8080 포트 | 닫힘 | 닫힘 | 닫힘 | 열림 |
| 압축 라이브러리 판 | 1.2 | 1.2 | 1.3 | 1.2 |
굵게 칠한 칸이 드리프트입니다. 서버 B 는 파일과도 다르고 서버 A 와도 다릅니다. 표의 네 칸 중 어느 것도 서버를 멈추게 하지는 않습니다.
장애 난 밤에 고친 한 줄
위 표의 타임아웃 칸 하나를 따라가 봅니다.
밤에 서버 B 에서 요청이 자꾸 끊깁니다. 당번 개발자가 서버에 원격으로 들어가 타임아웃을 30초에서 60초로 늘립니다. 끊김이 멈춥니다. 급한 불을 껐으니 다들 자러 갑니다.
이 변경은 선언형 설정 파일을 거치지 않았습니다. 파일에는 여전히 30초가 적혀 있습니다. 이 순간부터 서버 B 의 실제 상태가 원하는 상태와 다릅니다.
다음 날 누군가 설정 관리 도구를 다시 돌립니다. 도구는 파일과 서버를 견주고 60초를 30초로 되돌립니다. 도구 쪽에서 보면 어긋난 것을 바로잡았을 뿐입니다. 밤사이 고친 것이 사라집니다. 끊김이 다시 시작됩니다.
sequenceDiagram
participant 개발자
participant 도구 as 설정 관리 도구
participant 서버 as 서버 B
도구->>서버: 파일대로 타임아웃 30초
Note over 도구,서버: 두 상태가 같다
Note over 서버: 밤에 요청이 끊긴다
개발자->>서버: 손으로 60초로 바꾼다
Note over 도구: 파일에는 여전히 30초
도구->>서버: 다음 적용 때 30초로 되돌린다
Note over 서버: 끊김이 다시 난다
도구를 다시 돌리지 않는 팀에서는 반대 일이 생깁니다. 서버를 한 대 더 늘리면 새 서버는 파일대로 30초로 만들어집니다. 그러면 새 서버에서만 요청이 끊깁니다. 서버 B 와 무엇이 다른지는 아무도 기억하지 못합니다.
드리프트가 생기는 조건
위 이야기에서 어긋남을 만든 것은 손으로 친 명령 하나였습니다. 다른 길로도 같은 일이 생깁니다.
드리프트는 두 조건이 겹칠 때 생깁니다. 서버의 실제 상태가 선언형 설정 파일과 달라집니다. 그 차이가 파일에 남지 않습니다. 차이를 만든 것이 사람이든 프로그램이든 같습니다.
| 차이가 생긴 길 | 예 |
|---|---|
| 손으로 고침 | 장애 중 서버에 들어가 설정 값을 바꾼다 |
| 관리 화면에서 고침 | 클라우드 관리 화면에서 방화벽 규칙을 하나 연다 |
| 일부 서버에만 적용됨 | 배포가 중간에 끊겨 열 대 중 일곱 대만 새 설정을 받는다 |
| 자동 갱신 | 운영체제가 밤사이 보안 패치를 깔아 라이브러리 판이 서버마다 달라진다 |
| 프로그램이 스스로 씀 | 애플리케이션이 실행 중에 자기 설정 파일을 고친다 |
표의 길은 대부분 파일은 두고 서버만 바꿉니다. 일부 서버에만 적용된 경우는 방향이 반대입니다. 파일은 바뀌었는데 서버 일부가 따라가지 못합니다. 어느 쪽이든 파일만 읽어서는 차이가 보이지 않습니다.
드리프트가 늦게 드러나는 까닭
드리프트는 생기는 순간 아무 오류도 내지 않습니다. 서버 B 는 60초 타임아웃으로 오히려 더 잘 돕니다. 경보도 울리지 않습니다.
드러나는 때는 대개 서버를 새로 만들거나 설정을 다시 적용할 때입니다. 그때 나는 장애는 방금 한 일과 상관없어 보입니다. 원인은 몇 주나 몇 달 전에 들어간 변경입니다.
진단도 어려워집니다. 장애를 쫓는 사람은 선언형 설정 파일을 읽고 서버가 그렇게 생겼다고 믿습니다. 파일과 서버가 다르면 엉뚱한 곳을 뒤지게 됩니다.
드리프트가 보안 구멍이 되기도 합니다. 점검하려고 잠깐 연 포트가 닫히지 않고 남는 식입니다. 선언형 설정 파일만 검토하는 점검에서는 이 포트가 보이지 않습니다.
드리프트가 오래 쌓인 서버를 눈송이 서버라 부릅니다. 눈송이처럼 한 대 한 대가 다 다르다는 뜻입니다. 이런 서버는 망가지면 똑같이 다시 세우기 어렵습니다. 무엇이 들어 있었는지가 파일 어디에도 없기 때문입니다.
서버 밖의 설정
드리프트는 서버 안의 설정 파일에서만 생기지 않습니다. 관리 화면이나 명령으로 곧바로 바꿀 수 있는 설정이면 어디서든 생깁니다.
다른 프로그램이 서비스를 부를 때 쓰는 인터페이스를 API(Application Programming Interface, 응용 프로그램 인터페이스)라 합니다. API 게이트웨이는 바깥에서 들어오는 API 호출을 먼저 받아 뒤의 여러 서비스로 나눠 주는 관문입니다.
게이트웨이의 설정은 어느 주소를 어느 서비스로 보낼지 정한 라우팅 규칙입니다. 관리 화면에서 규칙 하나를 급히 고치고 파일에 안 남기면 드리프트입니다.
서비스 메시도 같습니다. 서비스끼리 주고받는 호출을 각 서비스 옆에 붙은 프록시가 대신 전달하는 구조입니다. 새 설정이 수십 개 프록시 중 일부에 닿지 못하면, 그 프록시만 옛 설정을 가지고 있게 됩니다. 그러면 같은 호출이 어느 프록시를 지나느냐에 따라 다르게 처리됩니다.
클라우드의 자원도 마찬가지입니다. 방화벽 규칙, 저장소 권한, 서버 크기를 관리 화면에서 바꾸면 선언형 설정 파일과 벌어집니다.
드리프트를 찾고 막는 방법
찾고 막는 방법마다 따로 항목이 있습니다. 아래 표는 이름과 하는 일만 모읍니다.
| 방법 | 하는 일 |
|---|---|
| 드리프트 탐지 | 실제 상태를 읽어 선언형 설정 파일과 견주고 다른 곳을 알린다 |
| 주기적 재적용 | 선언형 설정 파일을 정해진 간격으로 다시 적용해 어긋난 것을 되돌린다 |
| 조정 루프 | 원하는 상태와 실제 상태를 쉬지 않고 견주며 차이를 줄인다 |
| GitOps | 저장소의 파일이 바뀔 때만 서버가 바뀌게 한다 |
| 불변 인프라 | 서버를 고치지 않는다. 바꿀 일이 생기면 새로 만들어 갈아 끼운다 |
| 직접 접속 제한 | 운영 서버에 사람이 들어가 고치는 길을 막는다 |
앞의 셋은 이미 생긴 드리프트를 찾거나 되돌립니다. 뒤의 셋은 선언형 설정 파일을 거치지 않는 변경이 애초에 들어오지 못하게 합니다.
되돌리기만 하면 앞의 타임아웃 이야기처럼 급히 고친 것이 사라집니다. 급한 변경이 선언형 설정 파일에 다시 적힐 때 비로소 그 드리프트가 닫힙니다.
관련 항목
구성 드리프트를 가르는 두 상태와 기준
원하는 상태 · 실제 상태 · 선언적 설정 · 단일 진실 공급원 · 코드형 인프라
구성 드리프트를 찾거나 막는 방법
드리프트 탐지 · 조정 루프 · GitOps · 불변 인프라 · 설정 관리 · 멱등성 · 버전관리
구성 드리프트가 쌓여 생기는 장애
눈송이 서버 · 설정 오류 · 보안 설정 오류 · 부분 배포
구성 드리프트가 일어나는 설정 대상
서버 · 패키지 · 설정 파일 · API 게이트웨이 · 서비스 메시 · 방화벽 · 클라우드
구성 드리프트를 다루는 상위 분야
이름만 같은 다른 드리프트
데이터 드리프트 · 개념 드리프트 · 스키마 드리프트 · 클럭 드리프트
다른 이름: configuration drift · 설정 드리프트 · 구성 표류 · 인프라 드리프트