Slide 1

Slide 1 text

ECS Best Practice All on board Toshinori Kikuchi Classmethod, Inc.

Slide 2

Slide 2 text

Self-Introduction 2 ● 【Name】:Toshinori Kikuchi ● 【Company Affiliation】:Classmethod, Inc. ● 【AWS Title】 ○ 2024 Japan AWS Top Engineers ○ 2024 Japan AWS All Certifications Engineers ● 【Blog】 https://dev.classmethod.jp/author/tooti/ ● 【X】 https://x.com/tttkkk215 ● 【Favorite Technologies】 Containers, Terraform, Amazon EventBridge, AWS Step Functions

Slide 3

Slide 3 text

3 このセッションの対象者と目標 ● 対象者 ○ ECSを使い始めたばかりの方 ○ ECSを使っているが、正しく使えてるかわからない。 ○ ECSに移行し、次のステップを模索している。 ● 目標 ○ ECSのベストプラクティスに沿ったシステム構築ができる ○ 現行のECSに基づいて構築されたシステムの改善点を特定で きる

Slide 4

Slide 4 text

4 Amazon ECSのベストプラクティスとは? ● AWSはECSのベストプラクティスとして以下のドキュメントを発行し ています。 ○ Amazon ECS ベストプラクティス ■Amazon Elastic Container Service ● AWS Service Delivery Program(Amazon ECS Delivery Partners)には、ECSのデリバリがベストプラクティスに沿っている かどうかを確認するためのチェックリストがあります。 ● 私はこれらのドキュメントを基に独自のチェックリストを作成した。 ○ https://github.com/ice1203/ecs-bestpractice-checklist

Slide 5

Slide 5 text

5 Amazon ECSのベストプラクティスとは? ● 本セッションでは、これらのベストプラクティスの中で、実際に適用 する際に問題になりそうな項目をアジェンダ化してみました。 ● 各項目について、設計時に考慮すべきポイントを解説する。

Slide 6

Slide 6 text

アジェンダ 6 ● CI/CD ● タスク定義(タスクサイジング、リソース予約・制限) ● セキュリティ(コンテナイメージセキュリティスキャン/ランタイムセキュリ ティ) ● サービス間ネットワーク構成 ● オブザーバビリティ

Slide 7

Slide 7 text

7 ● 考慮すべき設計のポイント CI/CD ● ソース管理 ○ どのバージョン管理システムを使うか( GitHub、GitLabな ど) ○ システムのどの単位でリポジトリを分けるか ○ インフラとアプリケーションでリポジトリを分けるかどうか ○ ブランチの保護方法(ブランチ保護ルールの使用など) ● ブランチ戦略の確立 ○ どのようなブランチ戦略を使うか( GitFlow、GitHub Flow、TrunkBaseなど) ○ 環境の違いをどのように表現するか ● パイプライン全体の設計 ○ どのCI/CDツールを使うか(GitHub Actionsなど) ○ プロセスの流れは? ○ 各ステージの役割と目的を明確にする ● トリガーを設定する ○ どのような処理をトリガーするか ○ 定期的な実行の有無(例:毎日のビルド) ○ 手動トリガーオプションの提供 ● テストの自動化 ○ どのようなテストを行うのですか? ■ 単体テストと統合テスト ● IaCの選択 ○ どのIaCを使うか ■ AWS CDK ■ テラフォーム ○ ECSタスク定義、サービス管理方法 ● 展開方法の選択 ○ どのデプロイメント戦略? ■ ブルー/グリーン・デプロイメント ■ ローリングアップデート ● ロールバック戦略 ○ 自動ロールバックメカニズム ○ 手動ロールバック・プロセスの確立 ● セキュリティ・スキャン ○ どのようなセキュリティスキャンを行いますか? ■ コンテナ・イメージの脆弱性スキャン ■ IaCコードのセキュリティ・スキャン ● 監視と通知設定 ○ デプロイの成功/失敗の通知 ○ デプロイ中に監視するメトリクスの決定 など

Slide 8

Slide 8 text

8 ● IaC ○ CDKやTerraformをベースにすれば間違いない。 ○ インフラとアプリのライフサイクルは違う。タスク定義とサービス 定義はアプリのライフサイクルと同じ。 ○ そのため、アプリ側でタスク定義やサービス定義を管理したい ⇒ecspresso CI/CD (IaC)

