FastNetMon

Friday, 26 September 2014

Как понять в каком месте завис Perl скрипт?

Берем вот этот скрипт: https://raw.githubusercontent.com/ahiguti/gdbperl/master/gdbperl.pl

Стягиваем gdb: yum install -y gdb

Получаем нечто вот такое:
perl gdbperl.pl 755934
command:
gdb -silent -nw /usr/bin/perl 755934

environ:
SHELL=/bin/sh
MAILTO=root
USER=root
PATH=/usr/bin:/bin
PWD=/root
SHLVL=1
HOME=/root
LOGNAME=root
_=/usr/bin/fastvz_backup.pl

c_backtrace:
#0  0x0000003f7540da70 in __read_nocancel () from /lib64/libpthread.so.0
#1  0x0000003f774f0990 in PerlIOUnix_read () from /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/CORE/libperl.so
#2  0x0000003f774f5055 in PerlIOBuf_fill () from /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/CORE/libperl.so
#3  0x0000003f774ef848 in Perl_PerlIO_fill () from /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/CORE/libperl.so
#4  0x0000003f774f4cbf in PerlIOBase_read () from /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/CORE/libperl.so
#5  0x0000003f774f4dfb in PerlIO_getc () from /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/CORE/libperl.so
#6  0x0000003f774a29b0 in Perl_sv_gets () from /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/CORE/libperl.so
#7  0x0000003f7748dbd3 in Perl_do_readline () from /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/CORE/libperl.so
#8  0x0000003f7748a37e in Perl_runops_standard () from /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/CORE/libperl.so
#9  0x0000003f774380ba in perl_run () from /usr/lib64/perl5/5.8.8/x86_64-linux-thread-multi/CORE/libperl.so
#10 0x00000000004017bc in main ()

perl_backtrace:
[5] Tool::get_backups_list("7xxxxx", "xxx", "7549") <- /usr/local/lib/perl/FastBackup.pm:253(FastBackup)
[4] Tool::get_last_full_backup_info("xxxx", "xxxx", "7549") <- /usr/bin/fastssad.pl:268(main)
[3] (other) <- /usr/bin/faxxx.pl:266(main)
[2] (loop) <- /usr/bin/fasxxxxx.pl:224(main)
[1] main::function() <- /usr/bin/faxxxx.pl:156(main)
Источник: http://www.slideshare.net/hirose31/inspect-runningperl


Tuesday, 23 September 2014

Странные проблемы rsync при работе с флагом -z

Итак, есть 16 Гб крупным бинарным файлом.

Пробуем перелить его силами rsync без флага -z:

time rsync -a --progress /vz/private/1210 root@technode4.fv.ee:/tmp/1210
Потребление процессора разумное (32%):
395053 root      20   0  106m 1500  988 R 32.3  0.0   0:06.84 rsync                                                         
Итоги:
sent 16906158370 bytes  received 96 bytes  103 401 580.83 bytes/sec
total size is 16904094532  speedup is 1.00
real 2m42.437s
user 1m23.115s
sys 0m38.441s

Пробуем перелить с флагом -z:
time rsync -az --progress /vz/private/1210 root@technode4.fv.ee:/tmp/1210

Сразу в процессе видно, что скорость падает с 100 мегабайт/секунду до 20, а rsync начинает висеть вот в таком мерзком виде в top (да, да, он целиком выедает ядро процессора): 
391791 root      20   0  106m 1812 1020 R 99.7  0.0   0:54.36 rsync   

В итоге пришлось прервать процесс, так как он не завершился бы в разумные сроки - половина скопировалось лишь за 5 минут и скорость упала до 5 мегабайт/секунду:

real 5m54.894s
user 4m24.249s
sys 0m20.234s
В итоге данные в лучшем случае перелились бы за 10-20 минут, что уже в 4-5 раз хуже, чем вариант без использования сжатия.

Почеум так? Сжатие силами протокола gzip довольно требовательно к процессору и очень быстро упирается в производительность одного ядра, которая даже на топовых процессорах очень слабая.

Сжатие, безусловно, даст ускорение передачи данных, но лишь в случае, когда процессор будет успевать сжимать данные быстрее, чем выдерживает канал связи, этого можно достичь, например, используя внешнее сжатие через парраллельный компрессор pigz.


