사전 온콜
개념

온콜

gabury1고친 사람 github-actions[bot]

온콜은 서비스 장애를 곧바로 맡기로 미리 정한 당번입니다. 업무 시간이 끝난 뒤에 난 장애도 정해진 사람에게 호출이 갑니다. 그래서 밤에 난 장애가 아침까지 방치되지 않습니다.

쉽고 빠른 이해

온콜은 장애가 났을 때 연락을 받기로 한 당번입니다. 새벽 세 시에 결제가 멎으면 이번 주 당번의 휴대폰이 울립니다.

이게 없으면 장애를 누가 맡을지 매번 새로 찾아야 합니다. 누가 깨어 있는지 모릅니다. 연락이 닿아도 고칠 권한이 없을 수 있습니다. 그동안 서비스는 멎어 있습니다.

  1. 누가 언제 당번인지를 표로 짭니다
  2. 감시하던 값이 조건을 벗어나면 지금 당번에게 호출이 갑니다
  3. 당번이 정해진 시간 안에 응답하지 않으면 다음 사람에게 넘어갑니다

대가는 당번이 그 기간 동안 생활을 묶어 둬야 한다는 것입니다. 고칠 것 없는 호출이 쌓이면 진짜 호출까지 덜 주의 깊게 보게 될 수 있습니다. 밤에 멈춰도 다음 날 아침에 고치면 되는 서비스라면 당번을 두지 않습니다.

상세

병원은 밤에도 과마다 당직 의사를 한 명씩 세웁니다. 새벽에 응급 환자가 들어오면 간호사는 누구에게 전화할지 고민하지 않고 그 의사를 부릅니다.

이 절은 온콜이 무엇을 미리 정하는 제도인지부터 봅니다. 그다음 호출이 당번에게 닿는 경로를 봅니다. 마지막으로 당번이 호출을 받은 뒤 대응하려면 무엇을 쥐고 있어야 하는지를 봅니다.

미리 정하는 세 가지

온콜은 근무 시간 안이든 밖이든 부르면 응답하기로 한 대기 근무입니다. 서비스 운영에서는 장애가 났을 때 연락을 받을 사람을 정해 두는 제도를 말합니다.

이 말은 당번 한 사람을 가리키기도 하고 당번을 돌리는 제도 전체를 가리키기도 합니다. 「이번 주 온콜이 누구냐」는 사람이고 「우리 팀은 온콜을 돈다」는 제도입니다. 이 글에서는 사람을 말할 때 당번, 제도를 말할 때 온콜이라고 씁니다.

정하는 것은 셋입니다. 누가 받는지, 언제부터 언제까지 받는지, 그 사람에게 연락이 닿지 않으면 다음에 누구에게 가는지입니다.

교대 근무와는 다릅니다. 교대 근무는 정해진 시간에 나와서 일하는 근무입니다. 온콜은 평소 일을 하거나 집에 있다가 호출이 오면 대응에 나서는 대기입니다.

호출이 당번에게 닿는 경로

호출은 대개 감시 체계에서 자동으로 옵니다. 값을 재는 모니터링이 조건을 벗어난 값을 찾습니다.

모니터링이 내놓는 기록 하나하나를 사건이라고 합니다. 사건이 모두 사람을 부르지는 않습니다. 조건을 벗어났다는 판정이 붙은 사건이 경보입니다.

경보를 지금 당번에게 실어 나르는 것이 알림입니다. 당번에게 나가는 이 알림을 이 글에서는 호출이라고 씁니다.

당번이 정해진 시간 안에 응답하지 않으면 호출은 다음 사람에게 넘어갑니다. 이렇게 넘기는 규칙이 에스컬레이션입니다.

flowchart TD
    A["모니터링이 값을 잰다"] --> B["조건을 벗어났나"]
    B -->|"조건 안"| A
    B -->|"조건 밖"| C["경보를 올린다"]
    C --> G["알림으로 당번을 호출한다"]
    G --> D["정해진 시간 안에 응답했나"]
    D -->|"응답"| E["당번이 문제를 분류한다"]
    D -->|"무응답"| F["다음 사람에게 넘긴다"]
    F --> D

