Upgrade to Pro — share decks privately, control downloads, hide ads and more …

はてなリモートインターンシップ2023 インフラ講義資料

Avatar for Hatena Hatena
October 18, 2023

はてなリモートインターンシップ2023 インフラ講義資料

Avatar for Hatena

Hatena

October 18, 2023
Tweet

More Decks by Hatena

Other Decks in Programming

Transcript

  1. システム全体 機能 • アプリケーション • データベース、KVS、全⽂検 索、ストレージ、DNSなど 周辺サービス • ネットワーク

    ⾮機能 • バックアップやログ記録 • テスト、ビルド、デプロイ のパイプライン • モニタリング !
  2. 影響が強い3つの⼒(フォース) • 信頼性、⽣産性、コスト • トレードオフ関係ではない • 緊張関係にある +--------------+ | |

    | Reliability +---------------+ | | | +------+-------+ +-----+------+ | | | | | Cost | | | | +------+-------+ +-----+------+ | | | | Productivity +---------------+ | | +--------------+ ( ᯣ _ ᯣ ) !!" Monitoring !"
  3. 可⽤性(Availability) • 稼働率 • Քಇ࣌ؒ/ܭଌ࣌ؒ で表される • ⽬標として⽴てる場合は 99.999% "Five

    nines" のように9の数を数える • 99.5%だと"two and half nines" • 99.999% は 1年で5分間のダウンタイムを許容することになる • 1ヶ⽉で合計30秒落ちると可⽤性⽬標を下回る、ということになる !"
  4. X-Nines と許容可能ダウンタイム 可⽤性⽬標 365⽇ 30⽇ 28⽇ 14⽇ 7⽇ 00 (3N)

    3.65 ⽇ 7.2 時間 6.72 時間 3.36 時間 1.68時間 00.0 (9N) 8.76 時間 43.2 分 40.32 分 20.16 分 10.08 分 00.0; 1.752 時間 8.64 分 8.064 分 4.032 分 2.016 分 00.00 (<N) 52.56 分 4.32 分 4.032 分 2.016 分 1.008 分 00.000 (=N) 5.256 分 25.92 秒 24.192 秒 12.096 秒 6.048 秒 !"
  5. 複合システムの可⽤性 • シンプルなシステム構成を考える • すべてのコンポーネントの単独の可⽤性が 99.9% だとすると... +-----+ +-----+ +-----+

    +-----+ | | | | | | | | | CDN +!!" LB +!!"+ App +!!"+ DB | | | | | | | | | +-----+ +-----+ +-----+ +-----+ 99.9% 99.9% 99.9% 99.9% # 0.999 * 0.999 * 0.999 * 0.999 = 0.996 全体では 99.6% 99.9%を下回ってしまった! !"
  6. 伝統的な構成の⼯夫 • 素朴なアーキテクチャに⾒える • 様々な要求に応える⼯夫が詰まっている +-----+ | CDN | +!"+!"+

    | +!"+!"+ | LB | ( reverse proxy ) +!"+!"+ | +!"+!"+ | APP | +!"+!"+ +--------+ +!"+!"+ +!"+!"+ | DB | | KVS | +-----+ +-----+ !"
  7. アプリケーションは横に並べられるようにす る • アプリケーションはもっとも頻繁に変更されるた め、独⽴して変更できるように分割する • ユーザー数増加などで必要な計算能⼒が変動しや すい • ⽔平分散できるとよい(冗⻑化も同じ仕組みで

    可能になる) • クライアントが分散しているノードを知らないと いけないのは不便 • クライアントのいるネットワークに⾯したリバ ースプロキシをロードバランサとする +!"+!"+ | LB | ( reverse proxy ) +!"+!"+ | +!"+!"+ | APP | +!"+!"+ ※ LB(Load Balancer = 負荷分散装置) !"
  8. http ロードバランサーをNginxで実装する http { upstream backend { server main.example.hatena.ne.jp weight=5;

    server sub1.example.hatena.ne.jp; server sub2.example.hatena.ne.jp; server backup.example.hatena.ne.jp backup; } access_log /var/log/nginx/access.log; !" ΞΫηεϩάΛอଘ͢Δػೳ΋࣋ͨͤΔ server { listen 80 listen 443 ssl; !" SSLΛฏจʹ΄Ͳ͘໾ׂΛ࣋ͨͤΔ !!# location / { proxy_pass http:!"backend; } } } !"
  9. いろいろなロードバランシング • 設定で重み付けを⾏う • ラウンドロビン(順番に回していく) • コネクション数が少ないサーバーに対して振っていく • 処理時間が短い(⾼速な)サーバーに多く振っていく •

    なんらかの計測値に基づきリソースの余裕があるサーバに振る • IPアドレスやCookieの値に基づいて決まったサーバーに割り振るs ! アプリケーションレイヤーのキャッシュをうまく効かせたいなどの理由で、特定のクライアントの接続を特定の ノードに偏らせたい場合があります。ノードの増減があった場合に対応する Consistent Hashing などのアルゴリ ズムが使われます。 !"
  10. keepalived と LVS のアクティブ‧スタンバ イ • IPレベルで冗⻑構成を取れる • VRRPでアクティブとスタンバイのサーバーが お互いに通信を⾏う

    • アクティブなサーバーがダウンするとスタン バイサーバーがアクティブとなる • DNSラウンドロビンと組み合わせることで冗 ⻑化と同時に⽔平分散を構成できる • マルチキャストが必要であるためAWSのVPC で使えない ┌────────────────┐ │ │ ┌───►│ Active Server │ │ │ │ │ └────────────────┘ ┌────────────────┐ │ ▲ │ │ VIP │ │ │ Client ├───────┘ │ VRRP │ │ │ └────────────────┘ ▼ ┌────────────────┐ │ │ │ Standby Server │ │ │ └────────────────┘ !"
  11. DNS ラウンドロビン • DNS で 複数の IP アドレスの 1 つを返

    す • 低コストに導⼊できる • クライアントのDNSキャッシュの影響 を受ける • ダウンしたノードに対してもリクエス トが送られるY • DNS名が使えない場⾯では使えない Q1: server.example.com A1: 192.0.2.1 ┌─────────────────┐ ┌────────────────┐ ┌────────────────┐ │ │ │ │ │ │ │ DNS Server │◄────────────►│ Client A ├────────►│ Server X │ │ │ │ │ │ 192.0.2.1 │ │ │ │ │ ┌────►│ │ └─────────────────┘ └────────────────┘ │ └────────────────┘ ▲ ▲ ▲ │ │ │ │ ┌────────────────┐ │ ┌────────────────┐ │ │ │ │ │ │ │ │ │ │ │ │ Client B ├───┼────►│ Server Y │ │ │ └────────────────►│ │ │ │ 192.0.2.2 │ │ │ Q2: server.example.com│ │ │ │ │ │ │ A2: 192.0.2.2 └────────────────┘ │ └────────────────┘ │ │ │ │ │ ┌────────────────┐ │ ┌────────────────┐ │ │ │ │ │ │ │ │ │ │ Client C ├───┼────►│ Server Z │ │ └──────────────────────►│ │ │ │ 192.0.2.3 │ │ Q3: server.example.com│ │ │ │ │ │ A3: 192.0.2.3 └────────────────┘ │ └────────────────┘ │ │ │ ┌────────────────┐ │ │ │ │ │ │ │ Client D │ │ └────────────────────────────►│ ├───┘ Q4: server.example.com│ │ A4: 192.0.2.1 └────────────────┘ ! AWSのRoute,-など、ヘルスチェック機能を持つDNSサービスを利⽤することで回避できる場合があります !"
  12. CDNサービス • Amazon CloudFront • Google Cloud CDN • Azure

    Content Delivery Network • さくらウェブアクセラレータ • Akamai • Fastly • Cloudflare !"
  13. 永続化層 • メモリ上のデータをプロセスが終了しても消えないようにする • データベースやアップロードされたファイル、レポート、セッション情報など多岐 にわたる +--------+ +!"+!"+ +!"+!"+ |

    DB | | KVS | +-----+ +-----+ • 参照系と更新系で特性が⼤きく異なる • 可⽤性、冗⻑性に加えて⼀貫性、整合 性や堅牢性が主要な話題になる • 更新処理を受け付けるノードはSPOF であることを許容することがある !"
  14. レプリケーションとシャーディング 説明 レプリケーション 全く同じ内容のデータセットを構築して負荷分散する 参照系は読み取り専⽤のレプリカを増やせばよいため負荷 分散しやすいが、更新系の負荷が⾼まると⼯夫が必要になる 特定のテーブルのみを持つレプリカを構成する場合もある が、レプリカが同じデータを持つ場合、冗⻑化やバックアッ プとしても利⽤できる シャーディング

    (⽔平パーティショニング) データをなんらかのルールで分割し、異なるノードに保存 する。たとえば奇数IDならDBê、偶数IDならDBíというよう に分割する 更新が多い場合でも負荷分散しやすいが、アプリケーション でロジックを持つことになる場合がある 冗⻑化は複数ノードを考慮する必要がある !"
  15. 構成例 • Writerはスタンバイ系に対して同期的レ プリケーションを⾏う • Readerは複数ノードを⽤意し⽔平分散で きるようにする • Writerのパフォーマンスを劣化させない ため、Readerへは⾮同期レプリケーショ

    ンを⾏う • Readerは結果整合モデルとなる • 強整合の参照をしたい場合はWriterで 参照を⾏う +-----------+ Replication +-----------+ | | (sync) | | | Writer | | Writer | | (Active) +--------------> (Stand By)| | | | | +-----+-----+ +-----------+ v Replication (async) + +-----------+-+------------+ | | | +!!"v----+ +----v!!"+ +----v!!"+ | | | | | | | Reader | | Reader | | Reader | | | | | | | +--------+ +--------+ +--------+ • Writer(Active)に問題が起こった場合、 Writer(Stand By)をActiveに昇格する • 短時間のダウンタイムは許容する !"
  16. 強整合性(即時整合性)と結果整合性 この例では単⼀のクライアントのみ が読み書きを⾏なっているとします def read(): with Db.connect() as db: #

    σʔλϕʔε͔ΒಡΈग़ͨ͠஋Λฦ͢ return db.read("key1") def write_and_read(value): with Db.connect() as db: # σʔλϕʔε΁ॻ͖ࠐΈΛߦ͏ db.write("key1", value) return read() 強整合 • write_and_read() の戻り値は パラメータに渡した値と必ず⼀ 致する • read() の戻り値は最後に呼び出 した write_and_read() のパ ラメータと必ず⼀致する !!
  17. 強整合性(即時整合性)と結果整合性 この例では単⼀のクライアントのみ が読み書きを⾏なっているとします def read(): with Db.connect() as db: #

    σʔλϕʔε͔ΒಡΈग़ͨ͠஋Λฦ͢ return db.read("key1") def write_and_read(value): with Db.connect() as db: # σʔλϕʔε΁ॻ͖ࠐΈΛߦ͏ db.write("key1", value) return read() 結果整合 • write_and_read() の戻り値は 引数に渡した値と⼀致しないか もしれない • read() の結果は最後に呼び出し た write_and_read() の引数 に収束する !"
  18. ⾼可⽤への道 • 冗⻑化をして故障や障害に備える • 負荷分散を⾏い⾼負荷に耐えられるようにする • それがやりやすいようにコンポーネントを分割する • ファイル配信はCDNに寄せられるといい •

    アプリケーションは横に並べられるようにしよう • 永続化層は読み書きのワークロードの違いがある • なるべくクラウドの提供するサービスを利⽤する !"
  19. 伝統的な構成 取り上げなかったポイント • セキュリティやガバナンス • ログ転送や分析システム • ビルドシステムやリポジトリ • 監視

    +-----+ | CDN | +!"+!"+ | +!"+!"+ | LB | ( reverse proxy ) +!"+!"+ | +!"+!"+ | APP | +!"+!"+ +--------+ +!"+!"+ +!"+!"+ | DB | | KVS | +-----+ +-----+ !"
  20. 「現在利⽤されているバージョン」を⾒つけ る 現在利⽤されているバージョンが... • 統⼀されている • システム的に特定できる • 利⽤可能である !

    < 「利⽤可能である」当たり前のようですが、しばらくデプロイされていないシステムで は新しくセットアップしようとするとうまくいかない、ということは往々にしてあります !"
  21. 開発運⽤全体と分離できない 信頼性、⽣産性、コスト、モニタリング +--------------+ | | | Reliability +---------------+ | |

    | +------+-------+ +-----+------+ | | | | | Cost | | | | +------+-------+ +-----+------+ | | | | Productivity +---------------+ | | +--------------+ ( ᯣ _ ᯣ ) !!" Monitoring 信頼性を作り込もうとすると結局... • アプリケーションに対する制約や、デプロ イの仕組みを設計することになる • インフラの構成は開発するための環境に影 響を与える • インフラの作りが開発のボトルネックに なっていないか? 認知負荷や⼿元環境 構築がコスト⾼くないか? • コストはシステムの⽣み出す価値と天秤に かける必要がある !"
  22. ⽣産性(Productivity) 悪化や改善を気にするなら指標が必要(デマルコの⾔葉を思いだそう) • Four Keys • DevOps Research and Assesment

    (DORA) チームが実施した研究で、 開発チームのパフォーマンスを表す指標として⽰されたもの • 書籍「LeanとDevOpsの科学」などに詳しい • 変更リードタイム、デプロイ回数、変更障害率、サービス復元時間 • Google が Four Keys と呼んでる !"
  23. データがないと評価できない • デプロイ回数を取得するには? • 変更リードタイムはどう測定する? • インフラ費⽤はどのように変化しているか? それは妥当か? • 変更障害率、サービス復元時間はどう計算する? データを取るためには形式化、システム化する必要がある。たとえばサーバー

    にログインしてコードを書き換える、というような⾏為は禁⽌しなければいけ ない。障害が起こったらそれを記録しなければいけない。コストについてはビ ジネス担当と認識を揃えていこう。 !"