FastNetMon

Wednesday, 20 May 2015

Technical comparison of OpenVZ and commercial Virtualization Platforms from Parallels/Odin


There are bunch promotion articles about PCS (Parallels/Odin Cloud Server) and Virtuozzo. But I can't find any technical comparison between OpenVZ (open source and free) and commercial platforms.

I have 7 years experience with OpenVZ and 2 year experience with PCS in heavy production, thus I could create this comparison table manually :)


Feature Commercial OpenVZ
API Yes No
Central management Yes, PVA (awfully buggy) No, multiple open source solutions
Toolkit for compaction of fat ploop images Yes, pcompact No, but could be done in few lines of code with vzctl compact
Toolkit for migration physical servers to containers Yes, p2c migrate No
Rebootless kernel update (without physical server rebootm kernel reboot only) Yes, vzreboot No
Pure kernel live updates (without physical server reboot, no kernel reboot) No, only with external tool KernelCare No, only with external tool KernelCare
Repair mode for VPS Yes No
Live migration between servers (no zero downtime) Yes Yes
Live migration between servers (zero downtime) Yes No
Flexible container OS templates Yes, vztemplates No, only precreated templates
Memory deduplication for binary files Yes, pfcache techology No
Support for cloud storages for containers Yes, Parallels Cloud Storage No, only NFS
Completely isolated disk subsystem for containers Yes, ploop Yes, ploop
Support for fully virtualized virtual machines Yes, bundled support for Parallels VM No but works perfectly with KVM on same server
Fast and reliable kernel on top of RHEL 2.6.32 Yes (same version as OpenVZ) Yes
Full backup capability Yes No but open source solutions exists
Incremental backup Yes No and no open source solutions
NUMA optimization (balancing) Yes No, but some open source solutions exists
Finally, you could decide what are you want and select proper product for your company.

Tuesday, 19 May 2015

Технология дедупликации бинарных файлов в OpenVZ - pfcache и оценка ее эффективности

Что это такое?

Это довольно грамотный и умный механизм, суть которой сводится к хешированию (SHA-1) определенных файлов в папках (стандартно /bin, /lib, /lib64, /opt, /sbin, /usr источник, стр 15) внутри контейнера и сохранению их хэшей в расширенных атрибутах ext4 (xattr).

То есть схема такая:
1) Ставится ОС в контейнер
2) User space демон pfcached забегает в контейнер и прописывает SHA-1 хэши в расширенные атрибуты ext4 для всех файлов в папках /bin, /lib, /lib64, /opt, /sbin, /usr.

В случае, когда установка идет из ранее подготовленных ploop тушек, генерации можно избежать. Также ее можно избежать, если особым образом перепаковать обычные щаблоны с download.openvz.org.

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

Также подобные «общие» файлы выносятся (тупо копируются) в отдельную файловую иерархию /vz/pfcache силами специального демона (имеется лишь в проприетарной версии OpemVZ - PCS/Virtuozzo). За счет этого множественные загрузки данных бинарных файлов в память из разных контейнеров приводят к тому, что они занимают меньше места в оперативной памяти и кэшируются (в страничном кэше Linux) ровно один раз. Что дает очень весомый профит в экономии памяти и работе системы в целом. Причем, наибольшей экономии удается добиться именно в случае, когда все контейнеры максимально унифицированы по версиям ПО/дистрибутивам.

Ради интереса содержимое этого спец дескриптора можно прочесть вот так:
getfattr -ntrusted.pfcache --only-values /vz/root/51822/usr/lib/apache2/mpm-prefork/apache2 2>/dev/null
На выходе получим обычный SHA1:
563a0ab97f09171c4b5ac9bcf1602c2aeb3eab18
Насколько это эффективная штука можно провести исследование самолично: https://gist.github.com/vps2fast/eb15c7de0dd7ff38a30e

В конкретно нашем случае (довольно большой разброд в ОС - 3 версии Debian, 2 версии CentOS + немного кастомных дистрибутивов и все это в различном состоянии обновленности)экономия составила около 2.5-4%, что очень высокая цена за фактическую потерю одного ядра (используется процессом pfcached, который хэширует файлы).

