えいのうにっき

a-knowの日記です

大事なことは「コード化すること」だけじゃない 〜 Infrastructure as Code を読んだ

「いつか読みたいな」と欲しいものリストに入れていた Infrastructure as Code を、まさかまさか、有り難いことに監訳者である @gosukenator さんからご恵贈いただいたのが、昨年11月のこと。

はやくも4ヶ月が経過してしまった。相変わらずの遅読さよ。すみませんすみません。

感想

以前はchef、最近だと itamae といったプロビジョニングツールは必ず使うようにしていて、特に GitHub - a-know/a-know-home-server: a-know-home chef recipe repository なんかは、

  • chef(knife solo)によるプロビジョニング
  • Serverspec によるテスト
  • CircleCI による chef recipe の CI

といったことまで頑張って実施をしていたので、「Infrastructure as Code」、自分はできていると思っていた。少なくとも、「できている方」だと思っていた。......そんな甘くも浅はかな自己認識を打ち砕いてくれる、素晴らしい本だった。「Infrastructure as Code チョットデキル」なんて口を滑らせる前に出会えてよかった。。(怖がりすぎ)

Infrastructure as Code とは、単なる「インフラ設定・構成のコード化」ではないことはさることながら、「それによるソフトウェア開発のベストプラクティスの活用」にとどまらず、また「それを組み込んでの自動化を実現すること」だけにもあらず。Infrastructure as Code を実現する、ということは、それに合った形にチーム、運用の形を変える、ということなのだ。本の中でも紹介されている Conway の法則の力を信じるのなら、「Infrastructure as Code には、チーム、運用の形を変える力がある」とも言えるかもしれない。それを踏まえた上で、自分に欠けていたなぁという認識とすれば、「ツールではなくオートメーション」ということな気がする。

同じく、この本を読むことで再確認できたことのひとつが、『常に・頻繁に計測、観測されている・そのフィードバックを素早く得られる環境であるからこそ安心して何か(変化を起こすための「何か」)がおこなえる』ということ。この本の文脈では、それは「インフラに対する継続的なテストシステムを持つこと」の意義であるし、僕の仕事に照らしあわせて考えると「サーバーモニタリングを継続的に実施すること」の意義であると言える。

また、「構成管理ツールを頑張るか」「イミュータブルサーバー構成にすることを頑張るか」みたいな新たな視点も得られた気がする。あらためて、こんな素晴らしい本を、本当にありがとうございました。

f:id:a-know:20180314212553j:plain

読書メモ