여기서 응답은 고쳤다는 뜻이 아니라 호출을 받았다는 뜻입니다. 이 신호가 있어야 호출 체계가 다음 사람을 부르는 것을 멈춥니다.

응답한 당번은 먼저 문제를 분류합니다. 그다음 해결 쪽으로 갑니다. 혼자 감당이 안 되면 다른 팀원을 부르거나 위로 넘깁니다.

장애 하나가 경보를 여럿 낼 수 있습니다. 같은 원인에서 나온 사건과 경보는 한 건으로 묶어 다룹니다. 이 한 건을 사고라고 합니다.

당번이 쥐고 있어야 하는 것

당번은 연락을 받는 사람에서 끝나지 않습니다. 받은 뒤에 대응할 수 있어야 당번입니다. 대개 셋이 필요합니다.

  • 대응 절차를 적은 문서 — 경보마다 그 경보가 얼마나 심각한지, 무엇을 먼저 확인하고 무엇을 만지는지 적은 문서를 런북 또는 플레이북이라고 합니다
  • 프로덕션을 만질 권한 — 재시작이나 설정 변경, 배포 되돌리기 같은 변경을 직접 하거나 남이 하려는 변경을 검토할 수 있어야 합니다
  • 상태를 볼 수 있는 화면과 기록 — 대시보드와 로그에 새벽에도 들어갈 수 있어야 합니다

셋 중 하나라도 빠지면 당번은 호출을 받고도 다른 사람을 깨워야 할 수 있습니다. 그러면 정해 둔 순서가 무너집니다. 장애가 날 때마다 아는 사람을 찾는 일로 돌아갑니다.

손에 넘치는 장애를 넘길 경로와 사고를 다루는 절차도 당번이 기대는 것입니다. 넘길 곳이 정해져 있으면 당번 혼자 모든 것을 끝까지 떠안지 않습니다.

배경

서비스는 근무 시간을 가리지 않고 멈춥니다. 받을 사람을 정하지 않았다면 장애가 난 순간 사람을 찾는 일부터 시작해야 합니다. 새벽에는 누가 깨어 있는지 모릅니다. 연락이 닿아도 그 사람에게 서버를 만질 권한이 없을 수 있습니다. 그동안 서비스는 멎어 있습니다.

멈춘 시간이 곧 손해로 쌓이는 서비스는 근무 밖에도 장애를 받을 사람을 세울 필요가 생깁니다. 고장을 알아챈 뒤 사람이 대응을 시작하기까지 걸리는 시간은 평균 복구 시간을 이루는 한 구간입니다. 당번은 그 구간을 짧게 잡는 장치입니다.

반대로 밤에 멈춰도 다음 날 아침에 고치면 되는 서비스는 당번을 두지 않습니다. 사람을 묶는 비용이 멎어 있는 동안의 손해보다 크기 때문입니다.

온콜이라는 말은 의료나 소방처럼 근무 시간이 아니어도 부르면 나오기로 한 당번을 가리키던 말입니다. 그 말이 서비스 운영으로 넘어왔습니다. 서비스 운영에서는 오랫동안 운영 전담 팀이 이 당번을 맡아 자기 서비스를 건강하게 지켰습니다.

예시

구글 SRE 팀의 응답 목표

구글의 SRE(Site Reliability Engineering, 사이트 신뢰성 엔지니어링) 팀에서 당번은 호출을 받으면 몇 분 안에 프로덕션 시스템을 만질 수 있어야 합니다. 몇 분인지는 팀과 그 시스템을 가진 사업 쪽이 합의한 호출 응답 시간이 정합니다.

시스템 흔히 잡는 응답 목표
사용자를 직접 마주하거나 시간에 매우 민감한 서비스 5분
덜 급한 시스템 30분

호출을 받는 기기는 회사가 줍니다. 대개 휴대폰입니다. 호출은 이메일과 SMS(Short Message Service, 문자 메시지), 자동 음성 전화, 앱 같은 여러 방식으로 여러 기기에 나갈 수 있습니다.

GitLab 의 당번표와 에스컬레이션 정책

GitLab 에서 당번표는 스케줄 하나에 로테이션을 붙여 만듭니다. 로테이션은 여러 사람이 차례로 돌아가며 당번을 서는 순번입니다. 스케줄에는 이름과 설명, 시간대를 넣습니다.

