Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ryuheechul/c6643e797d14f83bed2eb2f7614230e0 to your computer and use it in GitHub Desktop.
Save ryuheechul/c6643e797d14f83bed2eb2f7614230e0 to your computer and use it in GitHub Desktop.
[요약] 분산 시스템 모니터링 (구글의 SRE 책의 일부)

분산 시스템 모니터링

https://sre.google/sre-book/monitoring-distributed-systems/ 을 간단히 의역 및 요약

모니터링을 왜 하는가 Why Monitor?

  • 롱텀 트렌드 분석 Analyzing long-term trends
  • 시간 또는 실험 그룹등을 비교 Comparing over time or experiment groups
  • Alerting
  • Building dashboards
  • 특별케이스의 회고 분석 (예: 디버깅) Conducting ad hoc retrospective analysis (i.e., debugging)

기타

  • 모니터링과 알럿팅을 통해서 이미 손상된 시스템이나 곧 손상될 시스템을 말할 수 있음
  • 시스템 스스로 문제를 복구하지 못할 경우 사람에게 알려서 나서야 하지만
    • 알럿을 남용하면 안됨
      • 예) "뭔가 이상해서"
      • 사람을 호출하는 것은 비싼 낭비가 될 수 있음
        • 일하는 시간에는 다른 일을 방해
        • 여가 시간에는 쉬는 걸 방해할 뿐 아니라 심지어 잠까지 방해 가능!
      • 효과적인 알럿 시스템은 (의미있는) 신호가 있고 노이즈는 적음

모니터링에 대한 합리적인 기대를 설정 Setting Reasonable Expectations for Monitoring

  • 모니터링은 그 자체만으로 꽤나 많은 노력이 들어가는 일이 될 수 있고 아무리 (자동) 시스템에 많은 투자가 들어갔다 하더라도 (구글 SRE팀의 경우) 10-12명의 팀에서 (돌아가면서) 한 두명은 "모니터링 담당자"가 될 수 있을 정도
    • 하지만 담당자가 스크린을 계속 쳐다보면서 문제를 기다리는 일은 피해야함
  • 구글은 단순하고 빠른 모니터링 시스템을 선호하고 더 헤비한 툴링은 사후 분석에
  • 모니터링 룰을 만들 때 시스템간의 디펜던시는 최대한 피함
    • 예) "데이터베이스가 느린 것이 파악되었을 때는 데이터 베이스가 느리다고 알리고 아니면 웹사이트가 느리다고 알릴 것"
  • 모니터링 시스템은 심플하고 빠르게 이해할 수 있어야 함
    • 특히 문제 발견 부터 사람 호출, 카테고리/등급 분류(triage), 깊게 들어가는 디버깅까지의 critical path를 서포트
  • 노이즈를 줄이고 신호를 높이기 위해서는 어떻게 호출까지 이어지는지에 대한 과정이 단순하고 탄탄해야하고 호출에 포함되는 알럿의 내용은 사람이 이해하기 쉽게 어떤 부분이 실패하고 있는지를 단순하고 명확하게 알려야함

증상 vs 원인 Symptoms Versus Causes

  • 모니터링 시스템이 다뤄야 하는 것 두가지: 무엇(어떤 것)이 고장났고 왜 그런지?
  • 무엇이 고장 났는지를 알려면 증상을 통해서
  • 왜 고장났는지를 파악하는 것은 원인을 알게되는 것
  • 무엇 vs 왜 를 구별하는 것이 최대 신호와 최소 노이즈를 유지하는 모니터링을 구축하는 핵심