なるほど

  • 新しいサーバーをプロビジョニングするために何日、何週間もかかっていた時代の原則では、数分、数秒以下でプロビジョニングを完了する時代に対応するのは難しい。(P.4)
  • オートメーション恐怖症の悪循環(P.9)
    • オートメーションに自信が持てなかったのは、サーバーに統一性がなかったから。
    • サーバーに統一性がなかったのは、ひんぱんに統一してオートメーションを実行していなかったから。
  • システム疲労:エントロピー増大の法則に則り、新しい要件がなくても、インフラは時間の経過とともに壊れていく。(P.10)
    • OSのアップグレード、カーネルパッチ、各種ミドルウェアのセキュリティ脆弱性の修正アップデート
    • ログファイルの成長によるディスク残容量の減少
  • 「鉄の時代」とクラウドの時代の根本的な違い(P.11)
    • ハードウェアの信頼性がきわめて高いことを前提とした信頼性の低いソフトウェアから
    • 信頼性の低いハードウェアのもとで確実に実行されるソフトウェアへのシフト
  • インフラチームがうまく仕事できているかどうかを示すシグナル(P.19)
    • ほとんど労力をかけずにインフラストラクチャのすべての構成要素をすばやく再構築できる
    • チームメンバーが、自分の仕事は計測可能な価値を会社に与えていると実感していること
    • など
  • 信頼性の高い無人実行をサポートするために、スクリプトやタスクが備えるべき特長(P.44)
    • べき等
    • 事前チェック
    • 事後チェック
    • 目に見える形の失敗
    • パラメータ化
  • 構成レジストリはCMDBか(P.56)
    • 別のものとして扱った方がよい
    • 構成レジストリ:オートメーションをサポートするためのデータ共有が目的。オートメーションツールがインフラについてのデータを共有して、現在の状態に基いてダイナミックに構成/設定を変更できるようにするためのもの
    • CMDB:資産についての情報の記録が目的。もともとIT資産を管理するために作られたもの。どのハードウェア、デバイス、ソフトウェアライセンスを持っているか、どこで使われているか、何のために使われているか、等。
  • CMDBに対する Infrastructure as Code のアプローチ(P.58)
  • サーバー変更管理のモデル(P.67)
    • 随時変更
    • 構成/設定の同期
    • イミュータブルインフラストラクチャ
  • コンテナの分離とセキュリティ(P.75)
    • コンテナは、ホスト上で実行されるプロセスを互いに切り離すが、この分離は破れないものではない
    • コンテナを使うときには、チームはそのテクノロジがどのような仕組みになっているのか・脆弱性がどこに潜んでいるのかを完全に理解するようにすべきだ
  • ダイナミックインフラストラクチャに適したツールを見分けるために使える基準(P.79)
    • 環境全体を含め、追加、削除される構成要素を穏やかに処理できること
  • サーバーにパッケージを配布する方法(P.103)
    • 構成ツール(Puppet, Chef, Ansible)の定義ファイルを使う
    • 構成定義が扱いにくくなりがちなので、何らかの形で非公開アーティファクトリポジトリを用意する
  • テンプレートを使ったサーバーのプロビジョニング(P.114)
    • 構成/設定やソフトウェアパッケージのなかのどれをサーバーテンプレートでプロビジョニングし、どれを新サーバー作成時に追加すべきかという問題に悩むのは自然なこと
  • ブートをしないサーバーテンプレートのカスタマイズ(P.121)
    • サーバーインスタンスとして原始サーバーイメージをブートし、カスタマイズして、テンプレートイメージを焼き込むためにインスタンスをシャットダウンするプロセスは、時間がかかることがある
    • 代わりに、ディスクボリュームとしてマウントできるソースイメージを使う方法がある
  • サーバー変更管理モデル(P.130)
    • 随時変更
    • 継続的な構成/設定の同期
    • イミュータブルサーバー
    • コンテナ化サーバー
  • 継続的デプロイのパターンとプラクティス(P.133)
    • プッシュ同期
    • プル同期
    • パターン:マスターレス構成管理
    • プラクティス:cronを利用せよ
    • 継続的同期フロー
      • オートメーションの外から加えられた変更を打ち消す効果がある
    • 構成管理の対象外の部分
      • 継続的同期を使うときには、サーバーの大部分は、構成管理ツールを実行するたびに適用される構成定義の管轄外になっていることに意識する
  • プラクティス:アプリケーションコードとインフラストラクチャコードを統一的に管理せよ(P.160)
    • 開発と運用を分離する伝統に従ったものだが、技術的にも組織的にも余分なオーバーヘッドがかかってしまう。
  • Infrastructure as Code が実際に行なうことは、品質の着目点を定義とツールにシフトすること(P.175)
  • 継続的デリバリーは継続的デプロイではないということ(P.183)
    • CDのポイントは、すべての変更をすぐに本番環境に適用することではなく、すべての変更をすぐに本番に送り込める状態に高めること。
  • プラクティス:テストの有効性を継続的に評価せよ(P.195)
    • 次のような兆候が現れたときには、テストを大きく変えることを検討した方がよい。
      • テストが問題をキャッチしてくれることによって節約できる時間よりも、テストを修正、メンテナンスするためにかけている時間の方が長い。
      • 本番環境で問題が起きることが多い。
  • インフラの変更管理パイプラインは、ソフトウェアのデプロイパイプラインと何ら異なるものではない。(P.218)
  • パイプラインの有効性の計測:リードタイム(P.236)
    • リードタイムとは、変更が必要だと判断してから、本番システムでその変更が実際に使われるまでの時間のことである。
    • リードタイムの開始時は、変更管理プロセスの最初の瞬間を反映した早いタイミングにすることが大切である。パイプラインをトリガリングする変更のコミットがリードタイムの開始時であってはならない。
  • 「リフトアンドシフト」とは、静的インフラストラクチャを対象として書かれたソフトウェアをダイナミックインフラストラクチャにインストールすることである。(P.272)
    • ダイナミックインフラストラクチャプラットフォームでソフトウェアを実行することはできるが、インフラストラクチャは、ソフトウェアのどこかが壊れるのを避けるためにスタティックに管理しなければならない。
  • インフラストラクチャのオートメーションをより発展的に実装するアプローチが、Trailblazer(パイプライン)である(P.302)
    • 単純なエンドツーエンドの変更管理パイプラインを作るという「深さ優先」アプローチを取る。
  • インフラチームのために役立つ指標を選択する(P.304)
    • リードタイム
      • 技術的ではないアクティビティやプロセスを所感するチームがコントロールできないことでもすべて含めるようにすることが大切である。(P.306)
    • MTTR
    • MTBF
    • 可用性
      • 予定メンテナンスを含まない
    • 本物の可用性
      • 予定メンテナンスを含む
  • トライブ:職能横断型チームで専門能力を維持する方法(P.314)
    • 職能横断型チームにあらゆる職能の人々をまとめている会社では、専門能力やツール共有のメリットを失ったりする危険がある。
    • この問題に対処するためのアプローチとして広く使われているのが、「トライブ」と呼ばれるチーム横断型コミュニティである。