Monday, 15 September 2014

Утилита для монтирования OpenVZ ploop дисков на любой машине с Linux

Предлагаю к Вашему вниманию очередную разработку нашей компании: ploop userspace. Это утилита для монтирования дисков в формате ploop, которые используются системой виртуализации OpenVZ.

Поддерживаются оба формата хранения - v1 и v2. Поддержка записи не планируется в виду высокой сложности задачи.

Прошу: GitHub

Thursday, 28 August 2014

Что делать если atop показывает не все сетевые интерфейсы?

То нажмите l в окне atop, потом прощелкайте Enter до - Maximum lines for interface statistics и забивайте там нужное число, например - 10.

Самый удобный и просто метод посчитать pps (число пакетов-секунду) на интерфейсе

Как починить падения Puppet DB от ошибок OOM killer?

Проявляется бага как:
Warning: Error 400 on SERVER: Could not retrieve facts for ovz14.fastvps.ru: Failed to submit 'replace facts' command for ovzxxx.ru to PuppetDB at xxxxxx:8081: Connection refused - connect(2)
Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Failed to submit 'replace facts' command for oxxxxs.ru to PuppetDB at xxxxx:8081: Connection refused - connect(2)


В логе (/var/log/puppetdb/puppetdb-daemon.log ) при этом:
# java.lang.OutOfMemoryError: Java heap space
# -XX:OnOutOfMemoryError="kill -9 %p"
#   Executing /bin/sh -c "kill -9 15190"...
java.lang.OutOfMemoryError: Java heap space
Dumping heap to /var/log/puppetdb/puppetdb-oom.hprof ...
Heap dump file created [225222767 bytes in 1,713 secs]
Чиним, открываем конфиг: /etc/sysconfig/puppetdb и там заменяем Xmx192m на Xmx1024m.

Применяем:
/etc/init.d/puppetdb restart
Убеждаемся, что Java завелась с новым лимитом памяти:
 ps aux|grep Xmx -i --color
puppetdb 29429 11.7  1.8 1654504 593832 ?      Sl   11:35   0:26 /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java -XX:OnOutOfMemoryError=kill -9 %p -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/puppetdb/puppetdb-oom.hprof -Djava.security.egd=file:/dev/urandom -cp /usr/share/puppetdb/puppetdb.jar clojure.main -m com.puppetlabs.puppetdb.core services -c /etc/puppetdb/conf.d

Monday, 25 August 2014

perf trace - эффективная замена strace в ряде случаев!

perf trace /bin/echo "Php suxx"
     0.000 ( 0.000 ms):  ... [continued]: read()) = 0
Problems reading syscall 59(execve) information
     0.288 ( 0.000 ms):  ... [continued]: execve()) = 0
