もりはやメモφ(・ω・ )

インフラなエンジニアからSREへ

S3のWebページリダイレクト機能を試す

S3のWebページリダイレクト機能をお試しして、これは便利だ、となった作業メモです。

経緯

仕事でやってるいくつかのシステムで、Webコンテンツの画像資産がサーバ上に残っている問題があり、それをS3に持っていきたいねという流れがあって、本番と開発の差分をどうやって吸収&区別するかを悩んでいたりします。具体的には

  • 本番環境の画像が更新されたら開発環境にも展開したい
  • ただし開発環境で作業している画像はそのままにしたい
  • 開発が終わったファイルをそのまま開発環境から本番環境へ展開したい

と言った要望があります。 この要件を満たすためにいくつかの検討をしていて、その一つが「開発したいファイルだけ開発環境のS3におけると嬉しいのでは?」というものでした。

それを満たしてくれそうな機能が S3のWebページリダイレクト という機能です。

作業メモ

S3バケットの作成

まずは2つのS3バケットを作成しました。今回はこれだけなので普通にWebコンソールからやります。ポイントはWebホスティングをするためにパブリック設定をする必要がある点ですが、ドキュメントの通りにやるだけなので迷うことはありませんでした。*1

docs.aws - 静的ウェブサイトホスティング用に S3 バケットを設定する方法

S3バケットポリシーは以下の様になりました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::morihaya-test-public01/*"
            ]
        }
    ]
}

テストファイルの配置

続いてテスト用のファイルを配置します。

画像2つとindex.htmlだけのシンプルな構成です。 2つのバケットの一方には猫の画像、もう一方には犬の画像が同名で配置してあります。

.
├── images
│   ├── cat01.jpg
│   └── cat02.jpg
└── index.html

index.htmlは以下です。シンプルです。

<html>
<head>
<meta charset="utf-8">
<title>タイトル</title>
</head>
<body>
cat01
<img src="images/cat01.jpg" alt="cat01" style="width:200px;">
<BR>
cat02
<img src="images/cat02.jpg" alt="cat02" style="width:200px;">

</body>
</html>

画像はスライド資料作りなどでも愛用している unsplash さんから拝借しました。いつもありがとうございます。

この状態でWebアクセスをします。ここで一点注意ですが、Webホスティング用のURLを利用しましょう。オブジェクト参照用のURLではないことに注意です。

# OKこっちを使う
http://morihaya-test-public01.s3-website-ap-northeast-1.amazonaws.com/

# NGこっちはオブジェクト参照のURLで、リダイレクト効かない
http://morihaya-test-public01.s3-ap-northeast-1.amazonaws.com

以下のクールなWebページが参照できました。これは開発状態を想定しています。なぜなら本番環境には犬の画像をアップしてしまったので、急いで修正しようとしている設定です。

f:id:morihaya:20200111195102p:plain
初期状態

この状態でcat02の画像名を変更します。

f:id:morihaya:20200111195346p:plain
cat02.jpgをリネーム

当然ですがcat02の画像は404が返ってきました。 f:id:morihaya:20200111195552p:plain

この状態でS3のStatic Web Hostingのメニューから、Webページリダイレクトに以下の設定を入れます。

<RoutingRules>
  <RoutingRule>
    <Condition>
      <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
    </Condition>
    <Redirect>
      <HostName>morihaya-test-public02.s3-website-ap-northeast-1.amazonaws.com</HostName>
    </Redirect>
  </RoutingRule>
</RoutingRules>

その状態でキャッシュを消しつつリロードすると、以下の応答がきます。1つ目のバケットにimages/cat02.jpg が存在しないため、2つ目のバケットにリダイレクトされています。

開発用のバケットにある猫の画像から、本番環境の間違ってアップした犬の画像が見えるようになった、という想定です。

f:id:morihaya:20200111200202p:plain
リダイレクトルールの追加後

curlコマンドで確認しても、cat01.jpgは200が、cat02.jpgについては301がリターンされました。

# cat01.pngは存在するので 200 がリターン
curl -v http://morihaya-test-public01.s3-website-ap-northeast-1.amazonaws.com/images/cat01.jpg
*   Trying 52.219.16.56...
* TCP_NODELAY set
* Connected to morihaya-test-public01.s3-website-ap-northeast-1.amazonaws.com (52.219.16.56) port 80 (#0)
> GET /images/cat01.jpg HTTP/1.1
> Host: morihaya-test-public01.s3-website-ap-northeast-1.amazonaws.com
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< x-amz-id-2: HV9eQ9gxQHkhA7Eg9QCaSSOIKkJccl/2SONZCWPTLXzgZjKPpJRSa9AXNUQV95P9msOJ4VRO0gY=
< x-amz-request-id: 13E5DCF35B6D47A0
< Date: Sat, 11 Jan 2020 11:05:43 GMT
< Last-Modified: Sat, 11 Jan 2020 09:05:20 GMT
< ETag: "cb0269c57b764ca3110308fd003fccc5"
< Content-Type: image/jpeg
< Content-Length: 1903102
< Server: AmazonS3
<

# cat02.pngは存在しないため、301でリダイレクトが発生している
curl -v http://morihaya-test-public01.s3-website-ap-northeast-1.amazonaws.com/images/cat02.jpg
*   Trying 52.219.4.90...
* TCP_NODELAY set
* Connected to morihaya-test-public01.s3-website-ap-northeast-1.amazonaws.com (52.219.4.90) port 80 (#0)
> GET /images/cat02.jpg HTTP/1.1
> Host: morihaya-test-public01.s3-website-ap-northeast-1.amazonaws.com
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< x-amz-id-2: KVOrB7N6JPhEe4UAmuXQy7ATVlZvwhYae5Mj0p10mCrIxVIsNZCY4B3gWxbqRIwTod52i1P6y2M=
< x-amz-request-id: 6A1BB10B8FFEDA6A
< Date: Sat, 11 Jan 2020 11:04:28 GMT
< Location: http://morihaya-test-public02.s3-website-ap-northeast-1.amazonaws.com/images/cat02.jpg
< Content-Length: 0
< Server: AmazonS3
<

まとめ

この検証結果には大満足しました。機能としては十分と言えるでしょう。

改めて要望を振り返ると

  • 本番環境の画像が更新されたら開発環境にも展開したい
    • OK。開発用のバケットになければ本番用のバケットにアクセスさせられる
  • ただし開発環境で作業している画像はそのままにしたい
    • OK。開発用のバケットにあれば、それがそのまま表示される
  • 開発が終わったファイルをそのまま開発環境から本番環境へ展開したい
    • OK。開発用のバケットには、開発に必要なファイルしか置かない運用とすれば、s3 rsyncなどでまとめてデプロイするだけ

しかし、実際の運用として考えると「差分ファイルだけ配置する」というのは開発やデザイナ側に取って大変ではないかと言った懸念はあります。ディレクトリだけ作成しておく、とか工夫が必要と感じているので、利用する彼らと詰めていきたいと考えています。

*1:当たり前ですが、パブリックというのは世界中に公開するという意味なので変なファイルはおかない様に注意します