はじめに
ALB + ECSの構成におけるStatic Fileの管理方法には、複数の選択肢があります。
例えば、以下のような方法です。
- appとともに直接ecs内部に格納
- S3で管理し、CloudFront + S3の構成とする
前者の場合、static fileを直接更新するには、appのdeployが必要になります。
後者の場合、CloudFrontを利用するため、client視点では通信経路が増え、社内申請や管理が煩雑になるところもあります。
以下のいくつかの要件に対応できる案を考えた。
- Static FileをS3で管理
- CloudFrontを利用せず、追加Domainなし
- S3へのアクセスはPrivateLinkを経由
構成図(簡略版)及び注意点
appとともに直接ecs内部に格納の場合(比較するため)
考案(VPC interface endpoint経由)
【注意点】Bucket名
Bucket名は、ALBのDNS名と同じにしないといけない
- ALB DNS: 検証のため、今回の検証では単にAWS public DNS名 「internal-alb-s3-vpce-123456789.ap-northeast-1.elb.amazonaws.com」を利用。実際に閉域網における利用は、Route 53のPrivate Host Zoneを利用する必要
- Bucket名:「internal-alb-s3-vpce-123456789.ap-northeast-1.elb.amazonaws.com」
構築リソース(ECS、ECRは別途構築、ここでは省略)
- VPC Interface Endpoint for S3
- Bucket
- Target Group
- ALB
VPC Interface Endpoint for S3
Target Groupを作成する際に利用するため、EndpointのIPアドレス 「10.1.1.196」をメモしておきます。
Bucket
- Bucket Policy
VPC Interface Endpointからのアクセスを許可する。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject4",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::internal-alb-s3-vpce-123456789.ap-northeast-1.elb.amazonaws.com/*",
"Condition": {
"StringEquals": {
"aws:SourceVpce": "vpce-...."
}
}
}
]
}
TargetGroup
Target Groupを作成し、IPモードでVPC Interface EndpointをTarget Groupに登録します。
ALB
以下の通り、Listener rulesを作成します。
- Path Patternが「/static/*」の場合、上記にて作成したVPC Interface EndpointのTarget Groupにforward
- それ以外の場合、別途作成済みのECSのTarget Groupにforward
DEMO
説明
このDEMOでは、S3に保存されたJavaScriptファイルを更新することで、クライアント側の画像のsrcが動的に変更され、表示する画像も変わることを確認します。
APP構成(Container化し、ECSで利用)
│ app.js
└─public
index.html
index.html
初期表示時、"dogImage"の画像(300.jpg)がALB経由で取得すると記述しました。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dog Image Button</title>
<script defer src="https://internal-alb-s3-vpce-123456789.ap-northeast-1.elb.amazonaws.com/static/js/script.js"></script>
<style>
body {
text-align: center;
font-family: Arial, sans-serif;
}
img {
max-width: 100%;
height: auto;
margin-top: 20px;
}
</style>
</head>
<body>
<h1>Click the Button to See a Dog</h1>
<button id="changeDog">Show Another Dog</button>
<br>
<img id="dogImage" src="https://internal-alb-s3-vpce-123456789.ap-northeast-1.elb.amazonaws.com/static/image/300.jpg" alt="Random Dog">
</body>
</html>
Bucket folder構成
static folderの配下にimage及びjsを配置します。
> aws s3 ls s3://internal-alb-s3-vpce-123456789.ap-northeast-1.elb.amazonaws.com/static --recursive --human-readable --summarize | cut -c 32-
static/image/300.jpg
static/image/400.jpg
static/image/500.jpg
static/js/script.js
script.js
Click eventが発生した際に、画像を「400.jpg」に変更します。
document.addEventListener("DOMContentLoaded", function () {
const button = document.getElementById("changeDog");
const image = document.getElementById("dogImage");
button.addEventListener("click", function () {
// 新しいランダムな犬の画像を取得
const newImageUrl = `https://internal-alb-s3-vpce-123456789.ap-northeast-1.elb.amazonaws.com/static/image/400.jpg`;
image.src = newImageUrl;
});
});
実際の表示
初期画面表示
画像300.jpgが表示されます。
Dog画像変更
Button Clickすると、画像が400.jpgに変わります。
S3側のscript.jsを置き換え
- const newImageUrl = `https://internal-alb-s3-vpce-123456789.ap-northeast-1.elb.amazonaws.com/js/400.jpg`;
+ const newImageUrl = `https://internal-alb-s3-vpce-123456789.ap-northeast-1.elb.amazonaws.com/js/500.jpg`;
初期画面表示
同様に画像300.jpgが表示されます。
Dog画像変更
Button Clickすると、画像が500.jpgに変わります。
Other
Dog画像の元URL:https://placedog.net/