Docker+MariaDB+WordPress服务器Crash问题修复

这个问题在我购买的腾讯云轻量应用服务器上频繁出现,往往是粘贴一个屏幕截图或者手机端上传一个图片时,服务器突然卡死,需要好一会儿才能恢复。轻量应用服务器的配置真的很一般,不过我仅是用作博客记录,所以应该是够用的,至少在之前使用lnmp框架时,几乎没有出什么问题。但是换用docker之后,就频繁出现了上述的情况,使我一度怀疑遭受了黑客的攻击。

经过查询得知应该是MariaDB对内存资源占用太高导致的,因为轻量服务器的内存实在是太小了只有1GB,所以即便是开一个站点其资源消耗就已经够呛了。因此解决方案在于如何优化Mariadb的内存占用。

限定容器(Container)的资源消耗

Docker中的每一个容器都可以设定其对内存资源和CPU的消耗上限,在使用docker compose工具的情况下其设置返利如下:

service:
  image: nginx
  mem_limit: 512m
  mem_reservation: 128M
  cpus: 0.5
  ports:
    - "80:80"

对于1GB的可怜内存,我将Mariadb的内存设定在了200MB,保留内存(mem_reservation)设置为其一半。经过测试如果限定内存为128MB时,数据库服务不会成功启动。同时我们也需要按照同样方法对wordpress容器做出限制,我将其内存限制设定在了256MB。

最低配置Mariadb

如果使用数据库默认配置,其对CPU和内存的占用要求数倍于当前的配置,因此我们需要修改/etc/mysql/my.cnf降低(minimum)其配置。因此我们需要建立一个.cnf文件匹配容器中的配置文件。

   my_app_db:
      image: mariadb:latest
      mem_limit: 200M
      mem_reservation: 100M
      cpus: 0.5
      container_name: app_db
      volumes:
        - ./mysql:/var/lib/mysql
        - ./my.cnf:/etc/mysql/my.cnf
      restart: always

至于.cnf文件中的内容,我们可以配置如下:

# The MariaDB configuration file
#
# The MariaDB/MySQL tools read configuration files in the following order:
# 0. "/etc/mysql/my.cnf" symlinks to this file, reason why all the rest is read.
# 1. "/etc/mysql/mariadb.cnf" (this file) to set global defaults,
# 2. "/etc/mysql/conf.d/*.cnf" to set global options.
# 3. "/etc/mysql/mariadb.conf.d/*.cnf" to set MariaDB-only options.
# 4. "~/.my.cnf" to set user-specific options.
#
# If the same option is defined multiple times, the last one will apply.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# If you are new to MariaDB, check out https://mariadb.com/kb/en/basic-mariadb-articles/

#
# This group is read both by the client and the server
# use it for options that affect everything
#
[client-server]
# Port or socket location where to connect
# port = 3306
socket = /run/mysqld/mysqld.sock

# Import all .cnf files from configuration directory
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mariadb.conf.d/

# /etc/my.cnf:
# http://www.tocker.ca/2014/03/10/configuring-mysql-to-use-minimal-memory.html
innodb_buffer_pool_size=5M
innodb_log_buffer_size=256K
query_cache_size=0
max_connections=10
key_buffer_size=8
thread_cache_size=0
host_cache_size=0
innodb_ft_cache_size=1600000
innodb_ft_total_cache_size=32000000

# per thread or per operation settings
thread_stack=131072
sort_buffer_size=32K
read_buffer_size=8200
read_rnd_buffer_size=8200
max_heap_table_size=16K
tmp_table_size=1K
bulk_insert_buffer_size=0
join_buffer_size=128
net_buffer_length=1K
innodb_sort_buffer_size=64K

#settings that relate to the binary log (if enabled)
binlog_cache_size=4K
binlog_stmt_cache_size=4K

在StackOverflow相关问题中,有提到关闭 performance_schema,但是很遗憾我没有找到进行修改的位置。一说应该如上在/etc/mysql/my.cnf中设置,但是我无论添加performance_schema=off还是performance_schema=0都会导致数据库服务启动不成功。不过目前看似问题已经解决,留待以后遇到问题再行调整。

Docker查看容器状态

通过docker stats可以查看各个容器对资源的消耗情况。

@2022.10.06 问题并没有解决,当我从手机端上传图片的时候

文件上传未提示成功且服务器处于卡死状态:一开始我以为只有手机端才会有这个问题,后来发现从浏览器网页端同样会出现这个问题。查看系统日志:var/log/syslog,没发现明确提示,但是总在宕机时间段附近有几个反复出现的字符qcloudYunJing,于是一番搜索原来这是腾讯云的云服务器安全监控组件,搜索资料查证其对服务器资源的消耗着实影响不小。于是使用下述代码进行卸载:

/usr/local/qcloud/stargate/admin/uninstall.sh
/usr/local/qcloud/YunJing/uninst.sh
/usr/local/qcloud/monitor/barad/admin/uninstall.sh

或者使用如下的代码

chmod +x /usr/local/qcloud/YunJing/YDService
/usr/local/qcloud/YunJing/YDService stop
rm -rf /usr/local/qcloud

然后验证是否卸载干净,使用下述代码如无任何输出返回则表明已经卸载干净。

ps -A | grep agent

但是我使用了上面的代码仍然有一行返回值,不过通过登录后台法先确已关闭云监控。

root@VM-8-2-debian:~# ps -A | grep agent
    660 ?        00:00:00 tat_agent
登录腾讯云后台可以看见重新安装的提示,可千万别再装了我的大爷

将腾讯云监控的组件关闭后,终于,上传媒体文件就不再引发宕机现象了。不过在手机端上传一些尺寸大于2mb的图片仍然提示失败,说明不能顺利上传图片不仅仅是因为腾讯云监控组件对资源的消耗。

WordPress ios APP上传文件失败的界面截图
文件确已上传,且写入数据库,但并没有产生缩略图

WordPress ios APP上传文件提示失败,但是到wordpress的uploads文件中查看,该文件确实已经传上去了,但是却没有产生任何尺寸的缩略图,这意味着在php发挥作用裁切图片之前该服务就已经停止了。查看手机端,报错提示为http 502

于是又去翻查系统日志,在错误出现的时间给出了 Memory cgroup out of memery提示,这意思就是内存不够了。

出现该问题的原因,是实际内存超出了容器内存的限制,一想起之前对wordpress的服务内存限制在256MB,于是赶紧修改调整到512MB,重启容器在上传手机拍摄的图片就没有上传失败的提示了

      mem_limit: 512M
      mem_reservation: 256M

那么将限制内存调整到了512MB,可以上传的最大文件大小是多少呢?在网页端上传100MB左右的视频都没有问题,但在手机端上传HLG格式视频无法成功(在网页端是可以成功上传的,但是默认播放器只闻其声而无法播放画面)。

参考资料:

k8s Memory cgroup out of memory: Kill process
卸载腾讯云服务器安全监控组件