5
1

More than 1 year has passed since last update.

Step Functionsから ECS Task(Fargate) を動かすときのTips

Last updated at Posted at 2023-01-20

Step FunctionsでECSのタスク(Fargate)を動かす時に, 詰まったポイントを中心にtipsとしてまとめます. 僕自身あまり詳しくない+日本語苦手なので, 読みづらい部分があると思うんですけど, 我慢して読んでください.

はじめに

Lambdaの制限

Lamnda関数で時間のかかる処理を動かす時(APIを叩くとか?), 何かと問題があります. 例えば..

  • 実行時間制限を設定しないといけないけど, 見込みを立てるのが難しい
  • 15分を超える処理を実行できない
    とか?

解決策?

そこでひとつのLamnda関数で処理を行うのではなく, 複数のLambda関数に分散させて,

  • LambdaからLambdaを呼び出すとか
  • Step FunctionsにLambda関数を組み込むとか

色々やってみたんですけど, 結局は実行時間の解決になってないし, そもそも実行時間に不安があるなら ECSタスク(Fargate)で動かしたらいいのでは? という結論に至りました.

今回のテーマ

で, そもそもStep Functions上で動かしていたLambda関数をECSタスク(Fargate)に移行させたという背景もあるので,
「Step Functionsから ECS Task(Fargate) を動かすときのTips」というテーマに至ります.

技術的な背景

Step Functions

  • AWSが提供しているワークフローサービス
  • FargateやLambdaなどAWS上のサービスをタスクとして, フローの中に組み込むことができる

ECS(Elastic Container Service)とは

AWSが提供するコンテナオーケストレーションサービス, kubernetesみたいな? ただしAWSにはEKS(Elastic Kubernetes Service)があるので, kubernetesとは違うはず.
構成要素

  • クラスタ ... 実行の基盤 複数のサブネットにラップをかけるみたいなイメージ?
  • サービス ... タスクをよりデーモンっぽくすることができる? ただしタスクでもデーモンのような動作は可能 ポートの開放などはサービスで設定する..たしか
  • タスク ... タスク定義に基づいて起動するコンテナの集まり, docker-composeで起動する複数のコンテナ群みたいな?
  • タスク定義 ... タスクを定義するテンプレートみたいなもの, docker-compose.ymlみたいな?

ECS Task(Fargate)

  • ECS上で動作するコンテナ向けのサーバレスなサービス

LambdaとECS Task(Fargate)の比較

Fargate Lambda
実行時間 制約なし 最大15分以内の実行時間, また自分で実行時間制限を指定する必要がある
コスト 実行時間に対してコストが発生. Lambdaに比べるとコストが高い 必要な時のみ起動するため, コストが低い. 毎月のリクエストが100万件までは無制限で無料枠になるので, 少ないリクエスト数であれば実質無料
学習コスト ECS(コンテナオーケストレーション)についての理解が必須. またDockerの知識も必要 実行OSや制限を抑えれば, その他の学習することはあまりない. コンテナイメージを実行することもあるが, Lambda用のコンテナイメージのDockerfileが用意されているため, 学習コストはほぼゼロ

参考: スタートアップCTOが解説するECS Fargateのユースケース&Lambdaの使い分け!😎AWSのサーバーレスコンピューティングを使いこなしましょう🐕 -> https://www.ragate.co.jp/blog/articles/11589

  • Lambda: 短い処理に向いている. 実行時間が長い処理や重い処理には向いていない
  • Fargate: コンテナに対しての自由度が高いので, LambdaでできないことをFargateが包括しているというイメージ

個人的な使い方としては, 基本はLambdaを使って, Lambdaで無理だったらFarateを使うくらいの意識でいいのかな..という感じです. Lambdaでは制限が多いけど, Lambda専用のDockerfileが用意されており実装が楽, 逆にFargateは, 自由度が高いものの, コンテナイメージを自前で用意しないといけない..みたいな感じだと思います.

今回作ったもの

GitHub APIを叩いて, 指定したリポジトリ内のIssueの割合を可視化(matplotlib)+S3上に保存するフローを作成しています. 作った理由は特にありません.

全体の概要図

Step Function自体は, タスクとしてFargateを呼び出しているだけでシンプルな構成になっています.
image.png
基本的にECS側では, タスク定義の作成やロールの割り当て 以外はやることがない印象です.
タスク定義についても, docker-compose.ymlを書いてるみたいなイメージで, docker-compose.ymlを触ったことがある人ならすんなり設定を進められると思います(たぶん).

生成した円グラフ

Issueに割り当てられたラベルの割合を元に作成しています.
Graph.png

今回必要なもの

  • ECS
    • ECSクラスター
    • ECSタスク定義
    • ECSタスク実行ロール
  • Step Functions
    • VPCサブネット
    • セキュリティグループ
  • ECR
    • 自作のコンテナイメージ
  • APIキー
    • GitHub APIキー
  • etc...

