Sia-Minio統合ポストモーテム
Googleで働いて学んだことの中で最も良かったことの一つが、非難なきポストモーテムの文化です。何か問題が起きたときは、ほとぼりが冷めてから、何が起きたのかを分析するレポートを書きます。そのレポートでは問題がどのように発生したかを説明し、同じ問題を今後防ぐためにチームが取れる具体的な対策を定義します。
先週、ポストモーテムを行う絶好の機会がありました。バウンティ(懸賞金)によるプロジェクトとして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はMinio(オープンソースのS3互換ファイルサーバー)とのSia統合に対して300,000 SCのバウンティを発表しました。開発者のDavid Gore氏(@dvstate)は5日後に概念実証を公開し、その10日足らずで満額の賞金が授与されました。
その後、統合がMinioのリポジトリにマージされるまで、さらに3か月を要しました。コードをMinioに受け入れてもらうためには全面的な再設計が必要となり、@dvstate氏はバウンティでは正式に補償されない多大な作業を担うことになりました。
統合自体は機能していますが、完成にあたってはバウンティで想定されていなかったいくつかの制限を追加する必要がありました。
- ファイル名に使える文字が限られたホワイトリスト方式に制限されており、Siaが本来許容する範囲よりも厳しくなっています。
- マルチパートでのファイル転送には対応していません。
- 自動テストのカバレッジがあるのは、ごく単純な2つの関数のみです。
影響
今回の出来事で最も大きな影響は、重要なパートナーとの統合が数か月遅れたことです。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バウンティを発表し、MinioとのSia統合のバウンティから開始しました。
- 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メンテナーからの要件に対応するため、統合を大幅に異なる3つのバージョン(1つ目、2つ目、3つ目)で書き上げることになりました。
推奨されるアクションアイテム:
今後のSiaバウンティでは、サードパーティのメンテナーと事前に要件を固め、バウンティの受賞基準に含めるようにします。
バウンティに対する客観的な受け入れテストを定めます。例えば次のようにします。
allowanceとして500 SCが割り当てられたsiadが動作するサーバーを用意します。
クライアントは次のコマンドでminioを起動します。
export MINIO_ACCESS_KEY=minioaccesskey export MINIO_SECRET_KEY=miniosecretkey ./minio gateway siaクライアントマシンには、1 KBから10 GBまでサイズが異なる100個のファイルが、
~/test-dataフォルダー内に合計4 TBを超えない範囲で用意されています。ファイルには最大で深さ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ハッシュと一致します。
バウンティ告知に曖昧な点が見つかった場合は、コンテスト期間を通じて変更履歴を示しながら継続的に更新します。
バウンティの受賞要件については、バウンティのissueトラッカーが正式な情報源であることを明確にします。
バウンティ参加者は、公式のバウンティトラッカー以外で寄せられた要望に応える必要はありません。
概念実証ではなく統合成功を基準とすべきだったバウンティの支払い
NebulousはSiaコア開発者によるレビューの後にバウンティを授与しましたが、それはMinioメンテナーからの承認を得る前でした。バウンティの真の目的はMinioリポジトリへの統合であり、そうでなければユーザーは@dvstate氏のメンテナンスされていないフォークのコードを導入することを躊躇してしまいます。
Siaは幸運にも、@dvstate氏が自身の責務が終わった後も長くPRに取り組み続けてくれましたが、バウンティの真の目的の達成を、受賞者の善意に依存させるべきではありません。
バウンティが授与される前は、賞を獲得するために切迫感があり、要望された変更は数時間から数日で実装されていました。授与後は、遅延が数週間に延びました。
これは@dvstate氏がボランティアのベストエフォートで作業していたことを考えれば当然かつ妥当なことです。Siaとしては、遅延が無限大にならなかっただけでも幸運でした。
推奨されるアクションアイテム:
- バウンティの支払いは概念実証ではなく、統合の成功を基準に行います。
- 対象リポジトリへのマージ成功を、今後のバウンティの明確な要件とします。
Minio統合におけるsiacコマンドラインクライアントとのロジック重複
Minioの統合コードの30〜40%は、Sia APIを実装するためのロジックに過ぎません。これはSiaコアリポジトリに既に存在するコードの重複であり、siacコマンドラインクライアントが同じ機能を実装しているからです。
Siaのネイティブ言語であるGoを含め、どの言語にも公式のSia APIバインディングが存在しません。
推奨されるアクションアイテム:
- Sia API用の公式Goクライアントライブラリを作成します。
siacをこのライブラリのリファレンスクライアントとし、Minio統合をこのライブラリを使う形にリファクタリングします。 - Go以外のコードを必要とする今後のバウンティでは、必要なSia API機能を実装するためのライブラリを作成することを提出要件とします。このライブラリはアプリケーション固有のコードから独立したものとします。
Minio統合のテストカバレッジが極めて低い
自動テストの対象となっているのはごく単純な2つの関数のみであり、Sia Minioコードへの変更がMinioの機能を壊しても検出することが困難です。
推奨されるアクションアイテム:
- 今後のSiaバウンティでは、自動テストを要件とします。
レビュー時の情報のサイロ化
PRに必要な変更に関する重要な議論が非公開で行われました。@dvstate氏や@harshavardhana氏以外は、進捗を追ったりPRを前に進める手助けをしたりすることができませんでした。
推奨されるアクションアイテム:
- バウンティの支払いは概念実証ではなく、統合の成功を基準に行います。
- 議論は一つの集約された場所(例:バウンティ用のGithub issue)で行うことを必須とし、すべてのバウンティ応募者が同じ情報にアクセスできるようにします。
「最初に完了した者が勝つ」方式のバウンティがもたらす逆インセンティブ
バウンティプログラムのルールには次のように記載されています。
バウンティは一つの提出に対して一度だけ支払われ、別途指定がない限り、バウンティに定められたすべての基準を最初に満たした個人またはチームに支払われます。
この仕組みは、バウンティ応募者が実装コストを最小化するようにソリューションを最適化することを促し、その結果、可読性や保守性、明確なドキュメントに時間をかける動機を削いでしまいます。
Minio統合のケースでは、コードには十分なドキュメントがあるものの、テストが不足しており、SiaのロジックとMinioのロジックが混在しているため、将来の保守性に課題が生じる可能性があります。
この制度は、コラボレーションや改善の意欲も削ぎます。ある開発者がソリューションを公開すると、バウンティはおそらく最初の提出者に支払われるため、他の開発者が別のソリューションに挑戦する動機がなくなります。ルールがそのような状況を想定していないため、他の応募者の提出物を改善する道筋もありません。
推奨されるアクションアイテム:
- 無差別な「提出ウィンドウ」を設けます。
- 提出の速さが問われない期間を定めます(例:バウンティコンテストの最初の2週間に受け付けたすべての提出を同等に扱います)。
- 応募者は早期に提出できますが、他者がその成果をフォークして改善することを認めます(単なるシンボル名の変更などではなく、実質的な改善である必要があります)。この場合、バウンティはNebulousの裁量で貢献した開発者間で分割されます。
- 最初の提出ウィンドウが終了した後は、有効な最初の提出に賞が授与されます。
サードパーティによる検証の困難さ
MinioチームはそれまでSiaの経験がありませんでした。Minioが安心してPRをマージできるようになるまでに、@dvstate氏は自費でテストサーバーを用意し、事前に告知されていなかった一連の手動検証ステップについてMinioメンテナーと共に作業する必要がありました。
推奨されるアクションアイテム:
- サードパーティ統合に関する今後のバウンティでは、バウンティ主催者がソリューションの検証と、サードパーティパートナーが検証を行う際の支援に責任を持つようにします。
- バウンティに対する客観的な受け入れテストを定めます(「要件の不明確さ」を参照)。
記事をランダムに読む