Cuando se habla de cgroups, los usuarios de Red Hat a menudo hacen la misma pregunta: “Tengo una aplicación que es muy sensible en términos de demoras. ¿Es posible usar cgroups para aislar esta aplicación del resto uniéndola a ciertos núcleos de procesador?

Por supuesto que puedes. De lo contrario, no elegiríamos este tema como tema del artículo de hoy.
En la infancia, a menudo se nos decía que compartir es bueno y correcto. En general, tal como es. Pero hay excepciones.
Como escribimos en la
primera publicación de esta serie , por defecto, Red Hat Enterprise Linux 7 se comporta como una abuela amable y esférica. En el sentido de que está tratando de distribuir equitativamente los recursos del sistema entre todos los que los solicitan. Sin embargo, en la vida real, las abuelas tienen mascotas que reciben más. Traducido a sysadmin, esto significa que hay situaciones en que algunas aplicaciones o servicios son más importantes que otros, por lo que se les debe prestar toda la atención posible para que sean lo más receptivos posible.
Red Hat Enterprise Linux 7 hace esto en dos pasos:
- Aislamos parte de los núcleos del procesador para transferirlos al uso exclusivo de dicha aplicación.
- Creamos grupos cgroups y archivos unitarios que vinculan esta aplicación a núcleos aislados.
Una pequeña digresión sobre los ejemplos de estas publicaciones
Hat Enterprise Linux 7.4 ha cambiado el funcionamiento de los segmentos de corta duración, como las sesiones de usuario. Como resultado, ya no pueden cambiar la configuración de cgroup sobre la marcha, realizar cambios permanentes en la configuración o crear archivos desplegables utilizando el comando systemctl set-property. Sí, es una pena, pero la comunidad de desarrollo de Linux lo ha decidido. La buena noticia es que estos cambios no han afectado el servicio. Es decir, si las aplicaciones comienzan y se detienen a través de los archivos de la unidad (funcionan como demonios), entonces todos nuestros ejemplos funcionan. Además, sigue siendo posible crear sus propios cgroups usando herramientas antiguas como cgcreate y cgset, y luego colocar sesiones y procesos de usuario en estos grupos para usar bolas de CPU y otros controles. En la vida, todo cambia, por lo que solo podemos adaptarnos e inventar nuevas técnicas. Y ahora pasamos al tema de hoy.
Construyendo el separatismo con isolcpus
Uno de los componentes más importantes en el kernel de Linux es el planificador de procesos. Si es un poco más profundo, entonces un proceso es un código ejecutable que forma parte de una aplicación o servicio. De hecho, el proceso consiste en una serie de instrucciones que la computadora lleva a cabo, haciendo este o aquel trabajo, ya sea mirando sellos o algo más serio.
Estas instrucciones son manejadas por el procesador central, también conocido como CPU. En las computadoras modernas, la CPU generalmente consta de varios procesadores llamados núcleos.
Por defecto, el planificador considera cada núcleo del procesador como uno de los módulos ejecutivos a los que asigna nuevos procesos a medida que aparecen. En este caso, el planificador intenta distribuir más o menos uniformemente los procesos emergentes entre los núcleos, teniendo en cuenta la carga. Desafortunadamente, no se puede decir al programador que este proceso en particular dará lugar a un grupo completo de procesos, y este grupo deberá ejecutarse de manera aislada de otros procesos, en el sentido de que no deberían tener núcleos de procesador comunes.
Por lo tanto, necesitamos decirle al planificador de alguna manera para que no toque parte de los núcleos del procesador, es decir, no les dé ningún proceso que golpee. Y luego nosotros mismos (o con la ayuda de algún otro proceso) aplicaremos por la fuerza aquellos procesos que consideremos necesarios para aislarlos del programador del núcleo. Esto se puede hacer usando el parámetro isolcpus en la línea de arranque del kernel en el archivo de configuración de grub. En el ejemplo a continuación, tenemos una máquina con cuatro núcleos en los que hay dos archivos grub: uno se encuentra en / etc / default y se llama grub.noiso (esta es la copia de seguridad de configuración predeterminada), y el segundo se encuentra allí y simplemente se llama grub para que recogido grub2-mkconfig. Este segundo archivo ha sido editado para aislar los núcleos 1-3 del programador de procesos.