로테이션 항목 무엇을 정하나
Name 로테이션 이름
Participants 이 로테이션에서 돌아가며 당번을 설 사람들
Rotation length 한 사람이 당번을 서는 길이
Starts on 로테이션이 시작하는 날짜와 시각
Enable end date 켜면 로테이션이 끝나는 날짜와 시각을 고른다
Restrict to time intervals 켜면 로테이션을 고른 시간 구간에만 돌린다

GitLab 에서는 처음 호출하는 일과 응답이 없을 때 넘기는 일을 에스컬레이션 정책 하나가 맡습니다. 정책은 시간을 정한 단계들로 이루어집니다. 앞 단계에서 호출받은 사람(응답자)이 응답하지 않으면 다음 단계의 응답자를 자동으로 호출합니다.

단계마다 「Email on-call user in schedule」을 고르면 그 스케줄의 모든 로테이션에서 지금 당번인 사람에게 알림이 갑니다. 단계에 적는 시간은 0분에서 1440분 사이여야 합니다.

Evernote 의 주 단위 당번과 세 등급

Evernote 에서 호출을 먼저 받는 1차 당번은 작지만 악착같은 엔지니어 팀이 돌아가며 섭니다. 이 팀은 프로덕션 인프라와 몇몇 업무 시스템을 책임집니다. 당번은 일주일 단위로 하루 24시간 돕니다. 교대 때는 손에 익은 인수인계 절차를 따릅니다. 아침마다 일일 스탠드업에서 지난 사고를 함께 훑습니다.

팀은 작습니다. 그에 비해 맡은 범위는 넓습니다. 이 팀은 절차의 짐을 가볍게 두려고 애씁니다. 그 방법의 하나로 지표와 모니터링이 낸 사건을 모두 세 등급으로 가릅니다. P1 · P2 · P3 은 우선순위(Priority level) 1 · 2 · 3 등급입니다.

등급 언제 다루나 어떻게 알리나
P1 곧바로. 바로 조치할 수 있어야 한다 · 서비스 수준 목표에 영향을 준다 당번을 호출한다
P2 다음 영업일. 대개 고객이 직접 보지 않거나 범위가 아주 좁다 팀에 이메일을 보내고 사건 채널에 알린다
P3 정보로만 쓴다. 용량 계획에 쓰는 정보도 여기 든다 대시보드와 이메일에 모은다

당번을 호출하는 것은 P1 하나뿐입니다. P2 는 다음 영업일에 다룹니다. P3 은 정보로 모일 뿐입니다.

갈래

당번을 시간 위에 어떻게 배치하느냐로 갈립니다. 한 사람에게 긴 기간을 전부 맡길 수 있습니다. 하루를 낮과 밤으로 쪼갤 수도 있습니다. 두 사람을 겹쳐 세우기도 합니다. 시간대가 다른 거점에 나눠 맡기기도 합니다.

주 단위 단일 당번

한 사람이 정해진 기간을 혼자 맡습니다. 기간이 끝나면 다음 사람에게 넘깁니다. 일주일 단위로 돌리는 팀이 있습니다.

AWS(Amazon Web Services)의 Incident Manager 는 이 길이를 일·주·월 단위로 고르게 합니다. 「Weekly」를 고르고 3을 넣으면 한 사람의 당번이 3주 이어집니다. 이 서비스는 지금 새 고객을 받지 않습니다.

어디가 아픈지는 길이에서 나옵니다. 일주일 내내 하루 24시간을 쉼 없이 맡는 당번은 오래 버티기 어려운 구성이라고 구글 SRE 는 봅니다. 그 주에 호출이 몰리면 한 사람이 전부 받습니다.

낮과 밤을 나눈 12시간 교대

하루에 호출이 한 번 이상 오는 로테이션이라면 구글 SRE 는 한 번의 당번을 12시간 안으로 줄이기를 권합니다. 교대가 길면 지칠 위험이 있습니다. 지친 사람은 실수합니다.

