【LAMP環境】OOM Killerの対処法

こんにちは、技術のTです。
今回は、「OOM Killer(Out of Memory Killer)」について書かせていただきます。
先日、ec2にLAMP環境構築を行っている際、エラーでMySQLを起動できませんでした。
その際に調べたこと・試したこと等を書いていきたいと思います。

環境

– Amazon Linux 2
– Apache:2.4.54
– MySQL:8.0.32
– PHP:7.4.33

参考

1. OOM KIllerとは

OOM Killerとは、

プロセスを実行するためのメモリが物理的に枯渇した場合、カーネルが強制的にプロセスを終了させメモリ確保を行う仕組みのこと

です。

2. OOM Killerの確認方法

私は、以下のコマンドでMySQLの状態とログを確認しました。コマンドの詳細に関しては、また別の機会に書いてみたいと思います。

				
					$systemctl status mysqld.service
				
			
				
					$journalctl -xe
				
			
				
					$cat /var/log/messages | grep Kill
				
			

3. 対処方法

ネットで出てきた解決策は以下の通りでした。

> Swap設定する
> 優先度を設定する
> メモリを拡張する

この中から今回は、「プロセスの優先度を設定する」を試してみました。
優先度とは、メモリ枯渇時にkillされる優先順位のことです。
デフォルトで`0`に設定されており、`-1000`にすることでkill対象外にできるそうです。

4. 試したこと:プロセスの優先度を設定する

プロセスの優先度を変更し、プロセス停止の対象外にしていきます。
まずは、ログを確認。

				
					[ec2-user@xx-xxx-xxx-xxx-xxx ~]$systemctl status mysqld.service
● mysqld.service - MySQL Server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
   Active: activating (start) since Sun 2023-02-19 10:51:15 UTC; 6s ago
     Docs: man:mysqld(8)
           http://dev.mysql.com/doc/refman/en/using-systemd.html
  Process: 3397 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS)
 Main PID: 3421 (mysqld)
   Status: "Server startup in progress"
   CGroup: /system.slice/mysqld.service
           └─3421 /usr/sbin/mysqld

Feb 19 10:51:15 ip-xxx-xx-xx-xxx.ap-northeast-1.compute.internal systemd[1]: Starting MySQL Server...
				
			
				
					[ec2-user@xx-xxx-xxx-xxx-xxx ~]journalctl -xe
(~略~)
Feb 20 12:05:07 ip-xxx-xx-xx-xxx.ap-northeast-1.compute.internal kernel: [  19976]    27 19976   193232    79500   884736        0             0 mysqld
Feb 20 12:05:07 ip-xxx-xx-xx-xxx.ap-northeast-1.compute.internal kernel: oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/,task=mysqld,pid=19976,uid=27
Feb 20 12:05:07 ip-xxx-xx-xx-xxx.ap-northeast-1.compute.internal kernel: Out of memory: Killed process 19976 (mysqld) total-vm:772928kB, anon-rss:318000kB, file-rss:0kB, shmem-rss:0kB, UID:27 pgtables:864kB oom_score_adj:0
Feb 20 12:05:06 ip-xxx-xx-xx-xxx.ap-northeast-1.compute.internal systemd[1]: mysqld.service: main process exited, code=killed, status=9/KILL
Feb 20 12:05:06 ip-xxx-xx-xx-xxx.ap-northeast-1.compute.internal systemd[1]: Failed to start MySQL Server.
-- Subject: Unit mysqld.service has failed
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit mysqld.service has failed.
--
-- The result is failed.
Feb 20 12:05:06 ip-xxx-xx-xx-xxx.ap-northeast-1.compute.internal systemd[1]: Unit mysqld.service entered failed state.
Feb 20 12:05:06 ip-xxx-xx-xx-xxx.ap-northeast-1.compute.internal systemd[1]: mysqld.service failed.
Feb 20 12:05:07 ip-xxx-xx-xx-xxx.ap-northeast-1.compute.internal systemd[1]: mysqld.service holdoff time over, scheduling restart.
Feb 20 12:05:07 ip-xxx-xx-xx-xxx.ap-northeast-1.compute.internal systemd[1]: Stopped MySQL Server.
-- Subject: Unit mysqld.service has finished shutting down
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit mysqld.service has finished shutting down.
Feb 20 12:05:07 ip-xxx-xx-xx-xxx.ap-northeast-1.compute.internal systemd[1]: Starting MySQL Server...
-- Subject: Unit mysqld.service has begun start-up
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit mysqld.service has begun starting up.
				
			
				
					[ec2-user@xx-xxx-xxx-xxx-xxx ~]$cat /var/log/messages | grep Kill