Black-Box Versus White-Box

  • 화이트박스 모니터링을 많이 사용하고 소소하지만 크리티컬한 블랙박스 모니터링

    • 블랙박스 모니터링은 증상 위주의 지금 당장 일어나고 있는 문제를 타겟
    • 화이트박스 모니터링은 측정장치를 통해 시스템 내부를 (로그, HTTP endpoints) 살펴서 (재시도 등으로 인해서 가려졌지만) 곧 일어날 문제를 타겟
  • 하나의 증상이 누군가에게는 증상이 또 다른이에게는 원인이 될 수 있음, 예를 들어 데이터베이스가 느려진 경우

    • 데이터베이스 SRE에게는 증상으로, FE SRE에게는 원인으로
    • 그러므로 화이트박스 모니터링이 때에 따라서 증상위주 일 수도 혹은 원인 위주 일 수도
      • 얼마나 자세한 정보를 가지고 있냐에 따라서도 갈릴 수 있음
  • 디버깅을 위한 원격측정의 경우 화이트박스가 제격

    • 웹요청이 데이터베이스를 많이 사용하는 경우에
      • 웹서버 관점에서 데이터베이스가 얼마나 빠르게 응답하는 것 처럼 보이는지와
      • 데이터베이스 스스로의 관점에서 얼마나 빠르게 동작하고 있는지
      • 를 둘다 알아야함
        • 그렇지 않을 경우 데이터베이스가 느린 이유가 네트워크 이슈인지 데이터베이스 자체 이슈인지 알 수 없음
  • (사람) 호출 시

    • 블랙박스가 더 알맞음
      • 진짜 문제 + 당장 일어나고 있는 문제를 사람에게 알리게 되므로
      • 반대로 당장 일어나지 않고 있지만 언제가는 곧 일어날 문제에 블랙박스는 적합하지 않음

4가지 골든 시그널 The Four Golden Signals

Latency

  • 요청을 처리하는 데에 걸리는 시간
  • 성공과 실패의 경우를 구분하는 것이 중요
    • 예를 들어
      • HTTP 500 에러가 데이터베이스나 다른 백엔드 이슈로 인해서 발생한 케이스는 빠를 수 있음
        • 그래서 다른 (에러가 아닌) 응답들과 레이턴시를 같이 섞을 경우 의미가 희석 될 수 있음
      • 게다가 느린 에러는 빠른 에러보다 문제가 더 심함!
    • 그러므로 에러의 경우에도 단순히 에러의 여부만 체크하는 것이 아니라 레이턴시를 살펴보아야 함

Traffic

  • (하이레벨 메트릭을 이용해서) 시스템의 디맨드를 재는 데에 사용
    • 웹서비스의 경우 초당 요청 수 (요청의 종류 별로 나누는 것도 좋음, 예: 정적, 동적)
    • 오디오 스트리밍 시스템은 네트워크 I/O 비율 또는 동시 세션 수
    • 키밸류 스토리지 시스템은 트랜잭션 수나 초당 요청 수

Errors

  • 실패 비율을 측정해야 함
    • 단순명확 할 수도 있고 either explicitly
      • e.g., HTTP 500s
    • 표면에 드러나지 않을 수도 있음 implicitly
      • 200 성공이지만 내용이 잘못 된 경우
    • 또는 내부 정책으로 실패로 간주 가능
      • "1초 이상 걸리는 응답은 에러다"
  • 응답코드로만 충분하지 않은 경우 이차적인 정보를 이용하여 부분적인 실패도 알아낼 수 있음
    • 예를 들어 로드 밸런서의 500 코드를 통해서 당연한 에러들을 감지 할 수 있지만 컨텐츠가 잘못된 경우는 e2e 테스트로만 잡아 낼 수 있음

Saturation

  • 시스템이 얼마나 가동 중인지를 알려줌
    • 리소스가 몇 퍼센트나 이용되고 있는지
      • 제약이 잘 드러나는 부분을 탐지할 것, 예를 들면
        • 메모리 제약적인 (혹은 민감한) 시스템은 메모리를
        • I/O 제약적인 시스템은 I/O를
    • 많은 시스템이 100%에 도달하기 전에 이미 성능저하가 일어나기 시작
    • 그래서 활용 수치 타겟을 아는 것이 중요
  • supplement with other measurements
    • in complex systems, saturation can be supplemented with higher-level load measurement:
      • can your service properly
        • handle double the traffic?
        • handle only 10% more traffic?
        • or handle even less traffic than it currently receives?
    • for very simple services that have no parameters that alter the complexity of the request
      • (e.g., "Give me a nonce" or "I need a globally unique monotonic integer")
      • that rarely change configuration, a static value from a load test might be adequate
  • 대부분의 서비스는 간접적인 시그널 (예: CPU 활용비율, 네트워크 bandwidth 처럼 알려진 상한선이 있는) 을 이용
  • 레이턴시가 증가하는 것은 포화상태로인한 것일 확률이 높음
    • p99 응답시간을 짧은 시간 범위에서 재면 포화상태로 진입하게되는 초기 현상을 잡아낼 수 있음
  • 포화 상태의 경우 현재의 값도 중요하지만 곧 일어나게 될 미래를 예측하는 것에도 사용됨
    • 예를 들어, 데이터베이스의 스토리지가 4시간 이후에는 꽉찰 예정

