【完結】テスト環境を構築検討していく⑧【NestJSの構築】
こんにちは投資ロウトです。
背景
ある程度NestJSでAPIの作成も進んできたので、Postmanによる単体テストではなく、アプリからのAPI呼び出しで動作を確認していきたいという思いも進めていくと出てくると思います。
ただなるべくコストを抑えていきたいため、本番環境よりもコストを抑えた類似環境でテスト環境を構築していきます。
※ECSなどはリソースだけで費用がかかるので、EC2などのインスタンスを止めながら開発コストを抑えたい。
そのため本番環境を簡易で構築し、テストを行う環境を整備していきます。
NestJS(NodeJS)の環境構築
①nodejsを入れる
sudo yum update -y
問題1
sudo yum install -y nodejs npm
上記実行時にエラーが発生
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
パッケージ nodejs は利用できません。
パッケージ npm は利用できません。
エラー: 何もしません
対処1
AWS EC2インスタンスで、yumを利用して直接インストールできないことがあるとのこと
# NodeSourceリポジトリを追加してNode.jsをインストール
curl -fsSL https://rpm.nodesource.com/setup_16.x | sudo bash -
続き
sudo yum install -y nodejs
# 今度は成功。ただし実行のnodeのバージョンは合わせること
node -v
# nodeのバージョンの修正
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
# 対象のバージョンを入力
nvm install 対象のバージョン
nvm use 対象のバージョン
# 対象のバージョンから切り替わっていることを確認
node -v
# npmのバージョンの確認
npm -v
# 自環境と変わらなかった。
②codecommitのソースを引っ張ってくる
git clone リポジトリ
問題2
gitコマンドがない
-bash: git: コマンドが見つかりません
対処2
sudo yum install -y git
続き
# 再度実行
git clone リポジトリ
cd フォルダ名
npm install
# 起動
PORT=対象のポート npm start
問題3
PORT=対象のポート npm start
> xxx@0.0.1 start /home/ユーザー名/リポジトリ名
> xxx nest start
<--- Last few GCs --->
[7700:0x4145e20] 16392 ms: Mark-sweep 482.2 (484.3) -> 482.0 (484.3) MB, 300.0 / 0.0 ms (+ 115.0 ms in 23 steps since start of marking, biggest step 17.3 ms, walltime since start of marking 472 ms) (average mu = 0.290, current mu = 0.157) allocation f[7700:0x4145e20] 17070 ms: Mark-sweep 482.4 (484.3) -> 481.6 (484.6) MB, 677.3 / 0.0 ms (+ 0.0 ms in 5 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 678 ms) (average mu = 0.135, current mu = 0.002) allocation failu
<--- JS stacktrace --->
==== JS stack trace =========================================
0: ExitFrame [pc: 0x140dff9]
Security context: 0x04c38b8c08d1 <JSObject>
1: iterateCommentRanges(aka iterateCommentRanges) [0x6cc49856a91] [/home/ユーザー名/リポジトリ名/node_modules/typescript/lib/typescript.js:~10713] [pc=0x3f20064f76e4](this=0x226fcbd804b1 <undefined>,0x226fcbd80639 <true>,0x0c7a09d00119 <Very long string[152935]>,74398,0x226fcbd806e9 <false>,0x06cc49856b51 <JSFunction appendCommentRange (sfi = 0x36eeb01c3159)>,0x...
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
1: 0xa1a640 node::Abort() [node]
2: 0xa1aa4c node::OnFatalError(char const*, char const*) [node]
3: 0xb9a9fe v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [node]
4: 0xb9ad79 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node]
5: 0xd57ff5 [node]
6: 0xd58686 v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [node]
7: 0xd64f45 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [node]
8: 0xd65df5 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
9: 0xd688ac v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
10: 0xd2f2cb v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationType, v8::internal::AllocationOrigin) [node]
11: 0x107189e v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [node]
12: 0x140dff9 [node]
対処3
# JavaScriptのヒープメモリが不足しているために発生しているとのこと
# EC2インスタンスのメモリを確認
total used free shared buff/cache available
Mem: 965 65 854 0 46 807
Swap: 0 0 0
# メモリが1GBしかないのが問題のようでした。
# スペックを落としすぎたのが、原因のようです。
# ローカルで動く環境を確認してみる
8GBのメモリと1GBのswapがあり、それは動かないと言うことになりました。
total used free shared buff/cache available
Mem: 7859 1240 4664 307 1954 6013
Swap: 1023 0 1023
今度はサーバーのスペックを上げていく。
t2.microが1GBなのでt2.large
問題4
awsのcloudformationで削除時、DBのauroraが削除できない。
Db cluster dm-dev-aurora-cluster is in stopped state (Service: Rds, Status Code: 400, Request ID: aaaa604e-bbbb-cccc-dddd-eeeed4d7ffff
)
対処4
aurora mysqlのインスタンスをとめているのが要因なので、起動してから削除をながす
※よくよく考えたら、DB削除する必要はなかったです。。。
続き
# 一旦上記の流れで再度実施する。
# メモリの件は解消されていた
# Aurora MySQLの接続方法
# RDSから接続とセキュリティを選び、エンドポイントを確認。
# ライターとリーダーがあるが、更新がある場合はライターで接続を行う
# MySQLなので3306のportで、他はAurora MySQLを作成するために作成したものを使用。
ここまででAurora MySQLに接続が成功
検証
PostmanでALBで設定したサブドメインに対してAPIを投げる
問題1
<html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
</body>
</html>
解決1
# 原因:ヘルスチェックが行われていないのが原因の一つだった
# 問題点1:ヘルスチェック用のAPIをつけていなかった
cloudwatchで全てのメトリクスでフィルター
cloudwatchでのメトリクスの件数は1334件が12時間で存在した。
Application ALBの項目をクリックする
→メトリクスをUnHealthyHostCountでフィルターをする
ディメンションでフィルターをさらにする
Application Load Balancerは「AvailabilityZone」と「LoadBalancer」と「TargetGroup」でフィルターできる
UnHealthyHostCountで引っ掛かっていることが確認できる。
※ヘルスチェックでNGとなっている確認方法
# privateサブネットからヘルスチェックが帰ってくる設定になっているか確認。
# privateサブネットでNestJSを起動した状態で、もう一つprivateサブネットでターミナルを開き、下記コマンドを実施。
curl localhost:対象のポート/
# 結果
{"statusCode":404,"message":"Cannot GET /","error":"Not Found"}
ヘルスチェックの動線を用意する必要があることが判明
NestJSに"/"のGetメソッドで200ステータスが返せれるように修正
# webサーバーのprivateサブネットから再度curlを実施
curl localhost:対象のポート/
# 成功したので、まずはヘルスチェックの口があることは問題ない。
この状態で再度APIを実施してみる
# まだ502が返ってしまう。詳細を確認していく。
# 対象のポートに対してヘルスチェックを行えていないことを確認
Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
Port: 送りたいポートに指定する
問題2
今度はtime outが表示された
<html>
<head>
<title>504 Gateway Time-out</title>
</head>
<body>
<center>
<h1>504 Gateway Time-out</h1>
</center>
</body>
</html>
解決2
問題なのは、セキュリティーグループ等でアクセスをブロックしていたのが原因だったため、セキュリティグループ及びターゲットとなるポートが問題なく通るように修正をします。
そして環境をまた壊すのは、待ち時間や構築にめちゃめちゃ時間がかかるので、地獄ですね。。。
そして結果。。。無事にリクエストが成功。。。長い格闘だった笑
新たに知ったこと
現状(2024/6/7時点)aws上ではA5M2や、cloudBeaverのようなGUIでDBを確認するツールは存在しない。
新たに知ったこと
ECSのFargateを構築した際に、CloudWatchとの連携が自動的に有効になり、以下の2点が有効となる。
①リソースのモニタリング
CPU使用率やメモリ使用率などのメトリクスが、CloudWatchコンソールやAPIから確認可能
②コンテナアプリケーションのログの永続化
Fargateタスクからのログストリームが、CloudWatch Logsに自動的に送信され、タスクログの確認やモニタリングが可能となる。
繰り返し出るが、cloudformationのかんぺ
Discussion