Slide 1

Slide 1 text

2021.06.18 株式会社はてな Mackerelチーム リードSRE 古川 雅大 MackerelにおけるEC2からFargate移行 の軌跡と Fargateのメリットデメリットについて

Slide 2

Slide 2 text

- 名前: 古川 雅大 ( id:masayoshi Twitter: @yoyogidesaiz ) - 所属: 株式会社はてな - MackerelチームのリードSRE (Site Reliability Engineer) - 趣味 - ネットワーク、サーバーをいじること - 格闘ゲーム 自己紹介

Slide 3

Slide 3 text

Mackerelとは

Slide 4

Slide 4 text

クラウド運用を簡単にはじめられる SaaS型サーバー監視サービス Mackerelの特徴 ● システムの運用・監視を簡単にはじめられます ● クラウド時代に最適な監視モデルをもとに素早く導入できます ● 日本語ドキュメントやサポートによって成長を後押しします 4

Slide 5

Slide 5 text

システムの運用・監視を簡単にはじめられます ➔ 導入はガイドにしたがってコマンドを実行するだけ ➔ エージェントが死活監視とメトリック取得を自動で開始 ➔ 直感的なUIでサービスの状況を可視化 ➔ 監視をはじめる敷居が下がり、チームで取り組めます 5

Slide 6

Slide 6 text

- 対象 - EC2やVM環境からFargate(ECS)を目指す人向けに事例紹介 - ECSに関わることが中心 (コンテナ化自体の話は省略) - 構成 - Mackerelのインフラ構成の変遷 - 移行前の課題と移行の目的 - 移行時、移行後で困った点 - 移行時の工夫 - 移行してよかったこと - これから移行する人へ - 付録 今日話すこと * Dockerfileの書き方とか工夫など

Slide 7

Slide 7 text

Mackerelのインフラ構成の変遷

Slide 8

Slide 8 text

Mackerelのインフラ構成の変遷 On-premises Cloud First Cloud Native 2014 2017 2019 2015 2016 2018 2020 2021 ・Compute VM Xen Hypervisor ・Time Series Database ioMemory Graphite ・Relational Database PostgreSQL ・Compute VM EC2 ・Time Series Database Redis DynamoDB S3 ・Relational Database RDS(PostgreSQL) ・Compute Container ECS ・Time Series Database ElastiCache DynamoDB S3 ・Relational Database RDS(PostgreSQL)

Slide 9

Slide 9 text

- On-premisesのときのTSDB(Graphite) - Mackerelを支える時系列データベース技術 オンプレ => AWS EC2移行(公開資料) https://blog.yuuk.io/entry/high-performance-graphite - Cloud First(AWS移行後)のTSDB(diamond) - 時系列データベースという概念をクラウドの技で再構築する - - AWSで実現した Mackerel 時系列データ1分粒度長期保存の裏側 - - On-premisesからAWS移行のお話 - Mackerel インフラ基盤 AWS 移行の舞台裏 - - Mackerel をオンプレミスから AWS に移してからの1年半を振り返る https://speakerdeck.com/kizkoh/mackerel-inhuraji-pan-aws-yi-xing-falsewu-tai-li https://blog.astj.space/entry/2018/02/06/175902 https://blog.yuuk.io/entry/the-rebuild-of-tsdb-on-cloud https://blog.astj.space/entry/2019/03/07/110234

Slide 10

Slide 10 text

- アプリケーションサーバーをEC2からECS Fargateに移行 - Scala アプリケーション1つ - go アプリケーション6つ - 実行環境はEC2だったが、BuildはDockerで実施 (Dockerfile化済み) - 移行した台数はEC2 100台以上 - 50台以上のRedis Cluster on EC2をElastiCacheに移行 - 参考 - 「Mackerel の時系列データベースにおける Redis Cluster の利用と Amazon ElastiCache への移行について」 - https://speakerdeck.com/astj/aws-purpose-built-databases-week EC2からECS Fargate移行

Slide 11

Slide 11 text

移行前の課題と移行の目的

Slide 12

Slide 12 text