이 4가지 골든 시그널을 측정하고 각각에 문제가 있을 때 (포화 상태의 경우에는 문제가 예상 될 때에도) 사람을 호출하면 서비스가 모니터링을 통해서 상당히 커버되고 있다고 볼 수 있음

꼬리를 신경써야함 Worrying About Your Tail (or, Instrumentation and Performance)

  • 모니터링 시스템을 처음부터 구축할 때 평균 값을 활용하고 싶어질 수 있음, 예를 들어 평균 CPU 사용량, 평균 데이터베이스 사용량
    • 하지만 CPU와 데이터베이스 모두 사용량의 균형이 아주 쉽게 깨짐
      • 레이턴시의 경우도 마찬가지임
        • 1000개 요청의 평균 레이턴시가 100ms 일 경우에는 상위 느린 1%는 아주 쉽게 5초 이상 일 수 있음
  • 이 것은 구별하는 가장 쉬운 방법은 평균의 느림정도와 아주 느린 "꼬리" 레이턴시를 히스토그램을 이용해서 수집
    • (raw 보다 히스토그램을 이용하면 훨씬 더 적은 양의 데이터로 비슷한 값을 볼 수 있음)
    • 0ms 에서 10ms 사이의 리퀘스트는 몇개 였는지?
    • 10ms 에서 30ms 사이의 리퀘스트는 몇개 였는지?
    • 30ms 에서 100ms 사이의 리퀘스트는 몇개 였는지?
    • 100ms 에서 300ms 사이의 리퀘스트는 몇개 였는지?
    • (버켓 간격은 기하급수적으로 유지하면 시각화하는데에 도움 - 위의 경우 3배씩)

요약자의 노트: Tail latency

P90 (가장 느린 10%를 제외한 90% 중에서 최대 느린 값) 혹은 P99 (빠른 순위로 99% 중에서 최대 값) 등의 "뒤 (꼬리) 쪽" 레이턴시

측정값의 적절한 해상도 찾기 Choosing an Appropriate Resolution for Measurements

  • CPU 로드를 1분 단위로 볼 경우 (CPU기준으로) 꽤나 길게 이어진 솟구친 꼬리 레이턴시 값들을 보고 힘듬 (더 짧은 단위로 체크가 필요)

  • 반대로 1년에 총 9시간의 다운타임 예산이 있는 경우 200초 이하로 자세하게 업타임을 체크하는 것은 의미없는 낭비

    • 비슷하게 하드디스크의 SLO가 99.9% 인 경우 얼마나 찼는지를 1-2분 단위보다 더 자주 체크하는 것도 낭비
  • 해상도를 높여서 메트릭을 수집하는 경우 데이타양이 너무 많아서 유지비용이 비쌀 수 있으니 주의할 것

    • 메트릭의 실시간성이 엄청나게 중요하지 않다면 샘플링등을 통해서 비용을 줄일 수 있음
      • 예를 들어 CPU사용량을 1초 단위로 기록하고
      • 5%의 값만 저장하고 1분 단위로 종합
    • 이런식으로 비용을 줄이면서도 높은 해상도를 유지하여 CPU hotspot을 감지 가능

