【Cloud Run】そのメモリ不足はコンテナ内に出力されたファイルが原因かもしれない話
何気なくCloud Runのドキュメントを眺めていると気になる記述が。
コンテナのファイル システムは書き込み可能で、次の動作の影響を受けます。
これはインメモリ ファイル システムであるため、書き込みにはコンテナ インスタンスのメモリが使用されます。
十分なメモリを割り当てているはずのCloud Runサービスが定期的にメモリ不足で落ちてしまう悩みを抱えていた私。
もしかして、アプリがコンテナ内にファイルを書き出してしまっておりそれが原因でメモリを多く消費しているのでは? という仮説のもと検証しました。
仮説
アプリケーションが動作するのに利用するメモリ以外に、コンテナ内に出力するファイルによってコンテナがメモリ制限に引っかかり落とされてしまっているのではないか?
検証環境
言語
PHP 8.2.0
Cloud Run
CPU: 1vCPU
メモリ: 128MB
最大インスタンス: 1
ポート: 80
その他はデフォルト値のまま。
コード
アクセスされるたびに 2KB x 1024 = 3MB
のファイルを作成するシンプルな処理で検証します。
一気にでかいファイルを作ると怖いので、小さいファイルを繰り返し作って検証します。
※1つのコンテナで検証したいので、Cloud Runの最大インスタンス数は1と設定しています
<?php
$filename = uniqid();
$fp = fopen("/tmp/${filename}", 'wb');
for($i = 0; $i < 1024; $i++) {
fputs($fp, random_bytes(2048));
}
fclose($fp);
$dir = '/tmp';
$files = scandir($dir, SCANDIR_SORT_DESCENDING);
print_r(count($files));
FROM php:8.2.0-apache-buster
COPY src/index.php /var/www/html/index.php
substitutions:
_SERVICE_NAME: run-memory-test
steps:
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'gcr.io/$PROJECT_ID/$_SERVICE_NAME', '.']
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/$PROJECT_ID/$_SERVICE_NAME']
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: gcloud
args: [
'run', 'deploy', '$_SERVICE_NAME', '--image', 'gcr.io/$PROJECT_ID/$_SERVICE_NAME',
'--region', 'us-central1',
'--port', '80',
'--max-instances', '1',
'--memory', '128Mi',
'--allow-unauthenticated'
]
結果
このコードで作成されたCloud Runにアクセスを続けるとメモリ制限にぶつかり、しっかりコンテナが落とされました。
Memory limit of 128 MiB exceeded with 130 MiB used. Consider increasing the memory limit, see https://cloud.google.com/run/docs/configuring/memory-limits
まとめ
過度にメモリを使用しているわけでもないのにメモリが使われ続けるといった事象に遭遇した場合。
アプリケーションのメモリリークという観点の他にファイルシステムの利用によってメモリを圧迫されてしまっている可能性があるので注意が必要です。
BigQueryなどに投入する大きめのデータをファイルに吐き出して削除してなかった場合などで問題が起きてそう。
Discussion