つまづいたポイント

タスクとサービスの違い,というよりは使い方

結論 -> タスクは単体で動作させることができる.

とりあえず大事なのはサービスはタスクの上位概念ではないということかなと思います. 個人的にはここに詰まってしましました. どちらもタスク定義書を元に, コンテナを動かしてるだけです. なのでタスク単体でも動かすことができます.

参考: AWS ECSを構成する3つの概念(Cluster, Service, Task)https://scrapbox.io/keroxp/AWS_ECS%E3%82%92%E6%A7%8B%E6%88%90%E3%81%99%E3%82%8B3%E3%81%A4%E3%81%AE%E6%A6%82%E5%BF%B5%EF%BC%88Cluster,_Service,_Task%EF%BC%89

Fargate(ECSタスク)でのコマンドの上書き

まずは, Dockerにおけるコマンドの上書きについて,
Dockerにおけるコマンド+コマンドの必要性

$ docker run -it --rm --name aoimaru ubuntu:latest ls #最後の"ls"がコマンド

このコマンドを実行することで, ubuntu環境下でのlsコマンドを再現することができます <- ここポイント
要は, サーバを再現しているのではなく, 特定環境下でのコマンド(プロセス)を再現しているだけ. だからDockerでは1コンテナ1プロセスが推奨されています. ここが理解できれば, 上のコマンドで最後に"ls"を指定する必要がすんなり理解できるかなと思います.

コマンドは, Dockerfileでも指定するんですけど, コマンドラインではコマンドの上書きができます.
例えば, Dockerfileの末尾がこんなDockerfileがあるとします.

...
ENTRYPOINT ["python", "app.py"]
CMD ["aoimaru", "atcoder"]

この時デフォルトでは, $ python app.py aoimaru atcoder というランタイムが実行されます.
で, 例えば以下のようなコマンド

$ docker run -it --rm original original:latest EC-CUBE ec-cube 

を実行すると, $ python app.py EC-CUBE ec-cube というランタイムが実行されます.

同じように, コマンドラインではなく, Fargateでコマンドを上書きした上で, 実行する時, ここに落とし穴があります
結論 -> 上書きを行うとき, スペースを空けない方がいい

[EC-CUBE,ec-cube]  # OK
[EC-CUBE, ec-cube] # NG
         ↑ ここ

上記のようにスペースがある場合, コマンドライン的には, このような認識になってしまいます.
落とし穴が分かりやすいように, 引数はダブルクォーテーションで囲みます

$ python app.py "EC-CUBE" " ec-cube"
                           ↑ ここに余計なスペースが入る

こうなると, 引数として正しく認識してくれない.
解決策 -> ランタイム側で無駄なスペースを削除する方法もあるが, 値を渡す段階でスペースを入れない方が無難です.

その他権限周りについて

基本的には, エラー(権限不足)が吐かれたタイミングでの対応でいいと思います.
ただし, Step Functionsについては, フローの中で他のAWSサービス(Farateなど)を実行するため"iam:PassRole"などが必要です

実装

実際のプログラム(Python)は省略します.

Fargateで動かすコンテナイメージのDockerfile

FROM python:3.9.0

RUN set -xe && \
    pip install matplotlib \
                boto3 \
                PyGithub \
                # matplotlibで日本語を使うためのライブラリ, 
                japanize-matplotlib && \
    echo "backend: Agg" >> /etc/matplotlibrc && \
    mkdir /opt/app

WORKDIR /opt/app
COPY ./src/app.py .

ENTRYPOINT ["python", "app.py"]
CMD [引数の指定]

Step Functions

{
    "StartAt": "GithubIssue",
    "Status" : {
        "GithubIssue": {
            "Type": "Task",
            "Resource": "arn:aws:states::ecs:runTask",
            "Parameters": {
                "LaunchType": "FARGATE",
                "Cluster": "$クラスターのARN",
                "TaskDefinition": "$タスク定義のARN",
                "Overrides": {
                    "ContainerOverrides": [
                        {
                            "Name": "$コンテナ名",
                            "Commands.$": "$.{Step Functionsでの入力Json}"
                        }
                    ]
                },
                "NetworkConfiguration": {
                    "AwsvpcConfiguration": {
                        "Subnets": [
                            "$サブネットのID"
                        ],
                        "SrcurityGroups": [
                            "$セキュリティグループのID"
                        ],
                        "AssignPublicIp": "ENABLED"
                    }
                }
            },
            "End": true,
            "Comment": "任意のコメント"
        }
    }
}

おわりに

タスクとサービスの違いがややこしい印象です. コマンドの上書きのスペースについても発見するのにそこそこ時間を割いてしまいました.
この記事が, このようなちょっとした詰まりポイントの解決や, 初めてFargateを触ってみる際の参考になれば幸いです.

参考文献

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1