Sia-Minio Integration Postmortem

Michael Lynch

Sia-Minio 통합 포스트모템

원문은 Michael Lynch님이 에 게재했습니다. 이 블로그 구독하기

구글에서 일하며 배운 것 중 가장 좋았던 것 중 하나는 비난 없는 포스트모템 문화다. 문제가 발생하면 먼지가 가라앉을 때까지 기다린 뒤 무슨 일이 있었는지 분석하는 보고서를 작성한다. 보고서에서는 문제가 어떻게 발생했는지 설명하고, 앞으로 유사한 문제를 완화하기 위해 팀이 취할 수 있는 구체적인 조치를 정의한다.

지난주에 포스트모템을 하기에 좋은 기회를 발견했다. 현상금으로 진행된 프로젝트인 Minio에 Sia 지원을 통합하는 작업이 공식적으로 완료됐지만, 예상보다 몇 달이나 더 걸렸고 대규모 재작업을 여러 차례 거쳤다.

Sia는 분산형 클라우드 스토리지 기술이다. 내가 가장 좋아하는 기술 중 하나라 이전에도 다룬 적이 있다. Minio는 오픈소스 S3 호환 파일 서버다. 두 기술의 통합으로 이제 사용자들은 Amazon S3와 호환되는 어떤 백업 소프트웨어를 사용해서든 Sia 네트워크에 데이터를 백업할 수 있게 됐다.

이번 통합은 매우 중요한 성과이며, 12월 Sia 릴리스 이후 소프트웨어가 안정화되면 이에 대해 더 자세히 다룰 예정이다. 그 전까지는 통합 과정에 대한 포스트모템을 주도할 좋은 기회라고 봤다. 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 책의 “Postmortem Culture: Learning from Failure”을 참고하라.

요약

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는 Minio가 테스트에 사용할 Sia 테스트 서버를 자발적으로 구축하고, 설정하고, 비용까지 부담했다.
  • Minio 메인테이너들은 시간을 아낌없이 내어 동일한 PR을 수개월 동안 계속 검토해 줬다.

타임라인

  • 2017-07-19: Nebulous Labs가 일련의 Sia 현상금을 발표하고, 그 첫 번째로 Sia와 Minio 통합 현상금을 공개한다.
  • 2017-07-24: @dvstate가 개념 증명 통합을 공개한다.
  • 2017-08-03: Nebulous Labs가 @dvstate에게 현상금 전액을 지급한다.
  • 2017-08-09: @dvstate가 Minio 소스에 Sia 통합을 위한 첫 번째 PR을 올린다.
  • 2017-08-09: @harshavardhana가 SQLite 대신 BoltDB를 사용하도록 PR을 다시 작성해 달라고 요청한다.
  • 2017-08-13: @harshavardhana가 Sia-Minio 통합을 수용하기로 동의한다.
  • 2017-08-16: @dvstate가 BoltDB로의 재작성을 완료한다.
  • 2017-08-28: 코드 리뷰 중 @harshavardhana가 데이터베이스를 아예 제거하고 캐싱 레이어 없이 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 Slack의 #bounties 채널이나 쪽지를 통해 @dvstate에게 연락해 기능을 요청했다. 요구사항에 대한 공식 정의가 없었기 때문에, @dvstate는 이를 무시하면 현상금을 받지 못할까 봐 해당 추가 기능들을 구현했다.

그 결과 @dvstate와 Minio 메인테이너, Sia 사용자 사이에서 다음 이슈들에 대해 혼란이 생겼다:

  • 어떤 서드파티 라이브러리를 사용할 수 있는지
  • Sia 통합이 상태 정보와 메타데이터를 보존하기 위해 파일시스템에 캐시를 유지해도 되는지
  • Sia 통합이 멀티파트 파일 전송을 구현해야 하는지
  • Sia 통합이 버킷 정책 설정을 지원해야 하는지
  • 어떤 S3 클라이언트 애플리케이션을 지원해야 하는지(예: mc, s3cmd)
  • 정상 동작을 입증하기 위해 어느 정도의 수동 테스트가 필요한지
  • Sia 통합이 Sia 전용 환경 변수를 몇 개까지 사용할 수 있는지
  • 테스트 커버리지는 어느 정도가 요구되는지
  • Minio UI에 어떤 변경이 필요하거나 허용되는지
  • Minio 문서에 어떤 변경이 필요한지

