## Memo - Microsoft - [[Internet Scale Services Checklist]] ## Morning Paper [On designing and deploying internet-scale services | the morning paper](https://blog.acolyer.org/2016/09/12/on-designing-and-deploying-internet-scale-services/) クラウドネイティブアプリケーションを構築する方法を知りたいですか?James Hamiltonが2007年に発表したこの論文に勝る知恵、ベストプラクティス、そして苦労して得た経験のコレクションを見つけるのは難しいでしょう。クラウドネイティブは、あなたが思っているほど新しいものではありません!この知識がすべて9年前(2007年)に収集され、書き留められたと考えると、驚きます。この論文には非常に多くの優れた点があり、しかも凝縮されているので、要約で正当な評価をするのは難しい。この記事を読んで興味を持たれた方は、ぜひ原著を読んでみてください。私は前回この論文を読んだとき、その内容の素晴らしさに衝撃を受け、この論文に基づいてサービスのチェックリストを作りました。システムの見直しや設計をされる方は、参考にしてみてください。 この論文は、3つの基本的な考え方と、運用に適したサービスを設計・展開するための様々な側面をカバーする10のサブセクションで構成されています。この論文では、運用に適したサービスは設計や開発から始まるものであり、後から付け足すものではないということを強調しています。 > 私たちは以前から、運用に関わる問題の8割は設計・開発に起因していると考えてきました。しかし、運用の問題のほとんどは、設計・開発の段階で発生しているか、あるいはそこで解決されるのがベストなのです。 この3つの原則は、他のすべての推奨事項にも共通するものです。 1. 失敗を予期せよ 2. 物事はシンプルに...複雑さは問題を生みますが、シンプルなものほどうまくいきやすいのです。 3. 人は間違いを犯し、睡眠を必要とし、物事を忘れるものです。自動化されたプロセスは、テスト可能であり、修正可能です。そのため、最終的にはより信頼できるものになります。 > Simplicity is the key to efficient operations. そして、10個のサブセクションの提言は、以下のカテゴリーに分かれる。 1. アプリケーション全体の設計(最大のセクション) - 21のベストプラクティス 2. 自動管理とプロビジョニング - 11のベストプラクティス 3. 依存性管理 - 6つのベストプラクティス 4. リリースサイクルとテスト - 12のベストプラクティス 5. ハードウェアの選択と標準化 - 4つのベストプラクティス(おそらくこの論文の中で最も古くなっているセクションですが、特別なペットのハードウェアに依存すべきではないという全体的な指摘は今でも的確です)。 6. 運用とキャパシティ・プランニング - 5つのベスト・プラクティス 7. 監査、モニタリング、アラート - 10のベストプラクティス 8. グレースフルデグラデーションとアドミッションコントロール - 3つのベストプラクティス 9. 顧客とプレスのコミュニケーション計画 - (必要になる前に)1つの場所に置く! 10. 顧客のセルフプロビジョニングとセルフヘルプ - すべての顧客が可能な限り自助努力すること この論文を要約するのが難しいと言った理由がお分かりいただけたでしょうか。上記はすべて私のチェックリスト[[Internet Scale Services Checklist]]に収められていますので、ご安心ください。 中には(当時は新しかったとはいえ)その後も度々繰り返されているアドバイスもあります。以下、あまり語られることのないもの、特に考えさせられるもの、あるいはあまりにもよくまとまっていて共有せずにはいられないものなどをピックアップしてみました。 NetflixがChaos Monkey([[Chaos Engineering]])について話し始める4年前に、ハミルトンはこう書いている。"この設計原則に完全に準拠するための厳しいテストは、次の通りだ。"運用チームは、最初に作業負荷を消耗することなく、いつでもサービス内のどのサーバでも停止させる意思と能力があるかどうかだ。 さらに彼は、セキュリティ脅威のモデリングに使用するのと同じアプローチで、コンポーネントの故障モードとその組み合わせを分析し、潜在的な脅威をそれぞれ検討し、適切な軽減策を実施することを推奨しています。 > 非常に珍しい故障の組み合わせは、そのような故障があってもシステムが動作できることを保証することは不経済であると判断される可能性があります。この判断は慎重に行う必要がある。私たちは、毎日何百万回もの部品故障の機会を生み出す何千台ものサーバーを運用する際に、いかに頻繁に「異常な」イベントの組み合わせが起こるかに驚いています。 サービスのバージョンは1つだけにするよう努力すること。最も経済的なサービスは、顧客が実行するバージョンを制御することを与えず、1つのバージョンのみをホストしています。ロールアウトと本番テストの間は、複数のバージョンが稼動することを認識する。すべてのコンポーネントのバージョンnとバージョンn+1は、平和的に共存する必要があります。 パーティションは無限に調整可能で細かく、現実世界の実体(人、コレクション、顧客など)には縛られないようにシステムを分割する。 > パーティションが会社別だと、大きな会社では1つのパーティションの大きさを超えてしまいます。パーティションが名前のプレフィックス別であれば、最終的には例えばPの全てが1台のサーバーに収まらなくなる。 - 自動化のための設計には、サービスモデルの大きな制約が含まれる場合があります。 > 設計と展開後のサービスの管理を自動化することは、非常に困難です。自動化を成功させるには、シンプルさと、明確で作りやすい運用上の決定が必要です。これは、自動化を容易にするために、必要であれば、レイテンシーとスループットを犠牲にする慎重なサービス設計に依存します。このトレードオフはしばしば困難であるが、大規模なサービスでは管理コストの削減は1桁以上にもなる。 (Hamilton氏が論文で挙げている例は、フェイルオーバーの決定を単純化するために同期レプリケーションを選択し、非同期レプリケーションの複雑さを回避するものである)。 - ライフサイクルを通じて、設定とコードを1つのユニットとして維持する。 - 障害を処理するのに一番適切なレベルはサービスレベルである。 > 障害を処理し、エラーを修正するのは、下位のソフトウェアレベルではなく、完全な実行コンテキストが利用可能なサービスレベルである。例えば、下位のソフトウェア層での復旧に依存するのではなく、サービスに冗長性を持たせる。 - 依存関係に気をつけよう ここでのHamilton氏のアドバイスと、マイクロサービス・アーキテクチャに向かうトレンドとを対比させると、興味深いことがわかります。 > 大規模なサービスにおける依存関係管理は、しばしばこのトピックに値するほどの注目を集めません。一般論として、小さなコンポーネントやサービスの依存関係は、それらを管理する複雑さを正当化するほどには保存されない。依存関係が意味を持つのは、次のような場合です。(1)依存するコンポーネントの規模や複雑さが大きい場合、(2)依存するサービスが単一の中心的なインスタンスであることに価値がある場合。 依存関係を導入する場合は、待ち時間を想定し、障害を分離し、実績のあるコンポーネント(サードパーティの依存)を使用し、サービス間の監視と警告を実装し、依存関係に障害が発生した場合にデグレードモードで運用を継続できるようにコンポーネントを切り離し、次のことを念頭に置いてください。 > 依存するサービスや依存するコンポーネントのプロデューサは、少なくとも依存するサービスと同じSLAにコミットする必要があります。 本番環境にできるだけ近い完全なステージング環境をわざわざ作ろうとしないでください(本番環境に近づくにつれ、コストは漸近し、prodのそれに急速に近づいていきます)。 > その代わり、新しいサービスのリリースは、標準的なユニットテスト、機能テスト、本番テストラボのテストを経て、最終テストフェーズとして限定本番に入ることをお勧めします。 これを自信を持って行うには、4つのルールに従う必要があります。 1. 本番システムは、壊滅的な障害から迅速に回復できるよう、十分な冗長性を持たなければならない。 2. データの破損や状態に関する障害は、極めて起こりにくいものでなければならない(機能テストはパスすること) 3. エラーが検出され、エンジニアリングチームがテスト中のコードのシステムヘルスを監視していなければならない。 4. すべての変更を迅速にロールバックすることが可能で、このロールバックは本番稼動前にテストされなければならない。 > もうひとつ、直感に反するかもしれませんが、夜間ではなく昼間にデプロイすることをお勧めします。夜間はミスのリスクが高くなります。また、夜中のデプロイで異常が発生した場合、それに対応できるエンジニアが少なくなってしまいます。 - 頻繁に出荷する 私たちは3ヶ月周期で出荷することを好んでいますが、他のスケジュールでも議論することができます。私たちの直感では、最終的には3カ月未満が標準になると思いますし、多くのサービスはすでに週単位で出荷しています。3ヶ月というのは、今の私にとっては氷河期のようです - プロダクションデータを使って問題を発見する > 大規模システムにおける品質保証は、データマイニングと可視化の問題であり、テストの問題ではありません。誰もが、本番環境における大量のデータを最大限に活用することに集中する必要があります。 - テストと開発では、サービス全体を単一のシステムで簡単にデプロイできるようにします。一部のコンポーネントでそれが不可能な場合は、エミュレータを作成します。「これがないと、単体テストが難しく、十分に実現できない」。 > システム全体を動かすことが困難な場合、開発者はシステムビューではなく、コンポーネントビューを取る傾向がある。 - 最悪の事態が発生した場合、破損したシステムから状態を移動させる手順を自動化する。 > サービスを効率的に運用するための鍵は、運用管理上のやりとりの大部分を排除するようにシステムを構築することです。信頼性の高い24時間365日のサービスを、8×5の少人数の運用スタッフで維持することを目標にすべきです。 - 開発チームに責任を持たせる... > 開発チームが夜中に頻繁に呼び出されるようであれば、自動化が考えられます。もしオペレーションが頻繁に呼び出されるなら、オペレーション・チームを大きくするのが通常の反応である。 ## Abstract 大規模サービスでは、管理コストを把握するための大まかな指標として、システム管理者比率がよく使われます。小規模で自動化されていないサービスでは、この比率は2:1と低くなることがありますが、業界をリードする高度に自動化されたサービスでは、2,500:1という高い比率を目にすることがあります。 Microsoftのサービスでは、Autopilot [1]がWindows Live Searchチームが高いシステム対管理者比率を達成するための魔法としてしばしば引用されています。自動管理は重要だが、最も重要なのはサービスそのものである。そのサービスは自動化するのに効率的か?一般的に言うところの「運用しやすい」(operations-friendly)サービスかどうか?オペレーションフレンドリーなサービスとは、人間がほとんど介在せず、管理者が介入することなく、最も曖昧な障害以外はすべて検知し、回復することができるサービスです。この論文では,MSN と Windows Live の最大規模のサービスを拡張するために,長年にわたって蓄積されたベストプラクティスを要約しています. ## 1. Introduction