- コンテナ運用知見の獲得 (Mackerelチーム特有の課題) - EC2運用の課題の解決 (一般的な課題) MackerelチームのFargate移行の目的

Slide 13

Slide 13 text

- Mackerel SREチームのミッション - SLOに基づいたサービス運用 - インフラ運用をドッグフーディングできる環境を開発チームに提供 - ミッションに基づいた目的設定 - コンテナ運用環境でMackerelをSLOに基づいて安定運用すること - 特にk8sとECS - 「コンテナ運用をすること」自体がプロダクトに貢献 - 「運用が楽になること」が目的ではない コンテナ運用知見の獲得 * 多くのサービスではコンテナ運用は手段であり、目的になることはほとんどないため、Mackerelチーム特有の課題

Slide 14

Slide 14 text

- デプロイがAMIを生成する方式ではなかった - 1回作ったEC2に、アプリケーションをデプロイする方式 (インプレース) - EC2はchefの実行や、社内ホスト名やDNS登録などをするため 社内共通スクリプトで構築していた - オンプレ環境のレガシー基盤に引きづられていた - Auto Scaling Groupを活用出来ていなかった - そのため、回復性の課題が存在した - 1台落ちたら人間が起動し直していた - EC2メンテナンスなどの対応が必要 (月1回以上の頻度) - AZ障害時にAZの移動に時間がかかっていた - EC2の構築のたびにchefを実行 EC2運用の課題

Slide 15

Slide 15 text

クラウドネイティブ技術は、 パブリッククラウド、プライベートクラウド、ハイブリッドクラウドなどの 近代的でダイナミックな環境において、 スケーラブルなアプリケーションを構築および実行するための能力を 組織にもたらします。 CloudNative CNCF Cloud Native Definition v1.0 https://github.com/cncf/toc/blob/main/DEFINITION.md (2021/06/08)

Slide 16

Slide 16 text

- 回復性 - サーバーの自動復旧 - オートスケール - 管理性 - 可観測性 CloudNative ~ダイナミックな環境~ CNCF Cloud Native Definition v1.0 https://github.com/cncf/toc/blob/main/DEFINITION.md (2021/06/08) これらの手法により、回復性、管理力、および可観測性のある疎結合システムが実 現します。

Slide 17

Slide 17 text

- EC2 Image Builder + AutoScaling Group - コンテナ運用知見の獲得にはつながらない - 検討時(2019/8) にはEC2 Image Builderもなかった - EKS (Fargate) - 検討時(2019/8) にはEKS on Fargateはなかった - EKS (EC2) - k8s自体の学習コストやk8sクラスター更新頻度の高さで不採用 - ECS (EC2) - Fargateで実現が難しければ採用 - ECS (Fargate) - 必要な要件を満たしており移行コストが一番下げられるので採用 - 社内でも運用実績があり、メンバーの学習コストが抑えられる AWSで実現するダイナミックな環境

Slide 18

Slide 18 text

- 当初はk8sに移行する予定だった - k8s運用のドッグフーディング + CloudNativeが目的 - 検討当時(2018夏)はEKSの東京リージョンがなかった - EC2上にk8sを自前で構築 - 本番環境は数ヶ月チャレンジしたが撤退した - 学習コスト、更新頻度などでSLOを満たすことが難しかった - 「SLOを満たす & コンテナ運用のドッグフーディング」 - AWSのコンテナサービスを活用してリトライ - 参考資料 - Blog - 発表資料 - 記事 (参考)k8s化にチャレンジして出直し https://developer.hatenastaff.com/entry/leading-kubernetes-at-hatena https://speakerdeck.com/hayajo/kubernetes-meetup-tokyo-number-22 https://www.atmarkit.co.jp/ait/articles/1911/08/news009.html * 当時MackerelチームのSREは1人だった

Slide 19

Slide 19 text

- 社内での運用実績や運用負荷を考慮し選択 - 自分たちがコンテナ運用環境を始めることを重視 - CodeDeployによるBlue/Green Deployを選択 - 最初はCFnによるローリングデプロイだった - Terraformの採用 - 他のクラウドサービスの利用 - 当時CFnがCodeDeploy Blue/Greenに非対応だった - module化が容易 - 参考: terraform周りの話 ECS Fargateへの移行 https://speakerdeck.com/heleeen/our-best-practice

