KCNA — 쿠버네티스·클라우드 네이티브 입문 · CNCF 생태계·관측 가능성·전달 · 이론
관측 가능성 — 세 개(혹은 네 개)의 시그널
한 줄 요약
모니터링은 "내가 미리 정해 둔 질문에 답하는 것"이고, 관측 가능성은 **"미리 생각 못 한 질문에도
답할 수 있는 성질"** 입니다. 시그널을 나누는 이유는 각각 답할 수 있는 질문이 다르기 때문입니다.
왜 이게 필요했나
단일 서버 시절엔 로그 파일 하나면 됐습니다. 마이크로서비스에서는 요청 하나가 서비스 열 개를 지나가고,
그중 어디가 느린지 로그만으로는 알 수 없습니다. 게다가 파드는 죽고 새로 뜨므로 **로그를 남긴 주체가
이미 사라진 뒤에 조사를 시작하게 됩니다.**
그래서 "장애가 나면 서버에 들어가서 본다"는 방식이 성립하지 않습니다. 애초에 들어갈 서버가 없거나
이미 교체됐으니까요. 데이터를 밖으로 내보내 두어야 합니다.
어떻게 동작하나
세 개의 기둥, 그리고 네 번째
| 시그널 | 답하는 질문 | 비용 | 대표 도구 |
| --- | --- | --- | --- |
| 메트릭(Metrics) | 지금 얼마나 나쁜가? 언제부터? | 싸다 (집계된 수치) | Prometheus |
| 로그(Logs) | 그때 정확히 무슨 일이 있었나? | 중간~비쌈 | Loki, Elasticsearch |
| 트레이스(Traces) | 이 요청이 어디서 시간을 썼나? | 비쌈 (보통 샘플링) | Jaeger, Tempo |
| 프로파일(Profiles) | 이 프로세스의 CPU/메모리를 누가 먹나? | 비쌈 | Pyroscope |
조사 순서도 대개 이 순입니다. **메트릭으로 이상을 감지하고 범위를 좁히고, 트레이스로 어느 구간인지
찾고, 로그로 그 구간의 사연을 읽습니다.** 로그부터 뒤지면 건초더미에서 바늘을 찾게 됩니다.
쿠버네티스에서의 수집 경로
- 메트릭: 각 컴포넌트와 앱이
/metrics를 노출 → Prometheus 가 주기적으로 pull - 로그: 컨테이너의 stdout/stderr → 노드 디스크의 파일 → DaemonSet 수집기가 읽어 전송
- 트레이스: 앱이 계측되어 OTLP 로 push → 컬렉터 → 백엔드
여기서 KCNA 가 짚는 포인트 하나. 컨테이너 로그는 stdout/stderr 로 보내야 합니다.
앱이 자기 파일에 쓰면 파드가 죽을 때 같이 사라지고 수집기도 보지 못합니다.
"로그는 이벤트 스트림"이라는 12-factor 항목이 바로 이 얘기입니다.
OpenTelemetry 가 푸는 문제
예전에는 백엔드마다 SDK 가 달랐습니다. Jaeger 를 쓰다 다른 걸로 바꾸면 애플리케이션 코드를 다시
고쳐야 했죠. OTel 은 계측 API/SDK 와 전송 프로토콜(OTLP)을 표준화해서 이 종속을 끊었습니다.
계측은 한 번, 백엔드는 컬렉터 설정으로 바꿉니다.
쿠버네티스가 원래부터 주는 관측 재료
- 이벤트 —
kubectl describe pod아래쪽. 스케줄링 실패, 이미지 pull 실패, 프로브 실패 등 - 상태(status) —
.status.conditions와.status.phase. - metrics-server —
kubectl top이 쓰는 최소한의 리소스 사용량. 장기 보관은 안 합니다.
컨트롤 플레인의 판단 근거가 여기 남습니다. 로그를 뒤지기 전에 볼 곳입니다.
신뢰성 용어
- SLI — 실제로 측정하는 지표 (예: 성공한 요청 비율)
- SLO — 그 지표의 목표 (예: 30일간 99.9%)
- SLA — 그 목표를 못 지켰을 때의 계약상 배상. 기술이 아니라 계약 개념
- 에러 버짓 — SLO 가 99.9% 면 0.1% 만큼은 깨져도 되는 예산. 이 예산이 남으면 배포를 더 빠르게,
바닥나면 안정화에 집중하는 식으로 의사결정 기준이 됩니다
현장에서 만나는 모습
저자의 홈랩에서 관측 가능성이 극적으로 드러난 사례가 둘 있습니다.
첫째, Cilium 의 Hubble 입니다. 사이드카를 하나도 주입하지 않고 eBPF 로 커널에서 직접 관측하는데,
실제 출력이 이렇습니다.
07:50:38.064: ebpf-demo/client:47918 -> ebpf-demo/api:80 http-request FORWARDED (HTTP/1.1 GET http://api/)07:50:38.223: ebpf-demo/client:47932 -> ebpf-demo/api:80 http-request DROPPED (HTTP/1.1 POST http://api/)07:50:38.223: ebpf-demo/client:47932 <- ebpf-demo/api:80 http-response FORWARDED (HTTP/1.1 403 0ms POST)메서드·경로·응답 코드·지연 시간이 전부 보이고, 정책에 의한 DROPPED 가 명시됩니다.
"왜 막혔는가"를 추측이 아니라 기록으로 알 수 있다는 게 핵심입니다.
같은 클러스터의 nginx 는 정책 적용 전 GET 200 / POST 200 이었다가 적용 후GET 200 / POST 403 으로 갈렸고, 그 변화가 그대로 흐름 로그에 남았습니다.
둘째, 앞서 나온 KubeVirt 사례입니다. 컴포넌트 상태는 전부 AllComponentsReady 인데 VM 은 안 떴습니다.
상태 필드는 "내가 켜졌다"고 말할 뿐 "내가 하는 일이 실제로 된다"고 말하지 않습니다.
그래서 저자는 클러스터 검증을 상태 조회가 아니라 실제 동작 시나리오 14 개(노드 Ready,
컨트롤 플레인 구성요소, CNI, CoreDNS, 워커 스케줄링, 파드 간 통신, 서비스 DNS + HTTP 200)로 짜서통과 14 / 실패 0 을 확인했습니다. 관측 가능성의 마지막 형태는 합성 점검(synthetic check) 입니다.
다음 퀴즈에서 확인할 것
이 코스의 마지막 퀴즈로 CNCF 생태계와 관측 가능성을 함께 점검합니다.
그다음은 KCSA — 지금까지 배운 구조를 공격자의 눈으로 다시 보는 코스입니다.