koudenpaのブログ

趣味のブログです。株式会社はてなでWebアプリケーションエンジニアをやっています。職業柄IT関連の記事が多いと思います。

Amazon EFSへのリソース配置をAWS CLI + 踏み台サーバでやってみる

先にAWS Lambdaの関数実行時にEFSをマウントしてみた。その時にはファイルの出力先として使ってみたのだけれど、入力ファイルの配置先としても使えると思う。Lambdaは何かと容量制限があるが、EFSなら容量制限とは無縁だ。Lambda + EFSの記事でも機械学習結果のモデルの配置が紹介されている。

が、このファイル配置は曲者で、結構面倒くさい様子だった。面倒くささへの愚痴と、手軽にはこんな感じだろうと試したAWS CLIと踏み台サーバでの配置を試した記録を書いておく。

EFSへの配置の面倒くささ

EFSはNFSでマウントして使うことが前提となっていて、APIでそのファイルシステム内のファイルを操作できたりはしない様子だった。

今回はCDKを使っていたのだけれど、何かしらのリソースをS3に配置したい場合はこの程度の記述でCDKデプロイ時に行える。

new BucketDeployment(this, "AssetBucketDeployment", new BucketDeploymentProps()
{
    Sources = new ISource[] { Source.Asset("assets") },
    DestinationBucket = assetBucket,
});

EFSではこうしたことは(多分)できない。何か別の形でファイルを配置する必要がある。

転送にはDataSyncの使用が推奨されているが、このDataSyncは使うまでの段取りがなかなか面倒くさく、ちょっと使ってみるかという気にはなれなかった。特にエージェントを用意しなくてはならないのが嫌だった。そんなものはマネージドしてくれ。

AWS CLI + 踏み台サーバでの配置

このように配置してみた。

  1. CI環境からAWS CLIでSSMで踏み台サーバへ aws s3 sync コマンドを発行する

f:id:koudenpa:20200828214327p:plain
大体こんな構成

前提として以下のような思考があった。

  • CD環境にはAWSの認証情報があるだろう
  • CD環境にAWS CLIを構成するのは楽だろう
    • 今回はGitHub Actionsなので既定のイメージにインストールされている
  • EFSをマウントできる踏み台サーバがある
    • 人間が中身を確認するために、など
    • なくてもこれを作ること自体は平易
  • 踏み台サーバへはSSMで接続できる
  • 配置したいファイルはS3にある
    • ないし配置できる
    • 前述の通りS3への任意のファイル配置は楽に行える

のならば、AWS CLIで踏み台サーバを使ってリソースを配置できるのではないか?

で実際できた。

CDKで配置したいリソースを置いたS3バケットEFSをマウントした踏み台サーバを構築GitHub ActionsでのCDKデプロイ後に踏み台サーバ上でS3からEFSへのマウント先への同期する処理を発行した。

- name: Sync assets
  run: |
    BastionInstanceId=$(aws cloudformation describe-stacks --stack-name HtmlRendererAppStack --query "Stacks[0].Outputs[?ExportName=='BastionInstanceId'].OutputValue" --output text)
    AssetBucketName=$(aws cloudformation describe-stacks --stack-name HtmlRendererAppStack --query "Stacks[0].Outputs[?ExportName=='AssetBucketName'].OutputValue" --output text)
    aws ssm send-command --document-name "AWS-RunShellScript" --document-version "1" --targets "[{\"Key\":\"InstanceIds\",\"Values\":[\"$BastionInstanceId\"]}]" --parameters "{\"workingDirectory\":[\"\"],\"executionTimeout\":[\"3600\"],\"commands\":[\"aws s3 sync s3://$AssetBucketName /mnt/efs/fs1/assets\"]}" --timeout-seconds 600 --max-concurrency "50" --max-errors "0"

aws ssm send-command のオプションはかなり冗長だろうと思う。AWSコンソールで得たコマンドまま)

まず、CloudFormationのアウトプットから踏み台のインスタンスIDと転送元となるS3バケット名を得ている。

その後、SSMを使って踏み台インスタンス上でS3からEFSのマウント先へのファイル同期コマンドを実行させている。

SSMはAWSのIAM認証でEC2インスタンスに接続したりできるもので、今回は任意のシェルスクリプトを実行できるコマンドを使って踏み台上で aws s3 sync を実行している。

前提条件が揃っていればそれなりに平易にEFSへ配置できるのではないだろうか。

感想

SSMは便利。