Contents

AWS ECS FargateでPythonバッチ駆動

やりたいこと

Dockerでbuild, 実行できるようにしたpythonバッチ処理を、Fargateで定時起動したい

構成

TBD

ECR - docker image登録 ECR - ECS上でFargateタスク実行 MySQL on

アプリケーション

概要

  • pythonモジュール。MySQLのテーブルを紹介して整形し、CSVに出力、S3のbucketにアップロードする

ディレクトリ構成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Project Root
  ├── .env.local      # ローカル環境用の環境変数
  ├── .env.staging    # ステージング環境用の環境変数
  ├── .env.prod       # 本番環境用の環境変数
  ├── .gitignore
  ├── Dockerfile
  ├── Makefile
  ├── README.md
  ├── docker-compose.yml
  ├── docs            # sphinx-apidocによるドキュメント生成先 
  ├── log             # ログ出力先
  ├── my_batch
  │   ├── __init__.py # モジュールとしてmy_batchを呼び出すために必要
  │   ├── __main__.py # __main__処理をwrapし、アプリケーション(batch.py)の関数を呼び出す
  │   ├── config      # アプリケーションの設定関連を入れる(my_batchの外でもいい)
  │   │   ├── app_config.json         # 列ヘッダの生成
  │   │   └── logging_config.yaml     # loggerのdictConfigが読み込むログ設定
  │   ├── batch.py    # アプリケーションのmain
  │   ├── aaa.py
  │   └── ...
  ├── requirements.txt
  ├── result          # CSVファイルのローカル出力先
  ├── setup.py
  └── tests

アプリケーション関連の主な設定

  • requirements.txt

    1
    2
    3
    4
    5
    6
    7
    
    sphinx
    sphinx-rtd-theme
    mysql-connector-python
    pyyaml
    pytest
    pandas
    boto3
    
  • setup.py

    • setup.py経由でrequirements.txtを呼び出してライブラリをインストールし、パッケージとしてmy_batch以下のモジュール登録する(pakcagesとpy_module)。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    from glob import glob
    from os.path import basename
    from os.path import splitext
    
    from setuptools import setup
    from setuptools import find_packages
    
    def _requires_from_file(filename):
        return open(filename).read().splitlines()
    
    setup(
        name="my-batch",
        version="0.1.0",
        description="Executes the data processing pipeline from database to CSV",
        author="tato",
        url="private",
        packages=find_packages("my_batch"),
        package_dir={"": "my_batch"},
        py_modules=[splitext(basename(path))[0] for path in glob('my_batch/*.py')],
        include_package_data=True,
        zip_safe=False,
        install_requires=_requires_from_file('requirements.txt'),
        setup_requires=["pytest-runner"],
        tests_require=["pytest", "pytest-cov"]
    )
    

    アプリケーションでは以下のように指定できる。

    1
    
    from my_batch.aaa import bbb
    
  • Dockerfile

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    FROM python:3 
    
    WORKDIR /app 
    
    COPY ./my_batch ./my_batch
    COPY requirements.txt requirements.txt
    COPY setup.py setup.py
    
    RUN mkdir -p log result
    
    RUN python3 -m pip install --upgrade pip 
    RUN python3 -m pip install --no-cache-dir -e . 
    
    ENTRYPOINT ["python3", "-m", "my_batch"] 
    
  • docker-compose.yml

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    version: '3.8'
    
    services:
    my_batch:
        env_file:
        - .env.local
        build:
        context: .
        dockerfile: Dockerfile
        image: my_batch
        restart: on-failure
        tty: true
    

.env.local, staging, prod など

DBやAWS関連のクレデンシャル情報はソースコードに埋め込まず、環境変数から取得して使う。

.env_template

1
2
3
4
5
6
7
MY_DB_HOST=<dbhost>
MY_DB_USER=<dbuser>
MY_DB_PASSWORD=<dbpass>
MY_DB_NAME=<dbname>
AWS_ACCESS_KEY_ID=<aws_access_key_id>
AWS_SECRET_ACCESS_KEY=<aws_secret_access_key>
AWS_DEFAULT_REGION=<aws_default_region>

アプリケーション単体での実行方法

今回のバッチは pythonのコマンドライン引数にを与えることで、参照先の業務テーブルを切り替える。

pythonのvenv上で実行する場合 (コンテナ無し)

