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

2021-06-cloud-native-reg-event

 2021-06-cloud-native-reg-event

発表タイトル:
MackerelにおけるEC2からFargate移行の軌跡とFargateのメリットデメリットについて

イベント名:
そろそろマネージド、クラウドネイティブで行こう!
コンテナサービスへの移行祭り

https://pages.awscloud.com/JAPAN-event-OE-20210617-Cloud-native-reg-event.html

masayoshi

June 17, 2021
Tweet

More Decks by masayoshi

Other Decks in Technology

Transcript

  1. - 名前: 古川 雅大 ( id:masayoshi Twitter: @yoyogidesaiz ) -

    所属: 株式会社はてな - MackerelチームのリードSRE (Site Reliability Engineer) - 趣味 - ネットワーク、サーバーをいじること - 格闘ゲーム 自己紹介
  2. - 対象 - EC2やVM環境からFargate(ECS)を目指す人向けに事例紹介 - ECSに関わることが中心 (コンテナ化自体の話は省略) - 構成 -

    Mackerelのインフラ構成の変遷 - 移行前の課題と移行の目的 - 移行時、移行後で困った点 - 移行時の工夫 - 移行してよかったこと - これから移行する人へ - 付録 今日話すこと * Dockerfileの書き方とか工夫など
  3. 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)
  4. - 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
  5. - アプリケーションサーバーを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移行
  6. - Mackerel SREチームのミッション - SLOに基づいたサービス運用 - インフラ運用をドッグフーディングできる環境を開発チームに提供 - ミッションに基づいた目的設定 -

    コンテナ運用環境でMackerelをSLOに基づいて安定運用すること - 特にk8sとECS - 「コンテナ運用をすること」自体がプロダクトに貢献 - 「運用が楽になること」が目的ではない コンテナ運用知見の獲得 * 多くのサービスではコンテナ運用は手段であり、目的になることはほとんどないため、Mackerelチーム特有の課題
  7. - デプロイがAMIを生成する方式ではなかった - 1回作ったEC2に、アプリケーションをデプロイする方式 (インプレース) - EC2はchefの実行や、社内ホスト名やDNS登録などをするため 社内共通スクリプトで構築していた - オンプレ環境のレガシー基盤に引きづられていた

    - Auto Scaling Groupを活用出来ていなかった - そのため、回復性の課題が存在した - 1台落ちたら人間が起動し直していた - EC2メンテナンスなどの対応が必要 (月1回以上の頻度) - AZ障害時にAZの移動に時間がかかっていた - EC2の構築のたびにchefを実行 EC2運用の課題
  8. - 回復性 - サーバーの自動復旧 - オートスケール - 管理性 - 可観測性

    CloudNative ~ダイナミックな環境~ CNCF Cloud Native Definition v1.0 https://github.com/cncf/toc/blob/main/DEFINITION.md (2021/06/08) これらの手法により、回復性、管理力、および可観測性のある疎結合システムが実 現します。
  9. - 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で実現するダイナミックな環境
  10. - 当初は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人だった
  11. - 社内での運用実績や運用負荷を考慮し選択 - 自分たちがコンテナ運用環境を始めることを重視 - CodeDeployによるBlue/Green Deployを選択 - 最初はCFnによるローリングデプロイだった -

    Terraformの採用 - 他のクラウドサービスの利用 - 当時CFnがCodeDeploy Blue/Greenに非対応だった - module化が容易 - 参考: terraform周りの話 ECS Fargateへの移行 https://speakerdeck.com/heleeen/our-best-practice
  12. - Fargate移行に関しての大きな困りごとはなかった - 移行コスト、難易度が低かった - 特にgoのアプリケーションは何事もなく移行完了 - JVM周りの注意点や困り事 - JVMのウォームアップ

    - JVMとECS TaskDefinitionとcpu.shares - JVMが利用するCPU数の設定に関する問題 (詳細は付録を参照) - Fargate環境における困り事 - デバッグが難しい - platform側で発生する問題 移行時、移行後に困った点 * 本発表は Java 11 を前提にしてお話しています
  13. - JVMは起動時に遅い - クラスのロードなど - ECSはALBのHealthCheckがUnhealthyだとタスク(コンテナ)を終了する - 起動時に遅い => 一瞬Unhealthyになる

    => 再起動 のクラッシュループ - Deploy時やコンテナの異常終了時に発生しうる - ALBに投入される前にウォームアップを完了する必要がある JVMのウォームアップ
  14. - 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以外にもタスク起動時の初期化でやりたい処理は同じ作戦が使える
  15. 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の組み合わせで初期化
  16. - 先程のwarmupや、cpu.sharesのリソース動作確認 - その他にもJVMのHeapdump取りたいなど - EC2と比べてリモート接続や特権制御により難しい - Fargateのデメリット - 解決策

    - JVMはJMXのリモート接続でモニタリング - SSHできるサイドカーを用意してデバッグ作業 - 現在はPlatform Version 1.4.0でECS execによるデバッグが可能 - サポートの活用 - SAなどへの相談やサポート問い合わせ デバッグが難しい
  17. - マネージドサービスもplatform側の問題やエラーもある - 不具合の起きないシステム、サービスはない - 致命的な問題は遭遇していない - 解決策 - サポートの活用

    - ユーザーだけの調査には限界がある - SA, TAMなどへの相談やサポート問い合わせ - 特にスペシャリストへの相談は非常に役立つ - ビジネス、エンタープライズサポートへの加入をお薦め platform側で発生する問題
  18. - 特定の条件でplatform側でエラーが発生する事象 - サポートが1ヶ月程度かけて調査してくれた - その間、我々は他のタスクに集中できる (調査工数の削減) - 現在も不明なエラー事象に遭遇している -

    platform側の問題なのか、設定やコード上の問題など原因の切り分け中 - SAの方と相談、サポートへの調査や再現を依頼 - マネージドサービスはOSSのようにコードを読めない、直せない - 代わりにサポートやスペシャリストと相談できる - マネージドサービスを利用するなら併せてサポートプランも検討 platform側で発生する問題
  19. - 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の活用
  20. - 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の同時稼働
  21. - SLOを基準に判断 - staging環境でSLOを満たしていたら本番投入OK - エラーレート1%以上 レイテンシ 99%ile 200ms 以上

    ならECS weightを0にして切り戻す - 「正常に動いている」とはどういうことを指すのかSLOで表現 - 本番投入時のスプリントはSLOを再検討 - 移設時などはSLOを下げるなど、スプリントで話し合うことで移設担当者の 精神的負荷を軽減できる - 移設タイミングでSLOが十分に余っていることを確認する - SLOが余っているなら積極的に投入していく SLOによる本番投入や切り戻し基準の設定
  22. - 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
  23. - EC2 メンテナンスから解放 - 月1回程度のEC2メンテナンスがほぼ0件に - Fargateもホスト側のメンテナンスがあるが勝手に起動 - 回復性 -

    タスク落ちても勝手に起動してくれる - warmupも対応したので対応が不要 - AZ障害のとき、CodeDeployでsubnet指定をしてデプロイするだけ - 管理性 - 台数増加が楽になった - ホストOSのバージョンアップやchefメンテナンスが不要 - 特にホストOSの脆弱性対応など EC2インスタンス管理から解放 * EC2 AutoScaling Groupでも実現可能な項目もある
  24. - メリット - CloudNativeな環境を容易に手に入れられる - 特に回復性 - AutoScaling Groupのキャパシティプランニングや構築より容易 -

    k8sと比べて学習コストや、クラスターのバージョンアップなどが容易 - デメリット - デバッグが難しい (デバッグが簡単にならない) - 自前の基盤を用意したとしてもFargateよりデバッグが容易になるとは限らない - サポートを活用することでカバーは可能 - ECS execなど、今後もデバッグが容易になる機能が追加されると思われる Fargateのメリット、デメリット * 充実したエコシステムを利用したCI/CDなどk8sはk8sでメリットも多い 移行コストを抑えながら、CloudNative移行ならFargate(ECS)がお薦め!
  25. - 移行の目的や判断基準をチーム内で共有する - SREの文化があるならSLOなどを活用 - マネージドサービスから検討し、だめなら自前で - ECSで行くなら Fargate >

    ECS on EC2 - k8sで行くなら Fargate for EKS > EKS - コンテナ化が難しいならEC2 AutoScaling Group - CloudNative実現にはかなり作り込みが必要 - サポートプランも併せて検討 - 移行時の相談やマネージドサービス利用時の不具合や障害で活用 - 移行後も運用は続く - 移行時にすべての問題を解決する必要はない - 「移行タイミングはいい機会だからあれもこれも」は要注意! これから移行に挑戦する方へ * コンテナの前にlambdaなどサーバーレスも検討できると最高!
  26. - 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
  27. - JVM自体が一種のコンテナ - コンテナ(JVM) on コンテナ(Docker) 的な感じになる - task全体のリソース制御 -

    Container毎のリソース制御(cgroup) - JVMのリソース制御 - warmup周りやイメージサイズなど起動時の問題 - その他にも - Xms, Xmx, InitialRAMPercentage, MaxRAMPercentage など JVMのリソース管理 * https://speakerdeck.com/hhiroshell/jvm-on-kubernetes
  28. - ユーザへのアラート通知や外形監視機能の接続元IPアドレス - ユーザーがfirewallなどの設定に利用 - 移行前の構成 - EC2にEIPをつけていた - ECSタスクに直接グローバルIPを付与することは出来ない

    - 解決策 - Subnetを別に作成しNatGatewayにEIPを付与 - NatGatewayが増えたのでコストは増えた グローバルIPの固定 * https://support.mackerel.io/hc/ja/articles/360039701332-Webhook通知や外形監視など-Mackerelからの通知元IPアドレスは-
  29. - 同じECS Serviceでもタスクがデプロイされるホストが異なることが ある - CPUが違ったり、ネットワークインターフェースが違ったり - 2020/6ではPlatform Version 1.4.0内でも3種類ぐらい確認

    - 同じvCPU指定でもパフォーマンスはタスクによって異なる - 大きくは異ならないようにしていると思われる - t3, m5相当? - C5などのEC2から移行する場合は1Coreあたりの処理性能に注意 - パフォーマンスのテストするときも注意 Fargateのホスト