거점이 하나뿐이어도 이렇게 돌릴 수 있습니다. 한 사람이 일주일 내내 24시간을 맡지 않습니다. 두 사람이 일주일을 나눠 한 사람은 낮을, 다른 사람은 밤을 맡는 편이 낫다고 봅니다. 당번 기간을 일주일보다 짧게 줄여 3일 서고 4일 쉬는 식으로 돌리는 방법도 있습니다.

1차·2차 당번

두 사람이 같은 시간에 당번을 섭니다. 호출을 먼저 받는 쪽이 1차, 뒤를 받치는 쪽이 2차입니다. 대가는 같은 시간에 대기하는 사람이 둘로 늘어난다는 것입니다. 1차와 2차를 함께 두는 팀이 많습니다. 다만 둘의 분담은 팀마다 다릅니다.

어떤 팀은 1차가 놓친 호출을 2차가 받게 하기도 합니다. 어떤 팀은 1차에게 호출만 맡기기도 합니다. 그러면 급하지 않은 나머지 프로덕션 일은 2차 몫입니다.

일을 나누는 데 2차 로테이션이 꼭 필요하지 않은 팀도 있습니다. 그런 팀에서는 관련된 두 팀이 서로의 2차가 되어 놓친 호출을 받아 주는 일이 흔합니다. 그러면 2차만을 위한 로테이션을 따로 둘 필요가 없어집니다.

거점 분산 (follow the sun)

서로 다른 시간대에 있는 거점이 각자 자기 낮 시간만 맡습니다. 해를 따라 당번이 넘어간다고 해서 follow the sun 이라고 부릅니다. 밤 근무는 사람의 건강에 해롭습니다. 이 방식은 밤 당번을 아예 없앨 수 있게 해 줍니다.

대가는 거점 사이의 소통과 조율 비용입니다. 거점을 나눌지는 각 방식의 대가와 시스템의 중요도, 그 시스템이 만드는 일의 양을 보고 정합니다.

시간대도 걸립니다. 로스앤젤레스와 더블린은 서머타임 일정이 달라 두 곳의 시차가 철마다 바뀝니다. 두 거점의 로테이션을 이어 붙인 당번표에는 서머타임이 바뀔 때 한 시간의 빈틈이나 겹침이 생길 수 있습니다.

운영

굴릴 때는 세 값을 잽니다. 한 사람이 당번에 쓰는 시간, 한 번의 당번이 다루는 사고 수, 호출에 응답하기까지의 시간입니다. 아래 수치는 전부 구글 SRE 가 자기 팀에 잡은 값입니다.

당번에 쓰는 시간의 상한

구글 SRE 는 엔지니어 시간의 50% 이상을 엔지니어링에 쓰려고 합니다. 나머지 가운데 당번에 쓰는 시간은 25% 를 넘지 않게 합니다. 남은 25% 까지는 프로젝트가 아닌 다른 운영 일에 씁니다.

이 25% 규칙에서 최소 인원이 나옵니다. 하루 24시간 늘 두 사람(1차와 2차)이 당번을 선다고 해 봅니다. 교대는 일주일 단위입니다. 그러면 거점 하나인 팀은 최소 8명이 필요합니다. 한 사람이 한 달에 한 주만 1차나 2차로 서는 셈입니다.

거점이 둘인 팀은 거점마다 6명을 합리적인 최소로 봅니다. 25% 규칙을 지키면서 팀으로 굴러갈 만한 인원을 갖추려는 수입니다.

당번을 너무 드물게 서도 문제입니다. 프로덕션에서 오래 떨어져 있으면 자기 실력을 과하게 믿거나 덜 믿게 될 수 있습니다. 모르는 것은 사고가 났을 때에야 드러납니다. 그래서 모든 엔지니어가 한 분기에 적어도 한두 번은 당번을 서도록 팀 크기를 잡아야 한다고 봅니다.

한 번의 당번이 다루는 사고 수

사후 분석은 장애가 끝난 뒤 원인과 고칠 점을 정리하는 글입니다. 구글 SRE 는 같은 근본 원인에서 나온 사건과 경보의 묶음을 사고 하나로 셉니다. 사후 분석 하나에서 함께 다룰 만큼이 한 사고입니다.

재 보니 사고 하나를 다루는 데 평균 6시간이 걸렸습니다. 근본 원인 분석과 복구, 사후 분석 작성과 버그 수정까지 넣은 시간입니다.

