Глубокое понимание серии Linux Cgroup (3): память

Linux

Оригинальная ссылка:Глубокое понимание серии Linux Cgroup (3): память

пройти черезПредыдущая статья, мы научились просматривать текущую информацию cgroup, как работать/sys/fs/cgroupкаталог для динамической настройки контрольных групп, а также научился устанавливать доли ЦП и квоты ЦП для управленияsliceвнутри и разныеsliceВремя использования ЦП между. Эта статья будет посвящена памяти и продемонстрирует, как ограничить использование памяти с помощью контрольных групп на конкретных примерах.

1. Найдите потерянную память

В прошлой статье нам рассказали, что контроллер ЦП предоставляет два метода ограничения времени использования ЦП, среди которыхCPUSharesиспользуется для установки относительных весов,CPUQuotaПроцент процессорного времени, используемый для ограничения пользователя, службы или виртуальной машины. Например: если пользователь устанавливает и CPUShares, и CPUQuota, предположим, что для CPUQuota установлено значение50%, затем, пока загрузка ЦП пользователя не достигнет 50%, ЦП можно использовать в соответствии с настройкой CPUShares.

Что касается памяти, в CentOS 7 systemd помог нам связать память с /sys/fs/cgroup/memory.systemdпредоставляется только один параметрMemoryLimitЧтобы управлять им, этот параметр представляет собой общий объем физической памяти, который может использовать пользователь или служба. В качестве примера возьмем предыдущего пользователя tom, его UID равен 1000, что можно установить с помощью следующей команды:

$ systemctl set-property user-1000.slice MemoryLimit=200M

используя пользователя сейчасtomвойти в систему черезstressКоманда порождает 8 дочерних процессов, и каждый процесс выделяет 256 МБ памяти:

$ stress --vm 8 --vm-bytes 256M

Как и ожидалось, использование памяти стрессовым процессом превысило предел, что должно вызватьoom-killer, но процесс на самом деле все еще запущен, почему? Посмотрим на занятую в данный момент память:

$ cd /sys/fs/cgroup/memory/user.slice/user-1000.slice

$ cat memory.usage_in_bytes
209661952

Странно, занятой памяти меньше 200М, куда девается остальная память? Не паникуйте, помните ли вы, что использование памяти в системе Linux включает не только физическую память, но и раздел подкачки, который является подкачкой, давайте посмотрим, является ли подкачка призраком. Прямо сейчас остановите процесс стресса, подождите 30 секунд и наблюдайте за занятостью пространства подкачки:

$ free -h
              total        used        free      shared  buff/cache   available
Mem:           3.7G        180M        3.2G        8.9M        318M        3.3G
Swap:          3.9G        512K        3.9G

Повторно запустите стресс-процесс:

$ stress --vm 8 --vm-bytes 256M

Проверьте использование памяти:

$ cat memory.usage_in_bytes
209637376

Установлено, что использование памяти находится всего в пределах 200M. Посмотрите на использование пространства подкачки:

$ free
              total        used        free      shared  buff/cache   available
Mem:        3880876      407464     3145260        9164      328152     3220164
Swap:       4063228     2031360     2031868

По сравнению с тем, что было сейчас, более2031360-512=2030848k, теперь в основном очевидно, что когда использование процесса достигает предела, ядро ​​попытается переместить данные из физической памяти в пространство подкачки, чтобы выделение памяти прошло успешно. Мы можем точно рассчитать общий объем физической памяти + пространство подкачки, используемое пользователем tom.Во-первых, нам нужно отдельно проверить использование физической памяти и пространства подкачки пользователем tom:

$ egrep "swap|rss" memory.stat
rss 209637376
rss_huge 0
swap 1938804736
total_rss 209637376
total_rss_huge 0
total_swap 1938804736

Вы можете видеть, что использование физической памяти209637376байт, использование пространства подкачки1938804736байт, всего(209637376+1938804736)/1024/1024=2048М. Общий объем памяти, необходимый стресс-процессу, равен256*8=2048м, оба равны.

В этот момент, если вы будете проверять каждые несколько секундmemory.failcntфайл, вы обнаружите, что значение в этом файле увеличивается:

$ cat memory.failcnt
59390293

Из вышеприведенных результатов видно, что при нехватке физической памяти число в memory.failcnt будет увеличено на 1, но процесс в это время не обязательно будет убит, ядро ​​попытается переместить данные в физическую память в середину пространства подкачки.

2. Закрыть своп

Чтобы лучше наблюдать за контролем памяти со стороны cgroup, мы можем использовать пользователя tom, чтобы не использовать пространство подкачки.Для этого есть несколько способов:

  1. будетmemory.swappinessЗначение файла изменено на 0:

    $ echo 0 > /sys/fs/cgroup/memory/user.slice/user-1000.slice/memory.swappiness
    

    После завершения этой настройки текущая контрольная группа не будет использовать пространство подкачки, даже если система включила пространство подкачки.

  2. Закройте пространство Swap System непосредственно:

    $ swapoff -a
    

    Если вы хотите сделать его постоянным, также закомментируйте/etc/fstabобмен в файле.

