← 전체 글

네트워크에는 기억이 있다

14시 02분에 네트워크가 믿고 있던 것을 재구성하기, 그리고 무엇이 바뀌었는가와 무엇을 알게 되었는가의 차이

Michel Wijnberg

이 시리즈에 나온 도구들은 지금까지 전부 지금에 관한 질문에 답합니다. 그런데 엔지니어가 도움을 가장 필요로 하는 두 순간에는 그 시제가 틀렸습니다.

첫째는 장애 진행 중입니다. 네트워크가 이상하게 굴고 있고, 필요한 것은 현재 상태가 아니라 누군가 손대기 시작하기 전인 20분 전의 상태입니다. 둘째는 장애 이후입니다. 네트워크는 다시 멀쩡해졌고, 모두가 나름의 가설을 갖고 있으며, 부서졌을 때의 토폴로지를 아무도 내놓지 못합니다.

Osprey의 답은 시계입니다.

7월 29일 14시 02분의 토폴로지. 아래쪽에 타임 트래블 스크러버
7월 29일 14시 02분의 토폴로지. 아래쪽에 타임 트래블 스크러버

이것은 녹화 재생이 아닙니다. 저 캔버스 위의 모든 요소가 어떤 타임스탬프에 맞춰 재구성된 것입니다. 장비, 링크, 그 코스트와 상태, 영역 소속까지. 아래 스크러버에는 Jul 29, 14:02(30/36)이라고 적혀 있습니다. 선택한 24시간 구간에서 서로 다른 서른여섯 개 토폴로지 상태 중 서른 번째라는 뜻입니다.

그 트랙 위의 점 하나하나가, 네트워크가 진짜로 달랐던 순간입니다.

모든 모니터링 도구가 이력을 보관하므로, 저 문장에는 더 날카로운 날이 필요합니다. 그들이 보관하는 것은 측정값입니다. CPU는 83%였고, 인터페이스는 4 Gbit를 냈고, 폴링은 성공했다. 이것들은 네트워크를 대상으로 읽어 낸 값이고, 14시 02분에 어떤 장비가 바빴다는 것을 알려 줍니다. 그것이 무엇을 믿고 있었는지는 알려 주지 못합니다. Osprey가 보관하는 것은 상태입니다. 어떤 인접이 존재했는지, 어떤 경로가 어떤 메트릭으로 설치되어 있었는지, 라우터가 어느 영역에 속했는지, 어떤 BGP 경로가 왜 선택되었는지. 차이는 진짜 질문을 던지는 순간 드러납니다. 측정값 이력은 14시 02분에 링크가 포화였다고 말해 줄 수 있습니다. 상태 이력은 그보다 4분 전에 어떤 ABR이 summary를 철회했고 그 지역의 절반이 갑자기 먼 길로 돌아가게 되어 포화되었다고 말해 줄 수 있습니다. 하나는 타임스탬프가 붙은 증상입니다. 다른 하나는 네트워크 자신의 추론이, 보존된 것입니다.


무슨 일이 있었을 때만 존재하는 스냅숏

순진한 구현은 타이머로 스냅숏을 씁니다. 5분마다 토폴로지를 덤프하는 식이죠. 간단하고, 대부분 똑같은 사본으로 채워진 데이터베이스와 그 너머를 볼 수 없는 해상도 한계를 만들어 냅니다.

Osprey는 토폴로지가 바뀔 때 스냅숏을 쓰고, 그 외에는 절대 쓰지 않습니다.

수집기에서 오는 모든 토폴로지 이벤트는 먼저 해시됩니다.

// computeTopologyHash computes an FNV-64a hash over the topology snapshot data.
// Uses addition accumulation of per-element hashes for order-independence.

장비는 자기 router ID와 ABR/ASBR 비트를, 링크는 방향을 정규화한 라우터 쌍과 양쪽 코스트 및 상태를, 스텁 네트워크와 인터페이스는 각자의 것을 기여합니다. 누적은 덧셈이라 해시가 요소가 도착한 순서에 의존하지 않습니다. 두 수집기가 같은 영역을 서로 다른 순서로 보고해도 같은 해시가 나와야 합니다. 그렇지 않으면 폴링할 때마다 변경처럼 보일 테니까요.