Php suxx
     0.304 ( 0.001 ms): brk(brk: 0                                                            ) = 9400320
     0.320 ( 0.002 ms): mmap(addr: 0, len: 4096, prot: 3, flags: 34, fd: 4294967295, off: 0   ) = -1309794304
     0.329 ( 0.005 ms): access(filename: 140268025023360, mode: 4                             ) = -1 ENOENT No such file or directory
     0.337 ( 0.003 ms): open(filename: 140268025016833, flags: 0, mode: 1                     ) = 3
     0.340 ( 0.001 ms): fstat(fd: 3, statbuf: 140735595271856                                 ) = 0
     0.343 ( 0.003 ms): mmap(addr: 0, len: 32186, prot: 1, flags: 2, fd: 3, off: 0            ) = -1309827072
     0.345 ( 0.001 ms): close(fd: 3                                                           ) = 0
     0.355 ( 0.003 ms): open(filename: 140268027119178, flags: 0, mode: 0                     ) = 3
     0.357 ( 0.002 ms): read(fd: 3, buf: 140735595272280, count: 832                          ) = 832
     0.361 ( 0.001 ms): fstat(fd: 3, statbuf: 140735595271936                                 ) = 0
     0.366 ( 0.003 ms): mmap(addr: 0, len: 3750152, prot: 5, flags: 2050, fd: 3, off: 0       ) = -1315766272
     0.371 ( 0.004 ms): mprotect(start: 140268022771712, len: 2093056, prot: 0                ) = 0
     0.376 ( 0.004 ms): mmap(addr: 140268024864768, len: 20480, prot: 3, flags: 2066, fd: 3, off: 1613824) = -1312055296
     0.382 ( 0.003 ms): mmap(addr: 140268024885248, len: 18696, prot: 3, flags: 50, fd: 4294967295, off: 0) = -1312034816
     0.386 ( 0.001 ms): close(fd: 3                                                           ) = 0
     0.396 ( 0.002 ms): mmap(addr: 0, len: 4096, prot: 3, flags: 34, fd: 4294967295, off: 0   ) = -1309831168
     0.401 ( 0.002 ms): mmap(addr: 0, len: 4096, prot: 3, flags: 34, fd: 4294967295, off: 0   ) = -1309835264
     0.405 ( 0.001 ms): mmap(addr: 0, len: 4096, prot: 3, flags: 34, fd: 4294967295, off: 0   ) = -1309839360
     0.407 ( 0.001 ms): arch_prctl(option: 4098, arg2: 140268027086592, arg3: 140268027080704, arg4: 34, arg5: 4294967295) = 0
     0.459 ( 0.003 ms): mprotect(start: 140268024864768, len: 16384, prot: 1                  ) = 0
     0.467 ( 0.002 ms): mprotect(start: 140268027129856, len: 4096, prot: 1                   ) = 0
     0.472 ( 0.004 ms): munmap(addr: 140268027092992, len: 32186                              ) = 0
     0.531 ( 0.001 ms): brk(brk: 0                                                            ) = 9400320
     0.534 ( 0.002 ms): brk(brk: 9535488                                                      ) = 9535488
     0.545 ( 0.005 ms): open(filename: 140268022569584, flags: 0, mode: 140268024885264       ) = 3
     0.547 ( 0.001 ms): fstat(fd: 3, statbuf: 140268024885312                                 ) = 0
     0.552 ( 0.003 ms): mmap(addr: 0, len: 99158576, prot: 1, flags: 2, fd: 3, off: 0         ) = -1414926336
     0.555 ( 0.001 ms): close(fd: 3                                                           ) = 0
     0.577 ( 0.001 ms): fstat(fd: 1, statbuf: 140735595273776                                 ) = 0
     0.580 ( 0.002 ms): mmap(addr: 0, len: 4096, prot: 3, flags: 34, fd: 4294967295, off: 0   ) = -1309798400
     0.587 ( 0.004 ms): write(fd: 1, buf: 140268027121664, count: 9                           ) = 9
     0.592 ( 0.001 ms): close(fd: 1                                                           ) = 0
     0.596 ( 0.003 ms): munmap(addr: 140268027121664, len: 4096                               ) = 0
     0.599 ( 0.001 ms): close(fd: 2                                                           ) = 0
     0.602 ( 0.000 ms): exit_group(error_code: 0                                              

Thursday, 14 August 2014

CPULIMIT, CPUUNITS и CPUS - детальное тестирование и описание параметров управляющих нагрузкой на CPU со стороне контейнеров OpenVZ

Выводы в самом конце - листайте :)

Тестовая среда: 2.6.32-042stab090.5, в контейнерах: Debian-7-x86_64 minimal. Процессор: 3.4 Ghz, число ядер: 8

На ноде выставлен режим максимальной частоты:
echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

На машине 8 ядер

Два контейнера - 101 и 102, им по дефалту выдано: CPUUNITS="1000" CPUS/CPULIMIT не использованы.

Изучение поведения шедулера OpenVZ:

1) Запускаем  stress --cpu 8 на первом контейнере:
 1  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]   
 2  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]   
 3  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]   
 4  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
 5  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
 6  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
 7  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
 8  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
То есть машина получила все доступные ресурсы.


2) Включаем ту же самую команду на второй машине (то есть теперь она включена на обоих). Получаем тоже самое:
 1  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]   
 2  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]   
 3  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]   
 4  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
 5  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
 6  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
 7  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
 8  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
Но теперь каждый контейнер грузит отдельно ядро не более чем на 50%.

open_vestat показывает следующее:
101:    cpu: 50.1 %   
102:    cpu: 49.8 %

3) Меняем лимиты на 100:
vzctl set 101 --cpuunits 100 --save; vzctl set 102 --cpuunits 100 --save;

