배포에서 중요한 것
유저에게 배포가 나갔는지도 모르게 하는 것
규모가 작거나 복잡하지 않은 환경에서는 배포에 대해 크게 신경 쓸 필요가 없습니다. 오히려 그 시간에 MAU를 늘릴 생각을 하는게 더 이득일 지도 모릅니다. 하지만 시스템의 구성요소가 많고 (카프카, 배치 등) 잠깐의 중단도 비즈니스에 악영향을 주는 환경에서는 배포 자체에 많은 리소스를 쓰게 됩니다.
🐜 무중단
불과 몇 년 전만 해도 새벽 시간에 점검을 한다고 하고 배포하는 일도 흔했습니다. 하지만 최근에는 어떤 서비스를 쓰든 배포를 한다고 점검을 걸고 서비스를 중단하는 일이 매우 적어졌습니다. 배포의 중요한 소양이 무중단이기 때문입니다. 말 그대로 서비스를 1초도 중단하지 않고 새로운 버전을 내야 합니다.
🐜 쉬운 롤백
이상적으로는 모든 배포는 테스트가 완벽하게 돼, 장애가 없어야 하지만... 현실은 그렇지 않습니다. 테스트가 부족한 경우도 있고, 대규모 트래픽이 들어와야만 알 수 있는 장애도 있습니다. (하지만 현업에서는 사실 테스트가 부족해서 그런 경우가 압도적이긴 합니다. 🥹) 이런 경우 최대한 빨리 이전 버전으로 돌아가 장애를 겪는 유저를 최소화 해야 합니다. 이건 인프라적인 것 뿐만 아니라 애플리케이션 코드도 롤백을 고려해 짜야 합니다. 캐시키 (Cache Key)에 버저닝 (Versioning)을 안 해서 새 버전과 구 버전이 호환이 안 된다던가 등의 일이 없아야 합니다.
블루그린 (Blue-Green Deployment)
블루그린에서는 새로운 버전을 운영 환경에서 띄웁니다. 여기서 필요하다면 추가적으로 테스트를 진행하고 기존 버전 트래픽을 한 번에 새로운 버전 트래픽으로 전환하는 상개발자식 배포 방식입니다.
🐜 장점으로는,
- 롤백이 간단합니다. 다시 기존 버전으로 트래픽을 돌리면 그만...
- 환경을 완전히 분리 돼 영향이 적습니다. (환경이 분리 안 된 경우가 있음?! 하신다면 밑에 카나리라는 친구는 안 됨!)
🐜 단점으로는,
- 일시적으로 인스턴스를 2배로 늘려야 합니다.
- 배포 전에 실제 트래픽에서 테스트를 해 보지는 못 합니다.
카나리 배포 (Canary Deployment)
카나리에서는 블루 그린과는 달리 트래픽을 한 번에 전환하는게 아니라 조금씩 점진적으로 전환합니다. 같은 환경에서 일부 트래픽을 조금씩 새 버전으로 바꿔서 새 버전에서 혹시 오류가 더 올라오지는 않는지, 성능 문제가 있지는 않은지 모티터링하다 에러 로그가 갑자기 많이 올라오면 롤백 하는 식입니다.
🐜 장점으로는,
- 실제 트래픽으로 테스트 / 모니터링을 할 수 있습니다!
- 저 블루그린 친구처럼 무식하게 인스턴스 2배로 안 늘려도 됨!
🐜 단점으로는,
- 롤백이 블루그린만큼 단순하지 않습니다.
- 같은 환경을 쓰기 때문에 여러 오류가 날 수 있습니다.
롤링 배포 (Rolling Deployment)?
카나리와 비슷하게 롤링 배포라는 친구도 있는데요. 이 친구와 카나리의 차이가 사실 좀 애매합니다.
- 롤링 배포는 점진적 배포를 진행할 때 인스턴스를 배치 단위로 나눠서 1개씩 새 버전으로 대체하는 점직적 배포의 구체적인 방법론에 가까운 친구이고,
- 카나리 배포는 운영 트래픽의 일부를 새 버전에 보내 테스트와 모니터링을 하고 문제가 있으면 빨리 롤백해서 배포를 좀 더 쉽게 하자는 철학(?)에 더 가까운 친구입니다.
카나리 + 블루그린 (Cancary + Blue Green)
카나리와 블루그린은 장단점이 확실하지만, 다행히 서로 Mutually Exclusive한 개념은 아닙니다!
- 블루그린 하듯이 인스턴스를 2배로 띄우지만
- 트래픽 전환은 점진적으로 해 카나리 배포하면
카나리와 블루그린의 장점을 모두 누릴 수 있습니다. 왜냐하면...
- 일부의 트래픽을 새 버전으로 보내면서~ 🍻
- 롤백할 때는 기존 버전이 다 살아 있기 때문에 "딸깍"하면 그만~
하지만 일부 단점도 공유하게 되는데요 🥹 인스턴스가 2배가 된다는 것 입니다. 그래서 카나리 + 블루그린의 조합에서는 보통 카나리를 진행하고 모니터링을 하다가 문제가 없다고 판명되면 블루그린을 트리거 해 기존 버전의 인스턴스를 없앱니다. (블루그린이 트리거 되면 이제 롤백이 기존 만큼 쉽지 않게 됩니다.)
착한 개발자라면 블루그린 + 카나리 환경에서는 중요도에 따라 모니터링을 진행하다 적절한 시점에 블루그린을 트리거 해 회사의 자원을 아껴야겠쬬?
그림자 배포 (Shadow Deployment)
오류가 너무 치명적이거나 코어 로직에 변화가 너무 많아서 오랜 시간 검증하고 싶은 경우 드물게 쓰는 방법이 그림자 배포입니다. 마치 그림자처럼 모든 트래픽은 기존 버전과 새로운 버전에 2번 갑니다. 즉, 서버에 HTTP 요청을 날리면 기존 버전과 새 버전이 모두 처리합니다.
당연히 DB에 데이터가 2번 쌓이거나 유저에게 응답이 2번 가지는 않습니다. 😅 새로운 버전은 DB나 유저에게 영향을 주는 코드는 모두 제거하고, 처리 결과만 로그에 남기거나 하는 식으로 기록하고, 이 처리 결과를 오랜 기간에 걸쳐서 기존 버전과 비교하는 방식입니다.
이렇게 말하면 단순해 보이지만 고려해야 할 것들이 매우 많습니다.
- 이렇게 하면 트래픽이 2배가 된다는 건데 피크 트래픽 때는 어떻게 해?
- 비교를 로그만 찍으면 수기로 해야 할 거 같은데 자동화를 어떻게 해?
- 멱등하지 않은 경우는 어떻게 처리해?
- 실수로 DB 등에 변화를 줄 수 있을 거 같은데 시스템적으로 못 막아?
이거 관련해서 스프링 캠프에서 들은 좋은 발표가 있어 살포시 추천하고 가겠습니다. 카카오뱅크에서 실제 그림자 배포 전략을 사용해 차세대를 한 얘기인데, 여러 재밌는 포인트가 많습니다.
🤔 생각해 볼 만한 것 - 롤백 가능하게 하기
카나리 배포 전략을 사용한다는건 언제든 롤백을 할 수 있다는 뜻입니다. 테스트가 부족하든 실제 트래픽을 받아야 알 수 있는 성능 관련 문제이든 장애가 나면 최대한 빨리 롤백해 장애를 겪는 유저를 최대한 적게 하는 것, 이게 카나리 배포의 핵심입니다.
하지만 이때 트래픽을 돌리는 것 만으로 롤백이 가능하게 해야 합니다. 예를들어 DB의 Column의 이름을 변경한다면...
- 기존 Column을 건들이지 않고 바꾸고 싶은 이름으로 Column을 새로 만듬
- 기존 Column과 새로운 Column에 모두 데이터를 넣는 버전을 배포함
- DDL로 새로운 Column에 기존 Column의 데이터 넣음
- 새로운 Column만 보는 버전 배포
- DB에서 기존 Column 지우기
하는 식으로 모든 단계에서 롤백이 될 수 있도록 신경써야 합니다.
무중단, 카나리 배포 환경에서 DB Schema 수정하기
문제 상황자주 있는 상황은 아니지만 DB의 Column을 수정해야 할 일이 있습니다.굳이 왜 수정해야 하나? 어차피 이름만 다른거 아니야? 하실 수 있지만 이름과 사용 용도가 다르면 장기적으로는 인
jinkpark.tistory.com
🤔 생각해 볼 만한 것 - 기능 제거하는데 이미 나갔다면 유지하기
기존 버전에 있는 기능을 제거해야 하는데 하위 호환성이나 비즈니스 로직상 기존 버전에서 이미 수행된 작업은 유지해야 할 수도 있습니다.
예를들어 제가 한 작업중에 여러 이유로 가상번호를 제거해야 하는 경우가 있었는데요. 가상번호란 진짜 핸드폰 번호가 아닌 050으로 시작하는 1회성 번호입니다. 이 번호를 제공하면 내 진짜 번호를 노출하지 않고 내 전화번호를 제공할 수 있습니다. 아무튼, 기존 버전에서는 가상번호를 사용하는데 새 버전에서는 사용하면 안 됩니다. 그런데 이미 가상번호로 전화번호가 제공됐다면 그건 유지해야 합니다. 이 경우 어떻게 할 수 있을까요?
여기서 최종 목표가 기능 제거라 해서 바로 제거하면 안 됩니다.
- 기존 기능의 하위 호환성을 위해 이미 가상번호가 나갔다면 가상 번호를 받거나 주도록 하고, 새로 온 고객에게만 가상번호를 사용하지 않게 하는 중간 버전을 일단 배포하고
- 시간이 충분히 지나 더 이상 가상 번호가 없는지 로그로 확인한 후에
- 가상번호 관련 코드를 아예 제거한 버전을 배포해야 합니다.
🤔 생각해 볼 만한 것 - 메세징 처리하기 (Producer, Consumer)
트래픽이 어느 정도 있는 서비스는 메세징 시스템 (Kafka, Rabbit MQ 등)을 쓰는 경우가 많은데, 이 경우 카나리/블루그린/그림자 배포에서 어떻게 처리해야 할까요?
메세징이 들어가니 훨씬 복잡해 질 거 같지만, 원리는 똑같습니다.
- 롤백 가능하게 하기
- 버저닝 (Versioning) 하기
- 멱등성 갖추기
기존 버전의 메세지와 신버전의 메세지를 각각 신버전과 기존 버전에서도 문제 없이 처리할 수 있게 처리하고, 여러번 컨슘해도 문제가 없도록 컨슈머를 멱등하게 하고, 필요하다면 새 버전을 위한 컨슈머 그룹을 만들거나 등의 전략을 구사하면 됩니다.
메세지는 어떤 상황인지에 따라 뭐를 해야 하는지가 다양할 수 있지만 기본적인 원칙을 기억하고 여러 하위 호환성을 지키기 위한 전략을 구가하면 문제 없이 배포하실 수 있습니다! 👍 (예를 들어, 특정 정보를 추가해 Produce하고 그 정보가 있으면 Consume할 때 특정 동작을 더 해야하는 상황은 중요 정보 통지를 정확히 1번만 해야 하는 상황이랑 필요한게 매우 다릅니다.)
'👨💻 프로그래밍 > ⚙️ DevOps' 카테고리의 다른 글
☁️ AWS에서 무중단 배포 구현하기 (0) | 2024.11.22 |
---|---|
ES, Kibana, Grafana, Prometheus, Thanos, Logstash 사이의 관계 이해하기 (0) | 2024.02.27 |
Logback 간단하게 알아보기 (0) | 2023.10.01 |
Git 파일의 Life Cycle 이해하기 (0) | 2023.06.29 |
쿠버네티스가 뭘까? 작동원리, 아키텍처 정리! (0) | 2023.04.02 |