Open32

herokuからの卒業

かわんじかわんじ

herokuからGCPへの引っ越しTODO

  • プロダクションの環境変数をherokuではなくcredentialsで管理する
  • DiQtをコンテナ化してherokuにコンテナデプロイする
  • Heroku Postgres, Heroku Redis, Heroku Bonsai Elastic Search, Heroku Scheduler以外のherokuのアドオンを剥がして本家サービスに移行する
  • 翻訳などGCPのAPIを、クレジットを持つGCPアカウントに変更する
  • S3のデータをGCSに複製・転送する
  • DBでS3のリソースを参照していたデータをGCSのリソースを参照するよう変更する
  • Heroku SchedulerをCloud Schedulerに移行する
  • Heroku Redisを、GCPのMemorystore for Redisに移行する
  • Heroku PostgresとHeroku Bonsai Elastic Searchを、GCPのCloud SQL for PostgreSQLとBonsai Elastic Searchに移行する
  • メンテナンスモードに入り、Heroku PostgresのdumpデータをCloud SQLに流し込む
  • DBの向き先をHeroku PostgresからCloud SQLに変更する
  • Bonsai Elastic Searchでreindexする
  • アプリケーションサーバーをCloud Runに移行する。
かわんじかわんじ

herokuからAWSへの引っ越しTODO

  • プロダクションの環境変数をherokuではなくcredentialsで管理する
  • DiQtをコンテナ化してherokuにコンテナデプロイする
    • まずはstagingに。
    • それからproduction
  • Heroku Postgres, Heroku Redis, Heroku Bonsai Elastic Search, Heroku Scheduler以外のherokuのアドオンを剥がして本家サービスに移行する
    • Sendgrid
    • Cloudinary
  • 翻訳などGCPのAPIを、クレジットを持つGCPアカウントに変更する(booqs.diqt@gmail.com -> aikawa@booqs.net
  • Heroku PosgresとHeroku Bonsai Elastic SearchをAmazon RDSと本家のBonsai ElasticSearchに移行する。
  • Heroku RedisをElastiCacheに移行する
  • アプリケーションサーバーをECSに移行する。
  • Heroku SchedulerをECSに移行する
かわんじかわんじ

DB移行

料金を試算する

白!
https://calculator.aws/#/createCalculator/AuroraPostgreSQL

RDSの作成

Amazon RDSでpostgresを用意する。

セルフマネージドを選び、パスワードは手動で設定して1passなどにメモしておくこと。

設定で作るようにおすすめされたのでキャッシュも作っておく。

パブリックアクセスをON

DBの変更が有効になったら「接続」の追加設定のパブリックアクセスをONにする

インバウンドルールの追加

EC2 Security Group - Inboundにて、インバウンドルールも

  • タイプ:PostgreSQL
  • プロトコル:TCP
  • ポート範囲:5432
  • 送信元:0.0.0.0/0

で設定しておく。

インバウンドルールの設定が完了すれば、
psql -h <エンドポイント> -U <ユーザー名> -d <データベース名>でローカルからpostgresを開けるようになるはず。
後で必要となるデータベース名はコンソールから確認できないので、この際に\lで確認しておくこと。
初期設定ならpostgresになってるはず。
データベース名とデータベース識別子は別物だから注意。

接続テスト

一旦、空のDBの状態でHerokuのStaging環境と接続できるかどうかを試してみる。
接続が失敗すればこんな具合にエラーが出るはずなので。

 heroku config:set DATABASE_URL=postgres://<ユーザー名>:<パスワード>@<エンドポイント>:5432/<データベース名> --app <あなたのHerokuアプリ名>

データベース名とデータベース識別子は別物だから注意。
繋がった。

herokuのdumpデータをRDSに流し込む

latest.dumpをローカルにダウンロードする。

https://qiita.com/Kawanji01/items/5a751d9532a5a108da38

ダウンロードしてきたら以下を実行する

pg_restore --verbose --clean --no-acl --no-owner -h <エンドポイント名> -U <ユーザー名> -d <データベース名> latest.dump

65GBほどのデータで大体1時間ほどかかった。

かわんじかわんじ

DBに関しては、heroku からAWSに移行しても安くはならないどころか、東京リージョンにすると値上がりするまであるなぁ。
まぁ$5000クレジットもらった自分にとってはそれでも移行するメリットあるけど。
herokuでも困ってはなかったし、西海岸にしておくか。
https://www.openupitengineer.co.jp/column/it-technology/8274

かわんじかわんじ

Auroraのセットアップ

DBつくる前に見積もれ!!破産したいのか???
https://calculator.aws/#/createCalculator/AuroraPostgreSQL

セットアップ

「標準設定」「Aurora postgres」

heroku postgresとのバージョンが異なるとdumpデータをrestore出来ない場合があるので、heroku postgresのバージョンを確認して同じ16に設定した。

パスワードは自前で設定して1passとかに保存しておく。
デフォルトで選択されてるI/O最適化は目ん玉飛び出るほど高いのでAurora Standardを選んだ。(見積もりで確認しろ!)

Heroku Postgres Standard-2に近い性能のインスタンス(RAM 8GB, Storage 256GB)を選んでおく。
互換性に問題がなければ、性能もコストもt3よりt4gの方が良いらしいので、Stagingで動作検証をすることも踏まえて、t4gを選んだ。

Herokuから利用する場合にはパブリックアクセスをONにしておくこと。
RDS Proxyも設定しておいた。

ここの「最初のデータベース名」、後でコンソールからは見れないから1Passに入れておこう。

Heroku Postgres Standard-2が$200なので$30以上も削減できた。
Storageは64GBなのでここにプラス$7.68とI/Oでも課金が発生するので、総合で見たらトントンかな?
まぁ北米から東京リージョンに変更できただけでもよしとしたい。

データベースを作成するとリコメンドが表示されるのでついでに作っておく。
もちろんRedisで。

インバウンドルール設定

EC2 Security Group - Inboundにて、インバウンドルールも

  • タイプ:PostgreSQL
  • プロトコル:TCP
  • ポート範囲:5432
  • 送信元:0.0.0.0/0

で設定しておく。

インバウンドルールの設定が完了すれば、
psql -h <エンドポイント> -U <ユーザー名> -d <データベース名>でローカルからpostgresを開けるようになるはず。
データベース名はデータベース識別子じゃなくて「最初のデータベース名」だから注意ね。

接続テスト

一旦、空のDBの状態でHerokuのStaging環境と接続できるかどうかを試してみる。
接続が失敗すればこんな具合にエラーが出るはずなので。

 heroku config:set DATABASE_URL=postgres://<ユーザー名>:<パスワード>@<エンドポイント>:5432/<データベース名> --app <あなたのHerokuアプリ名>

データベース名とデータベース識別子は別物だから注意。
繋がった。

herokuのdumpデータをRDSに流し込む

latest.dumpをローカルにダウンロードする。

https://qiita.com/Kawanji01/items/5a751d9532a5a108da38

ダウンロードしてきたら以下を実行する

pg_restore --verbose --clean --no-acl --no-owner -h <エンドポイント名> -U <ユーザー名> -d <データベース名> latest.dump

65GBほどのデータで大体1時間ほどかかった。

かわんじかわんじ

くっそ遅い

  • t4g.largeは遅すぎて死んでる。おそらく互換性の問題でrestoreしたときにindexがきちんと貼られてないとかそんな遅さ。
  • Aurora Serverless v2に変更しようと検討したけど、Aurora Serverless v2はオートスケールするが、通常のAuroraより1.5倍以上はコスト高くなるので、定常的に起動してるアプリにはコスパはよくないらしい

遅い原因調査

インスタンスタイプの違い:

Burstable性能: db.t4g.largeはバースト可能なパフォーマンスを持つインスタンスで、一定のCPUクレジットを使用します。長時間高負荷のワークロードには適していません。
解決策: CPUクレジットの消費状況を確認し、必要に応じてCPU性能が安定したdb.mまたはdb.rシリーズへの変更を検討してください。
設定の違い:

パラメータグループ: HerokuでのPostgres設定とAuroraのデフォルト設定が異なる可能性があります。
解決策: Herokuの設定を参照し、Auroraのパラメータグループを調整して同等の設定にします。
インデックスの欠如または最適化不足:

インデックス再構築: リストア時にインデックスが正しく再構築されていない可能性があります。
解決策: 必要なインデックスが存在するか確認し、統計情報を更新するためにANALYZEコマンドを実行します。
IOPS(Input/Output Operations Per Second)の制限:

ストレージタイプ: Auroraのストレージ設定がHerokuよりも低いIOPSを提供している可能性があります。
解決策: ストレージタイプとIOPS設定を確認し、必要に応じてプロビジョンドIOPSを使用します。
ネットワークレイテンシー:

地域とゾーン: データベースとアプリケーションが異なるリージョンやアベイラビリティゾーンにあると、レイテンシーが増加します。
解決策: データベースとアプリケーションを同じリージョンまたはゾーンに配置します。
クエリの最適化不足:

クエリプランの変化: データベースエンジンの違いにより、クエリプランが変化し、パフォーマンスに影響を与える可能性があります。
解決策: クエリの実行計画を確認し、必要に応じて最適化します。
接続プールの設定:

接続数の制限: 接続数が多すぎると、リソースが逼迫します。
解決策: 接続プールを使用し、接続数を適切に管理します。
拡張機能やモジュールの違い:

互換性の問題: Herokuで使用していた拡張機能がAuroraでサポートされていない可能性があります。
解決策: 必要な拡張機能が有効になっているか確認します。
リソースの競合:

他のサービスとの干渉: 同じインスタンスで他のサービスを動かしていると、リソースが共有されパフォーマンスが低下します。
解決策: データベース専用のインスタンスを使用します。
データベースエンジンの違い:

Aurora特有の挙動: AuroraはPostgreSQLと互換性がありますが、内部的な実装が異なるため、パフォーマンスに影響することがあります。
解決策: Auroraの特性を理解し、設定を最適化します。
次のステップ:

モニタリング: AWSのCloudWatchを使用して、CPU使用率、メモリ、ディスクIO、ネットワークトラフィックなどを監視します。
ログの確認: スロークエリログを有効にし、パフォーマンスのボトルネックとなっているクエリを特定します。
スケーリング: ワークロードに応じて、インスタンスサイズやクラスタ構成をスケーリングします。
これらのポイントを確認し、問題の原因を特定して対処することで、パフォーマンスの改善が期待できます。

かわんじかわんじ
  • リストア時にインデックスが正しく再構築されていない可能性
  • Auroraがそもそもいかん可能性がある。通常のRDSならいけるか?
  • db.t4g.largeは一定のCPUクレジットを使用し長時間高負荷のワークロードには適してないそうなのでdb.rシリーズへの変更を検討することを勧められた。t3.largeでもダメならそうする。ライトだけだなら$300以内だし。
  • TODO:
    • t3.largeにリストア(イマココ)

    • インデックスチェック

    • インデックスがきちんと再構築されてなかった場合

      • index貼り直す(REINDEX DATABASE database_name;)
      • 統計情報の更新(ANALYZE;)
    • インデックスが問題ない場合
      - db.r5.largeでDBを作り直してリストア
      - それでも遅い場合
      - Auroraから通常のRDSのt3.largeに移行。
      - まだ遅い場合にはdb.r5.largeに移行。

かわんじかわんじ

あぁ、t系(バースト可能パフォーマンスインスタンス)ってCPUクレジット(?)というのを使い果たすとパフォーマンスが大幅に低下するからそもそも本番稼働に向いてないのね。
本番運用ではm(汎用インスタンス)かr(メモリ最適化インスタンス)を使うといいらしい。初めてのRDSならmらしいからm使うか。

かわんじかわんじ

Aurora、mなくてrしかないんか〜い
まぁまぁr6g.largeなら255.52 USDだし、いいか。。。(感覚麻痺してきた。普通にherokuより高い)

かわんじかわんじ

indexを再構築

psql -h <エンドポイント> -U <ユーザー名> -d <データベース名>
REINDEX DATABASE <データベース名>;

統計情報の更新

psql -h <エンドポイント> -U <ユーザー名> -d <データベース名>
ANALYZE;
かわんじかわんじ

なんか前のLTでメモリオの中の人が、heroku postgresからRDSに移行する際にツール使ってた話をしてたんだけどこれだっけ??

https://aws.amazon.com/jp/dms/pricing/?nc=sn&loc=3

AWS Database Migration Service では現在、T2、T3、C4、C5、C6i、R4、R5、および R6i インスタンスクラスがサポートされています。

mないんだ。
auroraなら元々mないし、これ使えそう。

かわんじかわんじ

MEMORIO CTOの記事やっと見つかった。
なるほど〜同じリージョンからならすぐにリストアできるのか。

リハーサルを何度か行った結果、Herokuの東京リージョンにあるプライベートインスタンスとAWSの東京リージョンが同じネットワーク上にあることを利用してHeroku内のインスタンスにダウンロードしてからawsに直接アップロードしたほうが作業時間を7割以上削減できることがわかりました。
この短縮により、時間のかかるDBのリストアで失敗があってもサービスを停止する1時間以内にやり直すことができる余裕を得ることができました。

https://zenn.dev/iototaku/articles/7beb58415b042b

かわんじかわんじ

AWS Server Migration Service はherokuからの移行には使えないそう。

多分アプリケーションの移行はDB移行してからしばらく経ってからになると思う(Heroku Schedulerとかも色々と移行しないといけない)ので、やっぱ一旦DBのregionもus-east-1にすることにした。

Final and very importan PRO Tip is to create the RDS Instance in the same region as the Heroku Instance. This will drasticly decrease the latency of communicating to the DB . At the time of writing for heroku US hosting that is us-east-1 region. You can check the exact region for your setup here.

https://towardsdatascience.com/migrating-from-heroku-postgres-to-amazon-rds-2e738e7730e5

かわんじかわんじ

AWS loftで聞いてきた。
DBの設定もmetricsにもおかしい点はないらしい。
heroku側のmetricsを見てもなんら不審な点もないそうなので、アプリケーション側の問題っぽい。

かわんじかわんじ

解決した!

解決までにやったこと。

  • stagingにattachしていたproductionのHeorku Key Value Storeをdetachして、Stagingで新たにheroku key value storeを契約した。
  • Auroraを東京リージョンからherokuと同じ北ヴァージニア(east-us-1)で作り直した(それもdb.t4g.largeで!)

多分2つ目がきいたのだと思う。
もし1が原因だとすると、本番環境にも影響がないとおかしい気がするので。

かわんじかわんじ

やっとDBの引っ越し終わった〜〜〜〜
heroku postgres standard-2($200/month) からAmazon RDS for PostgreSQL db.t4g.large ($127/month) に移行して$73/month削減できた。
$5000クレジットが使い切るまでは無料で使い続けるので、実質$200/monthの削減だ。
今のところは問題なく動いてるっぽい。そのまま動いてくれ〜〜〜〜

かわんじかわんじ

一応AuroraではなくRDS for postgresにした理由:

  • Auroraだとt4g.largeをアップグレードする場合にはr7g.large($233)しか選択肢がなく、間にm系を挟むことができず、急にコストが上がる。RDSならt4g.largeの次にm7g.large($156)を間に挟むことができて、費用的にありがたい。
  • 書き込みの多いサービスなので、I/Oでお金がかかるのが不安。Auroraでのリストアの練習で結構請求されてた。
  • DBの移行自体は何度も予行練習して慣れたので、RDSで物足りなくなったらまた数時間メンテ入れてAuroraに引っ越せばいいか、という判断になった。
かわんじかわんじ

RDSのキャッシュクラスターは作成する必要がない

  • デフォルトではクラスターの作成をお勧めされるが、AWSの人に曰く、それほどの規模でないのなら作成する必要はないとのこと。
  • パフォーマンスが気になってから作成すれば良い。
  • サーバーレスでRedisを作るとめちゃくちゃ高いし。
かわんじかわんじ

VPSエンドポイントを消せ!!

RDS proxyを作成すると、VPSエンドポイントが自動で作成される。
そしてRDSを削除しても、VPSエンドポイントは残り続ける。
さらにVPSエンドポイントは時間で金がかかる。
消したはずの東京リージョンのDBのVPSエンドポイントが残ってる!!
しかし、VPSエンドポイントを消そうとしても、このままだと削除できない。

まずプロキシを消す

それからエンドポイントを削除する。

かわんじかわんじ

Redisの作成

選定

Heroku Key-Value Store のpremium-1は、以下のようなスペックなので、cache.t4g.microで良さそう。

$11.68だった。

作成

かわんじかわんじ

ElasticCacheは、AWSの外部サービス(heroku)には繋げられないそうなのでAmazon MemoryDBを利用する。