LoginSignup
2
0

Fargateでpythonを実行するまでの記録

Posted at

はじめに

今回は既存のLambdaで実行していたpythonプログラムを、Fargateでも実行できるように試行錯誤した備忘録を記録する。前提として、ECRやECS、Task定義は設定済。ECRやECS、Task定義などの設定の記録については以下記事に記録してある。↓

また、今回最終的に構築したいのは以下のような構成だが、本記事ではとりあえずPublisher Fargateを手動で起動(Task Run)できたところまでを記録する。
image.png

ちなみに、FargateではなくLambdaを用いた元々の構成を構築するまでの記録は以下記事に残してある。
(以下記事からさらに遡って追っていく必要があるのは申し訳ない。興味ある人だけ。)↓

今回は以下の順序で実施記録を整理していく。

  1. 実行したいDockerイメージをECRにプッシュ
  2. Task実行とエラー
  3. エラーを解決して再度Task実行して動作確認

実行するpythonプログラムを含むDockerイメージをECRにプッシュ

python

本来はAPIリクエストから受け取るメッセージ内容をMessageにセットしたいが、とりあえず固定文字で進めていく。

topic_publisher.py
import base64
import boto3
from datetime import datetime
import json

client = boto3.client('sns', region_name='ap-northeast-1')

def main():
    
    print('fargate started')
    
    params = {
        'TopicArn': 'arn:aws:sns:ap-northeast-1:123456789012:myFirstTopic_std',
        'Subject' : 'Published From: deliverTopicToSNS_Test01',
        'Message' : 'fargate message'
    }
    
    try:
        response = client.publish(
            TopicArn = params['TopicArn'],
            Subject = params['Subject'],
            Message = params['Message']
        )
        
        print(json.dumps(response))
        return {
            'statusCode': 200,
            'body': json.dumps('A new message has been published')
        }
        

    except Exception as e:
        print(e)
        raise e
    
main()

ちなみにboto3.client()としているところで、region_nameを指定していないとFargateでの実行時にNoRegionErrorが発生した。Lambdaで記述していた時には不要なパラメータだったが、Fargateでは必要なのだろうか?

Dockerfile

pythonは元々Lambdaで動かしていた3.8を指定。
ENV PYTHONBUFFERED=1としている。
ENTORYPOINT ["python", "./topic_publisher.py"]としている。
このように記述することでpythonプログラムのprint()の内容がCloudWatch Logsで確認できるようになるらしい。(詳しい方その原理を教えてください。)

FROM python:3.8

WORKDIR /app

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY topic_publisher.py ./

ENV PYTHONUNBUFFERED=1
# CMD ["python", "./topic_publisher.py"]
ENTRYPOINT ["python", "./topic_publisher.py"]

ちなみにpythonのバージョンを指定していないと(恐らく)最新のバージョンが利用されるのだと思う。その場合に以下の記事にもあるCode ImportErrorが発生した。今回はバージョンを3.8に指定することで解決した。

requirement.txt

以下のように利用boto3を指定

requirement.txt
boto3==1.9.183

DockerイメージをECRへプッシュ

ECRコンソールから確認できるプッシュ手順に従ってコマンドを打っていく。まずはECRへの認証。
image.png

docker buildでイメージのビルド
image.png
image.png

イメージへタグ付けしてリポジトリへのプッシュ準備
image.png

docker pushでリポジトリへプッシュ
image.png

Taskを作成してRun

ECRにイメージがプッシュされて実行準備が整ったので、新規Taskをコンソールから作成して実行してみる。以下のTaskを実行(デプロイ)する。
image.png

image.png

image.png
このNetworkingの設定のところでインタネットに出るルーティングがされていないSubnetを選択していたり、Public IP付与をOFFにしているとCannotPullContainerErrorが発生する。

エラー

Exit code:1でエラーとなった。
image.png

ログを見てみるとUnable to locate credentialsと出ている。
image.png
こちらの参考記事にある通り、このエラーはECSのTaskロールがうまく設定されていないと発生するっぽい。

Task定義を確認してみると、確かにTaskロールの方は設定されていなかった。Task execution roleとは別に付与が必要らしい。
image.png

以下のようにTaskロールの方にも同じロールを付与し(本来は別々のロールが良いかと思うが、ここでは同じロールを使おうと思う)、
image.png

当該ロールに対して、AmazonSNSFullAccessも付与しておく。SNSトピックを配信しているのでおそらく必要なポリシーだろう。
image.png

再実行

同じようにTaskを作成して再度Run。
今度は無事にTopicがpublishされた!
image.png

後続のLambdaなども想定通り動き、DynamoDBに新規Itemが格納され、手元にメールが届いたことも確認できました。
image.png

おわりに

所感として、ECS(Fargate)はLambdaよりも実行キャパが大きかったり時間制限がなかったりと、イベントドリブンでかつ処理が重いような機能の実行基盤としては向いていると思います。今回はコンソールから手動でTaskをRunしましたが、これをAPI Gateway経由で実行するようなところをこの後検証していこうと思います。

その他参考サイト

2
0
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
2
0