И 10000:
vzctl set 101 --cpuunits 10000 --save; vzctl set 102 --cpuunits 10000 --save;

Ничего при этом не меняется! Все ок, важно лишь отношение этих величин
4) Ставим неравные лимиты:
vzctl set 101 --cpuunits 100 --save; vzctl set 102 --cpuunits 200 --save;

И сразу приоритет перешел к машине 101:
101: cpu: 37.2 %
102: cpu: 62.7 %
Схема нагрузки на процы ноды:
 1  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]   
 2  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]   
 3  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]   
 4  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
 5  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
 6  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
 7  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
 8  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]

5) Теперь выдаем каждой машине ровно по 1 логическому ядру, тем самым ограничивая пиковую нагрузку на ядра:
vzctl set 101 --cpus 1 --cpuunits 1000 --save; vzctl set 102 --cpuunits 1000 --cpus 1 --save;

Картина мгновенно меняется - ограничение на число ядер, которое может выедать машина включилось в действие.

1 [ 0.0%]
2 [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
3 [ 0.0%]
4 [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
5 [ 0.0%]
6 [| 0.7%]
7 [ 0.0%]
8 [ 0.0%]

Разделение как и прежде идеальное:
101:    cpu: 49.8 %   
102:    cpu: 49.8 %

Мегагерцы также выдаются как и ранее:
vzctl exec 101 "cat /proc/cpuinfo|grep Mhz -i"; vzctl exec 102 "cat /proc/cpuinfo|grep Mhz -i";
cpu MHz        : 3401.000
cpu MHz        : 3401.000

6) Теперь выдаем каждой машине по 2 ядра:
vzctl  set 101 --cpus 2 --cpuunits 1000 --save; vzctl set 102 --cpuunits 1000 --cpus 2 --save;

Разделение продолжает быть идеальным:
101: cpu: 49.8 %
102: cpu: 49.8 %

Картина нагрузки следующая:
1 [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
2 [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
3 [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
4 [|| 1.3%]
5 [ 0.0%]
6 [ 0.0%]
7 [ 0.0%]
8 [|||||||||||||||||||||||||||||||||||||||||||||||||||||||||99.3%]
7) Вводим параметр cpulimit.
Для машины с 1 логическим процессором поидее поменяться нчиего не должно.
vzctl set 101 --cpus 1 --cpulimit 100 --save; vzctl set 102 --cpulimit 100 --cpus 1 --save;

Ну в общем ничего и не поменялось:
1 [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
2 [ 0.0%]
3 [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
4 [ 0.0%]
5 [ 0.0%]
6 [ 0.0%]
7 [ 0.0%]
8 [| 0.7%]
8) Срезаем пиковую нагрузку до 50:
vzctl set 101 --cpus 1 --cpulimit 50 --save; vzctl set 102 --cpulimit 50 --cpus 1 --save;

Несмотря на наличие доступных ресурсов - машины обрезало строго по половине ядра.

1 [||||||||||||||||||||||||||||||| 49.3%]
2 [ 0.0%]
3 [||||||||||||||||||||||||||||||| 49.7%]
4 [ 0.0%]
5 [ 0.0%]
6 [ 0.0%]
7 [ 0.0%]
8 [| 1.3%]

И мегагерцы поменялись:
vzctl exec 101 "cat /proc/cpuinfo|grep Mhz -i"; vzctl exec 102 "cat /proc/cpuinfo|grep Mhz -i";
cpu MHz        : 1700.500
cpu MHz        : 1700.500

9) Срезаем нагрузку до 10:
vzctl set 101 --cpus 1 --cpulimit 10 --save; vzctl set 102 --cpulimit 10 --cpus 1 --save;

1 [||||||| 9.9%]
5 [ 0.0%]
2 [ 0.0%]
6 [ 0.0%]
3 [ 0.0%]
7 [ 0.0%]
4 [||||||| 10.5%]
8 [| 0.7%]
И тут все работает идеально.

10) отключаем один контейнер, второй оставляем с ограничнием в 10%:
1 [||||||| 9.9%]
5 [|| 1.3%]
2 [ 0.0%]
6 [ 0.0%]
3 [ 0.0%]
7 [ 0.0%]
4 [ 0.0%]
8 [ 0.0%]
И тут все ок!

11) Что будет если сделать --cpulimit 200 при выданном одном процессоре для контейнера? Да ничего плохого - больше 100% он не съест :)