Slide 20

Slide 20 text

移行時、移行後で困った点

Slide 21

Slide 21 text

- Fargate移行に関しての大きな困りごとはなかった - 移行コスト、難易度が低かった - 特にgoのアプリケーションは何事もなく移行完了 - JVM周りの注意点や困り事 - JVMのウォームアップ - JVMとECS TaskDefinitionとcpu.shares - JVMが利用するCPU数の設定に関する問題 (詳細は付録を参照) - Fargate環境における困り事 - デバッグが難しい - platform側で発生する問題 移行時、移行後に困った点 * 本発表は Java 11 を前提にしてお話しています

Slide 22

Slide 22 text

- JVMは起動時に遅い - クラスのロードなど - ECSはALBのHealthCheckがUnhealthyだとタスク(コンテナ)を終了する - 起動時に遅い => 一瞬Unhealthyになる => 再起動 のクラッシュループ - Deploy時やコンテナの異常終了時に発生しうる - ALBに投入される前にウォームアップを完了する必要がある JVMのウォームアップ

Slide 23

Slide 23 text

- warmupコンテナ - dependsOnを利用し、appコンテナのHealthy状態を依存関係にしておく - いくつかのwarmupスクリプトをappコンテナに対して実行 - warmup中はAppをメンテナンスモードにしておく - warmupが終わったら終了 - Appコンテナ - HealthCheckのstartPeriodをwarmupの実行時間以上にしておく - その後HealthCheckが通ったら起動フェーズ終了 - ALBに投入 - ECS Service - HealthCheckGracePeriodSecondsも併せて検討 - RUNNING 状態になった後のヘルスチェックを無視できる JVMのウォームアップ ~解決策~ * k8sの場合はこちらが参考になります https://techblog.zozo.com/entry/zozomat-jvm-warmup * warmup以外にもタスク起動時の初期化でやりたい処理は同じ作戦が使える

Slide 24

Slide 24 text

containerDefinitions: - name: app essential: true healthCheck: command: - CMD-SHELL - curl -L -s -o /dev/null http://localhost:8000/healthcheck || exit 1 interval: 5 retries: 10 startPeriod: 60 timeout: 5 - name: warmup dependsOn: - condition: HEALTHY containerName: app entryPoint: - /opt/bin/warmup.sh JVMのウォームアップ ~解決策~ * dependsOnとhealthCheckの組み合わせで初期化

Slide 25

Slide 25 text

- 先程のwarmupや、cpu.sharesのリソース動作確認 - その他にもJVMのHeapdump取りたいなど - EC2と比べてリモート接続や特権制御により難しい - Fargateのデメリット - 解決策 - JVMはJMXのリモート接続でモニタリング - SSHできるサイドカーを用意してデバッグ作業 - 現在はPlatform Version 1.4.0でECS execによるデバッグが可能 - サポートの活用 - SAなどへの相談やサポート問い合わせ デバッグが難しい

Slide 26

Slide 26 text

- マネージドサービスもplatform側の問題やエラーもある - 不具合の起きないシステム、サービスはない - 致命的な問題は遭遇していない - 解決策 - サポートの活用 - ユーザーだけの調査には限界がある - SA, TAMなどへの相談やサポート問い合わせ - 特にスペシャリストへの相談は非常に役立つ - ビジネス、エンタープライズサポートへの加入をお薦め platform側で発生する問題

Slide 27

Slide 27 text

- 特定の条件でplatform側でエラーが発生する事象 - サポートが1ヶ月程度かけて調査してくれた - その間、我々は他のタスクに集中できる (調査工数の削減) - 現在も不明なエラー事象に遭遇している - platform側の問題なのか、設定やコード上の問題など原因の切り分け中 - SAの方と相談、サポートへの調査や再現を依頼 - マネージドサービスはOSSのようにコードを読めない、直せない - 代わりにサポートやスペシャリストと相談できる - マネージドサービスを利用するなら併せてサポートプランも検討 platform側で発生する問題