すごい

  • サーバーアップデートのトランザクション化(P.143)
  • 継続的ディザスタリカバリ(P.284)

わかる

  • 運用チームは、どんなサーバーであっても、自信を持ってすばやく再構築できなければならない。代わりとなるようなサーバーを構築できる新しい、再現可能なプロセスを作り上げることが、そのチームの最優先事項にならなければならない。(P.8)
  • 一斉変更ではなく小刻みな変更(P.17)
  • アンチフラジャイル:「堅牢」を越えて(P.18)
    • 変更の回数を最小限に抑えてITシステムを守ろうとしても、ITシステムは堅牢にはならない
    • システムを絶えず変更し、改良しているチームの方が、大小の障害に対処できる力を持っている
  • インフラチームでは、スクリプティングのスキルを身につけ、継続的に磨いていくことが大切(P.65)
  • アラートに値するイベントがアラートされるようにすることが重要(P.83)
  • アプリケーションサーバーのメモリ利用状況をグラフにするのは役に立つ。しかし、1週間に何度もアプリケーションサーバーが交換されるような環境では、ひとつのサーバーのデータはそれ自体ではあまり役に立たない。(P.84)
  • アンチパターン:ホットクローンによって作成されたサーバー(P.107)
    • 実行中のサーバーからクローニングされたサーバーは、再現できない。
    • サーバーのスナップショットを撮り、それをテンプレートとして使うのはよい。
      • テンプレートならスタティックで動かない
      • 作成されたテンプレートは決して実行されないので、変更やデータを蓄積していかない。
  • アンチパターン:スノーフレークファクトリ(P.108)
    • 多くの企業は、サーバーのプロビジョニングのために自動化ツールを採用しているが、依然として誰かがツールを実行してサーバーを作成し、そのときに個別にオプションを選択している
    • これは、手作業でサーバーをプロビジョニングしていたときのプロセスが自動化ツール導入後もそのまま持ち越されているために起きること
    • 新VMに構成/設定を適用するときに人間が介在しているから、統一性が取れなくなる
  • 中央集権的な統制に代わるべきものは、変更が影響を与える範囲を最小限に抑えるようなインフラ設計である(P.147)
  • 定義の共有に対するアプローチ(P.162)
    • よいコードの共有とチームの機動性確保の間で適切なバランスを取るのは難しい場合がある。
    • 機能や定義の共有が意味を持つのは、原則として、要件が本当に共通しており、変更がひんぱんに発生せず、変更のリスクが低いときである。
  • 高水準テストは、脆弱になりがち(P.193)
    • システムのひとつの変更によって多数のテストが壊れるようでは、そもそもの変更よりもテストの修復の方が大仕事になってしまう
    • すると、テストスイートが開発に追いつかなくなり、継続的に実行できなくなってしまう
    • 「バランスの悪いテストスイート」
      • テスト時間が長いことはテストスイートのバランスが悪いことを示す兆候である
  • プラクティス:できる限り低い水準でテストせよ(P.194)
  • アンチパターン:反射的テスト(P.206)
    • 低水準インフラストラクチャテストには、構成定義を言い直しているだけのテストを書いてしまうという落とし穴がある
      • 原則として、テストを書くのは、チェックしたいと思っているロジックにある程度複雑さが含まれている場合だけにすべきだ。
  • (インフラ変更管理パイプラインの)すべてのステージを通じて、環境、ツール、プロセスは本質的な部分で同じでなければならない(P.219)
  • パイプライン、アーキテクチャ、チーム:Conway の法則(P.238)
    • システムをデザインする企業は、必然的に企業のコミュニケーションの構造を引き写しにしたデザインを作ってしまう。
  • プラクティス:バックアップの正しさを継続的に確認せよ(P.283)
    • 定期的にバックアップデータを復元してテスト環境を再構築するとよい。
  • ダイナミックインフラストラクチャプラットフォームの面白いところは、信頼性の低いインフラストラクチャとよく似ているように見えるところだ。(P.285)
    • そのため、ダイナミックインフラストラクチャを管理するためのテクニックは、障害が起きた時の継続性の保証のためにも使えるのである。
  • 企業がたいていカオスを作って終わるのは、アーキテクチャに対して発展的な視点ではなく、スタティックな視点で臨んでいるからである。(P.300)
  • チームを強力な存在に返信させるには、彼らにエンドツーエンドの責任を与えることだ。(P.312)
    • 「構築するのも運用するのも同じチーム」
  • 品質に対する責任の共有(P.316)
    • 運用スタッフは、門番扱いされて、設計と実装のレビューのためにすべての時間を費やすようなことがないように注意しなければならない。
  • 現在のITシステムはF-1のレーシングカーに似ている。(P.317)

