🐬
MySQL コンテナのメモリドカ食いをとりあえずなんとかする
ある日突然、MySQL の Docker コンテナがめちゃくちゃメモリを消費するようになったので、その対応のメモです。
現象
- Docker Compose で設定していた MySQL のサービスを up しようとしたら、やけに遅い。
- メモリを大量に消費していることに気づく。25GB / 32GB くらい。
環境
- ホスト Linux
$ uname -a
Linux x1-carbon-gen10-arch 6.2.2-arch1-1 #1 SMP PREEMPT_DYNAMIC Fri, 03 Mar 2023 15:58:31 +0000 x86_64 GNU/Linux
$ cat /etc/os-release
NAME="Arch Linux"
PRETTY_NAME="Arch Linux"
ID=arch
BUILD_ID=rolling
ANSI_COLOR="38;2;23;147;209"
HOME_URL="https://archlinux.org/"
DOCUMENTATION_URL="https://wiki.archlinux.org/"
SUPPORT_URL="https://bbs.archlinux.org/"
BUG_REPORT_URL="https://bugs.archlinux.org/"
PRIVACY_POLICY_URL="https://terms.archlinux.org/docs/privacy-policy/"
LOGO=archlinux-logo
- systemd
$ systemctl --version
systemd 253 (253.1-1-arch)
+PAM +AUDIT -SELINUX -APPARMOR -IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY +P11KIT -QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK +XKBCOMMON +UTMP -SYSVINIT default-hierarchy=unified
- Docker
$ docker version
Client:
Version: 23.0.1
API version: 1.42
Go version: go1.20
Git commit: a5ee5b1dfc
Built: Sat Feb 11 13:58:04 2023
OS/Arch: linux/amd64
Context: default
Server:
Engine:
Version: 23.0.1
API version: 1.42 (minimum version 1.12)
Go version: go1.20
Git commit: bc3805a0a0
Built: Sat Feb 11 13:58:04 2023
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: v1.6.19
GitCommit: 1e1ea6e986c6c86565bc33d52e34b81b3e2bc71f.m
runc:
Version: 1.1.4
GitCommit:
docker-init:
Version: 0.19.0
GitCommit: de40ad0
- MySQL イメージタグ:
5.7
原因
コンテナ内のファイルディスクリプタの設定値が大きすぎて遅くなっていた可能性が高い。
詳しいこと
調査中…
とりあえず頑張って起動したコンテナに入って ulimit
で確認すると、約10億程度の数値でした。
# ulimit -Sn
1073741816
# ulimit -Hn
1073741816
やったこと
ファイルディスクリプタの上限値を適当な値に制限します。
やり方 - 1
デーモンの設定ファイルを作成(編集)します。
$ sudo vi /etc/docker/daemon.json
{
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 4096,
"Soft": 4096
}
}
}
再起動します。
$ sudo systemctl restart docker
やり方 - 2
昔のドキュメントに書かれていて、今は先述の方法になっていたので、多分古い方法です。
$ sudo vi /etc/default/docker
DOCKER_OPTS="--default-ulimit nofile=4096:4096"
systemd で動かしている Docker の場合、サービスの設定も必要です。
EnvironmentFile
に、先ほど作った /etc/default/docker
を指定します。
$ sudo vi /etc/systemd/system/docker.service.d/docker.conf
[Service]
EnvironmentFile=-/etc/default/docker
ExecStart=
ExecStart=/usr/sbin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock $DOCKER_OPTS
1つ目の ExecStart=
でデフォルト設定を無効化し、2つ目で上書きします。
dockerd
の場所は環境によって異なるので、調整します。
$ which dockerd
/usr/sbin/dockerd
デーモンの設定ファイルをリロードし、再起動します。
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
これが正常に起動し、EnvironmentFiles
の設定が正しく入って入れば OK です。
$ systemctl show docker | grep EnvironmentFile
EnvironmentFiles=/etc/default/docker (ignore_errors=yes)
参考
- Really high memory usage · Issue #579 · docker-library/mysql
- Bug #1839527 “mysqld eats more than 16 GB of memory on startup” : Bugs : mysql-5.7 package : Ubuntu
- 1.5.10 causes memory leak in mysql container; regression from 1.4.13 · Issue #6707 · containerd/containerd
- docker container has a too large file descriptor limit (ulimit -n) - Stack Overflow
- dockerd
- dockerd daemon — Docker-docs-ja 20.10 ドキュメント
- systemd で Docker の制御 — Docker-docs-ja 20.10 ドキュメント
- 20200123: docker - systemd に /etc/default/docker が反映されない - PIB
Discussion