Configure CGroup for LAMP stack

by Anish


Posted on Tuesday December 10/2019



CGroup were introduced into the kernel by Google in 2006 and it's stands for Control Groups

Cgroups allow you to allocate these subsystem resources among user-defined groups of tasks (processes) running on a system

  • cpu: Uses the scheduler to provide cgroup tasks access to the CPU.
  • blkio: Sets limits on input/output access to and from block devices such as physical drives
  • cpuacct: Generates automatic reports on CPU resources used by tasks in a cgroup
  • cpuset: Assigns individual CPUs and memory nodes to tasks in a cgroup
  • devices: Allows or denies access to devices by tasks in a cgroup
  • freezer: Suspends or resumes tasks in a cgroup
  • perf_event: Identifies cgroup membership of tasks and can be used for performance analysis
  • net_cls: Tags network packets with a class identifier
  • memory: Sets limits on memory use by tasks in a cgroup and generates automatic reports on memory resources used by those tasks

CGroup for LAMP

For example, let's say we wanted to assign or isolate the resources of an application, for the same purpose we will create two cgroup one for application and other for operating system itself.

cgroup lamp stack

Let's extend the scenario to more practical one imagine you have a LAMP stack, you have to manage the cpu, memory, disk and network bandwidth, for your LAMP application.

LAMP stack (Linux, Apache, MariaDB/MYSQL and PHP)

and your cloud/VM has 4GB of Memory and you have to limit the following configuration in the CGgroup

  • Form httpd service ( httpd.service): 30% of CPU, 1G of memory,
  • PHP service (here php-fpm.service): 20% of CPU, 1G of memory,
  • MariaDB service (here mariadb.service): 50% of CPU, 1G of memory.

and you have left 1G of memory for the operating system itself.

Without CGroup processes will share the server power and the memory as they need.

with CGroup the httpd service: will have CPUShares=3072 (3x 1024); and MemoryLimit=1G, and to configure in httpd service using systemctl

[[email protected] ~]$ sudo systemctl set-property httpd CPUShares=3072
[[email protected] ~]$ sudo systemctl set-property httpd  MemoryLimit=1G
[[email protected] ~]$ sudo systemctl daemon-reload
[[email protected] ~]$ sudo systemctl show -p CPUShares,MemoryLimit httpd
CPUShares=3072
MemoryLimit=1073741824

The httpd status shows CGroup configured with 1GB limit

[[email protected] ~]$ systemctl status httpd
 httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/httpd.service.d
           50-CPUShares.conf, 50-MemoryLimit.conf
   Active: active (running) since Tue 2019-12-10 02:13:24 EST; 6min ago
     Docs: man:httpd(8)
           man:apachectl(8)
 Main PID: 1551 (httpd)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"
    Tasks: 6
   Memory: 2.7M (limit: 1.0G)
   CGroup: /system.slice/httpd.service
           1551 /usr/sbin/httpd -DFOREGROUND
           1552 /usr/sbin/httpd -DFOREGROUND
           1553 /usr/sbin/httpd -DFOREGROUND

The drop-ins files

[[email protected] ~]$ cat /etc/systemd/system/httpd.service.d/50-CPUShares.conf 
[Service]
CPUShares=3072
[[email protected] ~]$ cat /etc/systemd/system/httpd.service.d/50-MemoryLimit.conf 
[Service]
MemoryLimit=1073741824

If you want the httpd service to display the amount of memory currently used through the systemd-cgtop command, you need to activate accounting by MemoryAccounting=true

[[email protected] ~]$ sudo systemctl set-property httpd  MemoryAccounting=true 
[[email protected] ~]$ sudo systemctl daemon-reload; sudo systemctl restart httpd

and then

[[email protected] ~]$ systemd-cgtop

systemd-cgtop

CGroup configuration for mariadb service: CPUShares=5120 (5 x 1024); MemoryLimit=1G and write below 2MB/s onto the /dev/vdb partition

