Почему на сервере Hetzner медленно работает диск

Заметил внезапное снижение производительности на одном из CentOS 7 серверов и не менее внезапное появление ошибок 502 Bad Gateway, которых даже во время хорошей нагрузки ни разу не было, а тут ночью во время простоя вдруг начали валить. Первым делом стал смотреть вывод iostat -x 3:

Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sdb 58.00 8.33 1614.33 0.33 107477.33 34.67 133.17 4.32 2.63 2.63 33.00 0.35 56.80
sda 79.33 8.33 1600.00 0.00 108074.67 0.00 135.09 29.38 18.14 18.14 0.00 0.62 100.00
md2 0.00 0.00 0.00 8.67 0.00 34.67 8.00 0.00 0.00 0.00 0.00 0.00 0.00
md0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
md1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
md3 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

Кто-то со страшной силой читает данные с диска со скоростью 100+ Мб/с, как видно, значение столбца rkB/s 107477.33 и 108074.67 для каждого из дисков в софт-рейде. Первым делом стал грешить на Docker, мало ли что происходит в одном из сотни контейнеров. Вполне мог задеплоиться кривой или дырявый релиз софта, однако Docker оказался не причём.

Решил посмотреть детализацию нагрузки по процессам, однако iotop ничего интересного не показал. Говорит что никто IO не грузит! Load average также в пределах 1-2, что не много для 8-ядерного процессора.

Стал постепенно и методично отключать по-одному сервисы, крутящиеся в docker-контейнерах, вплоть до полной остановки Docker. Однако нагрузка на чтение с диска осталась.

Стал внимательно изучать список всех оставшихся процессов (ps aux) на предмет аномалий, однако, тоже всё в порядке, за исключением неизвестной мне команды: /bin/bash /usr/sbin/raid-check. Но я её не запускал! Да и кто-то другой запустить её не мог. Оказалось, что есть интересный cron-файл /etc/cron.d/raid-check:

# Run system wide raid-check once a week on Sunday at 1am by default
0 1 * * Sun root /usr/sbin/raid-check

Который запускает каждое воскресенье в час ночи этот скрипт. Немного успокоился. Стал изучать скрипт /usr/sbin/raid-check, он берёт настройки из файла /etc/sysconfig/raid-check, заодно посмотрел и его:

#!/bin/bash
#
# Configuration file for /etc/cron.weekly/raid-check
#
# options:
#       ENABLED - must be yes in order for the raid check to proceed
#       CHECK - can be either check or repair depending on the type of
#               operation the user desires.  A check operation will scan
#               the drives looking for bad sectors and automatically
#               repairing only bad sectors.  If it finds good sectors that
#               contain bad data (meaning that the data in a sector does
#               not agree with what the data from another disk indicates
#               the data should be, for example the parity block + the other
#               data blocks would cause us to think that this data block
#               is incorrect), then it does nothing but increments the
#               counter in the file /sys/block/$dev/md/mismatch_count.
#               This allows the sysadmin to inspect the data in the sector
#               and the data that would be produced by rebuilding the
#               sector from redundant information and pick the correct
#               data to keep.  The repair option does the same thing, but
#               when it encounters a mismatch in the data, it automatically
#               updates the data to be consistent.  However, since we really
#               don't know whether it's the parity or the data block that's
#               correct (or which data block in the case of raid1), it's
#               luck of the draw whether or not the user gets the right
#               data instead of the bad data.  This option is the default
#               option for devices not listed in either CHECK_DEVS or
#               REPAIR_DEVS.
#       CHECK_DEVS - a space delimited list of devs that the user specifically
#               wants to run a check operation on.
#       REPAIR_DEVS - a space delimited list of devs that the user
#               specifically wants to run a repair on.
#       SKIP_DEVS - a space delimited list of devs that should be skipped
#       NICE - Change the raid check CPU and IO priority in order to make
#               the system more responsive during lengthy checks.  Valid
#               values are high, normal, low, idle.
#       MAXCONCURENT - Limit the number of devices to be checked at a time.
#               By default all devices will be checked at the same time.
#
# Note: the raid-check script intentionaly runs last in the cron.weekly
# sequence.  This is so we can wait for all the resync operations to complete
# and then check the mismatch_count on each array without unduly delaying
# other weekly cron jobs.  If any arrays have a non-0 mismatch_count after
# the check completes, we echo a warning to stdout which will then me emailed
# to the admin as long as mails from cron jobs have not been redirected to
# /dev/null.  We do not wait for repair operations to complete as the
# md stack will correct any mismatch_cnts automatically.
#
# Note2: you can not use symbolic names for the raid devices, such as you
# /dev/md/root.  The names used in this file must match the names seen in
# /proc/mdstat and in /sys/block.
ENABLED=yes
CHECK=check
NICE=low
# To check devs /dev/md0 and /dev/md3, use "md0 md3"
CHECK_DEVS=""
REPAIR_DEVS=""
SKIP_DEVS=""
MAXCONCURRENT=

Скрипт /usr/sbin/raid-check является частью mdadm, еженедельной запускаемый через cron для проверки raid-массива. После проверки он возвращает результат из /sys/block/*/md/mismatch_cnt.

Стало интересно, долго ли будет ещё продолжаться raid-check. Нашёл команду (cat /proc/mdstat) которая выводит статус:

Personalities : [raid1]
md3 : active raid1 sdb4[1] sda4[0]
      1839090112 blocks super 1.2 [2/2] [UU]
      [==============>......]  check = 72.6% (1336906432/1839090112) finish=81.6min speed=102523K/sec
      bitmap: 0/14 pages [0KB], 65536KB chunk
md1 : active raid1 sdb2[1] sda2[0]
      523712 blocks super 1.2 [2/2] [UU]
        resync=DELAYED
md0 : active raid1 sdb1[1] sda1[0]
      16760832 blocks super 1.2 [2/2] [UU]
        resync=DELAYED
md2 : active raid1 sdb3[1] sda3[0]
      1073610752 blocks super 1.2 [2/2] [UU]
        resync=DELAYED
      bitmap: 4/8 pages [16KB], 65536KB chunk
unused devices: <none>

Как можно заметить, значение speed=102523K/sec с точностью совпадает с данными по чтению из iostat. Получается, что этот raid-check утилизировал ресурс диска на 100%. Нужна ли мне эта еженедельная проверка рейда ещё для себя не решил. Но раз она настроена по-умолчанию, отключать без крайней необходимости не стал. Но на всякий случай в файле /etc/sysconfig/raid-check понизил приоритет NICE с low на idle.