@dvstate는 결국 원래 현상금 설명에는 없던 Minio 메인테이너의 요구사항에 대응하느라 완전히 다른 세 가지 버전의 통합을 작성하게 됐다(첫 번째, 두 번째, 세 번째).

권장 조치 사항:

  • 향후 Sia 현상금에서는 사전에 서드파티 메인테이너와 협력해 요구사항을 정하고 이를 현상금 지급 기준에 포함한다.

  • 현상금에 대한 객관적인 승인 테스트를 마련한다. 예를 들면 다음과 같다:

    1. allowance로 500 SC가 설정된 siad가 구동된 서버를 프로비저닝한다.

    2. 클라이언트는 다음 명령어로 minio를 실행한다:

      export MINIO_ACCESS_KEY=minioaccesskey
      export MINIO_SECRET_KEY=miniosecretkey
      ./minio gateway sia
      
    3. 클라이언트 머신의 ~/test-data 폴더에는 크기가 1KB부터 10GB까지 다양한 파일 100개가 있으며, 전체 용량은 4TB를 넘지 않는다. 파일들은 최대 3단계 깊이의 중첩 폴더를 포함한다.

    4. 클라이언트 머신에서 다음 명령어를 성공적으로 실행한다:

      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/
      
    5. 다운로드한 파일의 SHA-1 해시가 원본 파일의 SHA-1 해시와 일치한다

  • 현상금 공고에서 모호한 점이 발견되면, 콘테스트 기간 내내 변경 로그와 함께 공고를 계속 업데이트한다.

  • 현상금 수상을 위한 요구사항의 공식 출처는 현상금 이슈 트래커임을 명확히 한다.

  • 현상금 참가자는 공식 현상금 트래커 외부에서 제기된 요청을 충족할 필요가 없다.

성공적인 통합이 아닌 개념 증명을 기준으로 지급된 현상금

Nebulous는 Sia 코어 개발자들의 검토 후, 그러나 Minio 메인테이너의 승인을 받기 전에 현상금을 지급했다. 현상금의 진정한 목표는 Minio 저장소에 통합되는 것이었으며, 그렇지 않으면 사용자들은 @dvstate의 유지보수되지 않는 포크에 있는 코드를 배포하기를 꺼릴 것이기 때문이다.

Sia는 @dvstate가 자신의 책임이 끝난 뒤에도 오랫동안 PR 작업을 계속해 준 덕분에 운이 좋았지만, 현상금의 진정한 목표 달성이 수상자의 호의에 의존해서는 안 된다.

현상금이 지급되기 전에는 상을 받으려는 긴박감이 있어 요청된 변경 사항이 몇 시간 또는 며칠 안에 구현됐다. 지급된 후에는 지연 시간이 몇 주로 늘어났다.

이는 @dvstate가 자원봉사 형태로 최선을 다해 작업했기 때문에 예상 가능하고 합리적인 일이다. Sia 입장에서는 지연 시간이 무한대가 아니었던 것만으로도 운이 좋았다.

권장 조치 사항:

  • 개념 증명이 아닌 성공적인 통합을 기준으로 현상금을 지급한다.
  • 대상 저장소에 성공적으로 병합되는 것을 향후 현상금의 명시적 요건으로 만든다.

Minio 통합이 siac 커맨드라인 클라이언트의 로직을 중복함

Minio 통합 코드의 30~40%는 Sia API를 구현하는 로직에 불과하다. 이는 Sia 코어 저장소에 이미 존재하는 코드를 중복하는 것으로, siac 커맨드라인 클라이언트가 동일한 기능을 구현하고 있기 때문이다.

Go를 포함한 어떤 언어에 대해서도 공식 Sia API 바인딩이 존재하지 않는다. Go는 Sia의 네이티브 언어임에도 그렇다.

권장 조치 사항:

  • 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 메인테이너와 협력해야 했다.

권장 조치 사항:

  • 서드파티 통합을 위한 향후 현상금에서는 현상금 주최 측이 솔루션 검증과 서드파티 파트너의 검증을 돕는 책임을 진다.
  • 현상금에 대한 객관적인 승인 테스트를 마련한다. (“불명확한 요구사항” 참고).

이 글은 muse-spark-1.2-contributor 모델을 사용해 번역했습니다.

댓글