Slide 28

Slide 28 text

移行時の工夫

Slide 29

Slide 29 text

- terraform moduleの活用 - Weighted Routingを活用したEC2とECSの同時稼働 - SLOによる本番投入や切り戻し基準の設定 移行時の工夫

Slide 30

Slide 30 text

- module化 - ECSクラスタ、ECS Serviceの作成 - CodePipeline, CodeDeployのCI/CDパイプライン - 後述するデプロイ時に起動するlambdaなど - goとscala合わせて7つ移設 - すべて同じmoduleで構築できたため構築、管理工数削減 - 詳細はこちら - 「Mackerel におけるTerraform 運用 / Our (Best?) Practice」 - https://speakerdeck.com/heleeen/our-best-practice terraform moduleの活用

Slide 31

Slide 31 text

- DNSでやる方法 - ECS,EC2のALBエンドポイントをRoute53でDNSラウンドロビン - Route53の機能でできるので実装が容易 - 前段のクライアントの数が少ないと %の低い振り分けが難しい - 4台の場合1台のキャッシュに乗ると、短期的に見ると 25%のトラフィックが来てしまうことが ある - Weighted Routingでやる方法 - ECS, EC2のTargetGroupのWeightを変更することによって振り分け - 振り分けの%を正確にできる(1%とかも可能) - AWS側での機能がないのでlambdaで作り込みが必要 - B/GだとTargetGroupがデプロイのたびに変わる - B/Gの制約でECSのTargetGroupをEC2のALBにつけられない EC2とECSの同時稼働

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

- SLOを基準に判断 - staging環境でSLOを満たしていたら本番投入OK - エラーレート1%以上 レイテンシ 99%ile 200ms 以上 ならECS weightを0にして切り戻す - 「正常に動いている」とはどういうことを指すのかSLOで表現 - 本番投入時のスプリントはSLOを再検討 - 移設時などはSLOを下げるなど、スプリントで話し合うことで移設担当者の 精神的負荷を軽減できる - 移設タイミングでSLOが十分に余っていることを確認する - SLOが余っているなら積極的に投入していく SLOによる本番投入や切り戻し基準の設定

Slide 34

Slide 34 text

- SLOで判断するということはSLIの実装が必要 - ALBのステータスコードの割合、レイテンシなどはすぐ可視化できる - MackerelのAWSインテグレーション機能でメトリックを取得し、式グラフで可 視化、監視できる - MackerelでのALBの式監視の例はこちら - CloudWatch Logs Insightsでログ集計するlambdaを作成 - ログ数をカウントしMackerelにサービスメトリックとして投稿 - SLIの実装は大切だが、最初は実装難易度の高いものにしないほうが良い - いつまで経っても移行が終わらなくなってしまう - 運用は育てていくものなので、移行後にSLI/SLOを継続的に改善する SLIの実装 https://mackerel.io/ja/blog/entry/2020/12/12/000000

Slide 35

Slide 35 text

MackerelのSLO(可用性)ダッシュボードの例 ※ 数字ははめ込み加工なので実際の Mackerelの可用性とは異なります

Slide 36

Slide 36 text

移行してよかったこと

Slide 37

Slide 37 text

- EC2インスタンス管理から解放 - コンテナ運用知見の獲得 - CI/CDがB/Gになり、リリースフローが改善 移行してよかったこと

Slide 38

Slide 38 text

- EC2 メンテナンスから解放 - 月1回程度のEC2メンテナンスがほぼ0件に - Fargateもホスト側のメンテナンスがあるが勝手に起動 - 回復性 - タスク落ちても勝手に起動してくれる - warmupも対応したので対応が不要 - AZ障害のとき、CodeDeployでsubnet指定をしてデプロイするだけ - 管理性 - 台数増加が楽になった - ホストOSのバージョンアップやchefメンテナンスが不要 - 特にホストOSの脆弱性対応など EC2インスタンス管理から解放 * EC2 AutoScaling Groupでも実現可能な項目もある

Slide 39

Slide 39 text

