📝

CloudFormation で Glue ジョブのスクリプトファイルを疑似的にバージョニングしつつ動的に更新する方法

2025/02/05に公開

結論

cloudformation package コマンドでローカル環境のスクリプトファイルを S3 にアップロードする方法で実現可能です。

背景

以下の CloudFormation テンプレートで Glue ジョブを作成していました。

template.yaml
AWSTemplateFormatVersion: "2010-09-09"
Resources:
  GlueJob:
    Type: "AWS::Glue::Job"
    Properties:
      Name: "MyGlueJob"
      Role: arn:aws:iam::012345678901:role/service-role/AWSGlueServiceRole
      Command:
        Name: "glueetl"
        ScriptLocation: "s3://my-bucket-name/test.py"
        PythonVersion: "3"

上記テンプレートでのジョブ作成後、ジョブのスクリプトファイルを更新する場合には ScriptLocation を更新することになります。
ここで問題となるのが、どのように動的に更新するかという点です。

例えば、S3 のバージョニング機能を使用して ScriptLocation にバージョン番号を指定する方法が考えられますが、ScriptLocation にはバージョン番号を指定することができません。
AWS::Glue::Job JobCommand - AWS CloudFormation

Specifies the Amazon Simple Storage Service (Amazon S3) path to a script that executes a job (required).

回避策

cloudformation package コマンドを使用する方法であれば以下の挙動となり、疑似的に ScriptLocation にバージョニングのような指定が可能となります。

  1. ローカル環境で CloudFormation テンプレートファイルとジョブのスクリプトファイルを作成
  2. ScriptLocation にはジョブのスクリプトファイルへの相対パスを記載
  3. cloudformation package コマンドを実行
  4. 生成された CloudFormation テンプレートファイルの ScriptLocation には S3 にアップロードされたジョブのスクリプトファイルへのパスが記載される
    1. ジョブのスクリプトファイル名はランダムな文字列で生成されるため、以前のスクリプトファイルは保持される
  5. 4 の CloudFormation テンプレートでスタックを更新することで Glue ジョブのスクリプトファイルも更新される
    1. CloudFormation テンプレート側を手動で変更する必要がない

やってみた

スクリプトファイルは以下の内容で S3 バケットにアップロードし、ScriptLocation でパスを指定しました。

test.py
import sys

冒頭のテンプレートで CloudFormation スタックをデプロイします。

$ aws cloudformation deploy
--template-file template.yaml \
--stack-name test
  1. ローカル環境で CloudFormation テンプレートファイルとジョブのスクリプトファイルを作成
  2. ScriptLocation にはジョブのスクリプトファイルへの相対パスを記載

スタック作成後、ローカルのスクリプトファイルを以下の内容に書き換えます。

test.py
import sys
import json

以下のテンプレートをスクリプトファイルと同じディレクトリに作成しました。
ScriptLocation には相対パスを記載しています。

template.yaml
AWSTemplateFormatVersion: "2010-09-09"
Resources:
  GlueJob:
    Type: "AWS::Glue::Job"
    Properties:
      Name: "MyGlueJob"
      Role: arn:aws:iam::012345678901:role/service-role/AWSGlueServiceRole
      Command:
        Name: "glueetl"
        ScriptLocation: "./test.py"
        PythonVersion: "3"
  1. cloudformation package コマンドを実行

以下のコマンドを実行して、packaged-template.yaml を生成します。

$ aws cloudformation package \
--template-file ./template.yaml \
--s3-bucket your-bucket-name \
--output-template-file packaged-template.yaml \
--output yaml
  1. 生成された CloudFormation テンプレートファイルの ScriptLocation には S3 にアップロードされたジョブのスクリプトファイルへのパスが記載される

生成された packaged-template.yaml では ScriptLocation へのパスが S3 オブジェクトへのパスに変換されています。

packaged-template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  GlueJob:
    Type: AWS::Glue::Job
    Properties:
      Name: MyGlueJob
      Role: arn:aws:iam::012345678901:role/service-role/AWSGlueServiceRole
      Command:
        Name: glueetl
        ScriptLocation: s3://my-bucket/b28cd1a250f3e82904e86ef2a00f4d6e
        PythonVersion: '3'

この段階で S3 には上記オブジェクト名でスクリプトファイルがアップロードされています。
そのため、ScriptLocation からの参照も可能な状態になっています。

  1. 4 の CloudFormation テンプレートでスタックを更新することで Glue ジョブのスクリプトファイルも更新される

以下のコマンドで既存のスタックを更新します。

$ aws cloudformation update-stack \
--stack-name your-stack-name \
--template-body file://packaged-template.yaml

{
    "StackId": "arn:aws:cloudformation:ap-northeast-1:012345678901:stack/test/53a6f450-dd74-11ef-a4d4-0ad56fd0825f"
}

スタックの更新ができました。
これで CloudFormation スタック更新時にテンプレートの ScriptLocation を手動で書き換えずにスクリプトファイルを自動更新することが可能となりました。

まとめ

今回は CloudFormation で Glue ジョブのスクリプトファイルを疑似的にバージョニングしつつ動的に更新する方法を紹介しました。
どなたかの参考になれば幸いです。

参考資料

Discussion