Feb 20 13:06:08 ip-xxx-xx-xx-xxx kernel: Out of memory: Killed process 23939 (mysqld) total-vm:762684kB, anon-rss:317416kB, file-rss:0kB, shmem-rss:0kB, UID:27 pgtables:864kB oom_score_adj:0
Feb 20 13:06:10 ip-xxx-xx-xx-xxx kernel: Out of memory: Killed process 23982 (mysqld) total-vm:762684kB, anon-rss:317780kB, file-rss:0kB, shmem-rss:0kB, UID:27 pgtables:872kB oom_score_adj:0
(~略~)
				
			
次に、対象プロセス(UID : 27)の優先度を確認。
				
					[ec2-user@xx-xxx-xxx-xxx-xxx ~]$cat /proc/27/oom_score_adj
0
				
			
優先度を-1000に変更。
				
					[ec2-user@xx-xxx-xxx-xxx-xxx ~]$echo -1000 > /proc/27/oom_score_adj
				
			
優先度を再度確認。
				
					[ec2-user@xx-xxx-xxx-xxx-xxx ~]$cat /proc/27/oom_score_adj
-1000
				
			
変更されていたので、再度MySQLを起動します。
				
					[ec2-user@xx-xxx-xxx-xxx-xxx ~]$sudo systemctl start mysqld.service
Job for mysqld.service failed because a fatal signal was delivered to the control process. See "systemctl status mysqld.service" and "journalctl -xe" for details.
				
			
起動出来ず。。。 `systemctl status mysqld.service`と`journalctl -xe`を確認してみたところ、優先度変更前と同様の内容が表示されました。 優先度変更したのになぜ。。。

5. 解決策

解決出来ずに途方にくれていたところ、「MySQLのメモリ消費量を改善したら」というアドバイスを先輩に頂きました。`table_definition_cache`変数で設定できるらしい。。。 まずは、`/etc/my.cnf`を開きます。
				
					[ec2-user@xx-xxx-xxx-xxx-xxx ~]$vi /etc/my.cnf
				
			
メモリ消費量を抑えられるように以下の行を追加します。
				
					table_definition_cache=400
				
			
保存し、改めてMySQL Serverを起動してみます。
				
					[ec2-user@xx-xxx-xxx-xxx-xxx ~]$ sudo systemctl start mysqld
				
			
無事、起動。。。 エラー時のログをもう一度じっくり確認したところ、単純にメモリが不足していました。
				
					Feb 20 12:05:07 ip-xx-xxx-xxx-xxx-xxx.ap-northeast-1.compute.internal kernel: Out of memory: Killed process 19976 (mysqld) total-vm:772928kB, anon-rss:318000kB, file-rss:0kB, shmem-rss:0kB, UID:27 pgtables:864kB oom_score_adj:0
Feb 20 12:05:06 ip-xx-xxx-xxx-xxx-xxx.ap-northeast-1.compute.internal systemd[1]: mysqld.service: main process exited, code=killed, status=9/KILL
				
			
`total-vm:772928kB`、`anon-rss:318000kB`とありました。そもそもメモリがなかったら(t2.nanoインスタンスはメモリが500MB)、killする優先度を変更しても意味ないですよね。 ログをもっと隅々まで見る癖を付けたいと思います!

終わりに

最後までお読みいただきありがとうございます。 今回は「OOM Killer」について書かせていただきました。 もしOOM Killerに出会ってしまったら、是非参考にしてみてください!

スーパーソフトウエアの採用情報

あなたが活躍できるフィールドと充実した育成環境があります

blank
blank