よい

  • Infrastructure as Code の目標(P.5)
    • ITインフラを、「変化の障害や制約になる」ものから「変化を支えて実現する」ものへ
    • システム変更を日常作業にする
    • ITスタッフが、日常的・反復的なタスクに時間を使うのではなく、彼らの能力を活かした価値ある仕事のために時間を使えるようにすること
    • ×:失敗を完全に予防する ○:失敗が発生しても簡単かつスピーディに回復できるようにする
    • ビッグバンプロジェクトではなく、継続的な作業
  • クラウドと仮想化に対するマシンレベルの共感(P.39)
  • サーバーロール(P.104)
    • チームが異なれば、ロールの構造のパターン、戦略も異なるものになる
    • 大切なのは、チームにとってロール構造がどのくらい理解しやすく、扱いやすいか。
  • プラクティス:すべての新サーバーインスタンスをスモークテストせよ(P.110)
    • スモークテストは、自動的にトリガリングされなければならない
    • スモークテストは、モニタリングシステムに統合できる。スモークテストに組み込まれるようなチェックの大半は、日常的なモニタリングチェックとしても大いに役に立つ。
  • サーバーテンプレートのアップデート(P.122)
  • サーバー変更管理モデルごとの一般的なパターンとプラクティス(P.132)
    • プラクティス:サーバーテンプレートを最小化せよ
    • プラクティス:サーバーテンプレートの変更時にサーバーを交換せよ
    • パターン:フェニックスサーバー
  • イミュータブルサーバーによる構成管理ツールの単純化(P.140)
  • Infrastructure as Code を成り立たせているのは、ソフトウェアを実行するために使われるシステムやデバイスは、それ自体もソフトウェアであるかのように扱うことができるという考え方。(P.173)
    • ソフトウェア開発の世界で効果が実証されてきたツールや作業プラクティスが利用できるようになる。
    • ソフトウェアとインフラストラクチャの開発に品質を組み込むための原則
      • 早い段階で動作し、役に立つコードのデリバリーを始める
      • その時点で必要なものだけを作る
      • 個々の追加機能は、できるかぎり単純に構築する
  • 優れたテスト慣行を確立したければ、既存の機能をカバーする完全なテストスイートを構築しようなどとは思わないことだ(P.191)
    • 新しい変更が発生するたびに、そのためのテストを書くようにする
    • バグが見つかったときには、そのバグが明らかになるようなテストを書いて、バグをフィックスする
  • テストとしてのモニタリング(P.205)
    • モニタリングと自動テストは、どちらもシステムの問題点を検出するための手段である
    • テスト:システム変更を本番環境に適用する前に、その問題点を検出することを目的としている
    • モニタリング:実行中のテストの問題を検出することを目的としている
  • 変更管理パイプラインのメリット(P.219)
    • パイプラインよりも簡単に変更を加えられる方法はない。
  • すべての変更にすばやくフィードバックを返せ(P.220)
  • プラクティス:すべての変更で本番対応の品質を証明せよ(P.230)
    • VCSにコミットするたびに、自動チェックを通過したらそれが本番システムにデプロイされるかもしれないということを前提として仕事をしなければならない。
    • 仕上げ、クリーンアップ、その他の追加的な編集を加えられると思うのは禁物だ。
  • よいオートメーションワークフローのもっとも重要な特長は、スピードと確実性である。(P.251)
    • これ(オートメーションワークフロー)が緊急事態に対処するための正しい方法だと言えるくらいスピーディにシステムに変更を加えられなければならない。
    • 緊急時の修正のベストプロセスは通常のプロセスである(P.263)
  • (インフラストラクチャチームのワークフローにおける)最重要の目標とすべきことは、タスクをこなすためのフローからシステム管理者を取り除くことである。(P.252)
    • システム管理者の仕事は、オートメーションを構築し、問題を防ぎ、起きてしまった問題を処理し、改良を加えることだ。
  • ツールとオートメーション(P.255)
    • ツールの構築は、手作業を楽にするためのスクリプトやツールを書くことで、オートメーションはタスクを遂行するために人間を不要にすることである。
  • どのチームももっと効率的に仕事を進めたいと思っている、大切なのは、チームにとって効果的とはどういう意味なのかを意識することだ。(P.263)
    • ビジネスニーズにすばやく対応できることか
    • 高いレベルの可用性を保証することか
  • プラクティス:コールドスタンバイではなく再構築せよ(P.287)
  • パイプラインによる継続的なモニタリング(P.288)
    • モニタリングは、誤動作、故障しているインフラストラクチャ要素を交換する自動リカバリルーチンをトリガリングしてもよい。
    • インフラストラクチャのコア機能の常として、モニタリングは継続的に確認/チェックされるようにするtことが大切だ。
    • 開発、テスト環境でモニタリングを実行すると、モニタリング自体の正しさをチェックするチャンスが得られる。
    • アプリケーションコードやインフラストラクチャに変更を加えると、個々のモニタリングがチェックしていることの重要性が変わることがある。
    • 変更管理パイプラインにモニタリングシステム自体のテストを組み込むと役に立つ。
  • モニタリングと自動テストには多くの共通点がある。(P.289)
    • どちらも、インフラストラクチャやサービスの状態をアサートし、アサーションが失敗したときにはチームに問題をアラートする。
    • テストとモニタリングでコードを再利用するのは、それで楽になるとき以外は役に立たない。
  • モニタリング駆動開発(P.290)
    • 本番環境の問題をフィックスするためのワークフローを、インフラストラクチャ版のTDDとして実施する。
  • 発展的な設計と実装の基礎は、継続的に安全、簡単に低コストで変更を加えられることである。(P.300)
  • 職能横断型チームの組織(P.313)
    • インフラチームサービスを含む独立した別々のサービスを管理するチームを作ることはできる
    • 効率のよいバリューストリームを確保するための最重要原則は、エンドツーエンドの責任体制であり、そういったチームがチェックポイントやリクエストキューで待たされずに必要なものを送り届けられるよう、完全な権限を与えることだ。

