こんにちは、香田です。
今回はECS FargateのタスクからBigQueryへクエリを実行する方法について紹介していきます。
最終的にタスクで定義されたコンテナからbqコマンドでクエリ実行できるように設定していく流れとなります。
サービスアカウントキーの作成
はじめにECS FargateのタスクからBigQueryへクエリ実行できるようにする為、GCPにてサービスアカウントキーを作成します。
GCPの[IAMと管理]、[サービスアカウント]より[サービス アカウントの作成]を選択します。
[サービスアカウント名]を入力し作成をクリックします。
ここではロールに[BigQuery管理者]と[ストレージ管理者]を設定しています。
問題なければ[続行]、[完了]とクリックします。
作成したサービスアカウントを選択し、[キー]、[鍵を追加]、[新しい鍵を作成]より[JSON]を選択し作成します。
ダウンロードされたJSONファイルは以降の手順で使用します。
BigQuery テーブルの作成
次に検証用のBigQueryテーブルを作成します。
BigQueryの一般公開データセットより表のサイズが小さいbigquery-public-data:samples.shakespeare
テーブルを自身のプロジェクトにコピーしテーブルを作成します。
検証用のデータセットを作成します。
bq mk samples
自身のプロジェクトにテーブルをコピーします。
bq cp \
bigquery-public-data:samples.shakespeare \
samples.shakespeare
ECS 環境の準備
ECS クラスターの作成とECS タスク定義で利用するCloudWatch Logs、パラメータストアを作成します。
ECS クラスターを作成します。
aws ecs create-cluster --cluster-name ecs-cluster
ECS タスク用のCloudWatch Logs ロググループを作成します。
aws logs create-log-group --log-group-name ecs-fargate-bigquery
ECS タスクよりBigQueryを参照できるように、認証情報の保存先としてパラメータストアを利用していきます。
ダウンロードしたサービスアカウントキーをbase64で文字列にしSecureString
形式でパラメータストアへ保存します。
aws ssm put-parameter \
--name "/gcp/ecs-fargate-bigquery" \
--type "SecureString" \
--value $(base64 <サービスアカウトキー ファイルパス>)
IAM ロールの作成
次にタスク実行 IAM ロールを作成します。
ECSタスクにてコンテナイメージ取得、CloudWatch Logsへログ保存等を許可する為に利用されるIAM Roleになります。
AWS IAM コンソールより[ロールの作成]を選択し、[信頼されたエンティティの種類を選択] セクションで、[Elastic Container Service] を選択します。
[ユースケースの選択]で、[Elastic Container Service Task]を選択し、[次のステップ: アクセス権限]を選択します。
[Attach アクセス権限ポリシー]に[AmazonECSTaskExecutionRolePolicy]を選択し、[次にステップ:タグ]、[次のステップ:確認]と選択します。
[ロール名]にecsTaskExecutionRole
と入力し[ロールの作成]をクリックします。
次にパラメータストアを参照できるようにインラインポリシーを追加します。
作成したロールを選択し[インラインポリシーの追加]より、パラメータストアを参照できるよう下記のようなポリシーを作成し付与します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:GetParameters"
],
"Resource": [
"arn:aws:ssm:<リージョン>:<アカウントID>:parameter/gcp/ecs-fargate-bigquery"
]
}
]
}
Dockerfileの作成
BigQueryへクエリ実行する為にサンプルスクリプトを用意します。
bq_query.sh
という名前でファイルを作成します。
スクリプトで参照しているGCP_SERVICE_ACCOUNT
、GCP_PROJECT_ID
はECS タスク定義によって環境変数として取得可能となります。
#!/usr/bin/env bash
echo ${GCP_SERVICE_ACCOUNT} | base64 -d >/tmp/service-accounts.json
gcloud auth activate-service-account --key-file=/tmp/service-accounts.json
gcloud --quiet config set project ${GCP_PROJECT_ID}
bq query \
--nouse_legacy_sql \
'SELECT * FROM `samples.shakespeare` LIMIT 10'
作成したスクリプトを実行できるようにcloud-sdk
のイメージを元にDockerfile
を作成します。
FROM google/cloud-sdk:latest
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY ./bq_query.sh ./
ECRへイメージ登録
次にイメージをビルドしECRへ登録していきます。
ECRへログインします。
export ECR_URI_BASE=$(aws sts get-caller-identity --query Account --output text).dkr.ecr.ap-northeast-1.amazonaws.com
aws ecr get-login-password | docker login --username AWS \
--password-stdin $ECR_URI_BASE
ECR リポジトリを作成します。
aws ecr create-repository --repository-name ecs-fargate-bigquery \
--image-tag-mutability IMMUTABLE
イメージをビルドし、ECR リポジトリへ登録します。
docker build -t ecs-fargate-bigquery:latest .
docker tag ecs-fargate-bigquery:latest $ECR_URI_BASE/ecs-fargate-bigquery:latest
docker push $ECR_URI_BASE/ecs-fargate-bigquery:latest
ECS タスク定義の登録
次にECS タスク定義を作成します。
下記をコピーしecs-fargate-bigquery.json
という名前で保存します。
タスク定義で指定されているimage
のAWS アカウントID
とenvironment
のGCP プロジェクトID
の箇所は適宜修正してください。
{
"family": "ecs-fargate-bigquery",
"executionRoleArn": "ecsTaskExecutionRole",
"networkMode": "awsvpc",
"containerDefinitions": [
{
"name": "ecs-fargate-bigquery",
"environment": [
{
"name": "GCP_PROJECT_ID",
"value": "<GCP プロジェクトID>"
}
],
"secrets": [
{
"name": "GCP_SERVICE_ACCOUNT",
"valueFrom": "/gcp/ecs-fargate-bigquery"
}
],
"image": "<AWS アカウトID>.dkr.ecr.ap-northeast-1.amazonaws.com/ecs-fargate-bigquery:latest",
"linuxParameters": {
"initProcessEnabled": true
},
"command": [
"bash",
"bq_query.sh"
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "ecs-fargate-bigquery",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "bq_query"
}
},
"essential": true
}
],
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "256",
"memory": "512"
}
ECS タスク定義を登録します。
aws ecs register-task-definition \
--cli-input-json file://$PWD/ecs-fargate-bigquery.json
ECS タスク実行
登録したタスク定義を利用しタスクを実行していきます。
起動タイプとしてFARGATE
を指定し、ECS タスクを実行します。
awsvpcConfiguration
のsubnets
とsecurigyGroups
は適宜設定してください。
デフォルトで作成されているVPCのサブネットとセキュリティグループを利用しても問題なく実行できるはずです。
aws ecs run-task --cluster ecs-cluster \
--task-definition ecs-fargate-bigquery:1 --count 1 \
--launch-type FARGATE \
--network-configuration \
"awsvpcConfiguration={subnets=[subnet-xxx,subnet-xxx,subnet-xxx],securityGroups=[sg-xxx],assignPublicIp=ENABLED}"
タスク実行後、CloudWatch Logsのログを確認しBigQueryのクエリ実行結果が確認できれば成功です。
aws logs tail --follow ecs-fargate-bigquery
さいごに
ECS FargateのタスクからBigQueryへクエリを実行する方法いかがでしたしょうか?
AWS環境からGCPのBigQueryへデータをロードしたり、クエリ実行するといったケースはよくあると思います。
ECS FargateのコンテナにてBigQueryを利用する際、本記事が参考になれば幸いでございます。
最後までご覧いただきありがとうございます。