따라서 12시간 당번 한 번이 다룰 수 있는 사고는 최대 2건입니다. 이 상한을 지키려면 호출이 시간 위에 아주 고르게 퍼져 있어야 합니다. 그러면 하루 사고 수의 중앙값은 대개 0 입니다.

어떤 구성 요소나 문제 하나가 매일 호출을 낸다고 해 봅니다. 하루 사고 수의 중앙값이 1 을 넘는 경우입니다. 그러면 언젠가 다른 무엇도 깨져 허용치를 넘는 사고가 날 가능성이 큽니다.

한 분기처럼 이 상한을 잠깐 넘겼다면 운영 부하를 견딜 만한 수준으로 되돌리는 조치를 둡니다. 운영 부하는 호출보다 넓은 말입니다. 호출 대응에 티켓 처리 같은 다른 운영 일까지 더한 짐입니다. 티켓은 당번을 바로 부르지 않고 작업 목록에 올리는 요청입니다.

호출 부하를 만드는 것

운영 부하 가운데 호출 쪽만 재는 값이 호출 부하(pager load)입니다. 한 번의 당번 동안(하루나 일주일) 당번이 받는, 호출을 낸 사고의 수입니다. 사고 하나가 호출을 여러 번 낼 수 있습니다. 그래서 세는 단위는 호출이 아니라 사고입니다.

호출 부하에 영향을 주는 주된 요인은 셋입니다.

갈래 무엇이 부하를 키우나
프로덕션 이미 있는 버그의 수 · 새로 들어오는 버그 · 새 버그를 찾아내는 속도 · 버그를 막고 걷어내는 속도
경보 호출 경보를 울리는 문턱 값 · 새로 생기는 호출 경보 · 이 서비스의 SLO(Service Level Objective, 서비스 수준 목표)와 이 서비스가 기대는 서비스들의 SLO 가 맞물리는 정도
사람의 절차 버그 수정과 뒷마무리의 꼼꼼함 · 호출 경보에 대해 모은 자료의 질 · 호출 부하 추세에 쏟는 관심 · 사람이 손으로 하는 프로덕션 변경

넘칠 때 손보는 곳

운영 과부하는 당번이 감당할 수 있는 것보다 운영 일이 많아진 상태입니다. 그 증상은 재서 목표를 숫자로 잡는 것이 이상적입니다. 예를 들어 하루 티켓 5건 미만, 당번 한 번에 호출 2건 미만입니다.

이 2건은 앞 소절의 2건과 다른 값입니다. 앞의 것은 다룰 수 있는 사고 수의 상한입니다. 이것은 당번이 받는 호출 수의 목표입니다.

운영 과부하의 흔한 원인은 잘못 설정된 모니터링입니다. 그래서 호출을 내는 조건부터 봅니다. 호출 경보는 SLO 를 위협하는 증상과 맞아야 합니다. 서비스 수준 목표를 깨뜨릴 조짐이 보일 때 울려야 한다는 뜻입니다. 모든 호출 경보는 사람이 바로 조치할 수 있는 것이어야 합니다.

한 시간에 한 번 이상 당번을 건드리는 우선순위 낮은 경보는 일을 끊습니다. 그런 경보가 만드는 피로 때문에 심각한 경보까지 덜 주의 깊게 다루게 될 수 있습니다. 이 상태가 알림 피로입니다.

사고 하나에 경보가 여러 개 쏟아지는 것도 줄입니다. 관련된 경보를 모니터링이나 알림 체계가 한데 묶게 합니다. 사고 중에 중복이거나 정보가 없는 경보가 나오면 꺼서 당번이 사고에 집중하게 합니다. 사고마다 경보를 둘 이상 내는 시끄러운 경보는 경보와 사고가 1:1 에 가까워지게 고칩니다.

flowchart TD
    subgraph X["묶기 전"]
        I1["사고 하나"] --> A1["경보"]
        I1 --> A2["경보"]
        A1 --> P1["호출"]
        A2 --> P2["호출"]
    end
    subgraph Y["묶은 뒤"]
        I2["사고 하나"] --> A3["묶인 경보 하나"]
        A3 --> P3["호출"]
    end
    X -->|"관련된 경보를 한데 묶는다"| Y

