오늘 Hacker News에는 세 개의 글이 올라왔는데, 그중 어느 것도 서비스 장애에 관한 것이 아니었습니다.
Roku는 개발자 저장소(developer repositories)를 GitHub에서 GitLab으로 이전했습니다 (252점). Node2Shell은 HTTP2Shell로 성장했으며, 이제 영향 범위는 "많은 HTTP 라이브러리 및 앱"을 포괄합니다 (273점). Google은 Nest 온도 조절기 일체를 다시 단순한 온도 조절기로 되돌렸다고 보도되었습니다 (29점). 서로 다른 회사들, 서로 다른 카테고리이지만 공통된 사건이 있습니다. 바로 의무가 손을 바꿨는데 아무도 그 책임을 맡지 않은 경우입니다.
이것이 바로 승계 레이어(succession layer)입니다. 오늘 누가 소유자인지가 중요한 것이 아니라, 약속했던 주체가 더 이상 존재하지 않을 때 내일 누가 책임질 것인지가 중요합니다.
소유권과 승계는 다르다
모든 공급업체 관계는 두 가지 다른 것을 묶어 놓으며, 계약서가 가격을 매기는 것은 그중 하나에 불과합니다.
첫 번째는 **보관(custody)**입니다. 누가 코드, 키, 하드웨어, 계정을 보유하고 있는가 하는 것입니다. 이것은 문서화되고, 청구되며, 감사됩니다.
두 번째는 **승계(succession)**입니다. 보관자가 응답을 멈출 때 누가 그 의무를 상속받는가 하는 것입니다. 이것은 가정되는 것입니다.
계약서는 책임 소재를 이전할 수 있습니다. 하지만 전화를 받을 능력을 이전할 수는 없습니다. 유지보수 담당자(maintainer)가 번아웃되거나, 저장소(repository)의 호스트가 이동하거나, 제품 라인이 조용히 엔터프라이즈급으로 재조정될 때, 법적 의무는 온전하게 살아남을 수 있지만 실질적인 의무는 증발할 수 있습니다. 당신은 청구서만 가지고 남게 되고, 거래 상대방(counterparty)은 잃게 됩니다.
이러한 간극에서 세 가지 실패 형태가 발생하며, 오늘 우리는 그 모든 유형 중 하나를 목격했습니다.
주소지가 이동한다. Roku는 아무것도 삭제하지 않았습니다. 단지 위치를 옮겼을 뿐입니다. 이는 이전 주소를 가리키던 모든 파이프라인(pipeline), 웹훅(webhook), 패키지 참조, CI 배지(CI badge), 문서 링크가 이제 영원히 유지할 것이라고 약속한 사람이 없는 리다이렉트(redirect)에 의존한다는 의미입니다. 오류는 발생하지 않았습니다. 단지 종속성(dependency)이 새로운 건물주를 얻었을 뿐입니다.
위험 범위(Blast radius)가 당신의 아래에서 확장됩니다. HTTP2Shell은 코드에 존재하는 새로운 취약점이 아닙니다. 이는 라이브러리를 사용한 것이 또 다른 라이브러리를 사용하는 과정에서 상속받게 된 코드의 취약점입니다. 중간 연결 고리의 유지보수 담당자가 2021년에 답변을 중단했을 수 있습니다. 이제 당신은 남의 방치된 의무에 대한 복구 마감일을 떠안게 되었습니다.
제품이 서비스를 능가합니다. 온도 조절기는 금속과 라디오 덩어리입니다. 그것을 온도 조절기로 만든 것은 '서비스'였습니다. 서비스가 은퇴하면, 하드웨어는 계속 작동하며 당신이 구매했던 물건의 기능을 상실하게 됩니다. 아무도 그것을 훔치지 않았고, 어떤 것도 침해되지 않았습니다. 그 의무는 단순히 이를 이행할 인센티브를 가진 누구에게도 승계되지 않았을 뿐입니다.
새벽 두 시의 테스트(The two-in-the-morning test)
이것이 이번 주에 실행할 수 있는 가장 저렴한 감사 방법입니다. 고객에게 보이는 동작을 중단시킬 수 있는 모든 의존성(dependency)에 대해 한 가지 질문을 던지십시오: 새로운 인수합병 이후에도 내가 전화를 걸 사람과 그 사람이 실제로 존재할 것인가?
대부분의 팀은 회사 이름을 대는 것은 할 수 있습니다. 하지만 사람은 훨씬 적게 말할 수 있습니다. 그리고 거의 아무도 두 번째 절반에 답할 수 없습니다. 왜냐하면 정직한 답변을 하려면 계약서에는 없는 것을 알아야 하기 때문입니다:
- 공급업체 측에서 이 시스템의 변경 사항을 승인할 수 있는 사람은 누구입니까?
- 계정 소유자가 퇴사했을 때 자격 증명(credentials)은 누가 가지고 있습니까?
- 운영 매뉴얼(runbook)에 지정된 후임자가 있습니까, 아니면 계정이 노트북 하나를 가진 단 한 명의 사람에게 의존하고 있습니까?
- 공급업체가 인수합병될 경우, 귀하의 계약은 양도(assignment)를 거쳐 생존할 수 있으며, 심지어 아예 양도가 가능한지 여부를 누군가 확인했습니까?
이 네 가지 질문에서 도출되는 패턴은 불편합니다. 잃을 위험이 가장 큰 의존성은 보통 승계 가능성이 가장 취약한 것들입니다. 핵심 인프라는 세 명의 사람과 메일링 리스트에 의해 유지되는 경향이 있습니다. 40페이지짜리 계약서를 가진 엔터프라이즈 공급업체는 분기(quarter) 안에 대체할 수 있는 대상인 경우가 많습니다.
승계는 법적 결정이 아닌 설계상의 결정이다
당신은 계약서로 승계를 보장할 수 없습니다. 아키텍처를 통해 이를 구현해야 합니다. 네 가지 속성이 대부분의 작업을 처리합니다:
주소 독립성(Address independence). 의존성이 어디에 위치하는지 하드코딩하지 마십시오. 직접 통제할 수 있는 레이어—자체 미러(mirror), 자체 레지스트리 프록시(registry proxy), 또는 자체 DNS—를 통해 이를 해결해야 합니다. 누군가 저장소(repository)의 위치를 옮기더라도, 그것을 사고(incident)가 아닌 설정 변경(config change)으로 경험할 수 있어야 합니다.
키를 가진 에스크로(Escrow with a key). 에스크로에 맡긴 소스 코드는 빌드 시스템, 비밀값 로테이션 절차(secrets rotation procedure), 그리고 40개의 서비스 중 실제로 어떤 것이 중요한지 설명하는 문서를 함께 제공하지 않는 한 기념품에 불과합니다. 상자를 필요로 하기 전에 그 안에 무엇이 들어있는지 물어보십시오.
탈출 가능한 데이터(Exit-capable data). 시스템의 전체 상태를 외부인이 가져와서 임포트할 수 있는 형식으로 내보낼 수 없다면, 당신은 데이터를 소유한 것이 아니라 접근 권한을 임대하고 있는 것입니다. 이것은 연속성 레이어(continuity layer)에서 한 단계 낮은 수준에 적용된 동일한 테스트입니다.
자체 건물 안에 이름이 지정된 후임자. 모든 중요한 공급업체는 로그인하여 문서를 읽었고, 무엇이 고장 나는지 아는 두 번째 담당자가 필요합니다. 구매자 측의 버스 팩터(Bus factor)가 1인 것은 판매자 측에서 버스 팩터가 1인 것만큼이나 치명적이며, 이는 전적으로 당신의 통제 하에 있습니다.
고객에게 제공해야 할 것
만약 스택(stack)의 어떤 부분을 재판매한다면—그리고 만약 에이전시, SaaS 또는 에이전트 제품을 운영한다면, 당연히 그렇게 합니다—승계는 엔지니어링 문제가 되기 전에 공개(disclosure) 문제입니다.
고객들은 당신의 공급업체 목록을 원하지 않습니다. 그들이 원하는 것은 세 가지 문장입니다: 공급업체가 사라질 경우 그들의 서비스에 무슨 일이 발생하는지, 그것을 대체하는 동안 얼마나 오랫동안 운영을 유지할 수 있는지, 그리고 당신 회사 내에서 누가 그 답변에 책임을 지는지입니다. 이 세 문장을 제시할 수 없다면, 당신은 스트레스 테스트를 거치지 않은 의존성을 판매하고 있는 것입니다.
공급업체 이탈 상황에서도 우아하게 살아남는 팀들은 더 나은 공급업체를 가진 팀들이 아닙니다. 그들은 위험을 그것이 중요해지기 몇 달 전에 평범한 언어로 먼저 들었던 고객들을 가진 팀들입니다. 이는 한 단락의 비용으로 수년간의 신뢰를 구매합니다.
이번 주에 할 여섯 가지 일
- 상위 5개 의존성(dependencies)에 대해 새벽 2시 테스트를 수행하세요. 각 항목에 대해 회사 이름, 담당자 이름, 그리고 "누가 변경을 승인하는지"에 대한 답변이 필요합니다. 빈칸은 취약점(finding)입니다.
- 대체할 수 없는 것은 모두 복제(mirror)하세요. 내부 레지스트리 프록시 하나, 통제 가능한 DNS 계층 하나가 필요합니다. 저장소 이전이 빌드에 문제가 생길 것 같다면, 이전에 문제를 해결해야 합니다.
- 에스크로 박스를 열어보세요. 가지고 있다면, 단순히 소스 코드뿐만 아니라 빌드 지침과 비밀(secret) 순환 정보가 들어 있는지 확인하세요. 없다면, 가격을 매겨서 하나를 마련해야 합니다.
- 갱신 계약에 양도 조항을 추가하세요. 인수 시 양도가 불가능한 계약은 종이 자체보다 가치가 낮습니다. 만료(renewal) 때가 아니라, 서명할 때 이 질문을 하세요.
- 귀사 측의 버스 팩터(bus factor)를 1에서 높이세요. 두 번째 엔지니어가 로그인하여 실행서(runbook)를 읽고, 이번 달에 변경 사항을 하나 수행해야 합니다. 기록된 접근 권한은 실제로 사용되는 접근 권한과 같지 않습니다.
- 인계 문단을 작성하세요. 한 단락으로 구성되어야 합니다: "공급업체 X가 사라진다면, 변경되는 사항은 무엇이며, 얼마나 오래 지속될 것이고, 누가 소유권을 갖는지." 가장 큰 고객에게 그들이 묻기 전에 보내세요.
이 모든 것은 시연(demo)에서 드러나지 않습니다. 공급업체가 연락을 끊는 분기에 모두 드러납니다. 그때가 되면, 중요한 것은 누군가가 이미 누가 의무를 승계하는지 기록했는지 여부뿐입니다.
다음 시리즈에서는 에스크로 계층에 대해 다룹니다. 후임자가 행동하기 위해 상자에 실제로 무엇이 들어 있어야 하는지, 그리고 키와 빌드 과정, 실행서가 없는 소스 코드가 자산(asset)이 아닌 기념품(souvenir)인 이유입니다.