가능한 더 간단하게 하지만 그 이상은 피해야함 As Simple as Possible, No Simpler

  • 모든 요구사항을 충족시키려 하다가 모니터링 시스템이 아주 복잡해질 수 있음

    • 레이턴시 문턱마다 그리고 퍼센타일 별로 레이턴시 종류마다 (x3 복잡성) 알럿을 설정하는 경우
    • 추가 코드를 통해서 가능성이 있을 법한 원인을 탐지
    • 가능성이 있을 법한 원인 별로 대쉬보드를 유지
  • 복잡성을 부르는 원천은 끝이 없음, 어떠한 소프트웨어 시스템처럼 모니터링도 마찬가지로 아주 쉽게 복잡해질 수 있고 부서지기 쉬움

    • 그러면 변경이 어려워 짐으로 유지보수가 힘이 더 들어감
  • 그러므로 단순함을 추구할 것, 무엇을 모니터할지에 대해서는 다음의 가이드라인을 상기:

    • 진짜 incident 잡을 수 있는 (만들어야 하는) 규칙은 단순하고 예측가능하며 신뢰할만함
    • 데이터 수집, 종합, 알럿들 중 거의 사용되지 않는 것들은 제거해야함
    • 수집 되고 있는 시그널이지만 대시보드나 알럿에 사용되지 않는 것도 제거 대상
  • 구글에서의 경험을 비추어 보았을 때, 독립적인 시스템에 기본적인 메트릭의 수집과 종합을 대쉬보드와 알럿팅에 활용했을 때 잘 동작함

    • 자세한 시스템 프로파일링, single-process 디버깅, 예외/크래쉬 트래킹, 부하 테스팅, 로그 수집/분석, 트래픽 조사 등 복잡한 시스템을 구축하고자 유혹될 수 있음
      • 중첩될 수 있는 데이터가 너무 많아서 오히려 복잡하고 취약한 시스템이 될 수 있음
      • (소프트웨어 엔지니어링의 많은 관점에서 처럼, 목적이 뚜렷하게 다르고 단순명료하며 loosely coupled 된 여러시스템을 운영하는 것이 더 나은 전략)

WIP - 아래 부터는 아직 작업중

Tying These Principles Together

The principles discussed in this chapter can be tied together into a philosophy on monitoring and alerting that’s widely endorsed and followed within Google SRE teams. While this monitoring philosophy is a bit aspirational, it’s a good starting point for writing or reviewing a new alert, and it can help your organization ask the right questions, regardless of the size of your organization or the complexity of your service or system.

When creating rules for monitoring and alerting, asking the following questions can help you avoid false positives and pager burnout:24

Does this rule detect an otherwise undetected condition that is urgent, actionable, and actively or imminently user-visible?25
Will I ever be able to ignore this alert, knowing it’s benign? When and why will I be able to ignore this alert, and how can I avoid this scenario?
Does this alert definitely indicate that users are being negatively affected? Are there detectable cases in which users aren’t being negatively impacted, such as drained traffic or test deployments, that should be filtered out?
Can I take action in response to this alert? Is that action urgent, or could it wait until morning? Could the action be safely automated? Will that action be a long-term fix, or just a short-term workaround?
Are other people getting paged for this issue, therefore rendering at least one of the pages unnecessary?

These questions reflect a fundamental philosophy on pages and pagers:

Every time the pager goes off, I should be able to react with a sense of urgency. I can only react with a sense of urgency a few times a day before I become fatigued.
Every page should be actionable.
Every page response should require intelligence. If a page merely merits a robotic response, it shouldn’t be a page.
Pages should be about a novel problem or an event that hasn’t been seen before.

Such a perspective dissipates certain distinctions: if a page satisfies the preceding four bullets, it’s irrelevant whether the page is triggered by white-box or black-box monitoring. This perspective also amplifies certain distinctions: it’s better to spend much more effort on catching symptoms than causes; when it comes to causes, only worry about very definite, very imminent causes.

Monitoring for the Long Term

In modern production systems, monitoring systems track an ever-evolving system with changing software architecture, load characteristics, and performance targets. An alert that’s currently exceptionally rare and hard to automate might become frequent, perhaps even meriting a hacked-together script to resolve it. At this point, someone should find and eliminate the root causes of the problem; if such resolution isn’t possible, the alert response deserves to be fully automated.

It’s important that decisions about monitoring be made with long-term goals in mind. Every page that happens today distracts a human from improving the system for tomorrow, so there is often a case for taking a short-term hit to availability or performance in order to improve the long-term outlook for the system. Let’s take a look at two case studies that illustrate this trade-off.

Bigtable SRE: A Tale of Over-Alerting

Google’s internal infrastructure is typically offered and measured against a service level objective (SLO; see Service Level Objectives). Many years ago, the Bigtable service’s SLO was based on a synthetic well-behaved client’s mean performance. Because of problems in Bigtable and lower layers of the storage stack, the mean performance was driven by a "large" tail: the worst 5% of requests were often significantly slower than the rest.

Email alerts were triggered as the SLO approached, and paging alerts were triggered when the SLO was exceeded. Both types of alerts were firing voluminously, consuming unacceptable amounts of engineering time: the team spent significant amounts of time triaging the alerts to find the few that were really actionable, and we often missed the problems that actually affected users, because so few of them did. Many of the pages were non-urgent, due to well-understood problems in the infrastructure, and had either rote responses or received no response.

