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

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

Hatena
October 18, 2023

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

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. データがないと評価できない • デプロイ回数を取得するには? • 変更リードタイムはどう測定する? • インフラ費⽤はどのように変化しているか? それは妥当か? • 変更障害率、サービス復元時間はどう計算する? データを取るためには形式化、システム化する必要がある。たとえばサーバー

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