1  [                                                          0.0%]    
5  [|                                                         0.7%]
2  [                                                          0.0%]    
6  [                                                          0.0%]
3  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
7  [                                                          0.0%]
4  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
8  [                                                          0.0%]

12) Выдаем двум контейнера по два проца, но при этом жестко ограничиваем нагрузку 100% одного ядра:
vzctl set 101 --cpus 2 --cpulimit 100 --save; vzctl set 102 --cpulimit 100 --cpus 2 --save;

В итоге каждая машина получит по 2 ядра, но по 1.7 Ghz (половина мощности ядра аппаратной ноды):
vzctl exec 101 "cat /proc/cpuinfo|grep Mhz -i"; vzctl exec 102 "cat /proc/cpuinfo|grep Mhz -i";
cpu MHz        : 1700.500
cpu MHz        : 1700.500
cpu MHz        : 1700.500
cpu MHz        : 1700.500

Схема нагрузки будет вот такая:
1  [                                                          0.0%]    
5  [|                                                         0.7%]
2  [                                                          0.0%]    
6  [                                                          0.0%]
3  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
7  [                                                          0.0%]
4  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
8  [                                                          0.0%]
13) Выдаем полную нагрузку по обоим ядрам:
vzctl set 101 --cpus 2 --cpulimit 200 --save; vzctl set 102 --cpulimit 200 --cpus 2 --save;

Схема нагрузки меняется мгновенно:
1  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
5  [||                                                        1.3%]
2  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
6  [                                                          0.0%]
3  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
7  [                                                          0.0%]
4  [|||||||||||||||||||||||||||||||||||||||||||||||||||||||||99.3%]    
8  [                                                          0.0%]   
14) А если дать одному контейнеру приоритет в два раза:
vzctl set 101 --cpus 2 --cpulimit 200 --cpuunits 100 --save; vzctl set 102 --cpulimit 200 --cpus 2 --cpuunits 200 --save;

То ничего не поменяется, так как нету конкуренции за ресурс - у ноды достаточно ресурсов.

15) Устроим небольшой оверселл по ядрам:

set 101 --cpus 6 --cpulimit 600 --cpuunits 100 --save; vzctl set 102 --cpulimit 600 --cpus 6 --cpuunits 200 --save;
1  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
5  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
2  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
6  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
3  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
7  [|||||||||||||||||||||||||||||||||||||||||||||||||||||||||99.3%]
4  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
8  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]

  
И при этом процессор поделится 1 к 2:
102:    cpu: 66.5 %   
101:    cpu: 33.3 %

16) Теперь рассмотрим интересный кейс - что будет какой контейнер позволит получить больше ресурсов. Контейнер с полным доступом к одному ядру или контейнер с двумя ядрами, но с лимитом суммарной нагрузки 50я % на каждое.

vzctl set 101 --cpus 2 --cpulimit 100 --cpuunits 100 --save; vzctl set 102 --cpulimit 100 --cpus 1 --cpuunits 100 --save;

1  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
5  [                                                          0.0%]
2  [                                                          0.0%]    
6  [                                                          0.0%]
3  [                                                          0.0%]    
7  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
4  [                                                          0.0%]    
8  [||                                                        1.3%]
 
Разделение при этом будет следующее:
102:    cpu: 49.8 %   
101:    cpu: 49.8 %

Но схема с полным доступом к одному ядру будет предпочтительнее при использовании ПО, которое плохо распараллеливается.

17) Рассмотрим кейс, когда контейнер с большим числом ядер получает меньший вес cpuunits, чем контейнер с меньшим числом ядер
vzctl set 101 --cpus 10 --cpulimit 1000 --cpuunits 100 --save; vzctl set 102 --cpulimit 500 --cpus 5 --cpuunits 200 --save;
Получим полную прогрузку машины:
1  [|||||||||||||||||||||||||||||||||||||||||||||||||||||||||97.4%]    
5  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
2  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
6  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
3  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
7  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]
4  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]    
8  [||||||||||||||||||||||||||||||||||||||||||||||||||||||||100.0%]