1
2
3
4
5
export $(cat .env.local | grep -v "#" | xargs)
python -m venv .venv
source .venv/bin/activate
(.venv) pip install -r requirements.txt
(.venv) python -m my_batch <param1>

Dockerで実行する場合

Dockerfile上でENTRYPOINTとしてパラメータ無しのpythonモジュール実行コマンドを定義しているため、実行時は呼び出したサービス名の後にを追加してすれば良い。

  • build

    1
    
    docker build --tag my_batch .   
    
  • 実行→コンテナ削除

    1
    
    docker run --env-file .env.local --rm -t my_batch <param1>
    

イメージ削除する場合は、docker rmi <image id> で削除。

docker-composeで実行する場合

docker-composeからDockerfileを呼び出しているため、実行方法はDockerの場合と同様。
一方、環境設定については、docker-compose.ymlの中で、env_fileで.env.localを指定していると、コマンドラインで指定しても有効にならない(docker-compose --env-file .env.local.では効かない)ため、docker-compose.ymlを更新する必要がある。

  • build

    1
    
    docker-compose build 
    
  • 実行→コンテナ削除

    1
    
    docker-compose run --rm -t my_syokuiki_batch
    

イメージ削除する場合は、docker rmi <image id> で削除。

ECRにDocker imageを登録

ECRにレポジトリ作成

ECR > 使用方法

  • 可視性設定: “private”
  • リポジトリ名: my_batch_ecr

→ “リポジトリ作成”

レポジトリにdocker imageをpush

作成されたリポジトリを選択し、“プッシュコマンドの表示” 。ガイドに従って、以下を実施。

  • 認証トークンを取得し、レジストリに対して Docker クライアントを認証します。 AWS CLI を使用する
  • Dockerイメージを構築(イメージがなければ)
  • イメージにタグ付け - docker pushコマンドでAWSリポジトリにプッシュ

認証トークンの取得時に、AWSアクセスキーの承認が必要になる場合、以下を実施。

AWSアクセスキーの取得と設定

IAM > users > security credential > Access keys > Create access key

(“Download .csv file.csv” でCSVファイルをダウンロードできる)

aws cliで以下のコマンドで認証する。

1
aws configure

プロンプトに従い、AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_DEFAULT_REGIONを設定する。

ECS

タスク定義

ECS > “新しいタスクの定義”

  • タスク定義ファミリー: my_batch_task
  • 起動タイプ: AWS Fargate
  • オペレーティングシステム/アーキテクチャ: Linux/ARM
  • CPU: .25vCPU, メモリ: .5GB
  • コンテナ
    • 名前: my_batch_container
    • イメージのURI: ECRに登録したイメージのリストから取得
    • ポートマッピング
      • コンテナポート: 3306
      • プロトコル: TCP
      • ポート名: 指定なし, アプリケーションプロトコル: None
    • 環境変数
      • ~~“ファイルから追加"でロケーションにS3 bucketに追加した環境設定ファイル (.env.staging 等)のARNを追加 ~~ ← “正しいARNではない"エラーが出る。IAMの問題か。
      • ↑ができないため、個別に環境変数を設定する。
    • ログ収集の使用をONにする
  • ↑を設定し、“作成”

クラスター作成

ECS > “クラスター” > クラスター作成

  • クラスター名: my_batch_cluster
  • インフラストラクチャ: AWS Fargate(サーバーレス)
  • ↑を設定し、“作成”

一度、500番のランタイムエラーになるが、Cloud watchで再試行し、何度か画面更新すると"UPDATE CMPLETE"になる

サービス作成

ECS > “クラスター” > 対象となるクラスター(my_batch_cluster)を選択 > サービス作成

  • デプロイ設定
    • キャパシティプロバイダー: FARGATE
    • ファミリー: 作成したタスク(my_batch_task)を選択
    • サービス名: my_syokuiki_batch_service
    • サービスタイプ: レプリカ
    • 必要なタスク: 1
  • ネットワーキング
    • VPC、サブネット、セキュリティグループ
      • 環境ごとの規定のものがあれば選択
  • サービスの自動スケーリング
    • 自動スケーリングを使用のチェックを外す

サービス作成によってクラスターに登録したタスクを実行するサービスが起動される
結果はCloud Watch経由でログを確認できる

Reference