Slide 9

Slide 9 text

9 CI/CD (IaC) ● ecspresso ○ ECSのサービスやタスク に関連するResourceの コード管理やデプロイの ためのツール ○ tfstateファイルを読み込 んでリソース情報を参照 できる ○ CloudFormation Outputs、Export値も読 める ○ 最低限管理するファイル は3つだけ

Slide 10

Slide 10 text

10 ● ecspressoでデプロイする際の注意点 ○ ecspressoで管理できるのは、ECSのタスク定義とサービス定義 のみです。 ○ ApplicationAutoScalingとCodeDeployは対象外です。 ○ 初回は以下のように構築します。 i. IaC(Terraformなど)でALB、ECSクラスタなどを作成 ii. ecspressoによるECSタスク定義、ECSサービス作成 iii. IaCでCodeDeployやAutoScalingを作成 ○ 初回構築以降は、(基本的に)ecspressoとIaCは独立して更新で きます。 CI/CD (IaC)

Slide 11

Slide 11 text

11 ● どのようなブランチ戦略を使うべきか? ○ チームの規模やリリースサイクル、企業文化などによって適切 な形は異なるため、正解はありません。 ○ コンテナ特有の検討事項として、環境間でコンテナイメージを 共有するかどうかがある。 ■ 個人的には共有した方がいいと思う。 ○ それぞれのタイミングで何をすべきかを考えたので、インフラ とアプリに分けて考えてみる CI/CD(ブランチ戦略) ブランチカット

Slide 12

Slide 12 text

12 ● Infrastructure CI/CD CI/CD (branch strategy)

Slide 13

Slide 13 text

13 ● Infrastructure CI/CD CI/CD (branch strategy)

Slide 14

Slide 14 text

14 ● Application CI/CD CI/CD (branch strategy)

Slide 15

Slide 15 text

15 * Image source: DevelopersIO, https://dev.classmethod.jp/articles/ecs-deploytype/ CI/CD(デプロイ) ● ローリングアップデート ○ 利点 ■ シンプルであるため、設 計と構築が比較的容易 である。 ■ シンプルな設計のため、 故障箇所が限定される (その結果、トラブル シューティングが容易に なる) ○ デメリット ■ 古い仕事と新しい仕事が 混在する瞬間がある

Slide 16

Slide 16 text

CI/CD(デプロイ) 16 ● ブルー/グリーンデプロイ ○ 利点 ■ アプリケーションを一度に切り替え られるので、新旧のタスクが混在し ない ○ デメリット ■ ロードバランサーが必要 ■ 構成が複雑なため、設計・構築が 比較的難しく、新メンバーが理解す るのに時間がかかる。 ■ 追加の設定ファイルを管理する必 要がある(CodeDeployの設定な ど)。 ■ プロセスが複雑で、トラブルシュー ティングが難しくなる。 *画像ソース: DevelopersIO、https://dev.classmethod.jp/articles/ecs-deploytype/

Slide 17

Slide 17 text

17 CI/CD(デプロイ) ecspresso.yml ● ecspressoを使うことで、B/G デプロイの管理要素も減らす ことができます。 ○ appspec.yamlは基本的 に不要です。 ○ AutoScalingの停止コマ ンドが用意されているの で、CDプロセスにコマン ドを含めるだけで、デプロ イの前後にAutoScaling を停止したり再起動した りできます。 cluster: default service: test service_definition : ecs-service-def.json task_definition: ecs-task-def.json appspec: Hooks: - BeforeInstall: "LambdaFunctionToValidateBeforeInstall" - AfterInstall: "LambdaFunctionToValidateAfterTraffic" - AfterAllowTestTraffic : "LambdaFunctionToValidateAfterTestTrafficStarts" - BeforeAllowTraffic : "LambdaFunctionToValidateBeforeAllowingProductionTraffic" - AfterAllowTraffic: "LambdaFunctionToValidateAfterAllowingProductionTraffic"

Slide 18

Slide 18 text

