← Назад к вопросам

Что такое cgroups в Linux?

2.2 Middle🔥 81 комментариев
#Docker, Kubernetes и DevOps

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

cgroups в Linux и Java приложения

cgroups (control groups) — это механизм Linux ядра для ограничения, управления и мониторинга ресурсов процессов. Это критически важно для работы контейнеризации (Docker, Kubernetes) и виртуализации.

Основной принцип

cgroups позволяют:

  • Ограничить использование CPU, памяти, дискового I/O
  • Приоритизировать процессы
  • Отследить использование ресурсов
  • Изолировать процессы

Как Java работает с cgroups

Java автоматически обнаруживает ограничения cgroups и адаптирует свое поведение:

// В Docker контейнере с ограничением памяти 512MB
// Java автоматически устанавливает -Xmx на основе лимита cgroups

public class MemoryDetection {
    public static void main(String[] args) {
        Runtime runtime = Runtime.getRuntime();
        
        // В обычном процессе возвращает физическую память компьютера
        long totalMemory = runtime.totalMemory(); // Выделено JVM
        long maxMemory = runtime.maxMemory();     // -Xmx
        long freeMemory = runtime.freeMemory();   // Свободно в JVM
        
        System.out.println("Max memory: " + maxMemory / (1024 * 1024) + "MB");
        System.out.println("Free memory: " + freeMemory / (1024 * 1024) + "MB");
    }
}

cgroups v1 vs v2

cgroups v1 (старая версия):

# Структура папок в /sys/fs/cgroup/
memory/          # Контроль памяти
cpu/             # Контроль CPU
cpuacct/         # Учет CPU

cgroups v2 (современная версия, Ubuntu 21.04+):

  • Единая иерархия вместо множественной
  • Лучше распределение ресурсов между процессами

Ограничение памяти в Docker

FROM openjdk:17

WORKDIR /app
COPY target/app.jar .

# Java автоматически обнаружит это ограничение через cgroups
ENTRYPOINT ["java", "-jar", "app.jar"]
# Запуск контейнера с ограничением памяти
docker run -m 512m my-java-app
// Внутри контейнера Java "видит" ограничение
Runtime runtime = Runtime.getRuntime();
long maxMemory = runtime.maxMemory();
// Скорее всего будет примерно 512MB

Ограничение CPU

# Использовать только 1 CPU ядро
docker run --cpus="1" my-java-app

# Использовать 50% всех доступных ядер
docker run --cpus="0.5" my-java-app

# Приоритет CPU
docker run --cpu-shares=512 my-java-app
// Java может получить информацию о доступных процессорах
int availableProcessors = Runtime.getRuntime().availableProcessors();
// В контейнере с --cpus="1" вернет 1

ExecutorService executor = Executors.newFixedThreadPool(availableProcessors);

Мониторинг использования ресурсов

import java.lang.management.MemoryMXBean;
import java.lang.management.ManagementFactory;

public class ResourceMonitor {
    public static void main(String[] args) {
        MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
        
        long heapUsed = memoryBean.getHeapMemoryUsage().getUsed();
        long heapMax = memoryBean.getHeapMemoryUsage().getMax();
        
        System.out.println("Heap used: " + heapUsed / (1024 * 1024) + "MB");
        System.out.println("Heap max: " + heapMax / (1024 * 1024) + "MB");
        System.out.println("Heap usage: " + (100 * heapUsed / heapMax) + "%");
    }
}

Важные флаги JVM для контейнеров

java -XX:+UseContainerSupport \\
      -XX:MaxRAMPercentage=75.0 \\
      -XX:+UnlockExperimentalVMOptions \\
      -XX:G1NewSizePercent=30 \\
      -XX:G1MaxNewSizePercent=40 \\
      -jar app.jar
  • UseContainerSupport: автоматическое обнаружение cgroups (Java 10+)
  • MaxRAMPercentage: использовать 75% от лимита памяти контейнера
  • G1NewSizePercent: оптимизация GC для контейнеров
Что такое cgroups в Linux? | PrepBro