AWS Elastic BeanstalkのTomcatはyum updateで更新してはならない

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

旧タイトル:AWS Elastic BeanstalkのJava環境をRDSと同時起動した際にRDSのホスト名等がダブルクオートで囲まれる「ことがある」件

本件の原因は、Beanstalkのサーバに入って、無意識的にyum -y updateしていた為でした!

Elastic BeanstalkのTomcatには、固有のTomcat起動スクリプト/usr/sbin/tomcat7-elasticbeanstalkがあり、アップデートによりこれがデフォルトに戻されてしまうのが原因でした。

Beanstalkサーバのアップデートはしないのが無難! おとなしくAMIのアップデートを待つのが得策のようです。

よく訓練されたアップル信者、都元です。先週金曜日にハマった件があるのでシェアします。

Elastic Beanstalk environment with RDS instance

AWS Elastic Beanstalkにおいて、ManagementConsoleからenvironmentを作成する際に、同時にRDSのインスタンスを起動するオプションがあります。

ebrds-1

ebrds-2

便利ですね。しかし、データベースの接続情報(ホスト名、ポート番号、DB名等)は動的であるため、アプリケーション内にハードコーディングすることができなくなります。environmentをRDSと一緒に立ち上げただけで、アプリケーションとRDSがリンクする、つまり、アプリケーションがDB接続情報を取得できるような仕組みが必要です。あり〼。

このように立ち上げたRDSの接続情報は、環境変数から取得できます。各言語毎に取得手順が微妙に異なるため、詳細は以下のドキュメントを参照してください。

Javaにおける不具合

ここでは、以下Javaの例で話を進めます。ドキュメントによると、例えばこんな感じでJDBCの接続URLが手に入るそうです。

String dbName = System.getProperty("RDS_DB_NAME"); 
String userName = System.getProperty("RDS_USERNAME"); 
String password = System.getProperty("RDS_PASSWORD"); 
String hostname = System.getProperty("RDS_HOSTNAME");
String port = System.getProperty("RDS_PORT");
String jdbcUrl = "jdbc:mysql://" + hostname + ":" + port + "/" + dbName + "?user=" + userName + "&password=" + password;

このコードを実行した結果、jdbcUrlが以下のような文字列になるそうです。

jdbc:mysql://mydbinstance.abcdefghijkl.us-east-1.rds.amazonaws.com:3306/employees?user=sa&password=mypassword

現時点(2013/3/25)で、これが嘘なので注意してください、というのが本エントリの趣旨です。何も知らずにドキュメントを信じてアプリを実装し、DBに接続を試みると、以下のような例外が発生します。そこで思うわけです。なぜDNSの名前解決ができないのだ、と。

Caused by: java.net.UnknownHostException: "mydbinstance.abcdefghijkl.us-east-1.rds.amazonaws.com"

digで引いてみても問題ない、IPを直接ハードコーディングしてみると繋がる…。ハァ!? と思いながらも散々ハマること4時間。

謎解き編

ドキュメントによると、RDS_HOSTNAMEにはmydbinstance.abcdefghijkl.us-east-1.rds.amazonaws.comという文字列が入っているはずなのですが、実際には"mydbinstance.abcdefghijkl.us-east-1.rds.amazonaws.com"のように、ダブルクオートで囲まれた文字列が入っています。同様に、RDS_PORTには"3306"が入っています。

mydbinstance.abcdefghijkl.us-east-1.rds.amazonaws.comに繋ごうとした結果、DNSによるホスト名解決ができなかった時は、以下のような例外メッセージとなるはずです。ああ、ダブルクオートやん…。

Caused by: java.net.UnknownHostException: mydbinstance.abcdefghijkl.us-east-1.rds.amazonaws.com

しかし、なぜシステムプロパティの値の中にダブルクオートが入り込んでしまったのか、そこまでは追いきれませんでした。残念。従って、本現象は私の環境特有の事象の可能性もあります。

以上を一般的に発生する現象だとすれば、ドキュメント(仕様)と実装の不整合であるため、バグだと思います。AWSには通報済みですが、いつ直るのかは定かではありませんし、仕様側と実装側のどちらが修正されるのかも分かりません。しばらくはアプリケーション側のワークアラウンドで対処するしかないと思います。が、突然実装が修正されても落ちないように、アプリ側も対策しておく必要がありそうです。

と、いうわけで、本エントリがみなさまの大事な4時間をお守りできれば幸いでっす。続報があれば、追記や修正等していこうと思っています。

追記

2013-03-28: どうやら、他の環境ではダブルクオートで囲まれたりしないようです。AWSでも再現が確認出来なかったようで、かなり特殊ケースなのかもしれません。ただ、事象が再現しているコード及びenvironmentをAWSに提供したので、近々何らかの解決は見えると思います。