Приоритет возьмет свое и вторая машина получи ресурсов больше:
101:    cpu: 43.4 %
102:    cpu: 56.4 %   
Но тут нельзя сказать, что получит она ресурсов вдвое больше.

18) Этот пункт я добавил уже после публикации статьи, он исследует кейс поведения, как поведут себя контейнеры с одинаковым CPUUNITS, но разным числом процессоров, выданных контейнеру:
vzctl set 101 --cpus 8 --cpulimit 800 --cpuunits 100 --save; vzctl set 102 --cpulimit 200 --cpus 2 --cpuunits 100 --save;
А поведут они себя вот так (для чистоты эксперимента я запустил по 16 потоков утилиты stress в контейнерах):
101: cpu: 75.0 %  
102: cpu: 24.8 %
То есть, контейнер, которому дали большую процессорную мощность получит приоритет в 3-4 раза, как и ожидается. Но стоит обратить внимание, что очень сложно выдать приоритет контейнеру, у которого меньше ресурсов даже силами CPUUNITS.

Иными словами, довольно сложно дать приоритет контейнеру с 1 ядром, когда на ноде есть контейнеры с большим числом выданных ядер.

CPUS
 
CPUS - задает число логичеcких процессоров, которые доступны контейнеру. Стоит понимать, что если выдать  контейнеру 1 ядро, то его производительность будет жестко ограничена мощностью 1 ядра хост-сервера. Даже если на хост-серверер будут свободные ядра - контейнер их использовать не сможет. Это стоит учитывать всегда. Если данный параметр не указан или установлен в нуль - это означает, что контейнер может использовать все ядра хост-сервера.

Также стоит понимать, что логический процессор - это абстракция, в реальности процессы каждый раз выполняются на том ядре хост-сервера, у которого есть ресурсы.

Также параметр CPUS имеет важное значение при использовании параметра CPULIMIT.
CPULIMIT
 
CPULIMIT - задает максимальную суммарную нагрузку ядер контейнера. Максимально возможная нагрузка контейнера определяется так: N * 100, где N = числу ядер контейнера. То есть, если у контейнера 8 логических процессоров, то максимальное значение CPULIMIT может достигать 800.

В случае 1 процессора, выданного контейнеру, все просто - 50% означает 50% нагрузки на единственное ядро, то есть максимальная нагрузка на процессор ограничивается половиной ядра хост-сервера.

Если процессоров несколько, то все резко усложняется. Например, если задать CPULIMIT=100 для контейнера с двумя процессорами, то контейнер сможет нагружать каждое из выданных ему ядер не более чем на 50%.

Если же нужно полностью дать контейнеру, скажем, 4 ядра, то ему нужно выдать (4*100) CPULIMIT 400.

Именно этот параметр отображается внутри контейнера как частота виртуального процессора (Mhz /proc/cpuinfo). Частота рассчитывается вот так: HWN_FREQ * CPULIMIT / (100 * N_CPU), где N_CPU - число процессоров, выданных контейнеру. А HWN_FREQ - тактовая максимальная частота 1 ядра ноды. Например, в случае, когда у контейнера 2 ядра и CPULIMIT=100 мы получим: 1/2 HWN_FREQ (1.7 Ghz для моей тестовой ноды с процессором 3.4Ghz)

Лимит этот жесткий, то есть если на аппаратной ноде есть ресурсы, контейнер их не получит. Стоит обращать на это внимание!

CPUUNITS
 
CPUUNITS - задает отношение выделяемого процессорного времени одному контейнеру к другому. То есть, если задать для двух контейнеров 100 и 200, то второй получит вдвое больше ресурсов. CPUUNITS идеально работает когда контейнеру выдано 1 ядро. Но в случае многопроцессорных контейнеров и серьезной нагрузки на аппаратную ноду эти отношения перестают выполняться честно и второй контейнер будет получать больше ресурсов, чем первый, но не в два раза. Это объясняется особенности шедулера CFQ. Поэтому с разделением ресурсов между контейнерами с большим числом логических процессоров есть довольно серьезные проблемы.

Кого заинтересовала тулза open_vestat - могу поделиться, это скрипт обвязка cgroup на Perl, считает потребление cpu/blkio.time/blkio.sectors и отрисовывает топ10 грузящих контейнеров.