ADVERTENCIA: en Red Hat Enterprise Linux 7, nunca necesita modificar manualmente el archivo grub.conf en la carpeta / boot. En su lugar, realice los cambios necesarios en / etc / default / grub y luego reconstruya el archivo grub.conf usando la utilidad adecuada, por ejemplo, así:
Cuando se usa el parámetro isolcpus, es necesario enumerar los núcleos de procesador liberados separados por una coma, la numeración comienza desde 0. Después de que el sistema se reinicia, el programador de procesos no usará estos núcleos para nada, excepto para ciertos procesos a nivel de sistema que DEBEN ESTAR en cada núcleo. Para verificar si nuestro método funcionó, comenzaremos varios procesos de carga y luego analizaremos la carga de cada núcleo mediante el comando superior.
Como puede ver, todos los procesos de carga se ubicaron en la CPU 0, en lugar de distribuirse uniformemente en los cuatro núcleos. Entonces, registramos el parámetro de arranque correctamente.
Enlazar procesos a núcleos usando cpuset
Ahora pasamos a cosas
que es mejor no hacer si no comprende por qué está haciendo esto, y cuáles son mejores para implementar en producción solo después de pruebas exhaustivas .
¿Para qué son estas advertencias? Al hecho de que haremos, en general, cosas simples usando el kit de herramientas libcgroup, que se escribió en una publicación anterior. Si recuerdas, esto es solo un conjunto de comandos para crear, modificar y destruir cgroups. De hecho, son parte de Red Hat Enterprise Linux 6, pero también se pueden instalar en Red Hat Enterprise Linux 7, aunque es posible que esta posibilidad desaparezca en el futuro. Recuerde brevemente las principales recomendaciones para usar libcgroup:
- Use systemd para controlar los controladores de cgroup que están bajo el control de systemd (estos son la CPU, la memoria y las E / S de bloque).
- Use las herramientas de libcgroup para administrar todos los demás controladores de cgroup.
- Tenga mucho cuidado con las consecuencias no planificadas de sus acciones.
Todo es simple con el concepto cpuset: esta es una lista de núcleos de procesador (numeración, recuperación, comienza en 0), que acepta tareas que se ejecutarán SOLO en estos núcleos. Estos son los núcleos de procesador más comunes, pueden ser controlados por un planificador de procesos (así es como se configura el sistema de manera predeterminada) o, por el contrario, pueden aislarse del planificador (como lo hicimos en el ejemplo anterior).
Verifiquemos el sistema de archivos del directorio / sys / fs / cgroup en el sistema de nuestro ejemplo. Como puede ver, el directorio cpuset ya existe, ya que este controlador es parte del núcleo (aunque no está bajo el control de systemd). Sin embargo, todavía no tiene cgroups, por lo que solo vemos la configuración predeterminada en este directorio.
Verifique que el kit de herramientas libcgroup esté instalado en nuestra máquina:
Si no está instalado, esto se puede solucionar fácilmente con el comando yum install libcgroup, incluso no es necesario reiniciar.
Ahora crea cpuset. Para hacer esto, utilizaremos los siguientes comandos para crear un nuevo cgroup para cpuset y registrar sus propiedades:
El comando Cgcreate crea un cgroup llamado testset y lo coloca dentro del controlador cpuset. Luego asignamos el tercer núcleo de nuestra VM a este nuevo cpuset y le asignamos la zona NUMA 0. Incluso si su sistema no usa NUMA (y el nuestro simplemente no lo usa), aún necesita registrar la zona, de lo contrario no puede asignar tareas al grupo cgroup . Ahora verifique que el directorio del conjunto de pruebas se haya creado en el sistema de archivos y vea qué hay dentro.
Como puede ver, nuestros cambios están en su lugar, pero hasta ahora no se ha ejecutado ningún proceso en este cpuset. ¿Cómo plantar algún proceso aquí?
Hay varias formas de hacer esto:
- Puede conducir el PID de un proceso existente al archivo de tareas. Funciona, pero no muy bonito.
- Puede usar cgexec y especificar el grupo cuando comienza el proceso. Esto funciona si la aplicación no es un demonio; Además, todo esto se puede escribir maravillosamente en el script de inicio de la aplicación.
- Para una aplicación que se ejecuta como un demonio que ejecuta systemd, puede crear un archivo de servicio.
Veamos la opción cgexec.
Lanzamos foo.exe, a su vez, lanzó un proceso hijo, que solo carga activamente el procesador. La opción --sticky en el comando cgexec dice que "cualquier proceso hijo debe permanecer en el mismo grupo c que el proceso padre". Entonces esta es una opción importante, y debe ser recordada. Ahora vemos que dos procesos están girando en nuestro cgroup, y conocemos sus PID. Echa un vistazo a la parte superior:
Como puede ver, la CPU 3 ahora está cargada en los globos oculares, y el resto se está enfriando.
Y así es como se ve un archivo unitario para ejecutar la misma aplicación que un servicio systemd:
Hay tres comandos ExecStartPre en el archivo de la unidad que realizan la configuración que ya logramos hacer con nuestras manos. Luego viene el comando ExecStart, que inicia la aplicación. Y cuando la aplicación se detiene, el comando ExecStopPost se limpia después de sí mismo, eliminando cgroup.
Como puede ver, en el último ejemplo, creamos un nuevo cgroup llamado set1. Hicimos esto para mostrar que puede tener varios cgroups activos que comparten la misma CPU. Para quien puede parecer útil, pero por el contrario confundir a alguien.
Bueno, ¿funciona? ¡Parece que sí!
Y ahora completaremos el trabajo de nuestro servicio y verificaremos que cgroup esté destruido:
ATENCIÓN: los grupos de cgroup creados con cgcreate no se guardan después del reinicio. Por lo tanto, la creación de tales grupos debe prescribirse en scripts de inicio y archivos de unidad.
Entonces, ahora en su arsenal hay un par de herramientas más para trabajar con cgroups. ¡Esperamos que sean útiles!
Otras publicaciones de cgroups de nuestra serie Resource Fight están disponibles en: