Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

[Book] Release의 모든 것 - 대규모 웹 분산 시스템을 위한 운영 고려 설계

이 책은 2007년에 번역판이 나왔던 "릴리스 잇"의 2판이고 책 얘기는 종종 듣기는 했지만 1판을 읽지 않았다가 2판이 나와서 2판을 읽었다. 어떤 면에서는 원서의 제목보다 번역서의 제목이 내용을 잘 담고 있다는 느낌이 드는데 소프트웨어를 운영 환경에 배포한 뒤에 고려해야 할 모든 상황에 관해서 설명하는 책이라고 할 수 있다.

1부 안정성 구축

프로젝트 팀은 너무나 자주 운영 상황에서 발생할 문제에 대비하는 대신 QA 부서의 테스트를 통과하는 것을 목표로 삼는다. 다시 말해, 우리의 작업은 대부분 테스트를 통과하는 것에 초점이 맞추어져 있다. 하지만 (애자일, 실용주의, 자동화된 테스트라고 해도) 테스트만으로는 소프트웨어가 현실에서 사용할 준비가 되었다고 증명하기에 충분하지 않다.

결국 이런 버그 하나하나가 모두 제거되기를 기대하는 것은 환상일 뿐이다. 버그는 발생한다. 버그는 말살되기는커녕 반드시 살아남을 것이다.
이 지점에서 가장 심각한 문제는 한 시스템의 버그가 관련이 있는 다른 모든 시스템으로 전파될 수 있다는 사실이다. 버그를 예방할 방법을 찾는 것보다 더 나은 질문은 '한 시스템의 버그가 다른 시스템에 영향을 미치지 않게 하는 방법은 무엇인가?'이다.

장애가 일어날 것이라는 사실을 수용하면 특정 장애에 반응하도록 시스템을 설계할 수 있다.

1부는 운영환경이라는 것이 어떤 것인지 알려주는 느낌이다. 운영 환경을 어떤 시각으로 보아야 하고 운영 환경을 안전하게 운영할 때 필요한 다양한 패턴에 관해서도 설명한다.

필자가 외부 모니터링으로 내부 모니터(로그 파일 수집, 프로세스 모니터링, 포트 모니터링 등)를 보완하는 것을 옹호하는 이유다. (동일한 데이터 센터가 아닌) 어딘가에 있는 모의 클라이언트가 주기적으로 조작된 트랜잭션을 실행할 수 있다. 이 클라이언트는 실제 사용자와 동일한 관점에서 시스템을 경험한다. 해당 클라이언트가 조작해낸 트랜잭션이 처리되지 않으면 서버 프로세스가 죽지 않고 실행 중이라고 해도 문제가 있는 것이다.

가장 확장성이 뛰어난 아키텍처는 무공유 아키텍처다. 각 서버는 조율 과정이나 중앙 집중식 서비스 호출 없이도 독립적으로 작동한다. 아무것도 공유하지 않는 아키텍처에서는 처리 능력이 서버 수에 따라 선형적으로 확장되는 편이다.

한 무리의 서버가 순간적인 부하를 한 번에 가할 때 이를 도그파일(Dogpile)이라고 한다.
도그파일은 다음과 같은 상황에서 발생할 수 있다.
- 코드를 업그레이드하고 재시작할 때와 같이 여러 서버를 부팅할 때
- 크론 작업이 자정(또는 정각)에 발동할 때
- 구성 관리 시스템이 변경 사항을 푸시할 때

가능한 한 사람들이 운영 시스템에 가까이 가지 못하게 하는 것이 가장 좋다. 시스템이 계속 실행되게 하려고 사람이 조작 핸들을 돌리고 붙잡고 있어야 하는 일이 많다면 관리자는 항상 로그인 상태를 유지하는 습관을 갖게 될 것이다. 이 상황은 서버가 '가축'이 아니라 '반려 동물'이며 자꾸만 만지작 거리게 된다는 것을 의미한다. 따라서 시스템은 사람의 개입 없이 적어도 한 번의 출시 주기동안 운영될 수 있어야 한다. '조작 금지' 척도의 논리적인 극단은 불변 인프라다.