호출기 돌려주기

SRE 팀이 개발팀이 만든 시스템의 당번을 맡고 있을 때 쓰는 마지막 손잡이도 있습니다. 극단적인 경우 SRE 팀은 「호출기를 돌려준다(give back the pager)」는 선택지를 쓸 수 있습니다. 호출기는 호출을 받는 기기입니다. 시스템이 SRE 팀의 기준을 맞출 때까지 그 시스템의 당번을 개발팀이 전부 맡게 하는 것입니다.

이 일은 자주 일어나지 않습니다. 개발팀과 함께 운영 부하를 줄이는 쪽이 거의 언제나 가능하기 때문입니다.

여러 분기에 걸친 구조 변경이 필요할 때는 당번 책임을 개발팀과 다시 나누기도 합니다. 호출 경보의 일부나 전부를 개발팀 당번에게 보내는 식입니다. 이런 해법은 대개 임시 조치입니다. 그동안 두 팀이 함께 시스템을 다듬어 SRE 팀이 다시 맡을 수 있게 만듭니다.

응답 목표가 나오는 곳

응답 목표 시간은 그 서비스가 지켜야 할 가용성과 맞물려 있습니다. 단순하게 셈해 봅니다. 사용자를 마주하는 시스템이 한 분기에 99.99% 가용성을 지켜야 한다고 합시다. 그 분기에 멈춰도 되는 시간은 13분 남짓입니다.

그러면 당번의 반응도 분 단위여야 합니다. 엄밀히는 13분 안입니다. SLO 가 느슨한 시스템이라면 반응 시간은 수십 분 단위일 수 있습니다.

보상

근무 시간 밖의 대기에는 그에 맞는 보상을 따져야 합니다. 조직마다 방식이 다릅니다. 구글은 대체 휴무나 현금으로 보상합니다. 그 보상에는 전체 급여의 일정 비율이라는 상한을 둡니다.

이 상한은 한 사람이 떠맡을 수 있는 당번의 양에 상한을 거는 것과 같습니다. 이 보상 구조는 팀이 필요한 만큼 당번에 나설 동기를 줍니다. 동시에 당번이 몇 사람에게 몰리지 않게 합니다. 지나친 당번이 부르는 번아웃도 줄입니다. 프로젝트 일을 할 시간이 모자라는 것도 줄입니다.

교대 때 넘기는 인수인계

구글 SRE 가 사례로 든 한 팀은 당번에 들어가기 전에 당번의 책임을 적은 지침을 함께 읽었습니다. 그 지침은 교대를 이렇게 정합니다. 교대를 시작하는 당번은 앞 당번이 남긴 인수인계를 읽습니다. 교대를 끝내는 당번은 다음 당번에게 인수인계 메일을 보냅니다.

같은 지침은 언제 다른 사람에게 넘길지와 큰 사고의 사후 분석을 어떻게 쓸지도 정합니다.

관련 항목

당번이 호출을 받은 뒤 거치는 사고 대응 단계

탐지 · 사고 대응 · 완화 · 사후 분석 · 사고 지휘 체계 · 근본 원인 · 사고 관리

호출을 만들어 당번에게 넘기는 규칙

모니터링 · 경보 · 알림 · 에스컬레이션 · 심각도 · 알림 라우팅 · 호출기

당번이 대응에 쓰는 도구와 문서

런북 · 플레이북 · 대시보드 · 관측성 · 로그 · 자동화

온콜 운영을 재는 지표

호출 부하 · 평균 복구 시간 · 평균 고장 시간 · 서비스 수준 목표 · 오류 예산 · 골든 시그널 · 가용성

당번을 지치게 하는 부하와 그 증상

알림 피로 · 운영 과부하 · 토일 · 잡음 · 헛호출 · 번아웃

당번을 세우고 돌리는 조직 방식

SRE · 인프라와 SRE · 데브옵스 · 당번표 · 교대 근무 · 인수인계

당번표를 짜고 호출을 보내는 제품

GitLab · AWS Systems Manager Incident Manager · Grafana OnCall

다른 이름: on-call · oncall