해시는 그 영역의 직전 해시와 메모리에서 비교됩니다. 같으면 아무것도 쓰지 않습니다. 다르면 스냅숏 행이 하나 삽입됩니다.

그 결과는 구조적으로 정보 밀도가 높은 타임라인입니다. 제 랩은 지난 30일 동안 영역 51개에 걸쳐 스냅숏 478개를 만들었습니다. 환경 전체에서 하루 열여섯 개쯤이고, 하나하나가 실제 차이입니다. 스크러버의 점들은 표본이 아닙니다. 사건입니다.

이것은 또한 안정적인 영역은 몇 시간 동안 행이 하나도 없을 수 있다는 뜻이기도 합니다. 그것은 공백이 아니라 올바른 상태입니다. 아무 일도 없었으니 기록할 것도 없는 것입니다. 고른 타임스탬프 이하에서 가장 가까운 스냅숏이 곧 그 타임스탬프의 상태 그 자체입니다.


타임 트래블은 기능 하나가 아닙니다

시계는 눈에 보이는 부분입니다. 그것을 쓸모 있게 만드는 것은, 약 스무 개의 API 엔드포인트가 같은 at= 파라미터를 받아 그 시점 기준으로 답한다는 사실입니다. 토폴로지 그래프, LSDB 브라우저, 경로 계산, SPF 트리, 라우터별 RIB, 영역 간 경로와 외부 경로, ASBR 항목, 인터페이스, 스텁 네트워크, BGP 피어, BGP 베스트 패스, 피어별 수신 경로.

BGP는 스냅숏보다 더 강한 대접을 받습니다. BGP가 토폴로지보다 훨씬 자주 바뀌기 때문입니다. BGP는 바이템포럴 변경 로그로 저장됩니다. 모든 베스트 패스, 피어 세션, 그리고 (선택적으로) 수신한 모든 RIB 항목이 valid_fromvalid_to를 가진 구간이고, valid_to가 열려 있으면 “여전히 참”을 뜻합니다. 그러면 시점 T의 질문은 재구성이 아니라 술어가 됩니다. valid_from <= T AND (valid_to IS NULL OR valid_to > T).

그 안의 두 가지 세부가 제대로 만들기까지 가장 오래 걸렸고, 둘 다 무언가를 기록하지 않는 일에 관한 것입니다.

  • 구간이 요동치는 것은 속성 해시로 억제하는데, 그 해시는 IGP 메트릭과 해석된 넥스트 홉 장비를 의도적으로 제외합니다. 그 둘은 IGP가 재수렴할 때마다 바뀌고, 만약 그것들이 새 구간을 연다면 아무 상관 없는 링크 코스트가 움직일 때마다 네트워크의 모든 BGP 프리픽스가 플랩하는 것처럼 보일 것입니다.
  • 피어가 죽는 일은 대량 철회가 아니라 모니터링 공백으로 기록됩니다. BMP 세션이 끊겼을 때 라우터가 십만 개 프리픽스를 철회한 것이 아닙니다. 저에게 더 이상 알려 주지 않게 된 것뿐입니다. 그것을 철회로 쓰면, 모니터링 세션이 딸꾹질할 때마다 그 네트워크 역사상 가장 큰 라우팅 이벤트를 제조하는 셈이 됩니다.

둘 다 쉬운 구현이 사건을 지어내는 경우입니다. 사건을 지어내는 이력은 이력이 없는 것보다 나쁩니다. 당신이 그것을 조사하게 될 테니까요.


과거에서 시뮬레이션하기

두 모드는 합성됩니다. 이것이 제가 이 제품에서 가장 좋아하는 부분입니다.

타임 트래블에 들어가 시계를 맞춘 다음에 시뮬레이션에 들어갈 수 있습니다. 캔버스에는 SIMULATION @ <timestamp> 워터마크가 붙고, what-if는 그 순간 실제로 존재했던 토폴로지를 상대로 돌아갑니다.

그러니까 던질 수 있는 질문은 이런 것입니다.

14시 02분에 실제로 서 있던 그 네트워크였다면, 이 장애를 견뎌 냈을까?