매일(또는 밤마다) 일상처럼 관리자가 운영 서버에 로그인하는 습관을 갖게 만드는 것만큼 관리자를 괴롭히는 일은 없다.

시스템이 작업 실패를 미리 예측할 수 있다면 빨리 실패하는 것이 항상 좋다. 이렇게 하면 호출 측에서는 응답을 기다리느라 아무 일도 못하는 대신 다른 작업을 계속할 수 있다.

실패는 불가피하다. 우리 시스템과 우리가 의존하는 시스템은 어떤 방식으로든 실패할 것이다. 안정성 안티 패턴은 일시적인 사건을 증폭시킨다. 그들은 시스템의 균열을 가속한다. 안티 패턴을 예방한다고 나쁜 일이 일어나는 것을 막지는 못하지만 나쁜 일이 일어날 때 피해를 최소화할 수 있다.

2부 운영 고려 설계

이 책을 읽으면서 DevOps 생각도 많이 났다. DevOps도 개발할 때 운영 환경을 고려해야 하고 운영의 경험이 다시 개발에 녹아들어야 하는데 이러한 부분에 어떤 고려를 해야 하는지 설명한다.

구성(configuration)은 숨은 연결과 높은 복잡성으로 인해 어려움을 겪는다. 이 두 가지는 운영자 오류를 일으키는 큰 요인이며 시스템을 위험에 빠뜨린다. 구성은 시스템의 사용자 인터페이스의 일부, 즉 가장 간과되는 유권자인 개발자와 운영자를 위한 인터페이스이기 때문이다.

투명한 시스템은 디버깅하기가 훨씬 쉽다. 따라서 투명한 시스템은 불투명한 시스템보다 더 빨리 성숙할 것이다.

로그는 개발이나 테스트가 아닌 운영이 목표여야 한다. 오류(ERROR) 또는 심각(SEVERE) 수준으로 기록된 모든 로그는 운영의 일환으로 어떤 조치를 취할 필요가 있는 것이어야 한다는 뜻이다.

제어 평면은 운영 부하를 성공적으로 수행하기 위해 이면에서 작동하는 모든 소프트웨어와 서비스를 포괄하는 용어다. 제품 사용자 데이터가 통과하면 제품 소프트웨어, 다른 소프트웨어를 관리하는 것이 주로 하는 일이라면 제어 평면이라고 볼 수 있다.

이 사건은 인간이 시스템에 장애를 일으킨 경우가 아니다. 시스템이 인간을 실패하게 만든 경우다.

모니터링 팀은 모니터링을 하지 않는다. 다른 사람들이 직접 모니터링할 수 있게 만들어준다. 이것은 특정 업무를 전담하는 것에서 고객에게 서비스를 제공하는 것으로 인식이 전환됨을 뜻한다.

광범위하게 '애플리케이션 성능 관리(APM)'라고 부른다. 이는 오픈 소스 패키지로 대체되지 않은 운영 소프트웨어의 마지막 영역 중 하나인 것 같다.

다음은 구성 서비스와 관련된 지침이다.
- 구성 서비스가 없어도 인스턴스가 시작될 수 있어야 한다.
- 구성을 얻을 수 없어도 인스턴스의 작동이 중지되지 않아야 한다.
- 클러스터에서 분리된 구성 노드 때문에 전체 시스템이 종료될 가능성이 있는지 확인해야 한다.
- 여러 지역에 복제본을 만들어두어야 한다.

3부 시스템 전달

3부에서는 소프트웨어를 릴리즈하는 부분에 대해서 다룬다. 여기서는 배치라는 단어를 사용하고 있지만 일반적으로는 배포라고도 불러도 이해하는데 크게 문제는 없을거라고 생각한다.

TCP 규격에서 존 포스텔은 다양한 서비스에서 기능을 제공받으면서도 견고한 시스템을 구축하는 좋은 원칙을 제시했다. 포스텔의 견고함의 원칙은 '자신이 하는 일에는 보수주의자가 되고 외부를 수용할 때는 자유주의자가 되어야 한다'라고 말한다.

4부 체계적 문제 해결

