EC2インスタンスをS3エンドポイントとして振る舞わせる

Amazon Web Services Advent Calendarの11日目の記事です。

EC2インスタンスを中継したS3エンドポイントへのアクセスについて書きます。

S3エンドポイントについて

AWS CLIでS3リソースを操作したり、S3ファイルにアクセスしたりする際は、「S3エンドポイント」にアクセスすることになります。 東京リージョン(ap-northeast-1)では「s3-ap-northeast-1.amazonaws.com」というエンドポイント名になります。

AWS のリージョンとエンドポイント - アマゾン ウェブ サービス

このエンドポイントにインターネット経由でアクセスしたり、VPC内部からであればVPCエンドポイントという機能を使用することでAWS内部からでもアクセスができます。

f:id:ykarakita:20161211123718p:plain

通常のS3使用であればこの2パターンのどちらかの方法で問題無いと思います。

しかし最近これではクリアできない課題があったのでその時どう対処したかを書いておきます。

環境

  • AWS ↔ 社内をDirect Connectで接続している
  • 社内からインターネット接続はプロキシ経由が必須

やりたかったこと

課題点

  • PanzuraはS3エンドポイントまでの経路にプロキシをはさめない
  • (社内からVPCエンドポイントに直接アクセスしようと考えたが)VPCエンドポイントへのアクセスはVPC内部にあるリソース限定

つまり

最初に書いた2パターンのどちらの方法でも実現できない

f:id:ykarakita:20161211122632p:plain

どのように対処したか

社内とDirect ConnectでつながっているVPC内にEC2を作成し、S3エンドポイントとして振る舞わせることにしました。

f:id:ykarakita:20161211125345p:plain

具体的には透過型プロキシである「stone」というソフトウェアを利用しました。これは入り口として指定したポートに流れてきたパケットを行き先として指定したアドレス、ポートに転送するものです。

この中継サーバを置き、PanzuraのhostsにS3エンドポイントと中継サーバのIPアドレスを紐付けて書いてあげます。そうすることによって中継サーバがS3エンドポイントとして振る舞い、Panzuraからは中継サーバがあたかもS3エンドポイントのように見えるということです。

やってみます

家では実際にDirect Connect接続されている環境が用意できないので、VPC内に中継サーバを置き、PCからインターネット経由で中継サーバにアクセスしてS3アクセスを試してみます。
インターネット経由なのでグローバルIPアドレスでEC2インスタンスにアクセスします。
※もちろんDirect Connect経由でも検証済みです。

f:id:ykarakita:20161211130527p:plain

EC2を起動

このEC2インスタンスにはS3アクセス等の権限は必要ありません。クライアントにアクセスキーを登録しておくことでそのユーザ情報も含めて受け流してくれるためです。
S3のエンドポイントには443ポートでアクセスするので、セキュリティグループやネットワークACLでイン・アウトともに443を許可してあげます。
それとEC2を起動するサブネットのルーティングテーブルにエンドポイントを追加するのも忘れないでください。

EC2インスタンスが起動できたらpingを送信してみます。

$ ping s3-ap-northeast-1.amazonaws.com
PING s3-ap-northeast-1.amazonaws.com (52.219.4.16) 56(84) bytes of data.
64 bytes from 52.219.4.16: icmp_seq=1 ttl=55 time=2.37 ms

エンドポイント経由で疎通できているはずです。

Stoneインストール

インストール手順は以下のリンクを参考にしました。

CentOSにstoneをインストールしてみた | インフラ | DoRuby

Amazon Linuxの場合、インストール前に以下の手順が追加で必要でした。

$ sudo yum install gcc

Stone起動

$ sudo stone -d -d s3-ap-northeast-1.amazonaws.com:443 443
Dec 11 04:46:04.787469 140039676311360 start (2.3e) [2723]
Dec 11 04:46:04.787532 140039676311360 Debug level: 2
Dec 11 04:46:04.806718 140039676311360 stone 3: s3-ap-northeast-1.amazonaws.com:https <- 0.0.0.0:https

これでstoneが受け流してくれる状態になりました。
stoneのオプションの-dはデバッグするときにつけるもので、-dの数でデバッグレベルが決まります。
デバッグレベル2で起動するとパケットを受け付けたときのログを出力します。 今回はstone経由でS3アクセスしてることを確認するためにデバッグレベル2で起動します。(レベル4以上だと画面が大変なことになります。。)

クライアントでの操作

クライアントのhostsファイルを書き換えます。

クライアントのPCで実行
$ sudo /etc/hosts
以下を追加
[stoneサーバのIPアドレス] s3-ap-northeast-1.amazonaws.com

クライアントにIAMユーザのクレデンシャルを登録します。

クライアントのPCで実行
$ aws configure --profile stone_user
以下略

このユーザにはS3FullAccessをアタッチしていますが、必要に応じて権限を設定してあげてください。