오늘의 토폴로지가 아닙니다. 그것은 그사이 수리되고, 메트릭이 다시 매겨지고, 확장되었습니다. 그때 정말로 거기 있던 토폴로지를 상대로 묻는 것입니다. 사후 분석 작업에서 그것은 방어할 수 있는 답과 그럴듯한 답의 차이입니다.

자기 한계도 지킵니다. 과거 시점의 BGP 피어 장애 분석은 그 스코프에 대해 전체 RIB 이력이 기록되어 있어야 합니다. 그렇지 않은 경우 결과는 조용한 근사가 아니라 명시적인 건너뜀입니다.

BGP effects (peer failure, hot-potato exit shifts, BGP traffic) are not evaluated at this time: no full-RIB history (history_mode=‘full’) is recorded for the scope. Enable full history mode on a BMP target to time-travel BGP.

그 메시지는 빠진 입력과 그것을 제공해 줄 설정을 이름으로 밝힙니다. 행동으로 옮길 수 있는 메시지입니다.


과거에 없는 것을, 소리 내어 말하기

정말로 이력이 없는 것들이 몇 가지 있고, 그것들을 건드리는 엔드포인트는 라이브 데이터를 이력 데이터인 척 조용히 내주는 대신 그렇다고 말합니다.

LSDB 브라우저에 과거 시점을 요청하면 응답에 이런 문구가 실립니다.

Topology and route LSAs reflect the selected time; LSA header metadata (age/seq/ checksum) is not historized and shows live values.

과거 시점의 도메인 간 경로를 요청하면, 답이 실제로 라이브 근거에 기댄 경우에 한해서만 설명에 단계가 더 붙습니다.

Time travel: L2 detail is live: L2/port annotations on this path reflect current LLDP/CDP wiring, not the selected time. L2 adjacency is not historized.

Time travel: entry resolved via current router-id: identity attributes (router-id, local address) are not historized and were borrowed from the live session record.

조건부라는 점이 중요합니다. 전적으로 이력만으로 증명된 이어 붙이기에는 두 주석 중 어느 것도 붙지 않으므로, 주석이 나타났을 때 그것이 의미를 갖습니다. 모든 이력 뷰에 “일부 데이터는 라이브일 수 있습니다” 같은 포괄적 고지를 붙이면 기술적으로는 참이고, 영구히 무시되며, 쓸모가 없습니다.

한 가지 한계를 더 대놓고 말하겠습니다. 그러지 않으면 당신이 혼란 속에서 스스로 발견하게 될 테니까요. 타임 트래블 중에는 링크 사용률 색칠이 꺼집니다. 트래픽 히트맵은 이력 토폴로지 위에 라이브 부하를 보여 주는 대신 비어 버립니다. 그것은 안전한 동작이고, 틀린 동작입니다. 비어 있음은 “이 시점에는 제공되지 않음”으로 읽혀야 하는데 “트래픽 없음”으로 읽힙니다. 그것을 고칠 리더는 계획되어 있고, 아직 만들어지지 않았습니다.


무엇이 바뀌었는가와 무엇을 알게 되었는가의 차이

타임 트래블에는 짝이 되는 리포트가 있습니다. 두 시점을 비교해 차이를 나열하는 것입니다.

Topology Diff: 장비와 링크 변경 없음, 24시간 동안 스텁 네트워크 56개 추가
Topology Diff: 장비와 링크 변경 없음, 24시간 동안 스텁 네트워크 56개 추가

AS 200의 지난 24시간: 장비 추가도, 제거도, 변경도 없음. 링크 추가도 제거도 없음. 그리고 스텁 네트워크 56개 추가, 전부 IPv6 /128 루프백입니다.

네트워크 변경처럼 보입니다. 아닙니다.

그 56개 프리픽스가 데이터베이스에 처음 들어온 시각을 확인해 봤더니, 전부 오늘 아침 10:00:49에서 10:01:14 사이에 도착했습니다. 25초짜리 구간입니다. 어떤 네트워크도 라우터 64대에 걸친 루프백 56개를 25초 만에 다시 설정하지 않습니다. 실제로 일어난 일은 디스커버리 한 바퀴였습니다. 그 프리픽스들은 내내 OSPFv3 데이터베이스에 있었고, 이것은 Osprey가 그것들을 기록하기 시작한 순간입니다.