Но в случае, когда у Вас везде одна и та же ОС - это может дать весьма положительный эффект.

Monday, 18 May 2015

Оценка эффективности сжатия OpenVZ ploop образов

Общее

В процессе эксплуатации наших ферм (а именно при их резервированными посредством нашего кастомного бэкап решения) мы обнаружили, что в среднем бинарные файлы ploop сжимаются в 2-4 раза (в зависимости от данных хранимых внутри). При этом используемое нами оборудование позволяет выполнять сжатие посредством многопоточного архиватора pigz на столь высоких скоростях, что время просто архивации без сжатия совпадает со временем архивации со сжатием, также при этом используется довольно малое число процессорных ресурсов.

Преимущество сжатие образов

Во-первых, при сжатии мы экономим довольно серьезно объем данных требуемый для хранения контейнеров, то есть снижаем стоимость владения за счет экономии места на дорогой СХД. Во-вторых, мы выигрываем в скорости за счет того, что с/на системы хранения читается/записывается как минимум вдвое меньше данных.

Тесты

Чтобы максимально четко описать преимущества и реальную эффективность подхода мы выбрали наиболее "реальные" серверы с реальными клиентами и произвели замеры эффективности их сжатия. В процессе тестов мы попытались выполнить бинарное сжатие посредством архиватора gzip/pigz с целью показать, что внедрение функции сжатия в ploop контейнеры может дать огромный эффект по ускорению доступа к данным, а также по экономии дискового пространства. Далее приводятся результаты сжатия ploop образов от OpenVZ и Parallels Cloud Server. Сжатие осуществлялось тулкитом pigz: tar --use-compress-program=pigz -cpf

testovz1 / OpenVZ

Объем, занимаемый ploop образами до сжатия:  161G
После сжатия: 83 Gb
Итог: 1.93 раза сжатие

testpcs1 / Parallels Cloud Server

Объем, занимаемый ploop образами до сжатия:  427G
После сжатия: 258G
Итог: 1.6 раза сжатие

Выводы

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

Sunday, 17 May 2015

Python: TypeError: execve() arg 3 contains a non-string value