Первый метод, приведенный выше, проблематичен, если вы не хотите закрывать пространство подкачки системы, но также хотите, чтобы он не использовал пространство подкачки:

  • Вы можете изменить его только тогда, когда пользователь tom вошел в систему.memory.swappinessфайл, потому что если пользователь tom не войдет в систему, текущая контрольная группа исчезнет.
  • даже если вы изменитеmemory.swappinessЗначение файла также будет недействительным после повторного входа в систему.

Если мы решим эту проблему в соответствии с традиционным мышлением, это может быть очень сложно, мы можем найти другой путь и начать с PAM.

Linux PAM(Pluggable Authentication Modules) представляет собой инфраструктуру аутентификации пользователей на системном уровне, PAM разделяет методы разработки программ и методы аутентификации, а программа вызывает дополнительный модуль «аутентификации» для завершения своей работы во время выполнения. Локальный системный администратор настраивает, какие модули аутентификации использовать, где/etc/pam.d/Каталог специально используется для хранения конфигурации PAM, которая используется для установки независимых методов аутентификации для определенных приложений. Например, когда пользователь входит в систему через ssh, он загружает/etc/pam.d/sshdстратегия внутри.

от/etc/pam.d/sshdДля начала мы можем начать с создания сценария оболочки:

$ cat /usr/local/bin/tom-noswap.sh
#!/bin/bash

if [ $PAM_USER == 'tom' ]
  then
    echo 0 > /sys/fs/cgroup/memory/user.slice/user-1000.slice/memory.swappiness
fi

затем в/etc/pam.d/sshdвызвать скрипт через pam_exec в/etc/pam.d/sshdВ конце добавьте строку следующего содержания:

$ session optional pam_exec.so seteuid /usr/local/bin/tom-noswap.sh

Теперь войдите в систему с пользователем tom, и вы обнаружите, чтоmemory.swappinessзначение становится 0.

Здесь есть предпосылка, на которую следует обратить внимание: существует по крайней мере одна сессия входа в систему для пользователя tom, иsystemctl set-property user-1000.slice MemoryLimit=200MКоманда устанавливает лимит,/sys/fs/cgroup/memory/user.slice/user-1000.sliceкаталог существует. Поэтому для всех вышеперечисленных операций обязательно сохраните хотя бы один сеанс входа пользователя tom.

3. Контролируйте использование памяти

После закрытия свопа мы можем строго контролировать использование памяти процессом. Все еще используя пример, упомянутый в начале, войдите в систему как пользователь tom и сначала выполните следующую команду в первом окне оболочки:

$ journalctl -f

Откройте второе окно оболочки (по-прежнему пользователь tom) и создайте 8 дочерних процессов с помощью команды stress, каждому из которых выделено 256 МБ памяти:

$ stress --vm 8 --vm-bytes 256M
stress: info: [30150] dispatching hogs: 0 cpu, 0 io, 8 vm, 0 hdd
stress: FAIL: [30150] (415) <-- worker 30152 got signal 9
stress: WARN: [30150] (417) stress: FAIL: [30150] (415) <-- worker 30151 got signal 9
stress: WARN: [30150] (417) now reaping child worker processes
stress: FAIL: [30150] (415) <-- worker 30154 got signal 9
stress: WARN: [30150] (417) now reaping child worker processes
stress: FAIL: [30150] (415) <-- worker 30157 got signal 9
stress: WARN: [30150] (417) now reaping child worker processes
stress: FAIL: [30150] (415) <-- worker 30158 got signal 9
stress: WARN: [30150] (417) now reaping child worker processes
stress: FAIL: [30150] (451) failed run completed in 0s

Теперь вы можете видеть, что стресс-процесс быстро убит, и обратно в первое окно оболочки будет выведена следующая информация:

Видно, что лимит памяти cgroup сработал, использование памяти стресс-процессом превышает лимит, что приводит к срабатыванию oom-killer и уничтожению процесса.

4. Дополнительная документация

Добавьте небольшой эпизод, если вы хотите получить дополнительную документацию о CGroups, вы можете установить его через yumkernel-docМешок. После завершения установки вы можете войти/usr/share/docsподкаталоги, см. подробную документацию для каждого контроллера cgroup.

$ cd /usr/share/doc/kernel-doc-3.10.0/Documentation/cgroups
$ ll
总用量 172
 4 -r--r--r-- 1 root root   918 6月  14 02:29 00-INDEX
16 -r--r--r-- 1 root root 16355 6月  14 02:29 blkio-controller.txt
28 -r--r--r-- 1 root root 27027 6月  14 02:29 cgroups.txt
 4 -r--r--r-- 1 root root  1972 6月  14 02:29 cpuacct.txt
40 -r--r--r-- 1 root root 37225 6月  14 02:29 cpusets.txt
 8 -r--r--r-- 1 root root  4370 6月  14 02:29 devices.txt
 8 -r--r--r-- 1 root root  4908 6月  14 02:29 freezer-subsystem.txt
 4 -r--r--r-- 1 root root  1714 6月  14 02:29 hugetlb.txt
16 -r--r--r-- 1 root root 14124 6月  14 02:29 memcg_test.txt
36 -r--r--r-- 1 root root 36415 6月  14 02:29 memory.txt
 4 -r--r--r-- 1 root root  1267 6月  14 02:29 net_cls.txt
 4 -r--r--r-- 1 root root  2513 6月  14 02:29 net_prio.txt

В следующей статье мы обсудим, как использовать контрольные группы для ограничения ввода-вывода, так что следите за обновлениями~