Это четвертая статья из серии Cgroup, обзор прошлых выпусков:
- Начало работы с Cgroups в Linux: основные понятия
- Начало работы с Cgroups в Linux: ЦП
- Начало работы с Cgroups в Linux: память
пройти черезПредыдущая статья, мы научились просматривать текущую информацию cgroup, как работать/sys/fs/cgroup
каталог для динамической настройки контрольных групп, а также научился устанавливать доли ЦП и квоты ЦП для управленияslice
внутри и разныеslice
Время использования ЦП между. В этой статье мы продолжим изучение ограничений на время использования ЦП.
Для некоторых программ, интенсивно использующих ЦП, необходимо не только получить больше времени использования ЦП, но и уменьшить переключение контекста, вызванное рабочей нагрузкой при регулировании. В современных многоядерных системах каждое ядро имеет собственный кеш, и если процесс частого планирования выполняется на разных ядрах, это неизбежно приведет к накладным расходам, таким как аннулирование кеша. Так есть ли способ изолировать ядра процессора? Чтобы быть точным, запущенный процесс привязан к указанному ядру для запуска. Хотя все программы созданы равными операционной системе,Но некоторые программы более равны, чем другие.
Для тех более равных программ нам нужно выделять больше ресурсов процессора, ведь люди очень эксцентричны. Без лишних слов, давайте посмотрим, как использоватьcgroup
Ограничивает процесс от использования указанных ядер ЦП.
1. Просмотр конфигурации ЦП
Нумерация ядер ЦП обычно начинается с 0, а диапазон нумерации 4 ядер составляет0-3
. Мы можем видеть/proc/cpuinfo
чтобы определить некоторую информацию о процессоре:
$ cat /proc/cpuinfo
...
processor : 3
vendor_id : GenuineIntel
cpu family : 6
model : 26
model name : Intel(R) Xeon(R) CPU X5650 @ 2.67GHz
stepping : 4
microcode : 0x1f
cpu MHz : 2666.761
cache size : 12288 KB
physical id : 6
siblings : 1
core id : 0
cpu cores : 1
apicid : 6
initial apicid : 6
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc eagerfpu pni ssse3 cx16 sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer hypervisor lahf_lm ssbd ibrs ibpb stibp tsc_adjust arat spec_ctrl intel_stibp flush_l1d arch_capabilities
bogomips : 5333.52
clflush size : 64
cache_alignment : 64
address sizes : 43 bits physical, 48 bits virtual
-
processor
: указывает номер ядра, но это не ядро физического ЦП, точнее его можно назвать **номер логического ядра. -
physical id
: Указывает ядро физического ЦП, на котором расположено текущее логическое ядро, также пронумерованное от 0, что означает, что это логическое ядро находится на 7-м физическом ЦП. -
core id
: Если это значение больше 0, обратите внимание, возможно, на вашем сервере включена гиперпоточность. Если гиперпоточность включена, каждое физическое ядро ЦП будет эмулировать 2 потока, также называемых логическими ядрами (которые отличаются от логических ядер выше, но имеют одно и то же имя). Если вы хотите подтвердить, включена ли на сервере гиперпоточность, вы можете проверить это с помощью следующей команды:
$ cat /proc/cpuinfo | grep -e "core id" -e "physical id"
physical id : 0
core id : 0
physical id : 2
core id : 0
physical id : 4
core id : 0
physical id : 6
core id : 0
еслиphysical id
а такжеcore id
все так жеprocessor
Если он появляется дважды, можно сделать вывод, что гиперпоточность включена. Видимо мой сервер не работает.
2. Архитектура NUMA
Есть такое понятиеNUMA (неоднородный доступ к памяти),СейчасНеоднородная архитектура доступа к памяти. Если к материнской плате подключено несколько процессоров,NUMA
Архитектура. Каждый ЦП занимает отдельную область и обычно имеет независимый вентилятор.
ОдинNUMA
Узел включает аппаратные устройства, такие как ЦП и память, непосредственно подключенные к области.PCI-E
. Это также вводит понятие близости ЦП, то есть ЦП обращается к одному и тому жеNUMA
Память на узле быстрее, чем доступ к другому узлу.
Вы можете просмотреть архитектуру NUMA машины с помощью следующей команды:
$ numactl --hardware
available: 1 nodes (0)
node 0 cpus: 0 1 2 3
node 0 size: 2047 MB
node 0 free: 1335 MB
node distances:
node 0
0: 10
Видно, что сервер не используетсяNUMA
Архитектура, всего однаNUMA
Узел, то есть есть только один ЦП, и все 4 логических ядра находятся на этом ЦП.
3. isolcpus
Одной из самых важных обязанностей Linux является планирование процессов, а процесс — это просто абстракция процесса запуска программы, которая выполняет серию инструкций, и компьютер следует этим инструкциям, чтобы завершить фактическую работу. С аппаратной точки зрения именно центральный процессор или ЦП фактически выполняет эти инструкции. По умолчанию планировщик процессов может запланировать процесс на любое из ядер ЦП, поскольку он уравновешивает распределение вычислительных ресурсов в зависимости от нагрузки.
Чтобы увеличить видимый эффект эксперимента, можно изолировать определенные логические ядра, чтобы система никогда не использовала эти ядра по умолчанию, если я не укажу определенные процессы для их использования. Для этого используйте параметр ядраisolcpus
Например: если вы хотите, чтобы система по умолчанию не использовала логические ядра 2, 3 и 4, вы можете добавить в список параметров ядра следующее:
isolcpus=1,2,3
# 或者
isolcpus=1-3
Для CnetOS 7 его можно изменить напрямую/etc/default/grub
:
$ cat /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet isolcpus=1,2,3"
GRUB_DISABLE_RECOVERY="true"
затем перестроитьgrub.conf
:
$ grub2-mkconfig -o /boot/grub2/grub.cfg
После перезагрузки система больше не будет использовать логические ядра 2, 3 и 4, будет использоваться только ядро 1. Найдите программу для загрузки процессора (Предыдущая статьяпрограмма), используйте команду top для просмотра загрузки ЦП:
воплощать в жизнь
top
После команды нажмите клавишу с цифрой 1 на странице списка, чтобы увидеть все процессоры.
Вы можете видеть, что система использует только ядро 1. Давайте посмотрим, как привязать программу к определенному ядру процессора.
4. Создайте контрольную группу
Привязать программу к указанному ядру на самом деле очень просто, достаточно установитьcpuset
Контроллер подойдет.systemctl
может управлять ресурсами, находящимися под его контролемcgroup
Контроллеры, но может управлять только ограниченным количеством контроллеров (ЦП, Память и BlockIO) и не может управлятьcpuset
контроллер. Несмотря на то чтоsystemd
Он не поддерживает cpuset, но я думаю, что он будет поддерживаться в будущем.Кроме того, есть немного неуклюжий метод, который может достичь той же цели, который будет представлен позже.
Все операции, связанные с cgroup, основаны на виртуальной файловой системе cgroup в ядре.Использовать cgroup очень просто, просто смонтируйте файловую систему. По умолчанию файловая система монтируется в/sys/fs/cgroup
каталог, взгляните на этот каталог:
$ ll /sys/fs/cgroup
总用量 0
drwxr-xr-x 2 root root 0 3月 28 2020 blkio
lrwxrwxrwx 1 root root 11 3月 28 2020 cpu -> cpu,cpuacct
lrwxrwxrwx 1 root root 11 3月 28 2020 cpuacct -> cpu,cpuacct
drwxr-xr-x 2 root root 0 3月 28 2020 cpu,cpuacct
drwxr-xr-x 2 root root 0 3月 28 2020 cpuset
drwxr-xr-x 4 root root 0 3月 28 2020 devices
drwxr-xr-x 2 root root 0 3月 28 2020 freezer
drwxr-xr-x 2 root root 0 3月 28 2020 hugetlb
drwxr-xr-x 2 root root 0 3月 28 2020 memory
lrwxrwxrwx 1 root root 16 3月 28 2020 net_cls -> net_cls,net_prio
drwxr-xr-x 2 root root 0 3月 28 2020 net_cls,net_prio
lrwxrwxrwx 1 root root 16 3月 28 2020 net_prio -> net_cls,net_prio
drwxr-xr-x 2 root root 0 3月 28 2020 perf_event
drwxr-xr-x 2 root root 0 3月 28 2020 pids
drwxr-xr-x 4 root root 0 3月 28 2020 systemd
можно увидетьcpuset
Контроллеры уже созданы и смонтированы по умолчанию. посмотриcpuset
Что есть в каталоге:
$ ll /sys/fs/cgroup/cpuset
总用量 0
-rw-r--r-- 1 root root 0 3月 28 2020 cgroup.clone_children
--w--w--w- 1 root root 0 3月 28 2020 cgroup.event_control
-rw-r--r-- 1 root root 0 3月 28 2020 cgroup.procs
-r--r--r-- 1 root root 0 3月 28 2020 cgroup.sane_behavior
-rw-r--r-- 1 root root 0 3月 28 2020 cpuset.cpu_exclusive
-rw-r--r-- 1 root root 0 3月 28 2020 cpuset.cpus
-r--r--r-- 1 root root 0 3月 28 2020 cpuset.effective_cpus
-r--r--r-- 1 root root 0 3月 28 2020 cpuset.effective_mems
-rw-r--r-- 1 root root 0 3月 28 2020 cpuset.mem_exclusive
-rw-r--r-- 1 root root 0 3月 28 2020 cpuset.mem_hardwall
-rw-r--r-- 1 root root 0 3月 28 2020 cpuset.memory_migrate
-r--r--r-- 1 root root 0 3月 28 2020 cpuset.memory_pressure
-rw-r--r-- 1 root root 0 3月 28 2020 cpuset.memory_pressure_enabled
-rw-r--r-- 1 root root 0 3月 28 2020 cpuset.memory_spread_page
-rw-r--r-- 1 root root 0 3月 28 2020 cpuset.memory_spread_slab
-rw-r--r-- 1 root root 0 3月 28 2020 cpuset.mems
-rw-r--r-- 1 root root 0 3月 28 2020 cpuset.sched_load_balance
-rw-r--r-- 1 root root 0 3月 28 2020 cpuset.sched_relax_domain_level
-rw-r--r-- 1 root root 0 3月 28 2020 notify_on_release
-rw-r--r-- 1 root root 0 3月 28 2020 release_agent
-rw-r--r-- 1 root root 0 3月 28 2020 tasks
В этом каталоге есть только конфигурация по умолчанию, без какой-либо подсистемы cgroup. Далее мы создаемcpuset
подсистемы и установить соответствующие параметры привязки:
$ mkdir -p /sys/fs/cgroup/cpuset/test
$ echo "3" > /sys/fs/cgroup/cpuset/test/cpuset.cpus
$ echo "0" > /sys/fs/cgroup/cpuset/test/cpuset.mems
Сначала создайте подсистему cpuset с именемtest
, затем привяжите ядро 4 к этой подсистеме, т.е.cpu3
. заcpuset.mems
По параметрам каждый узел памяти иNUMA
Узлы соответствуют один к одному. Если требования к памяти процесса велики, вы можете поместить всеNUMA
В него настраиваются узлы. используется здесьNUMA
Концепция чего-либо. Из соображений производительности сконфигурированные логические ядра и узлы памяти обычно принадлежат одному и тому же серверу.NUMA
узел, доступныйnumactl --hardware
Команда изучает их отношение отображения. Видимо мой хост не используетNUMA
схемы, просто установите для нее узел 0.
Проверятьtest
содержание:
$ cd /sys/fs/cgroup/cpuset/test
$ ll
总用量 0
-rw-rw-r-- 1 root root 0 3月 28 17:07 cgroup.clone_children
--w--w---- 1 root root 0 3月 28 17:07 cgroup.event_control
-rw-rw-r-- 1 root root 0 3月 28 17:07 cgroup.procs
-rw-rw-r-- 1 root root 0 3月 28 17:07 cpuset.cpu_exclusive
-rw-rw-r-- 1 root root 0 3月 28 17:07 cpuset.cpus
-r--r--r-- 1 root root 0 3月 28 17:07 cpuset.effective_cpus
-r--r--r-- 1 root root 0 3月 28 17:07 cpuset.effective_mems
-rw-rw-r-- 1 root root 0 3月 28 17:07 cpuset.mem_exclusive
-rw-rw-r-- 1 root root 0 3月 28 17:07 cpuset.mem_hardwall
-rw-rw-r-- 1 root root 0 3月 28 17:07 cpuset.memory_migrate
-r--r--r-- 1 root root 0 3月 28 17:07 cpuset.memory_pressure
-rw-rw-r-- 1 root root 0 3月 28 17:07 cpuset.memory_spread_page
-rw-rw-r-- 1 root root 0 3月 28 17:07 cpuset.memory_spread_slab
-rw-rw-r-- 1 root root 0 3月 28 17:07 cpuset.mems
-rw-rw-r-- 1 root root 0 3月 28 17:07 cpuset.sched_load_balance
-rw-rw-r-- 1 root root 0 3月 28 17:07 cpuset.sched_relax_domain_level
-rw-rw-r-- 1 root root 0 3月 28 17:07 notify_on_release
-rw-rw-r-- 1 root root 0 3月 28 17:07 tasks
$ cat cpuset.cpus
3
$ cat cpuset.mems
0
В настоящее время файл задач пуст, то есть в этой подсистеме процессорного набора нет запущенных процессов. Вам нужно найти способ запустить указанный процесс в этой подсистеме, есть два пути:
- уже запущенный процесс
PID
написатьtasks
в файле; - использовать
systemd
Создайте демон, который записывает настройки cgroupservice
файл (по существу такой же, как метод 1).
Давайте сначала рассмотрим метод 1, сначала запустим программу:
$ nohup sha1sum /dev/zero &
[1] 3767
потомPID
записывается в тестовую директориюtasks
середина:
$ echo "3767" > /sys/fs/cgroup/cpuset/test/tasks
Проверьте загрузку процессора:
Видно, что ядерное связывание вступает в силу,PID
Процесс для 3767 запланирован наcpu3
начальство.
Давайте снова посмотрим на метод 2, хотя в настоящее времяsystemd
Не поддерживается для использованияcpuset
Чтобы указать ЦП службы, но у нас все еще есть замаскированный метод, содержимое файла службы выглядит следующим образом:
$ cat /etc/systemd/system/foo.service
[Unit]
Description=foo
After=syslog.target network.target auditd.service
[Service]
ExecStartPre=/usr/bin/mkdir -p /sys/fs/cgroup/cpuset/testset
ExecStartPre=/bin/bash -c '/usr/bin/echo "2" > /sys/fs/cgroup/cpuset/testset/cpuset.cpus'
ExecStartPre=/bin/bash -c '/usr/bin/echo "0" > /sys/fs/cgroup/cpuset/testset/cpuset.mems'
ExecStart=/bin/bash -c "/usr/bin/sha1sum /dev/zero"
ExecStartPost=/bin/bash -c '/usr/bin/echo $MAINPID > /sys/fs/cgroup/cpuset/testset/tasks'
ExecStopPost=/usr/bin/rmdir /sys/fs/cgroup/cpuset/testset
Restart=on-failure
[Install]
WantedBy=multi-user.target
Запустите службу и проверьте загрузку процессора:
Процесс в этой службе действительно запланирован наcpu2
начальство.
5. Вернуться к Докеру
Наконец мы возвращаемся кDocker
,Docker
Фактически реализуется нижний слой системыcgroup
,namespace
и другие технологии интегрированы в инструмент, который публикуется зеркально, таким образом формируяDocker
, я уверен, что все это знают, поэтому я не буду распространяться об этом. Для Docker есть ли способ держать контейнер всегда в одном или несколькихCPU
бегать на нем? На самом деле это довольно просто, просто используйте--cpuset-cpus
параметры могут это сделать!
Давайте продемонстрируем, как указать работающий контейнерCPU
Основной номер 1:
🐳 → docker run -d --name stress --cpuset-cpus="1" progrium/stress -c 4
Просмотр нагрузки на ЦП хоста:
ТолькоCpu1
Достиг100%
, другие процессоры контейнером не используются.
Если вы видели сериалпервая статья, следует знать, что в новом использованииsystemd
выполнитьinit
система (например,ConetOS 7
), система создает 3 верхнего уровняslice
:System
, User
а такжеMachine
,вmachine.slice
является расположением по умолчанию для всех виртуальных машин и контейнеров Linux, в то время как Docker на самом делеmachine.slice
Вариант , вы можете думать об этом какmachine.slice
.
Если в системе работает Kubernetes,machine.slice
это становитсяkubepods
:
Для облегчения управления cgroups,systemd
будет для каждогоslice
Создайте подсистему, например подсистему докеров:
Затем в соответствии с настройками контейнера поместите его под соответствующий контроллер, здесь нас интересуетcpuset
Контроллер, посмотрите, что находится в его каталоге:
Проверьте каталог докера:
Вы можете видеть, что Docker создает подкаталог для каждого контейнера.7766..
Это соответствует контейнеру, который мы создали ранее:
🐳 → docker ps|grep stress
7766580dd0d7 progrium/stress "/usr/bin/stress --v…" 36 minutes ago Up 36 minutes stress
Давайте проверим конфигурацию в этом каталоге:
$ cd /sys/fs/cgroup/cpuset/docker/7766580dd0d7d9728f3b603ed470b04d0cac1dd923f7a142fec614b12a4ba3be
$ cat cpuset.cpus
1
$ cat cpuset.mems
0
$ cat tasks
6536
6562
6563
6564
6565
$ ps -ef|grep stress
root 6536 6520 0 10:08 ? 00:00:00 /usr/bin/stress --verbose -c 4
root 6562 6536 24 10:08 ? 00:09:50 /usr/bin/stress --verbose -c 4
root 6563 6536 24 10:08 ? 00:09:50 /usr/bin/stress --verbose -c 4
root 6564 6536 24 10:08 ? 00:09:50 /usr/bin/stress --verbose -c 4
root 6565 6536 24 10:08 ? 00:09:50 /usr/bin/stress --verbose -c 4
Конечно, вы также можете связать контейнеры для запуска на нескольких ядрах ЦП, поэтому я не буду вдаваться в подробности. В следующей статье будет рассказано, как ограничить cgroupBlockIO
.
Публичный аккаунт WeChat
Отсканируйте QR-код ниже, чтобы подписаться на официальную учетную запись WeChat, и ответьте на официальную учетную запись ◉Добавить группу◉, чтобы присоединиться к нашей облачной коммуникационной группе и обсудить облачные технологии с Сунь Хунляном, директором Чжаном, Ян Мином и другими важными шишками.