CloudFormation で Glue ジョブのスクリプトファイルを疑似的にバージョニングしつつ動的に更新する方法
結論
cloudformation package
コマンドでローカル環境のスクリプトファイルを S3 にアップロードする方法で実現可能です。
背景
以下の CloudFormation テンプレートで Glue ジョブを作成していました。
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
にバージョニングのような指定が可能となります。
- ローカル環境で CloudFormation テンプレートファイルとジョブのスクリプトファイルを作成
-
ScriptLocation
にはジョブのスクリプトファイルへの相対パスを記載 -
cloudformation package
コマンドを実行 - 生成された CloudFormation テンプレートファイルの ScriptLocation には S3 にアップロードされたジョブのスクリプトファイルへのパスが記載される
- ジョブのスクリプトファイル名はランダムな文字列で生成されるため、以前のスクリプトファイルは保持される
- 4 の CloudFormation テンプレートでスタックを更新することで Glue ジョブのスクリプトファイルも更新される
- CloudFormation テンプレート側を手動で変更する必要がない
やってみた
スクリプトファイルは以下の内容で S3 バケットにアップロードし、ScriptLocation
でパスを指定しました。
import sys
冒頭のテンプレートで CloudFormation スタックをデプロイします。
$ aws cloudformation deploy
--template-file template.yaml \
--stack-name test
- ローカル環境で CloudFormation テンプレートファイルとジョブのスクリプトファイルを作成
ScriptLocation
にはジョブのスクリプトファイルへの相対パスを記載
スタック作成後、ローカルのスクリプトファイルを以下の内容に書き換えます。
import sys
import json
以下のテンプレートをスクリプトファイルと同じディレクトリに作成しました。
ScriptLocation
には相対パスを記載しています。
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"
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
- 生成された CloudFormation テンプレートファイルの ScriptLocation には S3 にアップロードされたジョブのスクリプトファイルへのパスが記載される
生成された packaged-template.yaml では ScriptLocation
へのパスが S3 オブジェクトへのパスに変換されています。
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
からの参照も可能な状態になっています。
- 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