- メリット - CloudNativeな環境を容易に手に入れられる - 特に回復性 - AutoScaling Groupのキャパシティプランニングや構築より容易 - k8sと比べて学習コストや、クラスターのバージョンアップなどが容易 - デメリット - デバッグが難しい (デバッグが簡単にならない) - 自前の基盤を用意したとしてもFargateよりデバッグが容易になるとは限らない - サポートを活用することでカバーは可能 - ECS execなど、今後もデバッグが容易になる機能が追加されると思われる Fargateのメリット、デメリット * 充実したエコシステムを利用したCI/CDなどk8sはk8sでメリットも多い 移行コストを抑えながら、CloudNative移行ならFargate(ECS)がお薦め!

Slide 40

Slide 40 text

これから移行に挑戦する方へ

Slide 41

Slide 41 text

- 移行の目的や判断基準をチーム内で共有する - SREの文化があるならSLOなどを活用 - マネージドサービスから検討し、だめなら自前で - ECSで行くなら Fargate > ECS on EC2 - k8sで行くなら Fargate for EKS > EKS - コンテナ化が難しいならEC2 AutoScaling Group - CloudNative実現にはかなり作り込みが必要 - サポートプランも併せて検討 - 移行時の相談やマネージドサービス利用時の不具合や障害で活用 - 移行後も運用は続く - 移行時にすべての問題を解決する必要はない - 「移行タイミングはいい機会だからあれもこれも」は要注意! これから移行に挑戦する方へ * コンテナの前にlambdaなどサーバーレスも検討できると最高!

Slide 42

Slide 42 text

(付録) 時間の関係で省略した内容

Slide 43

Slide 43 text

- containerDefinitionsでcpuを指定しないと0になる - Linuxではcpu.sharesの最低値が2なので2になる - JVMとしてはプロセッサカウント1になる - ceil(min(cpuset-cpus, cpu-shares/1024, cpus)) - ceil(2/1024) = 1 (processor) - taskdefで4096でもcontainerdefで0だと1024しか使えない - 解決策 - -XX:ActiveProcessorCountで明示的に設定 - JVM側でコンテナ対応のための変更が入る可能性がある - autodetectやデフォルト値の算出方法が変わる可能性あり JVMとECSとcpu.shares * https://github.com/aws/amazon-ecs-agent/issues/1735

Slide 44

Slide 44 text

- JVM自体が一種のコンテナ - コンテナ(JVM) on コンテナ(Docker) 的な感じになる - task全体のリソース制御 - Container毎のリソース制御(cgroup) - JVMのリソース制御 - warmup周りやイメージサイズなど起動時の問題 - その他にも - Xms, Xmx, InitialRAMPercentage, MaxRAMPercentage など JVMのリソース管理 * https://speakerdeck.com/hhiroshell/jvm-on-kubernetes

Slide 45

Slide 45 text

- ユーザへのアラート通知や外形監視機能の接続元IPアドレス - ユーザーがfirewallなどの設定に利用 - 移行前の構成 - EC2にEIPをつけていた - ECSタスクに直接グローバルIPを付与することは出来ない - 解決策 - Subnetを別に作成しNatGatewayにEIPを付与 - NatGatewayが増えたのでコストは増えた グローバルIPの固定 * https://support.mackerel.io/hc/ja/articles/360039701332-Webhook通知や外形監視など-Mackerelからの通知元IPアドレスは-

Slide 46

Slide 46 text

- 同じECS Serviceでもタスクがデプロイされるホストが異なることが ある - CPUが違ったり、ネットワークインターフェースが違ったり - 2020/6ではPlatform Version 1.4.0内でも3種類ぐらい確認 - 同じvCPU指定でもパフォーマンスはタスクによって異なる - 大きくは異ならないようにしていると思われる - t3, m5相当? - C5などのEC2から移行する場合は1Coreあたりの処理性能に注意 - パフォーマンスのテストするときも注意 Fargateのホスト

Slide 47

Slide 47 text

- 全部同じECS Serviceですが - CPUは3種類 - ネットワークインターフェースの作り方は2種類 - 最近はeth0に 169.254.172.2 をつけるようになった Fargateのホスト