18 ● 考慮すべき設計の主要な側面とは? タスクの定義 ● タスクサイズ ○ アプリケーション要件に基づく CPUとメモリの適切な割り 当て ○ リソース制限の設定 ● コンテナ・イメージ ○ 信頼できるリポジトリからの最新で安定したイメージの使 用 ○ 多段階ビルドの使用 ○ イメージサイズの最小化 ○ グレースフル・シャットダウンの導入 ○ 画像のタグ付け(LATESTタグの使用を避ける) ● ストレージの設定 ○ どのストレージを使うべきか? ○ EFSによる永続データの統合 ○ 一時ストレージの適切なサイジング ● セキュリティの強化 ○ タスクロールとタスク実行ロールの適切な構成 ○ 最小権限の原則に基づく IAM ポリシーの適用 ○ readOnlyRootFilesystem ● ログ設定 ○ CloudWatch ログ ○ firelensを考える ● 環境変数の管理 ○ 機密情報の安全な管理( AWS Secrets Managerの使 用) ● ヘルスチェックの実装 ○ コンテナのヘルスチェックコマンドの定義 ○ 適切なタイムアウトと間隔の設定 ● コンプライアンスと監査 ○ 必要なタグの適用 ○ 監査要件に基づくログ設定 ● ネットワーキングの最適化 ○ ENIトランキングの設定(必要な場合) その他

Slide 19

Slide 19 text

Task Definisions(TaskSize) 19 fields @timestamp, CpuUtilized, CpuReserved, CpuUtilized * 100 / CpuReserved as CpuUtilization, MemoryUtilized, MemoryReserved, MemoryUtilized * 100 / MemoryReserved as MemoryUtilization | filter ContainerName = "xxxxx" and Type = "Container" and TaskId = "yyyyy" | sort @timestamp asc | limit 10000 | stats avg(CpuUtilization),avg(MemoryUtilization) by bin(1m) ● 結論から言えば、稼働率をチェックし、パフォーマンステストなどで 調整するのがベストだ。 ● 各コンテナの利用率を確認するには ○ コンテナインサイトを有効にする ○ Cloudwatch Logs Insightsで以下のクエリを実行する。

Slide 20

Slide 20 text

Task Definisions(TaskSize) 20

Slide 21

Slide 21 text

21 ● タスクレベルとコンテナレベルの設定 ○ タスク・レベル:タスクのCPUとメモリの上限と制限を表す。 ■ タスクによって実行されるコンテナは、タスクサイズで定義さ れた容量しか使用できない ■ Fargateの場合、タスク実行時に使用するインスタンスを決定 する基準となる(ので、必ず指定する必要がある)。 タスク定義(TaskSize)

Slide 22

Slide 22 text

22 ● コンテナ・レベル: 各コンテナのCPUおよびメモリの予約または制 限。 ● ContainerInsightsは、コンテナレベルでCPUとメモリを設定しない と、コンテナごとの使用率を記録しないことに注意してください。 ○ CPU: ■ タスクレベルのCPU設定が利用可能な最大CPUを表してい るのに対して、コンテナレベルのCPU設定はCPU占有率で 重み付けされる。 ■ この重み付けは、CPUが競合している場合にのみ有効であ る。 タスク定義(タスクサイズ)

Slide 23

Slide 23 text

23 ● コンテナ・レベル: 各コンテナで使用可能なCPUとメモリの予約また は制限 ○ メモリ ■ ソフトリミットのみを指定する: 上限はタスクレベルで指定され た値(タスクに複数のコンテナがある場合、タスクレベルでメ モリ量を奪い合う)。 ■ ソフトリミットとハードリミットを指定:ソフトリミットは予約、ハー ドリミットは上限を表す。 ■ ハードリミットのみ指定:ハードリミットは予約と上限を表す タスク定義(TaskSize)

Slide 24

Slide 24 text

24 ● Dockerfileのベストプラクティス ○ マルチステージビルドの使用 ○ 1コンテナ1プロセス ○ ルートユーザーとして実行しない ○ コンテナはステートレス(状態を保持しない)。 ○ コンテナ・イメージのサイズをできるだけ小さくする ○ など ○ 詳細はこちら。 ■ https://docs.docker.jp/develop/develop-images/dockerfile _best-practices.html タスクの定義

Slide 25

Slide 25 text