S3のCLIを使ってみる

[クライアントPC]
$ aws --profile stone_user s3 ls
2016-12-11 13:15:14 stone-test1
[Stoneサーバ]
Dec 11 04:48:06.398530 140039676311360 stone 3: accepted TCP 5 from xxxxxxxxxxxxx.jp:63058 mode=0

↑アクセスが来ているのでstoneサーバ経由でS3アクセスしているようです。

アップロードもしてみます。

$ aws --profile stone_user s3 cp ./testfile.txt s3://stone-test1 --endpoint-url https://s3-ap-northeast-1.amazonaws.com
upload: ./testfile.txt to s3://stone-test1/testfile.txt

cpをする時は--endpoint-urlで明示的にエンドポイントを指定しないとstone経由でやってくれないみたいでした。
lsするときとcpする時のデフォルト設定でのエンドポイントが違うのかな?

今回ここでは書きませんが、wgetなどで中継サーバ経由でのファイルダウンロードもできます。

(おまけ)パフォーマンス

アップロードやダウンロード速度はどうしてもstoneを動かすEC2インスタンスのI/Oがボトルネックになってしまうかと思います。
S3エンドポイントへのアクセス方法によってどれくらい速度に差が出るのか試してみました。 512MBのダミーファイルを作成し、下の3通りの方法でアップロードしました。

  • クライアントPC → インターネット → S3
  • EC2インスタンス(t2.micro) → VPCエンドポイント → S3
  • クライアントPC → インターネット →中継サーバ (EC2/t2.micro)→ VPCエンドポイント → S3

実行時間計測結果

  • クライアントPC → インターネット → S3
    24.382s

  • EC2インスタンスVPCエンドポイント → S3
    16.407s

  • クライアントPC → インターネット → 中継サーバ(EC2/t2.micro) → VPCエンドポイント → S3
    46.320s

ご参考 自宅の回線のアップロード速度115.94Mbps (14.49MB/sec)

まとめ

めったにこの構成を選ぶことはないと思いますが、エンドポイントまわりやS3の仕様に少し詳しくなったのでよかったです。

こんなことしなくてもすぐにAmazonからいい感じのサービスが出るだろうと思っています。

久しぶりにブログを書いたら長くなってしまった。。

【新機能】VPCのDNSでRFC1918範囲外のプライベートIPアドレス名前解決

先ほど情報収集をしていたところAWSから以下のような発表が出ているのを見つけました。

Announcing EC2 DNS Support for Non-RFC 1918 Address Ranges

要するに、
今まではRFC1918で定義されている範囲内のものしかVPC内のDNSサーバでは名前解決できなかったけど、 その範囲外でも特別な設定不要でできるようになったよ。
ということみたいです。

ちなみにRFC1918で定義されているプライベートIPアドレスは以下のもの。

  • 10.0.0.0/8 (クラスA)
  • 172.16.0.0/12(クラスB)
  • 192.168.0.0/16(クラスC)

プライベート網のアドレス割当(RFC 1918) - JPNIC

私がこれまで関わったAWSのシステムはこの範囲内で済んでいたので困ったことはありませんでした。
あとこの範囲外だとVPCDNSで名前解決できなかったということも初めて知りました。

試してみます。

今回は28.0.0.0/16というVPCを作成し、そのVPC内に適当なサブネット、ルーティング、セキュリティグループなどを設定し、 同一サブネット内にEC2インスタンスを2つ起動して、片方からもう片方のホスト名で名前解決できるか試します。

インスタンス①にSSHログイン後、以下コマンドを実行します。

[ec2-user@ip-28-0-1-103 ~]$ nslookup ip-28-0-1-254.ap-northeast-1.compute.internal
Server:         28.0.0.2
Address:        28.0.0.2#53

** server can't find ip-28-0-1-254.ap-northeast-1.compute.internal: NXDOMAIN

え。。できませんがwww 東京リージョンは未対応だっけ?

と思いドキュメントをよく見るが、わからず。

DNSホスト名」設定が無効でした

凡ミスでした。VPCから「DNSホスト名」の設定を有効にしましょう。

改めてチャレンジ。

[ec2-user@ip-28-0-1-103 ~]$ nslookup ip-28-0-1-254.ap-northeast-1.compute.internal
Server:         28.0.0.2
Address:        28.0.0.2#53

Non-authoritative answer:
Name:   ip-28-0-1-254.ap-northeast-1.compute.internal
Address: 28.0.1.254

おおー!できたー

この機能を待ちわびていた人もいるんでしょうかね。

またひとつAWSを覚えました。

注意点

ドキュメントにもありますが、2016年10月以前に作成したVPCだとRFC1918範囲外のプライベートIPアドレスの名前解決ができないようです。 どうしてもやりたければサポートに連絡してね。とのことです。

docs.aws.amazon.com