Tuesday, 12 August 2014

Монтирование /tmp на OpenVZ контейнерах в tmpfs

Самое интересное, что монтирование /tmp и прочих специализированных файловых систем осуществляет вовсе не нода, как можно подумать изначально. А сам контейнер. Поэтому в /etc/fstab в контейнере нужно прописать следующую строку:
tmpfs                   /tmp                    tmpfs   size=512m       0 0
И после этого сделать команду:
mount /tmp
Или перезапустить контейнер.

Все смонтируется ок:
cat /proc/mounts|grep 6617|grep '/tmp'
tmpfs /vz/root/6617/tmp tmpfs rw,relatime,size=524288k,nr_inodes=153600 0 0
А память в пределах tmpfs будет обсчитываться в контексте счетчика physpages контейнера и не требует дополнительных ограничителей.

В OpenVZ нигде /etc/fstab не обрабатывается, поэтому можно делать не боясь, что конфигурация будет сброшена:
grep -HiR 'fstab' /etc/vz/dists/*|wc -l
0

К сожалению, сам OpenVZ глобально управлять этим не умеет, а хотелось бы, поэтому прошу в баг трекер: https://bugzilla.openvz.org/show_bug.cgi?id=3040 и плюсуем таску :)

Как выполнить MySQL запрос внутри OpenVZ контейнера на Debian

 mysql -udebian-sys-maint --socket /vz/root/7431/var/run/mysqld/mysqld.sock --password=`cat /vz/root/7431/etc/mysql/debian.cnf|grep password |tail -n 1|awk '{print $3}'` -e "show processlist"

Monday, 11 August 2014

Подсчитать объем сетевых tcp буферов используемых VPS на OpenVZ

cat /proc/user_beancounters |egrep 'tcp(snd|rcv)buf'| perl -e 'my$rcv=0; my $snd=0; for(<>){my @data=split/\s+/; if ($data[1] eq 'tcprcvbuf') {  $rcv+=$data[2] } else { $snd+=$data[2]}}; $snd=int $snd/1024**2; $rcv=int $rcv/1024**2; print "snd buffers: $snd MB rcv buffer: $rcv MB\n"'

snd buffers: 538 MB rcv buffer: 306 MB

Monday, 4 August 2014

Использование suexec на CentOS 5 в собственных целях

Готовим окружение:
cd /var/www
mkdir /var/www/username
chown username:username /var/www/username
vim /var/www/username/suxx.sh



Кладем вот туда вот такой код:
#!/bin/bash
echo "suxx";
/usr/bin/id

Меняем права:
chown mamonov:mamonov  /var/www/username/suxx.sh
chmod +x /var/www/username/suxx.sh


Входим под апачем:
cd /var/www/username
su apache -s /bin/bash
suexec username username suxx.sh

И получаем желаемое:
bash-3.2$ id
uid=48(apache) gid=48(apache) группы=48(apache)

bash-3.2$ suexec mamonov mamonov suxx.sh
suxx
uid=501(mamonov) gid=501(username) groups=501(username)

Рекомендую книгу: Сеть. Как устроен и как работает Интернет

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

Если для Вас сеть - нечто непонятно, работающее с помощью магии облако - эта книга для Вас. Вы сразу же поймете гениальную простоту архитектуры Интернета.

Это книга о людях и компаниях, которые создали Интернет. Тут объяснены причины успеха ИНтернета и причины его появления.

Если AMX-IX, DE-IX, Sprint, Cogent, Equnix, BGP - для Вас пустые слова, то эта книга для Вас.

Купить можно в Буквоеде (Спб) либо Озоне: http://www.ozon.ru/context/detail/id/26326082/ (на единственный идиотский отзыв призываю не обращать внимания).

А также Вы можете подписаться на Твиттер автора: https://twitter.com/ajblum

Tuesday, 29 July 2014

Сборка GNU parallel для CentOS/RHEL

Проще некуда:
cd /usr/src
wget http://ftp.gnu.org/gnu/parallel/parallel-latest.tar.bz2
tar -xf parallel-latest.tar.bz2
cd parallel-20140722/
./configure --prefix=/opt/parallel
make install
/opt/parallel/bin/parallel
А еще - Parallel написан на Perl и сборки-то в общем не требует.