タスク定義 25 # ビルドステージ FROM node:22 AS builder WORKDIR /usr/src/app # package.jsonとpackage-lock.jsonはバインドマウントされているのでコピーする必要はない #COPY package*.json ./ # 依存関係をインストールする。 RUN --mount=type=bind,source=package.json,target=package.json \ --mount=type=bind,source=package-lock.json,target=package-lock.json \ --mount=type=cache,target=/root/.npm,sharing=locked \ npm ci --omit=dev # アプリケーションのソースコードをコピーする COPY . . # 実行ステージ FROM gcr.io/distroless/nodejs22-debian12 # ビルド段階からアプリケーション・ディレクトリをコピーする COPY --chown=nonroot:nonroot --from=builder /usr/src/app /usr/src/app USER nonroot WORKDIR /usr/src/app CMD [ "index.js" ]。 ● 最近学んだこと ○ RUN --mount=type=bind ■ バインドマウント中にコマン ドを実行する ■ 不要なCOPYを減らすこと ができる。 ○ RUN --mount=type=cache ■ キャッシュディレクトリをマ ウントする。 ■ レイヤーキャッシュではな いので、依存パッケージに 変更があっても、最初から ダウンロードされることはな い。

Slide 26

Slide 26 text

タスク定義 26 # php FROM php:7.4-fpm-alpine as app_php RUN apk add --no-cache git COPY --from=composer:latest /usr/bin/composer /usr/bin/composer WORKDIR /var/www/html COPY composer.json composer.lock ./ RUN composer install --no-dev --optimize-autoloader --no-interaction --no-progress COPY . . CMD ["php-fpm"]. # NGINX FROM nginx:1.17-alpine AS app_nginx COPY docker/nginx/conf.d/default.conf /etc/nginx/conf.d/ WORKDIR /var/www/html COPY --from=app_php /var/www/html/public public/ ● 最近学んだこと ○ docker build --target=~ . ■ 中間ステージを成果物とし て生成することができま す。 ■ 例えば、テスト用のステー ジを用意し、テスト時にそ のステージを --target とし て指定することができま す。 ■ 多くのDockerfileを用意す る必要はないかもしれな い。

Slide 27

Slide 27 text

27 コンテナのセキュリティ ● コンテナのライフサイクルに沿ったセキュリティ対策 ○ 矢印の話

Slide 28

Slide 28 text

● 画像のチェック ○ 画像のチェック ■ 脆弱性が含まれていないか ■ Dockerfileの書き方に脆弱性はないか? ○ チェックするタイミング ■ ビルド時のチェック ■ 定期的なチェックも重要 ● Amazon Inspector 拡張スキャンは脆弱性DBにCVEが追 加されると自動的にスキャンする コンテナセキュリティ(レジストリ) 28

Slide 29

Slide 29 text

Container Security(Registry) 29

Slide 30

Slide 30 text

30 ● ランタイムセキュリティ ○ GuardDuty ランタイム監視 ■ 2023/11アップデートで追加されたECSのランタイムモニタリ ング ■ AWSネイティブサービスが実行時に脅威を検知できるように なった ■ 脅威を検出するだけだが、脅威が検出されたときに自動的に アクション(ECSタスク停止など)を取りたい場合は組み込む 必要がある コンテナ・セキュリティ

Slide 31

Slide 31 text

31 コンテナのセキュリティ ● 設定が非常に簡単

Slide 32

Slide 32 text

コンテナのセキュリティ 32 ● ランタイムセキュリティ ○ GuardDuty ランタイム・モニタリング vs Sysdig Secure ■ 対応ルール数 ● 36 vs. 少なくとも150以上ある。 ■ 検出速度 ● 約2分(※1) vs. 数秒 ■ ルールのカスタマイズ ● 不可能 vs. 可能 1 実際にインシデントが発生してからGuardDutyにイベントとして登録されるまでの時間(筆者 計測)。

Slide 33

Slide 33 text

Container Security 33

Slide 34

Slide 34 text

34 ● システムで何が起きているのかを明らかにするために、3種類の データを取得することがベストプラクティスである。 ○ メトリクス ○ トレース ○ ログ オブザーバビリティ

Slide 35

Slide 35 text

