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内部からでもアクセスができます。
通常のS3使用であればこの2パターンのどちらかの方法で問題無いと思います。
しかし最近これではクリアできない課題があったのでその時どう対処したかを書いておきます。
環境
- AWS ↔ 社内をDirect Connectで接続している
- 社内からインターネット接続はプロキシ経由が必須
やりたかったこと
- 社内環境でPanzuraという製品を使いたい
- ※PanzuraはS3をファイルサーバとして利用可能にするアプライアンス製品です。 AWS Partner SA ブログ: [ESP for AWS] Panzura クラウドファイルサーバ のご紹介 (SCSK株式会社)
課題点
つまり
最初に書いた2パターンのどちらの方法でも実現できない
どのように対処したか
社内とDirect ConnectでつながっているVPC内にEC2を作成し、S3エンドポイントとして振る舞わせることにしました。
具体的には透過型プロキシである「stone」というソフトウェアを利用しました。これは入り口として指定したポートに流れてきたパケットを行き先として指定したアドレス、ポートに転送するものです。
この中継サーバを置き、PanzuraのhostsにS3エンドポイントと中継サーバのIPアドレスを紐付けて書いてあげます。そうすることによって中継サーバがS3エンドポイントとして振る舞い、Panzuraからは中継サーバがあたかもS3エンドポイントのように見えるということです。
やってみます
家では実際にDirect Connect接続されている環境が用意できないので、VPC内に中継サーバを置き、PCからインターネット経由で中継サーバにアクセスしてS3アクセスを試してみます。
インターネット経由なのでグローバルIPアドレスでEC2インスタンスにアクセスします。
※もちろんDirect Connect経由でも検証済みです。
EC2を起動
このEC2インスタンスにはS3アクセス等の権限は必要ありません。クライアントにアクセスキーを登録しておくことでそのユーザ情報も含めて受け流してくれるためです。
S3のエンドポイントには443ポートでアクセスするので、セキュリティグループやネットワークACLでイン・アウトともに443を許可してあげます。
それとEC2を起動するサブネットのルーティングテーブルにエンドポイントを追加するのも忘れないでください。
$ 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クライアント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のシステムはこの範囲内で済んでいたので困ったことはありませんでした。
あとこの範囲外だとVPCのDNSで名前解決できなかったということも初めて知りました。
試してみます。
今回は28.0.0.0/16というVPCを作成し、そのVPC内に適当なサブネット、ルーティング、セキュリティグループなどを設定し、 同一サブネット内にEC2インスタンスを2つ起動して、片方からもう片方のホスト名で名前解決できるか試します。
EC2インスタンス①:ip-28-0-1-103.ap-northeast-1.compute.internal
EC2インスタンス②:ip-28-0-1-254.ap-northeast-1.compute.internal
インスタンス①に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アドレスの名前解決ができないようです。 どうしてもやりたければサポートに連絡してね。とのことです。