스노우플레이크 서버
고친 사람 github-actions[bot]
스노우플레이크 서버는 손으로 고쳐 가며 키워서 똑같이 다시 만들 수 없게 된 서버입니다. 눈송이처럼 세상에 하나뿐인 모양이 되었다는 뜻입니다. 고칠 때마다 가장 짧은 길을 고른 결과로 생깁니다. 그 서버가 죽으면 무엇을 되살려야 하는지 아는 사람이 없습니다.
쉽고 빠른 이해
스노우플레이크 서버는 사람이 접속해서 하나씩 손본 서버입니다. 패키지를 올립니다. 설정 파일 한 줄을 고칩니다. 급할 때 임시 수정도 넣습니다. 이것들이 기록 없이 쌓입니다.
사람들이 이 길로 드는 까닭은 그게 가장 빨라서입니다. 장애가 난 밤에는 접속해서 한 줄 고치는 쪽이 코드를 고쳐 다시 배포하는 쪽보다 훨씬 짧습니다.
어떻게 이렇게 되나:
- 처음에는 절차대로 만든 평범한 서버입니다
- 몇 달 동안 여러 사람이 손으로 고친 것이 쌓입니다
- 결국 지금 모습을 적은 곳이 없습니다. 같은 서버를 하나 더 만들 수 없습니다
대가는 그 서버를 건드리기가 무서워진다는 점입니다. 옮기지도, 늘리지도, 업그레이드하지도 못합니다.
벗어나는 길은 서버의 모습을 코드로 적는 것입니다. 사람이 읽는 절차서와 달리 코드는 도구가 읽어 서버를 만듭니다. 그래서 고칠 일이 생기면 코드를 고칩니다. 그 코드로 서버를 다시 만듭니다.
상세
이 절은 한 회사의 결제 서버 한 대가 스노우플레이크가 되는 과정을 따라갑니다. 왜 이 길로 들어서는지, 어디서 값을 치르는지, 어떻게 벗어나는지가 차례로 나옵니다. 끝으로 이름이 비슷한 이웃을 가릅니다.
오래된 집의 수리 흔적
오래된 집에는 집주인만 아는 수리 흔적이 있습니다. 물이 새던 벽에 덧댄 판자, 전구가 자꾸 나가서 따로 끌어온 전선 같은 것입니다. 집주인이 살아 있는 동안에는 아무 문제가 없습니다.
집을 똑같이 한 채 더 지으려 하면 사정이 달라집니다. 처음 설계도에는 그 판자와 전선이 없습니다. 설계도대로 지은 새 집은 옛 집과 다른 집이 됩니다.
다시 만들 수 없는 서버
서버는 운영체제 위에 여러 겹이 얹혀 돕니다. 설치한 패키지와 그 판, 설정 파일, 환경 변수, 예약 작업, 방화벽 규칙 같은 것입니다. 이 전부를 합친 것을 서버의 구성이라고 부릅니다.
스노우플레이크 서버는 지금의 구성을 적은 곳이 서버 밖에 없는 서버입니다. 처음 만들 때 따른 절차서가 있더라도, 그 뒤에 바꾼 것은 거기 없습니다. 사람이 SSH(Secure Shell, 원격 접속 프로토콜)로 들어가 명령을 치며 바꾼 것이 서버 안에만 남습니다. 그래서 지금 서버가 곧 유일한 원본입니다.
이름은 눈송이에서 왔습니다. 눈송이는 결정 모양이 하나도 같지 않다고들 합니다. 서버도 손을 탈수록 저마다 다른 모양이 됩니다. 같은 역할을 하는 서버 세 대가 있어도 세 대가 조금씩 다릅니다.
결제 서버 한 대가 자라는 과정
결제 서버는 처음에 절차서대로 만든 평범한 서버였습니다. 절차서는 무엇을 설치하고 어떤 값을 두는지 사람이 읽고 따라 치도록 적은 문서입니다. 아래 그림은 그 뒤 반년 동안 절차서와 실제 서버가 어떻게 벌어지는지를 나란히 놓습니다.
flowchart TD
subgraph doc["절차서"]
P["처음 모습 그대로 · 한 번도 안 고침"]
end
subgraph real["실제 서버"]
A["절차서대로 만든 서버"] --> B["장애 난 밤 · 데이터베이스 연결 수 상한을 손으로 고침"]
B --> C["보안 공지 · OpenSSL 만 업그레이드"]
C --> D["느려짐 · 열 수 있는 파일 수 상한을 손으로 바꿈"]
D --> E["담당자가 팀을 옮김"]
E --> F["아무도 전부를 모르는 서버"]
end
P -- "이대로 만듦" --> A
P -. "점점 벌어짐" .- F
실제 서버 쪽 칸마다 누군가 서버에 들어가 손으로 한 가지를 바꿨습니다. 데이터베이스 연결 수 상한, 암호화 라이브러리 OpenSSL의 버전, 운영체제 커널이 한 프로그램에 허락하는 열린 파일 수 상한이 그렇게 바뀌었습니다. 바꾼 사람은 그때 이유를 알았습니다.
절차서 쪽은 한 번도 고쳐지지 않았습니다. 오래된 집의 설계도에 덧댄 판자가 없는 것과 같습니다. 마지막 칸에 이르면 절차서로 서버를 새로 만들어도 지금 서버와 같아지지 않습니다.
서버의 실제 구성이 적어 둔 구성에서 이렇게 멀어지는 일을 구성 드리프트라고 합니다. 스노우플레이크 서버는 드리프트가 오래 쌓인 끝에 남는 서버입니다.
끌리는 이유
처음부터 스노우플레이크를 만들려는 사람은 없습니다. 고칠 때마다 그 순간 가장 짧은 길을 골랐을 뿐입니다.
장애가 난 밤을 떠올려 봅니다. 원인은 데이터베이스 연결 수 상한 값 하나입니다. 서버에 접속해 값을 고치고 서비스를 다시 띄우면 몇 분 안에 끝납니다. 코드를 고쳐 검토받고 배포하는 길은 한 시간이 넘게 걸립니다. 손님이 기다리는 중이라면 앞쪽을 고르는 것이 자연스럽습니다.
평소에도 비슷합니다. 서버가 한두 대뿐이면 자동화 도구를 익히는 것보다 손으로 하는 쪽이 빠릅니다. 서버에 직접 들어가 고치면 무엇을 했는지 바로 눈에 보입니다. 그래서 안심도 됩니다.
문제는 그 뒤입니다. 급한 불을 끈 뒤 같은 수정을 코드나 절차서에 옮겨 적는 일은 자주 잊힙니다.
한 대뿐인 원본이 치르는 값
결제 서버가 스노우플레이크가 된 뒤에는 곤란한 일이 넷 생깁니다. 넷 모두 「지금 서버가 유일한 원본이다」에서 나옵니다.
첫째, 서버가 죽으면 되살리기 어렵습니다. 디스크가 망가지면 새 서버를 만들어야 합니다. 그런데 무엇을 설치하고 무엇을 고쳐야 하는지 적힌 곳이 없습니다. 옛 서버의 기억을 더듬어 다시 맞추는 동안 서비스가 멈춥니다.
둘째, 대수를 늘리기 어렵습니다. 손님이 늘어 결제 서버를 두 대로 늘리려 해도 첫 대와 같은 서버를 만들 수 없습니다. 새로 만든 둘째 대는 어딘가 다릅니다. 그 차이 때문에 요청이 어느 서버로 가느냐에 따라 결과가 갈릴 수 있습니다.
셋째, 시험한 것과 운영하는 것이 달라집니다. 시험 서버와 운영 서버가 손으로 따로 고쳐졌다면 둘은 이미 다른 서버입니다. 시험 서버에서 통과한 변경이 운영 서버에서 깨질 수 있습니다. 운영에서 난 장애를 시험 서버에서 재현하기도 어렵습니다.
넷째, 바꾸기가 무서워집니다. 누가 왜 넣었는지 모르는 설정이 쌓이면 어느 것을 건드려도 무슨 일이 날지 모릅니다. 패키지 하나를 업그레이드했는데 전혀 다른 기능이 깨지는 일이 생깁니다. 그래서 사람들은 업그레이드를 미룹니다. 그 사이 서버는 더 낡아 갑니다.
알아보는 신호
스노우플레이크는 조금씩 자라서 언제 선을 넘었는지 알기 어렵습니다. 대신 겉으로 드러나는 조짐이 있습니다.
| 신호 | 무엇을 보나 |
|---|---|
| 담당자 | 「그 서버는 누구만 안다」는 말이 나오나 |
| 다시 만들기 | 절차서나 코드만으로 같은 서버를 지금 만들 수 있나 |
| 접속 기록 | 사람이 서버에 들어가 명령을 치는 일이 잦나 |
| 이름 | 역할 대신 고유한 별명으로 부르나. 별명이 붙은 서버는 버리고 새로 만들기보다 아껴 가며 고쳐 쓰게 됩니다 |
| 업그레이드 | 「건드리면 깨질까 봐」 미뤄 둔 업그레이드가 있나 |
표에서 가장 믿을 만한 것은 다시 만들기입니다. 서버 한 대를 지우고 적어 둔 것만으로 똑같이 만들어 보면 답이 나옵니다. 못 만들면 그 서버는 이미 스노우플레이크입니다.
벗어나는 방법
결제 서버를 다시 만들 수 있는 서버로 돌려놓으려면 기준이 필요합니다. 서버의 구성이 서버 밖에 적혀 있어야 합니다. 그리고 그 적힌 것이 곧 서버를 만드는 재료여야 합니다.
뒤쪽 조건이 중요합니다. 결제 서버에도 절차서는 있었습니다. 그런데 절차서는 사람이 읽고 손으로 따라 치는 문서입니다. 서버를 손으로 고쳐도 절차서는 바뀌지 않습니다. 둘이 어긋났다고 알려 주는 것도 없습니다. 절차서를 따라 칠 때 한 줄을 건너뛰어도 아무도 모릅니다.
코드로 적으면 사정이 달라집니다. 도구가 그 코드를 읽어 서버를 만들고 바꿉니다. 코드에 없는 변경은 서버에 들어갈 길이 없습니다. 도구를 다시 돌리면 서버가 코드에 적힌 모습으로 돌아가므로, 누가 몰래 바꾼 값도 드러나거나 지워집니다. 적은 것과 실제 서버가 벌어질 틈을 도구가 좁혀 주는 셈입니다.
첫걸음은 구성을 코드로 적는 것입니다. 서버에 무엇을 설치하고 어떤 설정을 두는지를 파일로 적고 버전 관리에 넣습니다. 이렇게 인프라를 코드로 다루는 방식을 코드형 인프라라고 합니다.
그 코드를 읽어 여러 서버에 같은 설정을 적용하는 도구를 설정 관리 도구라고 부릅니다. 앤서블과 퍼펫이 그런 도구입니다.
다음은 손으로 고치는 길을 좁히는 것입니다. 급한 수정도 코드에 먼저 적습니다. 서버에 반영하는 일은 도구에 맡깁니다. 운영 서버에 사람이 접속하는 일을 아예 막는 팀도 있습니다.
더 나아가면 서버를 고치지 않고 새로 만들어 갈아 끼웁니다. 바꿀 일이 생기면 코드를 고쳐 새 서버를 띄우고 옛 서버를 버립니다. 한번 띄운 서버는 손대지 않는다는 이 운영 방식을 불변 인프라라고 합니다.
이렇게 운영하면 서버 한 대 한 대가 언제든 버려도 되는 물건이 됩니다. 버려도 코드에서 똑같이 다시 태어나는 서버를 피닉스 서버라고 부릅니다.
flowchart TD
subgraph before["스노우플레이크"]
A["사람"] --> B["서버에 접속해 고침"]
B --> C["서버 안에만 남음"]
end
subgraph after["다시 만들 수 있는 서버"]
D["사람"] --> E["코드를 고침"]
E --> F["버전 관리에 남음"]
F --> G["도구가 서버를 만들거나 바꿈"]
end
그림의 두 묶음이 다른 점은 고친 내용이 어디에 남느냐입니다. 「스노우플레이크」 묶음에서는 서버 안에만 남아서 서버가 사라지면 같이 사라집니다. 「다시 만들 수 있는 서버」 묶음에서는 버전 관리에 남아서 서버가 몇 번 사라져도 같은 서버를 다시 만들 수 있습니다.
손으로 만져도 되는 때
모든 손작업이 스노우플레이크를 낳는 것은 아닙니다. 값을 덜 치르는 경우가 둘 있습니다.
첫째는 한 번 쓰고 버릴 서버입니다. 무언가를 시험해 보려고 잠깐 띄운 서버라면 다시 만들 일이 없습니다. 오래 쓸 서버가 되는 순간부터 앞의 값을 치르기 시작합니다.
둘째는 장애 중의 응급 조치입니다. 손으로 먼저 고쳐 불을 끄는 것은 흔한 일입니다. 다만 같은 수정을 곧바로 코드에 옮겨 적고 서버를 코드 기준으로 다시 맞춰야 스노우플레이크가 되지 않습니다.
이름이 비슷한 이웃
「서버가 적어 둔 모습과 다르다」를 둘러싼 이름은 여럿입니다. 무엇을 가리키는지가 저마다 다릅니다.
| 이름 | 무엇을 가리키나 | 스노우플레이크 서버와 다른 점 |
|---|---|---|
| 구성 드리프트 | 실제 구성이 적어 둔 구성에서 멀어지는 일 | 과정입니다. 스노우플레이크는 그 과정이 쌓여 남은 서버입니다 |
| 펫과 가축 | 서버를 이름 붙여 돌보는 대상으로 보느냐, 번호로 갈아 끼우는 대상으로 보느냐 | 운영 태도를 가르는 비유입니다. 펫처럼 돌본 서버가 스노우플레이크가 되기 쉽습니다 |
| 피닉스 서버 | 언제든 지우고 새로 만들 수 있는 서버 | 스노우플레이크의 반대편입니다 |
| 스노우플레이크 | 여러 서버가 겹치지 않는 번호를 각자 만드는 방식 | 이름만 같고 전혀 다른 것입니다 |
관련 항목
스노우플레이크 서버를 낳는 과정과 습관
구성 드리프트 · 수동 배포 · 핫픽스 · SSH · 설정 파일 · 기술 부채
스노우플레이크 서버가 무너뜨리는 성질
재현성 · 일관성 · 가용성 · 확장성 · 재해 복구 · 환경 일치
스노우플레이크 서버를 막는 운영 방식
코드형 인프라 · 불변 인프라 · 피닉스 서버 · 설정 관리 · 프로비저닝 · GitOps · 버전 관리
스노우플레이크 서버를 막는 도구
테라폼 · 앤서블 · 퍼펫 · Chef · 솔트 · Packer · 머신 이미지 · 컨테이너 이미지
스노우플레이크 서버와 맞세워지는 대립 개념
스노우플레이크 서버가 속하는 상위 분류
안티패턴 · 인프라 · 데브옵스 · 시스템 관리 · 서버
스노우플레이크 서버와 이름이 겹치는 이웃
스노우플레이크 · 눈송이 스키마 · Snowflake (데이터 웨어하우스)
다른 이름: snowflake server · 스노플레이크 서버 · 눈송이 서버