SLI (Service Level Indicator)
SLI는 서비스에 대한 수준을 측정하여, 정량적으로 정의한 지표
"REST API의 응답시간 = 300ms"와 같이 절대 값을 사용하기도 하지만, (측정값/이상적인 값)과 같은 상대적인 지표를 사용하는 것도 이해하기가 쉽다.
예를 들어 한달동안 30분 장애가 났다고 하면 장애에 대한 SLI를 30분이 아니라 가용성으로 SLI를 정의해서 (30일-30분)/(30일) * 100 = 99.9305 %와 같은 식으로 표현하는게 좋음
SLI로 사용할 수 있는 지표는 여러가지가 있지만 일반적으로 다음과 같은 지표들을 많이 사용
- 응답 시간 (Request latency) : 시스템의 응답시간
- 에러율 (Error rate%) : 전체 요청에서 실패한 요청의 비율
- 처리량(Throughput) : 일반적으로 초당 처리량으로 측정하고 TPS (Thoughput per second) 또는 QPS (Query per second)라는 단위를 사용
- 가용성(availability) : 시스템의 업타임 비율
- 내구성(Durability-스토리지 시스템만 해당) : 스토리지 시스템에만 해당하는데, 장애에도 데이타가 유실되지 않을 확률
어떤 지표를 SLI로 사용해야 하는가?
SLI로 정의할 수 있는 지표들이 많은데, 그러면 나의 서비스에서는 어떤 지표를 SLI로 정의해서 사용해야 할까?
특별히 정해진 정답은 없지만 시스템의 특성에 따라서 다음과 같이 정의한다.
- 사용자에게 서비스를 제공하는 서비스 시스템 (웹,모바일등) : 가용성, 응답시간, 처리량
- 스토리지 시스템(백업,저장 시스템): 가용성, 응답시간, 내구성
- 빅데이터 분석 시스템 : 처리량, 전체 End-to-End 처리 시간
- 머신러닝 시스템 : 서빙 응답시간, 학습 시간, 처리량, 가용성, 서빙 정확도
SLI 수집 및 표현
SLI 지표는 각종 모니터링 도구를 통해서 측정할 수 있고, 또는 로그 데이터에서 지표를 추출
예를 들어 정상 응답과 비정상 응답의 수를 카운트 하거나 또는 로그 메시지내에 있는 필드에서 값을 추출
이렇게 추출된 값을 합하거나 평균 값을 내서 SLI를 정할 수 있는데,
평균값 보다는 값의 분포를 퍼센타일에 따른 분포를 사용하는것이 좋음
아래 예제는 웹 시스템의 응답 시간을 표현한 그래프
(참고 소스 : https://medium.com/@jerub/service-level-indicators-in-practice-6a1125e24bee)
50%,85%,95%,99% 응답 시간의 분포를 본 것임
50%를 중간값이 이라고 생각하면 이 값이 일반적인 대표 값이 된다.
위의 그래프 값을 보면 20 ms 정도로 볼 수 있다.
느린 응답 시간, 즉 99%에 해당하는 응답 시간을 보면 5000ms (5초)가 나오는 것을 볼 수 있고 그래프 우측을 보면 응답 시간의 변화의 폭도 훨씬 큰것을 볼 수 있다.
실제 시스템에 문제가 되는 것은 느린값들 즉 99% 와 같은 구간에 속하는 응답시간이 문제가 되는데, 평균 값을 사용하게 되면, 느린 응답 시간이 희석화 되서 시스템의 안정성을 제대로 평가하기가 어렵다.
그래서 SRE에서는 퍼센트타일 기반의 SLI 분포도를 보고 90%,99%와 같이 문제가 되는 구간의 지표를 주요 SLI로 정해서 사용하는 것이 좋다.
SLI 지표의 표준화
SLI로 응답 시간이나 가용성 같은 지표를 사용하기로 정하면, 응답시간과 같은 SLI 지표는 여러 컴포넌트에 걸쳐서 측정해야 한다.
그런데 이러한 지표의 측정 단위가 표준화 되어 있지 않으면 혼선을 야기 하기 때문에, 표준을 정할 필요가 있다.
- 수집 주기 : 지표를 뽑아내는 수집 주기를 10초 단위로 한다.
- 수집 범위 : 수집 범위는 서비스 클러스터 단위로 한다.
- 지표화 주기 : 수집은 10초 단위로 했지만, 지표화는 1분 단위로 해서 시각화 한다.
- 어떤 호출들을 포함 할것인가? : HTTP GET 응답 시간만을 측정하고, 내부 호출은 측정하지 않는다.
- 어떻게 데이터를 수집할것인가? : 모니터링 시스템을 통해서 수집한다.
이러한 SLI 표준은 여러 시스템에 적용될 수 있기 때문에 재사용을 위해서 템플릿으로 만들어서 사용하는 것도 좋다.
SLO (Service Level Objective)
앞서 SLI를 통해서 시스템의 지표를 정의하는 방법을 이야기 하였다.
그러면 각 지표에 대한 목표 값은 어떻게 정의할까? 이를 SLO (Service Level Objective)라고 한다.
SLO = SLI + 목표값(Goal)
예를 들어 REST API의 응답시간을 SLI로 정했다면, SLO는 다음과 같이 정의할 수 있다.
“매주, 99% of REST API호출의 응답 시간은 100ms 이하여야한다.”
여기서 "매주,99% REST API 호출 응답시간"이 SLI가 되고, 응답시간 100ms가 목표값이 되서 위의 전체 문장이 SLO가 된다.
SLO가 중요한 이유?
SLO를 정의할때 잘못하면, 서비스 제공자 관점에서 생각해서 SLO를 정의하기 쉬운데, SLO는 사용자 관점에서 서비스에 얼마나 영향을 주는 가의 관점에서 결정해야 한다.
시스템 관점에서 API 호출 응답시간이 80% 퍼센타일 구간에서 1초면 꽤 높은 것으로 느껴질 수 있지만, 모바일 서비스를 가정한다면, 모바일 서비스의 경우 지하철이나 차량 이동등으로 인해서, 모바일 네트워크 통신 속도 자체가 느리기 때문에, 80% 퍼센타일 구간에서 1초의 지연이면 사용자에게 체감되는 속도는 그렇게 느린편은 아니다.
이를 무리하게 맞추기 위해서 API호출 응답시간을 1초 이하로 내리는 행위는 적절하지 않다.
또는 모바일 앱의 경우 통신망의 가용성이 99.99% 인데, 시스템의 가용성을 99.999%로 만든다 하더라도 통신망에서 더 많은 에러가 나기 때문에 쓸모 없는 SLO가 된다.
물론 많은 경우 사용자가 어떤 지표에 대해서 얼마 만큼의 기대값을 가지는지 알기 어려운 경우가 많다.
이런 경우에는 사용자의 기대치에 대해서 가설을 세워서 시작하고 측정하기 쉬운 항목부터 측정해가면서 나중에 실제로 유용한 SLO로 발전 시켜가는 접근 방법을 사용하도록 한다.
SLO는 반드시 사용자 관점에서 정의해야한다.
SLO 관점에서 시스템에 문제가 없다 하더라도, Customer Support Team으로, 불만(성능/안정성)이 들어온다면, SLO 설정을 잘못했을 가능성에 대해서도 생각해봐야 한다.
이런 지표를 효과적으로 수집하기 위해서 Customer Support 항목에 성능/안정성 등에 대한 항목을 넣고 이를 모니터링 하는 것도 좋은 방법중의 하나이다.
좋은 SLO 란?
그러면 좋은 SLO의 정의란 무엇인가?
SLO에서 설정하는 목표는 단순히 기술적인 목표가 아니라 그 비즈니스가 추구하고자 하는 가치를 반영한 목표여야 한다. 그러면 좋은 SLO를 만들기 위한 조건을 보자
- 단순할것
- 좋은 SLO를 복잡하지 않고 단순해서 이해하기 쉬워야함
- SLO는 개발/운영 조직뿐만 아니라 영업 조직 및 고위 임원까지 모두 동의하고 사용하는 지표이기 때문
- 현실 성이 없는 값을 사용하지 말 것
- 예를 들어 100% 업타임인 무장애 시스템은 존재하지 않음
- 상식적으로 타당한 선에서 SLO를 정의하자
- 되도록이면 적은 수의 SLO만 정의할것
- 여러개의 SLO 값을 지정해서 사용하는데많은 수의 SLO는 관리가 어렵고 실제로 제대로 사용되지도 않음
- 사용되는 SLO는 비지니스 의사결정의 기준으로 사용될 수 있는 SLO만 사용
- 지속적이고 점진적으로 SLO값을 발전 시킬것만약에 높은 값의 SLO를 목표값으로 시작했다가 개발/운영 조직이 이 목표를 맞추지 못했으니 SLO를 낮추자는 접근 방법은 그다지 좋지 않음
- 그래서 SLO의 목표값은 낮은 값에서 시작해서 점차적으로 높은 값으로 바꿔 나가는 것이 바람직하다.
SLO에 대한 기대치 관리
SLO는 의사 결정의 기준이 되는 지표로 사용되기 때문에, SLO를 잘 이해하고 활용하는 것이 중요한데, 그중에서도 SLO에 관련된 이해 당사자들의 SLO에 대한 기대치를 잘 관리하는 것이 중요하다.
엄격하게 지켜야할 SLO이기는 하지만 너무 타이트하게 SLO를 잡으면, 반대로 다른 부작용이 발생할 수 있다.
- SLO의 최소/최대 범위 지정
일반적으로 SLO는 "SLO<=목표값" 식으로 최대값만 설정하거나 또는 "최소값 <==SLO ⇐ 목표값" 형태로 설정을 한다." REST API 의 응답시간 ⇐ 300ms” 는 SLO로 크게 이상하지 않지만 “100ms <= REST API 응답시간 <==300ms”라고 정하는 것과 같이 최소값을 정하는 이유는 무엇일까?
100ms 이상의 지연을 허용한다는 점을 명시적으로 SLO에 적어놓게 되면, 개발자에게는 성능 향상의 목표가 생긴다.
300ms 이하를 유지 하면 되지만, 경우에 따라서 과하게 성능을 끌어 올리려고 몰두 하는 바람에, 정작 개발해야 하는 기능 개발을 하지 못할 수 있기 때문에, 오버 엔지니어링을 막는 차원에 SLO의 최소/최대 범위를 정하는 것도 좋은 방법이라고 할 수 있다.
- 여유 값을 둘것
SLO를 정의할때, SLO를 외부에 공유해야 하는 경우 (예를 들어, 클라우드 서비스와 같은 경우) 외부에 공유하는 SLO와 내부에서 사용하는 SLO 둘을 나눠서 관리하고 내부용 SLO에 여유치를 둬서 외부용 SLO를 정의하면, 문제 발생시 어느정도의 여유 폭을 가질 수 있다.
물론 외부용 SLO가 사용자의 기대치에 미치지 못하는 수준이면 안되지만, 사용자가 인정할 수 있는 범위라면 어느정도의 여유 폭을 두는게 좋다.
- 과하지 말 것
만약에 서비스에서 제공되는 성능이나 가용성이 SLO에 정의된 것보다 높다면 사용자는 당연히 현재의 성능에 익숙해진다. 예를 들어 시스템의 REST API 응답시간을 500ms 로 정해놨는데, 실제 시스템의 응답시간이 300ms 라면, 사용자는 이 300ms 응답시간에 익숙해질 것이고, 오히려 500ms 의 정상적인 응답시간이 나오면 느려진다고 느낄 수 있다.
- 앞에 언급했던 SLO의 최소/최대 범위를 정하는 것도 이런 이유 중의 하나이다.
SLO는 의사결정과 일의 우선 순위를 정하기 위한 매우 중요한 지표이다.
만약에 SLO가 의사 결정이나 우선 순위 결정에 사용되지 않는다면, 그 SLO와 넓게는 SRE 자체가 잘못된 것이다.
SLO 는 SRE에서 그만큼 중요한 지표이기 때문에, 정의할 때 신중해야 하는데, SLO를 지정할때 너무 높은 수준의 SLO를 정하게 되면 SLO 수준에 맞는 성능과 안정성을 위해서 개발 자원을 투자해야 하고 그로 인해서 새로운 기능 개발이 늦어진다. 반대로 너무 낮은 수준의 SLO를 정하게 되면, 서비스 자체의 품질을 떨어 뜨린다.
예시
실제 서비스에서는 어떻게 SLO/SLI를 정의하는지에 대해서 알아보자
SLI는 사용자 스토리당 3~5개 정도가 적당하다.
사용자 스토리는 로그인, 검색, 상품 상세 정보와 같이 하나의 기능을 의미한다고 보면된다.
이 서비스는 웹사이트를 가지고 있고, 그리고 앱을 통해서 접근이 가능한데, 내부적으로 API 서비스를 통해서 서비스가 된다. 내부 서비스에는 사용자 랭킹(Rank ), 사용자 프로파일 (User profiles) 등의 서비스가 있다.
이 서비스에서 "사용자 프로필" 에 대한 SLI를 정의해보도록 하자.
가용성 SLI
가용성은 프로파일 페이지가 성공적으로 로드된 것으로 측정한다.
그러면 성공적으로 로드 되었다는 것은 어떻게 측정할 것인가? 그리고, 성공호출 횟수와 실패 횟수는 어떻게 측정할것인가? 에 대한 질문이 생긴다.
이 서비스는 웹기반 서비스이기 때문에, HTTP GET /profile/{users}와 /profile/{users}/avatar 가 성공적으로 호출된 비율을 측정하면 된다.
성공 호출은 어떻게 정의할것인가? HTTP response code 200번만 성공으로 생각할 수 있지만 5xx는 시스템 에러이지만 3xx, 4xx는 애플리케이션에서 처리하는 에러 처리 루틴이라고 봤을때, 3xx,4xx도 성공 응답에 포함시켜야 한다. 그래서 2xx,3xx,4xx의 횟수를 성공 호출로 카운트 한다.
그러면 이 응답을 어디서 수집해야 할것인가?
앞의 아키텍쳐 다이어그램을 보면 API/웹서비스 앞에 로드밸런서가 있는 것을 볼 수 있는데, 개별 서버 (VM)에서 측정하는 것이 아니라 앞단의 로드밸런서에서 측정해도 HTTP 응답 코드를 받을 수 있기 때문에, 로드밸런서의 HTTP 응답 코드를 카운트 하기로 한다.
응답시간 SLI
그러면 같은 방식으로 응답시간에 대한 SLI를 정의해보자
응답 시간은 프로파일 페이지가 얼마나 빨리 로드 되었는지를 측정한다.
그런데 빠르다는 기준은 무엇이고, 언제부터 언제까지를 로딩 시간으로 측정해야 할것인가?
이 서비스는 HTTP GET /profile/{users} 를 호출하기 때문에, 이 서비스가 100ms 를 임의의 기준값으로 하여, 이 값 대비의 응답시간으로 정의한다.
응답 시간 역시 가용성과 마찬가지로 로드밸런서에서 측정하도록 한다.
이렇게 SLI를 정의하였으면, 여기에 측정 기간과 목표값을 정해서 SLO를 정한다.
가용성 SLO는 28일 동안 99.95%의 응답이 성공한것으로 정의한다.
응답시간 SLO는 28일 동안 90%의 응답이 500ms 안에 도착하는 것으로 정의한다.
또는 좀더 발전된 방법으로 99% 퍼센타일의 응답의 90%가 500ms 안에 도착하는 것으로 높게 잡을 수 있지만, 처음 정한 SLO이기때문에, 이정도 수준으로 시작하고 점차 높여가는 모델을 사용한다.
복잡한 서비스의 SLI 의 정의
앞의 예제를 통해서 SLI와 SLO를 정의하는 방법에 대해서 알아보았다. 사용자 스토리 단위로 SLI를 정한다하더라도, 현실에서의 서비스는 훨씬 복잡하고 많은 개수를 갖는다.
SLI가 많아지면, 관련된 사람들이 전체 SLI를 보기 어렵기 때문에 조금 더 단순화되고 직관적인 지표가 필요하다.
예를 들어보다. 구글 플레이 스토어를 예를 들어봤을때, 구글 플레이스토어는 홈 화면, 검색, 카테고리별 앱 리스트 그리고 앱 상세 정보와 같이 크게 4가지 사용자 스토리로 정의할 수 있다.
이 4가지 사용자 스토리를 aggregation (합이나 평균)으로 합쳐서 하나의 지표인 탐색(Browse)라는 지표로 재 정의할 수 있다.
아래는 4개의 SLI를 각각 측정한 값이다.
이 개별 SLI들을 합쳐서 표현하면 다음과 같이 표현할 수 있다. 전체 SLI의 값을 합친 후에, 백분률로 표현하였다.
이 하나의 지표를 사용하면 4개의 기능에 대한 SLI를 대표할 수 있다.
이렇게 개별 SLI의 합이나 평균을 사용하는 경우는 대부분의 경우에는 충분하지만 특정 서비스가 비지니스 임팩트가 더 클 경우 이를 동일하게 취급해서 합해버리면 중요한 서비스가 나도 이 대표값에는 제대로 반영이 안될 수 있기 때문에, 필요한 경우 개별 SLI에 적절한 가중치를 곱해서 값을 계산하는 것도 방법이 된다.
참고링크
'SRE-DevOps' 카테고리의 다른 글
다중화(Redundancy) - 2. 웹서버 다중화(LB 없이) (0) | 2023.12.20 |
---|---|
다중화(Redundancy) - 1. 다중화 개념 (0) | 2023.12.20 |
ALB, NLB 비교 (1) | 2023.12.10 |
Bastion Host - 배스쳔 호스트 (0) | 2023.11.26 |
SRE (0) | 2023.11.22 |