플랫폼 팀에게 한 가지 중요한 것은 자신의 일이 다른 팀에 실제 플랫폼 요소를 제공하는 구조를 구현하는 것임을 기억하는 것이다. 다시 말해, 플랫폼 팀은 구체적인 모니터링 규칙을 구현해서는 안 된다. 대신 각 팀이 플랫폼에서 제공하는 모니터링 서비스에 자체 모니터링 규칙을 적용할 수 있게 API를 제공한다.

개선을 하려면 폐쇄형 피드백 루프가 필수다. 피드백 루프가 더 빠르게 돌아갈수록 개선도 더 정확해질 것이다. 이렇게 되려면 자주 출시되어야 한다. 자주 출시하면서 점진적으로 기능을 사용자에게 제공하면 우리 회사가 경쟁자를 압도하고 시장을 주도할 주제를 설정할 수 있다.

효율성은 종종 '100% 활용'으로 이해된다. 다시 말해, 거의 모든 시간에 모든 개발자가 개발을 하고 모든 디자이너가 디자인을 한다면 그 회사는 '효율적'인 것이다. 한 사람만 보면 이 말이 맞아 보인다. 하지만 시스템을 통해 작업이 어떻게 진행되는지 본다면 이런 상황이 결코 효율적이지 않다는 것을 알 수 있다.

효율성에 관한 더 계몽적인 시각에서는 업무 수행 절차를 작업자가 아닌 작업의 관점에서 바라본다. 효율적인 가치 흐름은 짧은 주기로 막힘 없이 많은 작업을 처리한다. 이런 유형의 효율성은 높은 활용률보다 수익성을 개선하는 데 더 좋다. 하지만 여기에는 미묘한 함정이 있다. 가치 흐름의 효율을 높일수록 오늘 당장의 작업에 더 집중하게 된다. 이는 미래의 변화를 어렵게 만들 수 있다.

스키마를 기준으로 코드를 생성해야 하는 프레임워크를 피하라. 마찬가지로 메시지 유형마다 클래스를 작성해야 하거나 어노테이션으로 매핑해야 하는 것은 모두 피하라. 메시지를 객체가 아닌 데이터로 간주하면 아주 오래된 형식을 훨씬 수월하게 지원할 수 있다.

제럴드 와인버그는 "In General Principles of Systems Design"에서 근본적 조절기 역설(fundamental regulator paradox)을 설명한다.
변동을 제거해서 안정 상태를 만드는 것이 조절기의 역할이지만, 이 변동이 조절기가 잘 작동하게 만드는 궁극적인 정보의 출처다. 따라서 조절기가 잘 작동할수록 개선 방법에 관한 정보를 얻기 힘들어진다.
이 역설은 'IT 담당자가 휴가를 가기 전까지는 사람들이 그 사람에게 얼마나 의존하는지 모른다'는 한 문장으로 표현되기도 했다.
이와 관련된 역설로 폭스바겐 마이크로버스 역설이 있다. 이 역설에 따르면 고장이 잦은 물건을 고치는 방법은 배우지만 고장이 잘 나지 않는 물건을 고치는 방법은 배우지 않는다. 하지만 잘 고장나지 않는 물건이 고장나면 상황이 더 심각해질 위험이 크다. 시스템이 큰 일을 넉넉히 감당하게 하려면 지속적으로 고장률이 낮은 수준으로 유지되어야 한다.

카오스 공학을 막 시작하려고 한다면 무작위 선택은 다른 어떤 진행 방식보다 좋다. 대부분 소프트웨어는 너무나 문제가 많아서 무작위로 대상을 선정해서 공격해도 놀랄만한 무언가가 밝혀진다.

어려운 책은 아니라고 생각하지만, 꽤 많은 개념을 다루고 있기 때문에 경험이 많지 않다면 한 번에 받아들이기 어려울 수도 있다고 생각한다. 하지만 소프트웨어 개발이 개발만 있는 게 아니라 운영까지 고려해야 한다는 점에서 운영까지 나가고 다시 개발의 피드백 루프가 와야 하는 과정은 전체적으로 설명해 준다는 점에서 꽤 좋은 책이라고 생각한다.

2025/02/23 14:32 2025/02/23 14:32