at posts/single.html

Heroku + MongoHQ環境の移行でハマった

Heroku上で Sinatra と MongoHQ を使って動かしている Amazon API認証リバースプロキシの環境を移行するときに、 MongoHQ のお引っ越しでハマったという話。

事の発端は、Amazon API認証リバースプロキシから MongoHQ にアクセスできなくなったことから。13日の夜に @tdtds さんが事象を発見して @hsbt さんが調査して、いまだに bamboo スタックで動かしていたのを cedar スタックで動くところまで作ってくれた。Twiterで mention が飛びまくっていたのに、僕が気がついたのは14日の夕方だったという。これはひどい。

ひとまず復旧優先で、あたらしい cedar 環境にDNSを切り替えてもらって、プロキシも手動でいくつか登録。登録者MLにアナウンスを出して再登録をお願いしようか…と思っていたところでbambooスタックのMongoHQが復旧して繋がるようになった。急いで旧環境(bamboo)のデータを新環境(cader)へコピーする。新環境でも全プロキシが見えるようになってめでたしめでたし…。

と思っていたら、新環境をリスタートしたとたんに「Application Error」の画面が。herokuのlogやpsコマンドで状態を確認すると、APサーバがcrached状態になっている。ログを追うとまたMongoHQに繋がらなくなっていた。

@hsbt @tdtds Mongoに繋ぐところで認証エラーですね。 Failed to authenticate user 'heroku' on db 'app20350636' (Mongo::AuthenticationError)

ついさっきまで繋がっていたのになぜ?と。原因が分からない。ここで @hsbt さんが MongoHQ の代わりに MongoLab を使えるようにしてくれた(頼もしい)。 MongoHQ 内でのデータ移行は MongoHQ の機能(GUI)でできたけど、 MongoHQ から MongoLab へのデータ移行は mongodump と mongorestore コマンドを使う。これでまた全プロキシが見えるようになってめでたしめでたし…。

ところが、またまたリスタートすると「Application Error」で繋がらなくなる。これまたさっきと同じエラーになている。

@hsbt @tdtds やっぱり前と同じエラーが出ていますね。 Failed to authenticate user 'heroku_app20350636' on db 'heroku_app20350636' (Mongo::AuthenticationError)

最初の1回だけ動いていて、リスタートすると動かなくなるのが嫌らしい。しかも開発用の別環境では動いているので、コードには問題なさそう。大量アクセスが原因か…とか考えていたら、ここでも @hsbt さんから寝る前の一言。

@machu エスパーですけど、リストアしたら bson 内部にある認証情報まで消えてしまうとか?

みごとに、これが原因だった。

新環境でのサーバ起動直後は、 Heroku 上の AP サーバと MongoHQ の DB サーバがそれぞれ稼働している。 DB に接続するための認証情報 (ID, パスワード) は、APサーバの環境変数 (MONGOHQ_URL, MONGOLAB_URI) に設定されている。当然、DBサーバ上でも同じ認証情報を持っている。データは空だけど、APは動く状態。

次に、旧環境のデータを新環境へインポートする。MongoHQのGUIを使っても、mongodump と mongorestore を使っても、旧環境のデータは「すべて」新環境へとコピーされる。この「すべて」の中に認証情報も含まれており、APサーバが持つ認証情報とDBサーバが持つ認証情報が不一致になる。でも、APサーバとDBサーバはすでに確立したコネクションを使い続けるので、正常にDBへアクセスできる。

APサーバは起動時にDBサーバとのコネクションを確立する。なので、リスタートするまではちゃんと動いていた(ように見える状態だった)。

DBデータを移行したあとに、DBへの接続IDとパスワード(新環境のAPサーバに設定されている値)を個別に登録することで、リスタート後もちゃんと繋がるようになった。

というわけで、MongoDBのデータをお引っ越しするときには、DBに接続するための認証情報まで複製されちゃうことに注意しましょう、という話。

関連する日記