[[email protected] ~]$ sudo systemctl set-property mariadb CPUShares=5120
[[email protected] ~]$ sudo systemctl set-property mariadb  MemoryLimit=1G
[[email protected] ~]$ sudo systemctl set-property mariadb.service BlockIOWriteBandwidth="/dev/vdb 2M"
[[email protected] ~]$ sudo systemctl daemon-reload
[[email protected] ~]$ sudo systemctl restart mariadb

The mariadb status shows CGroup configured with 1GB limit and with required BlockIOWriteBandwidth and CPUShares

[[email protected] ~]$ systemctl status mariadb
 mariadb.service - MariaDB database server
   Loaded: loaded (/usr/lib/systemd/system/mariadb.service; disabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/mariadb.service.d
           50-BlockIOWriteBandwidth.conf, 50-CPUShares.conf, 50-MemoryLimit.conf
   Active: active (running) since Tue 2019-12-10 02:47:14 EST; 28s ago
  Process: 2371 ExecStartPost=/usr/libexec/mariadb-wait-ready $MAINPID (code=exited, status=0/SUCCESS)
  Process: 2335 ExecStartPre=/usr/libexec/mariadb-prepare-db-dir %n (code=exited, status=0/SUCCESS)
 Main PID: 2370 (mysqld_safe)
    Tasks: 20
   Memory: 74.4M (limit: 1.0G)
   CGroup: /system.slice/mariadb.service
           2370 /bin/sh /usr/bin/mysqld_safe --basedir=/usr
           2532 /usr/libexec/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log-error=/var/

CGroup Fundamentals

Installation on rhel7/8 and centos Like system,

if you are using systemd the systemd uses CGroups libcgroup package and is installed by default

$ yum -y install libcgroup libcgroup-tools
$ systemctl start cgroup
$ systemctl enable cgroup

lscgroup list all cgroups

[[email protected] ~]# lscgroup
cpu,cpuacct:/
cpu,cpuacct:/user.slice
cpu,cpuacct:/system.slice
cpu,cpuacct:/system.slice/mariadb.service
cpu,cpuacct:/system.slice/httpd.service
.....
.....

lssubsys - list hierarchies containing given subsystem

[[email protected] ~]# lssubsys
cpuset
cpu,cpuacct
memory
devices
freezer
net_cls,net_prio
blkio
perf_event
hugetlb
pids

limiting memory usage

This example shows how a new cgroup is created assiged a user to it and set some memmory limits

[[email protected] ~]# adduser testing

cgcreate will create a new directory within the mounted memory cgroup with assiged username

[[email protected] ~]# cgcreate -a testing -g memory,cpu:testing

For testing set 256MB of memory limit in this cgroup testing

[[email protected] ~]# echo 268435456 > /sys/fs/cgroup/memory/testing/memory.limit_in_bytes

Validate the memory.limit_in_bytes

[[email protected] ~]# cat /sys/fs/cgroup/memory/testing/memory.limit_in_bytes
268435456

Switch to newly created user

[[email protected] ~]# su - testing

run stress with the -m option to consume memory and see what happens

[[email protected] ~]$ stress -m 2 --vm-bytes 800M --vm-keep
stress: info: [2678] dispatching hogs: 0 cpu, 0 io, 2 vm, 0 hdd
stress: FAIL: [2678] (415) <-- worker 2679 got signal 9
stress: WARN: [2678] (417) now reaping child worker processes
stress: FAIL: [2678] (451) failed run completed in 1s

The Application just crash because of memory.oom_control

[[email protected] ~]$  cat /sys/fs/cgroup/memory/testing/memory.oom_control
oom_kill_disable 0
under_oom 0

Next Reading : Overview of Linux Namespace



Thanku for reading !!! Give a Share for Support

Asking for donation sound bad to me, so i'm raising fund from by offering all my eight book for just $9

Referefce 8gwifi.org
Online Terminals
Online Terminals
python Cryptography Topics
Topics
For Coffee/ Beer/ Amazon Bill and further development of the project Support by Purchasing, The Modern Cryptography CookBook for Just $9 Coupon Price

Kubernetes for DevOps

Hello Dockerfile

Cryptography for Python Developers

Cryptography for JavaScript Developers

Go lang ryptography for Developers