たしかに

  • システムを安全にすばやく変更できるようにするためのもっとも重要な手段は、ひんぱんな変更。変更がひんぱんなら、関係するすべての人々は否応なく変更管理に適した習慣を身につけていく。(P.14)
  • 開発中に継続的にテストを実行していると、変更に対するフィードバックをすばやく返すことができる。フィードバックが早ければ、すばやくひんぱんに変更を加えても大丈夫だという自信が生まれる。(P.17)
  • インフラストラクチャサービス、ツールが満たすべき条件・サービスやツールにおける Infrastructure as Code の原則(P.77)
    • サービスは簡単に再構築、再現できる
  • 外部定義を使えるインフラストラクチャサービス、ツールを選ぶ(P.78)
    • GUI, API でしか構成/設定できない閉じたツールは、スノーフレークサービスになる危険がある
  • イミュータブルサーバーは、定義ファイルで管理しなければならない部分を削減することを通じて構成管理も単純化することができる。(P.99)
  • サーバーに含まれるものの分類(P.101)
    • ソフトウェア
    • 構成/設定
    • データ
  • 高品質システムの要は、変更に対する高速なフィードバックである(P.175)
  • 継続的なブランチのテストは継続的インテグレーションではない(P.177)
  • 外部依存コンポーネントの管理(P.209)
    • サードパーティはもちろん、自前のサービスの間でも、インテグレーションが発生するあらゆる場所では、外部コンポーネントに問題が起きたらそれがすぐに可視化されるようなチェックと報告のメカニズムを実装すべきである
  • 自律的なオートメーションこそ、Infrastructure as Code が確実に機能する秘訣である。(P.254)
  • 求める結果について合意を得ることを優先する(P.303)
    • インフラストラクチャを含むITサービスの目標は、ユーザーをはじめとするステークホルダーが手動して決めなければならない。
    • ステークホルダー、ユーザー、ITスタッフを集めて現在の問題点とニーズを議論すると、驚くべき問題が明らかになることがよくある。クラウドやオートメーションなどの検討に進む前に、これらについて全員で合意を形成することが大事な一歩目である。

知らなかった

  • サーバースプロール:望ましいと思っているペースよりも早くサーバーの数が増えていくこと(P.6)
  • 構成ドリフト:サーバー間での構成・設定の不統一(P.6)
  • ユニカーネル:実行するアプリケーションとともにカスタムコンパイルされたOSイメージ(P.64)
  • ミニマルOS:完全なOSカーネルとプリインストールパッケージ、サービスのミニマルディストリビューションを組み合わせたもの。Red Hat Atomic, Microsoft Nano, Ubuntu Snappy, VMWare Photon など。
  • スリーアミーゴの話し合い(P.214)
  • パターン:単一のトランク(P.262)
    • 大規模トランクベース開発、Googleで採用されている
    • このような仕事の進め方をサポートするために作られた、広く流通しているツールはほとんどない
    • Googleはそのためのツールをカスタム整備している
  • データセンター全体(AWSの利用可能ゾーン)を取り除く Chaos Gorilla(P.286)