To remedy the situation, the team used a three-pronged approach: while making great efforts to improve the performance of Bigtable, we also temporarily dialed back our SLO target, using the 75th percentile request latency. We also disabled email alerts, as there were so many that spending time diagnosing them was infeasible.

This strategy gave us enough breathing room to actually fix the longer-term problems in Bigtable and the lower layers of the storage stack, rather than constantly fixing tactical problems. On-call engineers could actually accomplish work when they weren’t being kept up by pages at all hours. Ultimately, temporarily backing off on our alerts allowed us to make faster progress toward a better service.

Gmail: Predictable, Scriptable Responses from Humans

In the very early days of Gmail, the service was built on a retrofitted distributed process management system called Workqueue, which was originally created for batch processing of pieces of the search index. Workqueue was "adapted" to long-lived processes and subsequently applied to Gmail, but certain bugs in the relatively opaque codebase in the scheduler proved hard to beat.

At that time, the Gmail monitoring was structured such that alerts fired when individual tasks were “de-scheduled” by Workqueue. This setup was less than ideal because even at that time, Gmail had many, many thousands of tasks, each task representing a fraction of a percent of our users. We cared deeply about providing a good user experience for Gmail users, but such an alerting setup was unmaintainable.

To address this problem, Gmail SRE built a tool that helped “poke” the scheduler in just the right way to minimize impact to users. The team had several discussions about whether or not we should simply automate the entire loop from detecting the problem to nudging the rescheduler, until a better long-term solution was achieved, but some worried this kind of workaround would delay a real fix.

This kind of tension is common within a team, and often reflects an underlying mistrust of the team’s self-discipline: while some team members want to implement a “hack” to allow time for a proper fix, others worry that a hack will be forgotten or that the proper fix will be deprioritized indefinitely. This concern is credible, as it’s easy to build layers of unmaintainable technical debt by patching over problems instead of making real fixes. Managers and technical leaders play a key role in implementing true, long-term fixes by supporting and prioritizing potentially time-consuming long-term fixes even when the initial “pain” of paging subsides.

Pages with rote, algorithmic responses should be a red flag. Unwillingness on the part of your team to automate such pages implies that the team lacks confidence that they can clean up their technical debt. This is a major problem worth escalating.

The Long Run

A common theme connects the previous examples of Bigtable and Gmail: a tension between short-term and long-term availability. Often, sheer force of effort can help a rickety system achieve high availability, but this path is usually short-lived and fraught with burnout and dependence on a small number of heroic team members. Taking a controlled, short-term decrease in availability is often a painful, but strategic trade for the long-run stability of the system. It’s important not to think of every page as an event in isolation, but to consider whether the overall level of paging leads toward a healthy, appropriately available system with a healthy, viable team and long-term outlook. We review statistics about page frequency (usually expressed as incidents per shift, where an incident might be composed of a few related pages) in quarterly reports with management, ensuring that decision makers are kept up to date on the pager load and overall health of their teams.

결론 Conclusion

  • 건강한 모니터링/알럿팅 파이프라인은 단수하고 쉽게 추론 가능해야 함
  • 증상에는 호출을, 원인 위주의 경험적 조사는 문제를 디버깅할 때 사용할 것
  • "표면 위" 를 살펴보는 것이 더 쉽지만 데이터베이스 포화 상태등은 더 안쪽을 볼 수 밖에 없음
  • 이메일 알럿팅의 가치는 제한되고 노이즈가 될 확률이 높음
    • 차라리 대쉬보드를 통해서 아직 크리티컬하지 않은 문제를 미리발견하면 노이즈를 예방 가능
  • 대쉬보드는 로그와 페어링 가능
    • 메트릭과 로그의 역사적인 관계를 알아내기 위해
  • 온콜 로테이션과 당장의 (그리고 곧 일어날) 증상에 대해서 호출을 이용하고
    • 달성가능한 목적에 맞게 계속 타겟을 조절하면서
    • 모니터링 시스템이 빠른 진단을 돕는지만 확보하면 됨
@ryuheechul
Copy link
Author

관련주제로 노트하고 있는 다른 곳: https://github.com/ryuheechul/reflect/blob/main/org/concept/monitoring.org

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment