発表タイトル: MackerelにおけるEC2からFargate移行の軌跡とFargateのメリットデメリットについて
イベント名: そろそろマネージド、クラウドネイティブで行こう! コンテナサービスへの移行祭り
https://pages.awscloud.com/JAPAN-event-OE-20210617-Cloud-native-reg-event.html
2021.06.18株式会社はてなMackerelチーム リードSRE古川 雅大MackerelにおけるEC2からFargate移行の軌跡とFargateのメリットデメリットについて
View Slide
- 名前: 古川 雅大 ( id:masayoshi Twitter: @yoyogidesaiz )- 所属: 株式会社はてな- MackerelチームのリードSRE (Site Reliability Engineer)- 趣味- ネットワーク、サーバーをいじること- 格闘ゲーム自己紹介
Mackerelとは
クラウド運用を簡単にはじめられるSaaS型サーバー監視サービスMackerelの特徴● システムの運用・監視を簡単にはじめられます● クラウド時代に最適な監視モデルをもとに素早く導入できます● 日本語ドキュメントやサポートによって成長を後押しします4
システムの運用・監視を簡単にはじめられます➔ 導入はガイドにしたがってコマンドを実行するだけ➔ エージェントが死活監視とメトリック取得を自動で開始➔ 直感的なUIでサービスの状況を可視化➔ 監視をはじめる敷居が下がり、チームで取り組めます5
- 対象- EC2やVM環境からFargate(ECS)を目指す人向けに事例紹介- ECSに関わることが中心 (コンテナ化自体の話は省略)- 構成- Mackerelのインフラ構成の変遷- 移行前の課題と移行の目的- 移行時、移行後で困った点- 移行時の工夫- 移行してよかったこと- これから移行する人へ- 付録今日話すこと* Dockerfileの書き方とか工夫など
Mackerelのインフラ構成の変遷
Mackerelのインフラ構成の変遷On-premises Cloud First Cloud Native2014 2017 20192015 2016 2018 2020 2021・ComputeVMXen Hypervisor・Time Series DatabaseioMemoryGraphite・Relational DatabasePostgreSQL・ComputeVMEC2・Time Series DatabaseRedisDynamoDBS3・Relational DatabaseRDS(PostgreSQL)・ComputeContainerECS・Time Series DatabaseElastiCacheDynamoDBS3・Relational DatabaseRDS(PostgreSQL)
- 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-lihttps://blog.astj.space/entry/2018/02/06/175902https://blog.yuuk.io/entry/the-rebuild-of-tsdb-on-cloudhttps://blog.astj.space/entry/2019/03/07/110234
- アプリケーションサーバーを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-weekEC2からECS Fargate移行
移行前の課題と移行の目的
- コンテナ運用知見の獲得 (Mackerelチーム特有の課題)- EC2運用の課題の解決 (一般的な課題)MackerelチームのFargate移行の目的
- Mackerel SREチームのミッション- SLOに基づいたサービス運用- インフラ運用をドッグフーディングできる環境を開発チームに提供- ミッションに基づいた目的設定- コンテナ運用環境でMackerelをSLOに基づいて安定運用すること- 特にk8sとECS- 「コンテナ運用をすること」自体がプロダクトに貢献- 「運用が楽になること」が目的ではないコンテナ運用知見の獲得* 多くのサービスではコンテナ運用は手段であり、目的になることはほとんどないため、Mackerelチーム特有の課題
- デプロイがAMIを生成する方式ではなかった- 1回作ったEC2に、アプリケーションをデプロイする方式 (インプレース)- EC2はchefの実行や、社内ホスト名やDNS登録などをするため社内共通スクリプトで構築していた- オンプレ環境のレガシー基盤に引きづられていた- Auto Scaling Groupを活用出来ていなかった- そのため、回復性の課題が存在した- 1台落ちたら人間が起動し直していた- EC2メンテナンスなどの対応が必要 (月1回以上の頻度)- AZ障害時にAZの移動に時間がかかっていた- EC2の構築のたびにchefを実行EC2運用の課題
クラウドネイティブ技術は、パブリッククラウド、プライベートクラウド、ハイブリッドクラウドなどの近代的でダイナミックな環境において、スケーラブルなアプリケーションを構築および実行するための能力を組織にもたらします。CloudNativeCNCF Cloud Native Definition v1.0 https://github.com/cncf/toc/blob/main/DEFINITION.md (2021/06/08)
- 回復性- サーバーの自動復旧- オートスケール- 管理性- 可観測性CloudNative ~ダイナミックな環境~CNCF Cloud Native Definition v1.0 https://github.com/cncf/toc/blob/main/DEFINITION.md (2021/06/08)これらの手法により、回復性、管理力、および可観測性のある疎結合システムが実現します。
- 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で実現するダイナミックな環境
- 当初はk8sに移行する予定だった- k8s運用のドッグフーディング + CloudNativeが目的- 検討当時(2018夏)はEKSの東京リージョンがなかった- EC2上にk8sを自前で構築- 本番環境は数ヶ月チャレンジしたが撤退した- 学習コスト、更新頻度などでSLOを満たすことが難しかった- 「SLOを満たす & コンテナ運用のドッグフーディング」- AWSのコンテナサービスを活用してリトライ- 参考資料- Blog- 発表資料- 記事(参考)k8s化にチャレンジして出直しhttps://developer.hatenastaff.com/entry/leading-kubernetes-at-hatenahttps://speakerdeck.com/hayajo/kubernetes-meetup-tokyo-number-22https://www.atmarkit.co.jp/ait/articles/1911/08/news009.html* 当時MackerelチームのSREは1人だった
- 社内での運用実績や運用負荷を考慮し選択- 自分たちがコンテナ運用環境を始めることを重視- CodeDeployによるBlue/Green Deployを選択- 最初はCFnによるローリングデプロイだった- Terraformの採用- 他のクラウドサービスの利用- 当時CFnがCodeDeploy Blue/Greenに非対応だった- module化が容易- 参考: terraform周りの話ECS Fargateへの移行https://speakerdeck.com/heleeen/our-best-practice
移行時、移行後で困った点
- Fargate移行に関しての大きな困りごとはなかった- 移行コスト、難易度が低かった- 特にgoのアプリケーションは何事もなく移行完了- JVM周りの注意点や困り事- JVMのウォームアップ- JVMとECS TaskDefinitionとcpu.shares- JVMが利用するCPU数の設定に関する問題 (詳細は付録を参照)- Fargate環境における困り事- デバッグが難しい- platform側で発生する問題移行時、移行後に困った点* 本発表は Java 11 を前提にしてお話しています
- JVMは起動時に遅い- クラスのロードなど- ECSはALBのHealthCheckがUnhealthyだとタスク(コンテナ)を終了する- 起動時に遅い => 一瞬Unhealthyになる => 再起動 のクラッシュループ- Deploy時やコンテナの異常終了時に発生しうる- ALBに投入される前にウォームアップを完了する必要があるJVMのウォームアップ
- 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以外にもタスク起動時の初期化でやりたい処理は同じ作戦が使える
containerDefinitions:- name: appessential: truehealthCheck:command:- CMD-SHELL- curl -L -s -o /dev/null http://localhost:8000/healthcheck || exit 1interval: 5retries: 10startPeriod: 60timeout: 5- name: warmupdependsOn:- condition: HEALTHYcontainerName: appentryPoint:- /opt/bin/warmup.shJVMのウォームアップ ~解決策~* dependsOnとhealthCheckの組み合わせで初期化
- 先程のwarmupや、cpu.sharesのリソース動作確認- その他にもJVMのHeapdump取りたいなど- EC2と比べてリモート接続や特権制御により難しい- Fargateのデメリット- 解決策- JVMはJMXのリモート接続でモニタリング- SSHできるサイドカーを用意してデバッグ作業- 現在はPlatform Version 1.4.0でECS execによるデバッグが可能- サポートの活用- SAなどへの相談やサポート問い合わせデバッグが難しい
- マネージドサービスもplatform側の問題やエラーもある- 不具合の起きないシステム、サービスはない- 致命的な問題は遭遇していない- 解決策- サポートの活用- ユーザーだけの調査には限界がある- SA, TAMなどへの相談やサポート問い合わせ- 特にスペシャリストへの相談は非常に役立つ- ビジネス、エンタープライズサポートへの加入をお薦めplatform側で発生する問題
- 特定の条件でplatform側でエラーが発生する事象- サポートが1ヶ月程度かけて調査してくれた- その間、我々は他のタスクに集中できる (調査工数の削減)- 現在も不明なエラー事象に遭遇している- platform側の問題なのか、設定やコード上の問題など原因の切り分け中- SAの方と相談、サポートへの調査や再現を依頼- マネージドサービスはOSSのようにコードを読めない、直せない- 代わりにサポートやスペシャリストと相談できる- マネージドサービスを利用するなら併せてサポートプランも検討platform側で発生する問題
移行時の工夫
- terraform moduleの活用- Weighted Routingを活用したEC2とECSの同時稼働- SLOによる本番投入や切り戻し基準の設定移行時の工夫
- module化- ECSクラスタ、ECS Serviceの作成- CodePipeline, CodeDeployのCI/CDパイプライン- 後述するデプロイ時に起動するlambdaなど- goとscala合わせて7つ移設- すべて同じmoduleで構築できたため構築、管理工数削減- 詳細はこちら- 「Mackerel におけるTerraform 運用 / Our (Best?) Practice」- https://speakerdeck.com/heleeen/our-best-practiceterraform moduleの活用
- 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の同時稼働
- SLOを基準に判断- staging環境でSLOを満たしていたら本番投入OK- エラーレート1%以上 レイテンシ 99%ile 200ms 以上ならECS weightを0にして切り戻す- 「正常に動いている」とはどういうことを指すのかSLOで表現- 本番投入時のスプリントはSLOを再検討- 移設時などはSLOを下げるなど、スプリントで話し合うことで移設担当者の精神的負荷を軽減できる- 移設タイミングでSLOが十分に余っていることを確認する- SLOが余っているなら積極的に投入していくSLOによる本番投入や切り戻し基準の設定
- 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
MackerelのSLO(可用性)ダッシュボードの例※ 数字ははめ込み加工なので実際の Mackerelの可用性とは異なります
移行してよかったこと
- EC2インスタンス管理から解放- コンテナ運用知見の獲得- CI/CDがB/Gになり、リリースフローが改善移行してよかったこと
- EC2 メンテナンスから解放- 月1回程度のEC2メンテナンスがほぼ0件に- Fargateもホスト側のメンテナンスがあるが勝手に起動- 回復性- タスク落ちても勝手に起動してくれる- warmupも対応したので対応が不要- AZ障害のとき、CodeDeployでsubnet指定をしてデプロイするだけ- 管理性- 台数増加が楽になった- ホストOSのバージョンアップやchefメンテナンスが不要- 特にホストOSの脆弱性対応などEC2インスタンス管理から解放* EC2 AutoScaling Groupでも実現可能な項目もある
- メリット- CloudNativeな環境を容易に手に入れられる- 特に回復性- AutoScaling Groupのキャパシティプランニングや構築より容易- k8sと比べて学習コストや、クラスターのバージョンアップなどが容易- デメリット- デバッグが難しい (デバッグが簡単にならない)- 自前の基盤を用意したとしてもFargateよりデバッグが容易になるとは限らない- サポートを活用することでカバーは可能- ECS execなど、今後もデバッグが容易になる機能が追加されると思われるFargateのメリット、デメリット* 充実したエコシステムを利用したCI/CDなどk8sはk8sでメリットも多い移行コストを抑えながら、CloudNative移行ならFargate(ECS)がお薦め!
これから移行に挑戦する方へ
- 移行の目的や判断基準をチーム内で共有する- SREの文化があるならSLOなどを活用- マネージドサービスから検討し、だめなら自前で- ECSで行くなら Fargate > ECS on EC2- k8sで行くなら Fargate for EKS > EKS- コンテナ化が難しいならEC2 AutoScaling Group- CloudNative実現にはかなり作り込みが必要- サポートプランも併せて検討- 移行時の相談やマネージドサービス利用時の不具合や障害で活用- 移行後も運用は続く- 移行時にすべての問題を解決する必要はない- 「移行タイミングはいい機会だからあれもこれも」は要注意!これから移行に挑戦する方へ* コンテナの前にlambdaなどサーバーレスも検討できると最高!
(付録) 時間の関係で省略した内容
- 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
- JVM自体が一種のコンテナ- コンテナ(JVM) on コンテナ(Docker) 的な感じになる- task全体のリソース制御- Container毎のリソース制御(cgroup)- JVMのリソース制御- warmup周りやイメージサイズなど起動時の問題- その他にも- Xms, Xmx, InitialRAMPercentage, MaxRAMPercentage などJVMのリソース管理* https://speakerdeck.com/hhiroshell/jvm-on-kubernetes
- ユーザへのアラート通知や外形監視機能の接続元IPアドレス- ユーザーがfirewallなどの設定に利用- 移行前の構成- EC2にEIPをつけていた- ECSタスクに直接グローバルIPを付与することは出来ない- 解決策- Subnetを別に作成しNatGatewayにEIPを付与- NatGatewayが増えたのでコストは増えたグローバルIPの固定* https://support.mackerel.io/hc/ja/articles/360039701332-Webhook通知や外形監視など-Mackerelからの通知元IPアドレスは-
- 同じECS Serviceでもタスクがデプロイされるホストが異なることがある- CPUが違ったり、ネットワークインターフェースが違ったり- 2020/6ではPlatform Version 1.4.0内でも3種類ぐらい確認- 同じvCPU指定でもパフォーマンスはタスクによって異なる- 大きくは異ならないようにしていると思われる- t3, m5相当?- C5などのEC2から移行する場合は1Coreあたりの処理性能に注意- パフォーマンスのテストするときも注意Fargateのホスト
- 全部同じECS Serviceですが- CPUは3種類- ネットワークインターフェースの作り方は2種類- 最近はeth0に 169.254.172.2 をつけるようになったFargateのホスト