35 オブザーバビリティ ● AWS Distro for OpenTelemetry(ADOT)とは? ○ AWSがサポートするOpenTelemetry(OTel)ディス トリビューション ○ OTelはCNCFプロジェクトの一つなので将来性も ある ○ AWSサービスとの高い互換性 ● 主なコンポーネントはSDKとコレクター ● トレースだけでなく、ログやメトリクスも収集可能 ● トレース情報は、X-Ray、CloudWatch、Prometheus などに送信できる。 ● ECS Fargateの場合、コレクターはサイドカー・コンテ ナとして実装されている。 *画像ソース: One Observability Workshop,https://catalog.workshops.aws/observability/ja-JP/aws-managed-oss/adot/gowalk through

Slide 36

Slide 36 text

36 * For more information, see here. https://aws-otel.github.io/docs/getting-started/java-sdk/auto-instr ● 実装方法 ○ AutoInstrumentationエージェントをサポートしている言語であれ ば簡単に実装できる。 ○ Javaの例 i. アプリケーションのコンテナイメージに自動計測エージェント jarを含める ii. ECSタスク・ロールとECSタスク実行ロールにIAMポリシーを 追加 iii. 上記のコンテナイメージを含むECSタスク定義に、サイドカー コンテナとしてOTelコレクタを追加。 オブザーバビリティ

Slide 37

Slide 37 text

オブザーバビリティ 37 FROM amazoncorretto:17-alpine WORKDIR /アプリ ADD https://github.com/aws-observability/aws-otel-java-instrumentation/releases/download/v1 .21.1/aws-opentelemetry-agent.jar /app/aws-opentelemetry-agent.jar ENV JAVA_TOOL_OPTIONS "-javaagent:/app/aws-opentelemetry-agent.jar" ARG JAR_FILE=build/libs/*.jar COPY --from=build /app/${JAR_FILE} ./app.jar # OpenTelemetryエージェントの設定 ENV OTEL_TRACES_SAMPLER "parentbased_traceidratio" env otel_traces_sampler_arg "0.3" ENV OTEL_PROPAGATORS "tracecontext,baggage,xray" ENV OTEL_RESOURCE_ATTRIBUTES "service.name=PetSearch" env otel_imr_export_interval "10000" env otel_exporter_otlp_endpoint "http://localhost:4317" ENTRYPOINT ["java","-jar","/app/app.jar"]。 環境変数についてはこちらをご参照ください。,https://opentelemetry.io/docs/languages/sdk-configuration/general/ ● 環境変数でサンプリ ングレートや Observability Backendに表示され るサービス名などを 変更することができ ます。

Slide 38

Slide 38 text

オブザーバビリティ 38 { "name" : "aws-otel-collector" 、 "image" : "public.ecr.aws/aws-observability/aws-otel-collector:v0 .32.0" 、 "cpu" : 64 、 "メモリー" : 256 、 "links": []、 "portMappings" : []、 "essential" : true 、 "entryPoint": []、 "command": [ "--config" 、 "/etc/ecs/ecs-cloudwatch-xray.yaml" ], ● コレクター docker イ メージにはデフォル トでいくつかの設定 ファイルが含まれて おり、コンテナを起 動する際に引数とし て設定ファイルを指 定することができる。

Slide 39

Slide 39 text

39 ● 具体的な実装例 ○ インフラストラクチャリポジトリ ■ https://github.com/ice1203/ecs_sample_infra ○ アプリケーションリポジトリ ■ https://github.com/ice1203/ecs_sample_app 具体的な実装例

Slide 40

Slide 40 text

● Amazon ECS best practices - Amazon Elastic Container Service ● ECSのローリングアップデートとブルー/グリーンデプロイを比較してみた | DevelopersIO ● Amazon ECS タスク定義の"タスクサイズのCPU"と”コンテナのCPUユニット”の違いを調べてみた - のぴぴのメモ ● How Amazon ECS manages CPU and memory resources | Containers ● AWS ECS コンテナ毎のメトリクスを取得する #CloudWatch - Qiita ● https://github.com/phamthanhgiang/ECS-Fargate-hands-on/ ● Dockerfile を書くベストプラクティス — Docker-docs-ja 24.0 ドキュメント ● トレース|OpenTelemetry入門 40 bibliography

Slide 41

Slide 41 text

Thank you for your attention 41