이 구분에는 이름을 붙일 만합니다. 둘을 뒤섞으면 일어난 적도 없는 변경을 쫓게 만들기 때문입니다.

토폴로지 디프가 알려 주는 것은 모델이 무엇을 알게 되었는가입니다. 네트워크가 무엇을 했는가와 같은 것이 아닙니다.

때로는 둘이 겹칩니다. 링크가 죽으면 모델이 링크가 죽었다고 기록합니다. 때로는 겹치지 않고, 단서는 대개 타임스탬프의 모양에 있습니다. 진짜 네트워크 변경은 프로토콜 수렴의 타이밍으로 도착하고, 모델의 변경은 폴링 주기의 타이밍으로 도착합니다. 25초에 똑같은 프리픽스 쉰여섯 개는, 변경의 옷을 입은 폴링 주기입니다.

지금 보고 있는 것이 둘 중 어느 쪽인지 알려 주지 못하는 관측 제품은 언젠가 누군가의 오후를 잡아먹습니다. Osprey는 그것을 자동으로 라벨링하지 않습니다. 디프는 모델이 기록한 것을 보여 주고, 위의 추론은 도구가 아니라 제 것입니다. 그러나 모든 행에는 당신이 스스로 판단하는 데 필요한 타임스탬프가 실려 있습니다. 정직한 도구가 당신에게 지는 최소한의 빚이 그것이라고 저는 생각합니다.


이 시리즈가 끝나는 자리

세 개의 시리즈, 그리고 사실은 하나의 논증에 세 방향에서 도달했습니다.

시리즈 1은 모델이 참인가에 관한 것이었습니다. 네트워크를 있는 그대로 모델링하고, 그 일부가 되지 않으면서 관측하고, 포워딩을 홉 단위로 재현하고, 추측하기를 거부하는 것.

시리즈 2는 근거에 순위를 매길 수 있는가에 관한 것이었습니다. 여러 진실을 동시에 쥐고, 서로 모순되는 출처에 등급을 매기고, 고객보다 먼저 자기 실수를 찾아내는 것.

시리즈 3은 그것이 무엇을 사 주는가에 관한 것이었습니다. 그것으로 추론할 수 있을 만큼 정확한 모델입니다. 무언가를 부수고 무슨 일이 벌어지는지 보기. 무엇이 무엇에 의존하는지 묻기. 측정할 수 없는 것을 추정하고, 추정하고 있다고 말하기. 부서지기 한 시간 전에 네트워크가 무엇을 믿었는지 묻기.

믿지 못하는 모델 위에서는 그중 무엇도 작동하지 않습니다. 시리즈 1의 모든 정직한 거부와 시리즈 2의 등급 매겨진 모든 근거는, 시리즈 3의 답이 의미를 갖게 하기 위해 존재합니다. 9%가 허구인 토폴로지 위에 세운 what-if는 계획 도구가 아닙니다. 예쁜 캔버스가 달린 난수 생성기입니다.

여덟 번째 글은 그 논증을 가장 짧은 형태로 말했습니다. 토폴로지 엔진은 네트워크 상태를 위한 컴파일러다. 지저분하고 모순되는 입력, 결정론적인 모델 출력, 그리고 오라클은 라우터 자신. 컴파일러는 그럴듯함이 아니라 적합성으로 평가되고, 이 열두 편에 나온 모든 거부는 답을 구할 수 없는 경우에 적합성이 치르는 값입니다.

모델을 제대로 만드십시오. 어떻게 아는지 말하십시오. 그러고 나서, 오직 그러고 나서, 질문을 던지기 시작하십시오.


전체 시리즈: 신뢰: IGP 세 개, 지도 하나 · 제로 풋프린트 · 홉 바이 홉의 진실 · Osprey가 추측하기를 거부하는 것. 진실을 만들어 내기: 같은 라우터, 세 가지 다른 진실 · 네트워크가 스스로와 어긋날 때 · 내 토폴로지가 나에게 거짓말한 날 · 네트워크 엔지니어의 단위 테스트. 보는 것에서 추론하는 것으로: 이걸 망가뜨리면 어떻게 될까? · 영향 반경 · 측정할 수 없는 것을 추정하기 · 그리고 이 글.