Development··6 min read

Docker에서 K8s로 넘어가야 할 타이밍

Docker Compose로 버티다가 Kubernetes로 전환한 경험과 그 기준점에 대해 이야기한다.

새벽 2시, 잠옷 차림으로 EC2를 띄우다

이벤트 기간이었다. API 서버를 3대에서 6대로 늘려야 했는데, 수동으로 EC2 인스턴스를 만들고 docker-compose 파일을 복사해서 돌리는 짓을 했다. 새벽 2시에. 잠옷 차림으로.

솔직히 말하면, 나는 Kubernetes가 과하다고 생각하는 쪽이었다. Docker Compose 하나면 웬만한 서비스는 다 돌아간다고. 실제로 우리 팀은 API 서버 2대, Redis, PostgreSQL, Nginx를 docker-compose.yml 하나로 관리하면서 2년을 버텼다.

문제없었냐고? 문제 많았다. 근데 그게 K8s가 없어서 생긴 문제는 아니었다.

슬슬 한계가 보이기 시작한 지점

첫 번째 신호는 배포 시간이었다. 서비스가 3개에서 7개로 늘어나면서 docker-compose up -d 한 번에 5분이 넘어갔다. 특정 서비스만 재배포하고 싶은데 의존성 때문에 다른 것들도 같이 재시작됐다.

두 번째가 아까 말한 스케일링 문제. 트래픽 몰릴 때마다 수동으로 서버를 띄우는 건 사람이 할 짓이 아니다.

그래도 K8s가 아닌 경우가 많다

여기서 중요한 건, 위 상황이라고 무조건 K8s로 가야 하는 건 아니라는 거다. 서비스가 5개 이하이고, 트래픽 변동이 크지 않고, 팀에 인프라 담당자가 없다면 K8s는 오버엔지니어링이다.

ECS Fargate나 Cloud Run 같은 매니지드 컨테이너 서비스가 중간 단계로 훨씬 적합하다. 우리도 처음엔 ECS를 검토했다. 근데 이미 서비스가 7개였고, 각각 다른 스케일링 정책이 필요했고, 환경별 설정 관리가 복잡해지고 있었다.

YAML 지옥이라는 소문은 사실이었다

EKS를 선택했고, 전환에 3개월이 걸렸다. 예상보다 오래 걸린 이유는 YAML이었다. Deployment, Service, Ingress, ConfigMap, Secret... 서비스 하나당 최소 4-5개의 YAML 파일이 필요했다.

7개 서비스 곱하기 5개 파일이면 35개의 YAML이다. Helm 차트를 도입하면서 좀 나아졌지만, 학습 곡선이 가팔랐다. 팀원 4명 중 2명은 K8s를 처음 접했고, kubectl 명령어에 익숙해지는 데만 2주가 걸렸다.

(처음 한 달은 K8s를 운영하는 게 아니라 K8s와 싸우는 느낌이었다.)

전환하고 나서 확실히 달라진 것

오토스케일링. HPA 설정하니까 트래픽 피크에 자동으로 Pod가 늘어났다. 새벽 2시에 수동으로 서버 띄우던 시절은 끝났다. 솔직히 이것만으로도 전환한 보람이 있었다.

롤링 업데이트도 편해졌다. 배포 중 다운타임이 제로가 됐고, 문제가 생기면 kubectl rollback 한 줄로 이전 버전으로 돌아갈 수 있었다.

근데 운영 복잡도는 확실히 올라갔다. Pod가 CrashLoopBackOff에 빠지면 원인 추적이 Docker 시절보다 어려웠다. 로그를 보려면 어떤 Pod인지 먼저 찾아야 하고, 노드 문제인지 앱 문제인지 구분해야 한다. 네트워크 정책 때문에 서비스 간 통신이 안 되는 경우도 있었다.

내가 세운 전환 기준 세 가지

서비스가 5개 이상이다. 각 서비스의 스케일링 요구사항이 다르다. 팀에 인프라에 시간을 투자할 수 있는 사람이 최소 1명 있다.

이 중 하나라도 빠지면 K8s 대신 매니지드 서비스를 쓰는 게 낫다. 기술의 멋이 아니라 팀의 현실을 봐야 한다.

타이밍이라는 건

K8s로 전환한 건 맞는 선택이었다. 근데 6개월 더 일찍 했으면 삽질이 더 많았을 것이고, 6개월 더 늦었으면 장애가 더 났을 것이다.

Docker Compose가 버거워지는 순간, 바로 K8s로 뛰어들지 말고 중간 단계를 먼저 검토해보길. 그리고 정말 필요한 순간이 오면 두려워하지 말고 넘어가면 된다.

관련 글