This code will definitely produce this error:
new_env = os.environ.copy()
new_env['MY_ENV'] = 1234
subprocess.Popen( ['/bin/echo'], env=new_env)
How to fix? Add explicit conversion to str():
new_env = os.environ.copy()
new_env['MY_ENV'] = str(1234(
subprocess.Popen( ['/bin/echo'], env=new_env)

Как избавится от "No irq handler for vector (irq -1)" внутри KVM машины?

Среда - Debian 7 на железе и внутри виртуальной машины. Просто надо вырубить irqbalanced и на ноде и внутри виртуальной машины!

Если машины на systemd, то делать это так:
systemctl stop irqbalance
systemctl disable irqbalance

Saturday, 16 May 2015

Mac OS и упорщение ssh логина к машинам через jump хост

Всем привет!

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

То есть, схема следующая, мы логинимся на хост: ssh jump.ru, а после этого логинимся на хост ssh target.ru.

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

Но можем ли мы прописать тот же публичный ключ и войти по нему на машину target? Нет, не можем, потому что в этом случае нам придется положить свои приватные ключи на потенциально небезопасную машину jump.

Но как же тут быть? Тут нам поможет мега фича ssh под названием ssh-agent!

Суть ее в том, что ssh выдает доступ к приватному ключу посредством безопасного канала прямо от машины target до на нашей клиентской машины!

Для начала, на машину target нужно положить свой публичный ssh ключ.

Но эта фича в Mac OS отключена по умолчанию, включаем:
sudo vim /etc/ssh/ssh_config

И правим там вот так:
 Host *
   SendEnv LANG LC_*
   ForwardAgent yes
После этого пробуем залогинится на машину jump:
ssh jump

И смотрим содержимое переменных среды:
env|grep SSH_AUTH_SOCK
SSH_AUTH_SOCK=/tmp/ssh-12312asdasdasd/agent.5616
Это означает, что все заработало как нужно - безопасный сокет для обращения к ssh agent с клиентской машины был корректно передан на машину jump.

А после этого как ни в чем ни бывало заходим на машину target, без запроса пароля - используя ранее одобренный сертификат:
ssh target
А можно сделать еще круче, объединить логин на jump хост с логином на машину target:
ssh -t -jump "ssh target"
 Вот так можно сильно упростить себе жизнь! :)

Thursday, 14 May 2015

Birq - really awesome tool for IRQ interrupts balancing over all available cores

Site: https://src.libcode.org/birq Nice documentation: https://github.com/pavel-odintsov/birq_mirror/blob/master/doc/birq.md

Зеркало: https://github.com/pavel-odintsov/birq_mirror

Standard install:
cd /usr/src
git clone https://src.libcode.org/birq
cd birq
apt-get install -y autoconf
./autogen.sh
./configure --prefix=/opt/birq
make install
Run it with debug:
/opt/birq/sbin/birq   --verbose --debug
Awesome logic and care about NUMA/PCI-E locality here:
CPU0 package 0, core 0, irqs 2, old 1.84%, load 1.92%
    IRQ  14, [00000001], weight 0, intr 9, ata_piix
    IRQ  46, [00000001], weight 0, intr 32359, eth1-TxRx-6
CPU1 package 1, core 0, irqs 3, old 1.44%, load 1.67%
    IRQ   1, [00000002], weight 0, intr 0, i8042
    IRQ  15, [00000002], weight 0, intr 0, ata_piix
    IRQ  47, [00000002], weight 0, intr 32385, eth1-TxRx-7
CPU2 package 2, core 0, irqs 3, old 1.23%, load 1.67%
    IRQ   6, [00000004], weight 0, intr 0, floppy
    IRQ  40, [00000004], weight 0, intr 32374, eth1-TxRx-0
    IRQ  48, [00000004], weight 0, intr 0, eth1
CPU3 package 3, core 0, irqs 2, old 1.23%, load 2.33%
    IRQ   8, [00000008], weight 0, intr 0, rtc0
    IRQ  41, [00000008], weight 0, intr 32376, eth1-TxRx-1
CPU4 package 4, core 0, irqs 2, old 2.06%, load 2.32%
    IRQ   9, [00000010], weight 0, intr 0, acpi
    IRQ  42, [00000010], weight 0, intr 32331, eth1-TxRx-2
CPU5 package 5, core 0, irqs 2, old 1.85%, load 1.45%
    IRQ  10, [00000020], weight 0, intr 0, uhci_hcd:usb3, uhci_hcd:usb4, virtio0
    IRQ  43, [00000020], weight 0, intr 32322, eth1-TxRx-3
CPU6 package 6, core 0, irqs 2, old 2.70%, load 2.50%
    IRQ  11, [00000040], weight 0, intr 2, ehci_hcd:usb1, uhci_hcd:usb2, eth0
    IRQ  44, [00000040], weight 0, intr 32366, eth1-TxRx-4
CPU7 package 7, core 0, irqs 2, old 1.85%, load 1.67%
    IRQ  12, [00000080], weight 0, intr 0, i8042
    IRQ  45, [00000080], weight 0, intr 32353, eth1-TxRx-5

Tuesday, 12 May 2015

Build libcuckoo on Mac OS X 10.10 Yosemite

Install ports:
sudo port install automake autoconf m4 libtool
Pull code:
cd /usr/src
git clone https://github.com/efficient/libcuckoo.git
Build it:
autoreconf -fis
./configure --prefix=/op/libcuckoo
make
make install

Friday, 8 May 2015

pepsal 2.0.1 compilation on CentOS 6

Get code and build:
cd /usr/src/
wget 'http://downloads.sourceforge.net/project/pepsal/pepsal/pepsal-2.0.1/pepsal-2.0.1.tar.gz?r=https%3A%2F%2Fsourceforge.net%2Fprojects%2Fpepsal%2F&ts=1431072304&use_mirror=netcologne' -Opepsal-2.0.1.tar.gz
tar -xf pepsal-2.0.1.tar.gz
cd pepsal-2.0.1/
yum install -y libnetfilter_queue-devel
./configure --prefix=/opt/pepsal
But unfortunately something bad with code:
LANG=C make install
Making install in src
make[1]: Entering directory `/usr/src/pepsal-2.0.1/src'
gcc -DHAVE_CONFIG_H -I. -I../include    -I../include -g -O2 -MT pep.o -MD -MP -MF .deps/pep.Tpo -c -o pep.o pep.c
In file included from ../include/pepdefs.h:4,
                 from ../include/pepsal.h:16,
                 from pep.c:13:
/usr/include/sys/user.h:32: error: expected specifier-qualifier-list before '__uint16_t'
pep.c: In function 'nfqueue_get_syn':
pep.c:511: warning: passing argument 2 of 'nfq_get_payload' from incompatible pointer type
/usr/include/libnetfilter_queue/libnetfilter_queue.h:116: note: expected 'unsigned char **' but argument is of type 'char **'
make[1]: *** [pep.o] Error 1
make[1]: Leaving directory `/usr/src/pepsal-2.0.1/src'
make: *** [install-recursive] Error 1

And we need fix code. Please open include/pepdefs.h with editor and add this line before line #include <sys/user.h>:
#include <bits/types.h>

And compile again!

Well, everything works fins:
/opt/pepsal/bin/pepsal -V
PEPSal ver. 2.0.0
This bug related with broken code in sys/user.h: https://bugs.archlinux.org/task/20181

Tuesday, 5 May 2015

Linux TCP timestamp и его генерация

Столкнулся с интересной задачей по сетям и полез разбираться, как же генерируется TCP Timestamp в Linux. Испытания было решено провести на Linux 3.16 и моем любимом Debian Jessie.

Итак, для начала поднимем любой  http сервер на локалхосте и дернем его curl'ом с той же машины, глядя в этот момент на показания tcpdump.

 18:25:40.137056 IP 127.0.0.1.33673 > 127.0.0.1.80: Flags [S], seq 4291943858, win 43690, options [mss 65495,sackOK,TS val 170139796 ecr 0,nop,wscale 7], length 0
18:25:40.137079 IP 127.0.0.1.80 > 127.0.0.1.33673: Flags [S.], seq 3577086755, ack 4291943859, win 43690, options [mss 65495,sackOK,TS val 170139796 ecr 170139796,nop,wscale 7], length 0
Ок, что мы тут видим? Мы видим число 170139796,  которое и является TCP timestamp.

Как же оно сгенерировано?

После часа поисков по коду Линукс Ядра я наткнулся на вот такой код в файле include/net/tcp.h:
/* TCP timestamps are only 32-bits, this causes a slight
 * complication on 64-bit systems since we store a snapshot
 * of jiffies in the buffer control blocks below.  We decided
 * to use only the low 32-bits of jiffies and hide the ugly
 * casts with the following macro.
 */
#define tcp_time_stamp          ((__u32)(jiffies))
Стало быть, некий jiffie (который сам по себе 64 битный) преобразуется в 32 битное значение, путем отсечения старших битов.

Но что же такое jiffie и как его посчитать? Вопрос сложный и мерзкий. Если кратко, то jiffies - это число срабатываний прерываний таймера в Linux с момента загрузки системы (ключевое слово uptime).

Интерес заключается в том, что для каждой системы частота этого таймера индивидуальна (и зовется общепринято - HZ) и я потратил очень много времени прежде чем узнал, как часто срабатывает этот таймер на моей машине (на вашей показания могут быть совершенно иные!).

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

Ровно в момент когда я дергал curl я также загрузил этот модуль ядра и получил в dmesg следующие показания:
[680865.248893] Current jiffie: 4465108609
[680865.249188] Current jiffie converted to timestamp: 170141313
[680865.249480] Current HZ: 250
В то время, как все возможные статьи в интернете говорили о том, что HZ либо 100 либо 1000, но уж никак не 250.

Опа! Вы уже заметили. что странное число в поле "current jiffie converted to timestamp" очень похоже на TCP timestamp? Поздравляю! Это он и есть. Осталось понять, как он все-таки получается и как связан с аптаймом машины.

Итак, мы узнали, что таймер работает с частотой 250 герц, то есть срабатывает 1/250 раз в секунду. Чтобы перевести jiffies в секунды нужно jiffies поделить на HZ, получится следующее:
perl -e 'print 170141313/250'
680565.252
А в свою очередь это время в секундах показывающее, как давно был загружен сервер, его можно также взять в переменной /proc/uptime (первое число):
cat /proc/uptime
681437.68 5443271.52
Также uptimе можно получить с помощью соответствующей команды:
uptime
18:39:48 up 7 days, 21:21,  3 users,  load average: 0.11, 0.06, 0.06

Итак, мы теперь можем имея время аптайма в секундах сами сгенерировать TCP timestamp просто умножив на показания из /proc/uptime на 250 и отбросив дробные значения :)


