Sia-Minio 통합 포스트모템
Google에서 일하며 배운 가장 좋은 것 중 하나는 블레임 프리 포스트모템 관행입니다. 문제가 발생하면 먼지가 가라앉을 때까지 기다린 뒤, 무슨 일이 있었는지 분석하는 보고서를 작성합니다. 이 보고서는 문제가 어떻게 발생했는지 설명하고, 앞으로 유사한 문제를 완화하기 위해 팀이 취할 수 있는 구체적인 조치를 정의합니다.
지난주에 포스트모템을 하기에 좋은 기회를 발견했습니다. Minio에 Sia 지원을 통합하는 현상금 프로젝트가 공식적으로 완료됐는데, 예상보다 수개월이나 더 걸렸고 여러 차례 대규모 재작업을 거쳤기 때문입니다.
Sia는 탈중앙화 클라우드 스토리지 기술입니다. 제가 가장 좋아하는 기술 중 하나라서 이전에도 다룬 적이 있습니다. Minio는 오픈소스 S3 호환 파일 서버입니다. 두 기술의 통합으로 사용자는 이제 Amazon S3와 호환되는 어떤 백업 소프트웨어를 사용해서든 Sia 네트워크에 데이터를 백업할 수 있게 되었습니다.
이번 통합은 매우 중요한 성과이며, Sia의 12월 릴리스 이후 소프트웨어가 안정화되면 이에 대해 더 자세히 다룰 예정입니다. 그에 앞서 통합 과정에 대한 포스트모템을 진행할 좋은 기회라고 생각했습니다. Nebulous Labs 팀에 제안했더니 아이디어를 반겼고, Sia-Minio 통합 코드를 작성한 개발자에게 연락했더니 그 역시 흔쾌히 동의해 함께 보고서 작성에 참여했습니다. Nebulous Labs와 Minio 팀이 검토하고 게재를 승인했으므로, 아래에서 전체 보고서를 확인하실 수 있습니다:
Minio 통합 현상금 포스트모템
Nebulous Labs 인시던트 #1
날짜: 2017-12-01
작성자:
- Michael Lynch - @mtlynch - Sia 블로거 및 /r/siacoin 모더레이터.
- David Gore - @dvstate - 개발자, 현상금 수상자
검토자
- David Vorick - @taek42 - 리드 개발자, Nebulous Labs
- Zach Herbert - @zherbert - 운영 부사장, Nebulous Labs
- @harshavardhana - Minio 메인테이너
배경: 포스트모템이란 무엇인가?
포스트모템은 계획대로 진행되지 않은 최근의 경험을 통해 배우기 위한 활동입니다.
포스트모템은 블레임 프리 방식으로 진행됩니다. 즉, 잘못된 결과를 낳은 프로세스의 문제를 찾아내는 것이 목적이며, 사람을 찾아내 비난하려는 것이 아닙니다. 논의 대상이 된 사건에 참여한 모든 사람은 유능하고 선의를 가졌다는 것을 전제로 합니다.
자세한 내용은 SRE 책의 “포스트모템 문화: 실패로부터 배우기”를 참고하십시오.
요약
7월 19일, Nebulous Labs는 오픈소스 S3 호환 파일 서버인 Minio와 Sia를 통합하는 작업에 대해 300,000 SC의 현상금을 내걸었습니다. 개발자 David Gore(@dvstate)는 5일 뒤 개념 증명을 공개했고, 그로부터 10일도 채 지나지 않아 상금 전액을 받았습니다.
통합이 Minio 저장소에 병합되기까지는 추가로 3개월이 더 걸렸습니다. 코드를 Minio에 채택되게 하려면 코드를 완전히 재설계해야 했고, @dvstate는 현상금으로 공식적인 보상을 받지 못한 상당한 추가 작업을 수행해야 했습니다.
통합 자체는 동작하지만, 현상금에서 예상하지 못했던 몇 가지 제약이 추가된 채로 완료됐습니다:
- Sia가 허용하는 것보다 더 제한적인, 제한된 파일명 문자 화이트리스트만 지원합니다.
- 멀티파트 파일 전송을 지원하지 않습니다.
- 사소한 두 함수만이 자동화된 테스트 커버리지를 갖추고 있습니다.
영향
이번 일련의 사건이 미친 가장 큰 영향은 핵심 파트너와의 통합이 수개월 지연됐다는 점입니다. Sia가 S3 호환성을 확보한 것은 엄청난 이정표이지만, 과정이 너무 길어지면서 그 성취감이 반감된 느낌입니다.
이 과정에서 겪은 난항은 Sia에 대해 다음과 같은 부정적인 인식을 심어주었습니다:
- Sia와 통합하는 것은 어렵고, 심지어 Sia의 네이티브 언어인 Go에서도 중복된 노력이 필요합니다.
- Sia 현상금을 완수하는 것은 승인 기준이 불명확해 어렵습니다.
얻은 교훈
잘된 점
- Sia가 Minio에 성공적으로 통합되었습니다.
- Sia 커뮤니티 구성원들이 다양한 S3 클라이언트를 활용해 여러 시나리오에서 Minio 통합을 테스트하는 데 참여했습니다.
잘못된 점
- 기능과 요구사항에 대한 오해로 인해 통합을 여러 차례 다시 작성해야 했습니다.
- Minio 메인테이너의 리뷰와 PR 업데이트 사이에 긴 지연(경우에 따라 수 주)이 있었습니다.
- @dvstate는 Sia 통합 PR이 진행되는 동안 Minio 코드베이스 변경으로 인한 머지 충돌을 해결하는 데 적지 않은 시간을 써야 했습니다.
운이 좋았던 점
- @dvstate는 Nebulous가 현상금을 지급한 뒤에도 수개월간 자발적으로 시간을 내어 통합 작업을 이어갔습니다.
- @dvstate는 자발적으로 Sia 테스트 서버를 직접 구축·설정하고 비용까지 부담해 Minio가 테스트에 사용할 수 있도록 제공했습니다.
- Minio 메인테이너들이 시간을 아낌없이 내어 동일한 PR을 수개월 동안 계속 리뷰해 주었습니다.
타임라인
- 2017-07-19: Nebulous Labs가 일련의 Sia 현상금을 발표하고, 그 시작으로 Minio와 Sia를 통합하는 현상금을 내겁니다.
- 2017-07-24: @dvstate가 개념 증명 통합을 공개합니다.
- 2017-08-03: Nebulous Labs가 @dvstate에게 현상금 전액을 수여합니다.
- 2017-08-09: @dvstate가 Minio 소스에 Sia 통합을 위한 첫 번째 PR을 생성합니다.
- 2017-08-09: @harshavardhana가 @dvstate에게 SQLite 대신 BoltDB를 사용하도록 PR을 다시 작성해 달라고 요청합니다.
- 2017-08-13: @harshavardhana가 Sia-Minio 통합을 수락하기로 동의합니다.
- 2017-08-16: @dvstate가 BoltDB로의 재작성을 완료합니다.
- 2017-08-28: 코드 리뷰 중 @harshavardhana가 @dvstate에게 데이터베이스 자체를 제거하고 캐싱 계층 없이 PR을 다시 작성해 달라고 요청합니다.
- 2017-09-26: PR에 수주간 진전이 없자, @zherbert와 @mtlynch가 진행 상황 업데이트를 요청합니다.
- 2017-10-19: @dvstate가 캐싱 계층을 제거한 PR 재작성을 완료합니다.
- 2017-10-24: @harshavardhana가 @dvstate에게 패치를 보냅니다.
- 2017-10-25: @dvstate가 기존 PR을 닫고 Minio 측 요청과 @harshavardhana의 패치를 반영한 새로운 PR을 시작합니다.
- 2017-10-26 - 2017-11-21: @dvstate가 Sia-Minio 테스트 노드를 직접 구축하고 비용을 부담해 @harshavardhana에게 접근 권한을 제공합니다. 두 사람은 Minio 웹 앱, s3cmd, mc 커맨드라인 도구를 이용해 통합을 수동으로 테스트합니다.
- 2017-11-22: Minio PR이 병합됩니다.
관찰된 문제점
요구사항 불명확
현상금 설명에는 Sia-Minio 통합의 세부 사항이 상당 부분 정의되어 있지 않았습니다. “사용자가 Minio 클라이언트를 사용해 Sia 파일을 업로드/다운로드할 수 있어야 한다”고 명시했을 뿐, Minio 메인테이너 측의 제약이나 요구사항에 대해서는 언급하지 않았습니다.
게다가 여러 Sia 사용자가 Sia 슬랙의 #bounties 채널이나 비공개 메시지를 통해 @dvstate에게 기능을 요청했습니다. 요구사항에 대한 공식적인 정의가 없었기 때문에, @dvstate는 이를 무시하면 현상금 수상을 놓칠 수 있다는 우려에 해당 추가 기능들을 구현했습니다.
그 결과 @dvstate, Minio 메인테이너, Sia 사용자 사이에서 다음 이슈들에 대해 혼란이 발생했습니다:
- 어떤 서드파티 라이브러리를 사용할 수 있는지
- Sia 통합이 상태 정보와 메타데이터를 보존하기 위해 파일 시스템에 캐시를 유지해도 되는지
- Sia 통합이 멀티파트 파일 전송을 구현해야 하는지
- Sia 통합이 버킷 정책 설정을 지원해야 하는지
- 어떤 S3 클라이언트 애플리케이션(mc, s3cmd 등)을 지원해야 하는지
- 제대로 동작함을 입증하기 위해 어느 정도의 수동 테스트가 필요한지
- Sia 통합이 몇 개의 Sia 전용 환경 변수를 사용할 수 있는지
- 어느 정도의 테스트 커버리지가 필요한지
- Minio UI에 어떤 변경이 필요/허용되는지
- Minio 문서에 어떤 변경이 필요한지
@dvstate는 결국 원래 현상금 설명에는 없던 Minio 메인테이너의 요구사항 때문에 전혀 다른 세 가지 버전의 통합을 작성해야 했습니다(첫 번째, 두 번째, 세 번째).
권장 조치 사항:
향후 Sia 현상금에서는 사전에 서드파티 메인테이너와 협의해 요구사항을 정하고 이를 현상금 수상 기준에 포함합니다.
현상금에 대한 객관적인 인수 테스트를 마련합니다. 예를 들면:
500 SC의 할당량(allowance)이 설정된 siad가 설치된 서버를 프로비저닝합니다.
클라이언트는 다음 명령으로 minio를 실행합니다:
export MINIO_ACCESS_KEY=minioaccesskey export MINIO_SECRET_KEY=miniosecretkey ./minio gateway sia클라이언트 머신에는 크기가 1KB에서 10GB까지 다양한 파일 100개가 폴더
~/test-data에 있으며, 전체 용량은 4TB를 넘지 않습니다. 파일에는 최대 3단계 깊이의 중첩 폴더가 포함됩니다.클라이언트 머신에서 다음 명령을 성공적으로 실행합니다:
SERVER=insert.server.hostname # replace with actual server mc config host add minio-sia \ "http://${SERVER}" minioaccesskey miniosecretkey S3v4 mc mb minio-sia/sia-test-bucket # Upload test files. mc cp --recursive ~/test-data/* minio-sia/sia-test-bucket/ # Download test files. mc cp --recursive \ minio-sia/sia-test-bucket/* ~/test-data-downloaded/다운로드한 파일의 SHA-1 해시가 원본 파일의 SHA-1 해시와 일치합니다
현상금 공고에서 모호한 부분이 발견되면, 콘테스트 기간 내내 변경 사항을 changelog와 함께 계속 업데이트합니다.
현상금 이슈 트래커가 현상금 수상을 위한 요구사항의 공식 출처임을 명확히 합니다.
현상금 참가자는 공식 현상금 트래커 밖에 나타나는 요청을 충족할 필요가 없습니다.
개념 증명이 아닌 성공적인 통합을 기준으로 지급된 현상금
Nebulous는 Sia 코어 개발자들의 검토 후에, 그러나 Minio 메인테이너의 승인 전에 현상금을 수여했습니다. 현상금의 진정한 목표는 Minio 저장소에 통합되는 것이었으며, 그렇지 않으면 사용자들이 @dvstate의 유지보수되지 않는 포크에서 나온 코드를 배포하기를 꺼릴 것이기 때문입니다.
Sia는 @dvstate가 책임이 끝난 뒤에도 오랫동안 PR 작업을 계속해 준 덕분에 운이 좋았지만, 현상금의 진정한 목표 달성이 수상자의 선의에 의존해서는 안 됩니다.
현상금이 수여되기 전에는 상금을 차지하려는 긴박감 때문에 요청된 변경 사항이 수 시간 또는 수 일 내에 구현됐습니다. 수여된 뒤에는 지연 시간이 수 주로 늘어났습니다.
이는 @dvstate가 자원봉사 형태로 최선을 다해 작업했기 때문에 예상 가능하고 합리적인 일입니다. Sia 입장에서는 무한대가 아닌 지연 시간을 얻을 수 있었던 것만으로도 운이 좋았던 셈입니다.
권장 조치 사항:
- 현상금은 개념 증명이 아닌 성공적인 통합을 기준으로 지급합니다.
- 대상 저장소에 성공적으로 병합되는 것을 향후 현상금의 명시적 요건으로 만듭니다.
Minio 통합이 siac 커맨드라인 클라이언트의 로직을 중복
Minio 통합 코드의 30~40%는 단순히 Sia API를 구현하는 로직입니다. 이는 Sia 코어 저장소에 이미 존재하는 코드를 중복하는 것으로, siac 커맨드라인 클라이언트가 동일한 기능을 구현하고 있기 때문입니다.
Go를 비롯해 어떤 언어에 대해서도 공식 Sia API 바인딩이 존재하지 않으며, 여기에는 Sia의 네이티브 언어인 Go도 포함됩니다.
권장 조치 사항:
- Sia API를 위한 공식 Go 클라이언트 라이브러리를 만듭니다.
siac를 이 라이브러리의 레퍼런스 클라이언트로 삼고, Minio 통합은 이 라이브러리를 사용하도록 리팩터링합니다. - Go가 아닌 코드를 요구하는 향후 현상금에서는, 제출물이 필요한 Sia API 기능을 구현하는 라이브러리를 만들도록 요구합니다. 이 라이브러리는 애플리케이션 전용 코드와는 독립적이어야 합니다.
Minio 통합의 테스트 커버리지가 거의 없음
사소한 두 함수만이 테스트 커버리지를 갖추고 있어, Sia Minio 코드에 대한 변경이 Minio 기능을 깨뜨리는지 감지하기 어렵습니다.
권장 조치 사항:
- 자동화된 테스트를 향후 Sia 현상금의 요건으로 만듭니다.
리뷰 과정에서의 정보 사일로화
PR에 필요한 변경에 대한 핵심 논의가 비공개로 이루어졌습니다. @dvstate나 @harshavardhana 외에는 아무도 진행 상황을 추적하거나 PR을 앞으로 나아가게 도울 수 없었습니다.
권장 조치 사항:
- 현상금은 개념 증명이 아닌 성공적인 통합을 기준으로 지급합니다.
- 논의가 중앙화된 장소(예: 현상금을 위한 Github 이슈)에서 이루어지도록 하여 모든 현상금 지원자가 동일한 정보에 접근할 수 있게 합니다.
‘선착순 완료’ 현상금이 만드는 왜곡된 인센티브
현상금 프로그램 규정은 다음과 같이 명시합니다:
현상금은 한 번만, 하나의 제출물에만 지급되며, 별도로 명시되지 않는 한 현상금에 명시된 모든 기준을 가장 먼저 충족한 개인 또는 팀에게 지급됩니다.
이는 현상금 제출자가 구현 비용을 최소화하도록 솔루션을 최적화하게 만들고, 결과적으로 가독성, 유지보수성 또는 명확한 문서화에 시간을 투자할 유인을 떨어뜨립니다.
Minio 통합의 경우 코드는 문서화가 철저하지만, 테스트가 부족하고 Sia 로직과 Minio 로직이 뒤섞여 있어 향후 유지보수에 어려움을 겪을 수 있습니다.
이 시스템은 협업이나 개선에 대한 유인도 떨어뜨립니다. 개발자가 솔루션을 공개하면 다른 개발자는 현상금이 첫 번째 제출자에게 돌아갈 가능성이 높기 때문에 솔루션을 시도할 유인이 없습니다. 다른 지원자의 제출물을 개선할 경로도 없습니다. 규칙이 그런 시나리오를 다루지 않기 때문입니다.
권장 조치 사항:
- 무차별적인 “제출 기간”을 도입합니다
- 제출 속도가 중요하지 않은 기간을 지정합니다(예: 현상금 콘테스트 첫 2주 동안 접수된 모든 제출물은 동등하게 취급합니다).
- 지원자는 일찍 제출할 수 있지만, 다른 사람이 그 작업을 포크해 개선할 수 있습니다(단순히 심볼 이름을 바꾸는 수준이 아니라 실질적인 개선이어야 합니다). 이 경우 현상금은 Nebulous의 재량에 따라 기여한 개발자들끼리 나누어 지급됩니다.
- 초기 제출 기간이 끝난 뒤에는 첫 번째 유효한 제출물에게 상이 수여됩니다.
서드파티 검증의 어려움
Minio 팀은 Sia에 대한 사전 경험이 전혀 없었습니다. Minio가 PR을 병합하기에 앞서, @dvstate는 자비로 테스트 서버를 프로비저닝하고 이전에는 공지된 적 없던 일련의 수동 검증 단계를 Minio 메인테이너와 함께 수행해야 했습니다.
권장 조치 사항:
- 서드파티 통합을 위한 향후 현상금에서는, 현상금 주최 측이 솔루션을 검증하고 서드파티 파트너가 검증할 수 있도록 지원하는 책임을 집니다.
- 현상금에 대한 객관적인 인수 테스트를 마련합니다. (“요구사항 불명확” 참조).
글을 무작위로 읽기