Утилита для мониторинга нагрузки на процессор и диск от контейнеров OpenVZ

Прощу встречать и жаловать: https://github.com/FastVPSEestiOu/open_vestat

Тулкит долго время использовался нами для внутренних целей диагностики и недавно решено было поделиться им с Сообществом!

Тулза выдает вот такие крутые отчеты:

Thursday, 30 April 2015

How to sniff interface on remote machine with Wireshark from Mac OS?

Execute following commands on Mac OSX console.

Create fifo:
mkfifo /tmp/remote
Run wireshark:
wireshark -k -i /tmp/remote
And run tcpdump to this fifo over ssh:
ssh root@10.0.xxx.xxx  "tcpdump -s 0 -U -n -w - -i eth1 -S" > /tmp/remote
Works nice!

Source: http://serverfault.com/questions/362529/how-can-i-sniff-the-traffic-of-remote-machine-with-wireshark

Wednesday, 29 April 2015

How to code for DPDK with C++

Hello!

If you want to code for DPDK with C++ you need some beer and half of day for digging into DPDK maillist.

Or you could use my manual and do it in seconds!

Lets' go! First of all, please download and build DPDK 2.0.0 into folder /usr/src/dpdk2.0.0

After this, please download files https://www.dropbox.com/s/hy3eisssxn2cp1f/rte.compile-pre.mk?dl=0 and https://www.dropbox.com/s/u2bkcfl35yejwx4/rte.vars.mk?dl=0 and replace files /usr/src/dpdk-2.0.0/mk/toolchain/gcc/rte.vars.mk and /usr/src/dpdk-2.0.0/mk/internal/rte.compile-pre.mk accordingly.

After this you should fix you project Makefile and rename main.c to main.cpp.

I could provide example file for you%
ifeq ($(RTE_SDK),)
$(error "Please define RTE_SDK environment variable")
endif

# http://patchwork.dpdk.org/ml/archives/dev/2014-January/001127.html
CC=g++

# Default target, can be overriden by command line or environment
RTE_TARGET ?= x86_64-native-linuxapp-gcc

include $(RTE_SDK)/mk/rte.vars.mk

# binary name
APP = example

# all source are stored in SRCS-y
SRCS-y := main.cpp


CXXFLAGS += -std=gnu++11
CFLAGS += -O3
CFLAGS += -Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable
LDFLAGS += -lstdc++

include $(RTE_SDK)/mk/rte.extapp.mk
My huge thanks to author of this patches http://patchwork.dpdk.org/ml/archives/dev/2014-January/001127.html :)

Sunday, 26 April 2015

Поддержка BGP силами ExaBGP добавлена в тулкит для выявления DDoS атак FastNetMon

Прошу к официальной документации на GitHub :) Теперь можно обойтись без кривых скриптов и анонсировать атакуемый хост прямо силами BGP.