LINUX.ORG.RU
ФорумAdmin

Создание множества виртуалок с разными ip

 , , , ,


0

1

Добрый день, задача такая - надо создать много (100-500) виртуальных контейнеров на одной машине с уникальными ip. Каждый из них будет выполнять наипростейшии задачи - чтение из файла и построчная отправка на один сервак. Я так понимаю тут надо смотреть в сторону xen, docker? Или есть решение более оптимальное? Если не сложно поделитесь сылочками на мануалы.

Спасибо.

★★★★★

Важное замечание, необходимо что бы внешний сервак и все ip виртуалок были в одной подсети.

Dudraug ★★★★★ ()
Ответ на: комментарий от Dudraug

А сервер и виртуалки физически на одной машине? Если да, то никаких проблем. Универсально будет сделать под такое дело впн, но это из пушки по воробьям тоже будет.

imul ★★★★★ ()
Ответ на: комментарий от imul

Нет, сервак на винде вообще. То есть грубо говоря сеть такая

<сервер с виндой>---свич----<машина(ы) с виртуалками>

Желательно чтобы машина с виртуалками была одна, но можно и парочку. Идея в том, чтобы создать нагрузочное тестирование на сервак. А сервак к сожалению виндовый. И важно, что бы каждый клиент имел уникальный ip (то есть всякие NAT не подходят).

Dudraug ★★★★★ ()
Последнее исправление: Dudraug (всего исправлений: 1 )
Ответ на: комментарий от imul

nspawn

Хм, в принципе на сколько я понимаю надо просто сначала нагеренерить виртуальные интерфейсы на хосте в нужном кол-ве eth0:<n>. А потом запустить nspawn (в скрипте в цикле) для процесса эмуляции с опцией --network-interface=

Если это работает, то думаю то что нужно. Хотелось бы конечно такое под линукс, но в принципе сойдет=)

Dudraug ★★★★★ ()

Смотреть про tproxy.

Есть возможность устанавливать соединение с не локального адреса. Главное, чтоб ответный трафик шел через эту же мащину.

setsockopt(sock,SOL_IP, IP_TRANSPARENT,1);

bind(sock,nonlocal-ip)

Я так в свое время тестировал почтовик.

vel ★★★★★ ()
Последнее исправление: vel (всего исправлений: 1 )
Ответ на: комментарий от Dudraug

Оно и есть под линукс. Просто вдруг ты сыстемдэненавистник.
Насчёт одной машины. nspawn очень лёгкий недоконтейнер, но даже сотня таких виртуалок потребует неплохой компьютер. Там же в контейнере будет 6-7 процессов.

imul ★★★★★ ()
Ответ на: комментарий от staseg

Возможно виртуальные интерфейсы то что нужно, но как заставить конкретный инстанс процесса слать инфу через конкретный интерфейс?

То есть если на машине скажем 3 виртуальных интерфейса 192.168.1.1, 192.168.1.2, 192.168.1.3, то как нам запустить три экземпляра приложения (одного), что бы каждый экземпляр слал инфу через свой eth0:n?

Dudraug ★★★★★ ()
Ответ на: комментарий от imul

Оно и есть под линукс

Просто я почему-то подумал не о systemd тут, а о бсд=)

Dudraug ★★★★★ ()
Ответ на: комментарий от Dudraug

как заставить конкретный инстанс процесса слать инфу через конкретный интерфейс?

Снаружи процесса — не знаю. А так man bind / SO_BINDTODEVICE.

staseg ★★★★★ ()
Ответ на: комментарий от vel

Я это когда-то с наскоку не осилил и благополучно забыл. Спасибо, что напомнил :) Вот и третий вариант.

staseg ★★★★★ ()
Ответ на: комментарий от Dudraug

И важно, что бы каждый клиент имел уникальный ip (то есть всякие NAT не подходят).

Это еще почему?

snaf ★★★★★ ()
Ответ на: комментарий от snaf

Потому что сервак различает клиентов по ip, то есть создает коллекции, задачи, структуры по ip, ведет статистику и прочее. Цель - создать нагрузочное тестирование близкое к реальному, значит надо симулировать множество клиентов.

Dudraug ★★★★★ ()
Ответ на: комментарий от vel

Так, посмотрел ман пока не въехал до конца. Можешь ответить на вопрос ниже да/нет и если ответ да, то буду ковырять и разбираться.

Позволяет ли мне этот метод сделать следующее:

Запустить 100 экземпляров одного приложения. Каждый инстанс должен слать инфу на сервак с известным айпи. Каждый инстанс должен выглядеть для сервака отдельной машиной с собственным айпи. Выбор айпи для каждого инстанса пусть будет внешний (передача через параметр, выбор из пула, неважно, но допустим мы уже знаем нужный наш клиентский ip на момент старта каждого экземпляра) ?

Dudraug ★★★★★ ()
Ответ на: комментарий от Dudraug

Проще говоря я пускаю

myapp 192.168.1.2

И он запускает приложение которое шлет инфу на сервак, при этом для сервака он выглядит как клиент с ip 192.168.1.2, при этом это не является локальным ip и на него не создавался виртуальный интерфейс?

Dudraug ★★★★★ ()
Последнее исправление: Dudraug (всего исправлений: 2 )
Ответ на: комментарий от Dudraug

как нам запустить три экземпляра приложения (одного), что бы каждый экземпляр слал инфу через свой eth0:n?

А есть исходники и на чём написано?

imul ★★★★★ ()
Ответ на: комментарий от Dudraug

Насколько неплохой компьютер?

Ну вместо одного процесса клиента пустятся ещё 5-6 процессов в виртуалке. Всё это будет жрать память и время процессора. То есть вместо 100 полезных процессов у тебя будет 600-700.

imul ★★★★★ ()
Ответ на: комментарий от Dudraug

1) Клиентское приложение имеет возможность указать адрес с которого выполняется коннект ( т.е. оно может делать bind() на указанный ей адрес)?

2) исходники клиента есть ? т.е. добавить setsockopt() можно ? Теоретически это можно изобразить через LD_PRELOAD ( http://www.ryde.net/code/bind.c.txt )

IMHO создавать контейнер для запуска одной программы - слишком жирно.

vel ★★★★★ ()
Ответ на: комментарий от Dudraug

Приложение еще не существует, но планирую на си или плюсах.

Если на C то google:// use bind() before connect()
Наверняка нагуглишь примеров как привязаться к конкретному адресу для отправки пакетов.
На плюсах хз, 15 лет на них не писал уже.

imul ★★★★★ ()
Ответ на: комментарий от imul

PS: вот ещё вспомнил. zabbix-agentd умеет ходить на сервер с определённого (указанного в конфиге) адреса. Можно там ещё в код глянуть, как именно сделано.

imul ★★★★★ ()
Ответ на: комментарий от imul

Если на C то google:// use bind() before connect()

Присоединюсь, в структуре sockaddr_in указать адрес.

anc ★★★★★ ()
Ответ на: комментарий от vel

Написал такой код.

  int fd,portno;

  char buffer[256];
  struct sockaddr_in serv_addr;

  if (argc < 2)
  {
    fprintf(stderr,"ERROR, no port provided");
    exit(1);
  }

  fd = socket(AF_INET, SOCK_STREAM, 0);


  if (fd < 0)
    perror("ERROR opening socket");
  int value = 1;
  setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value));

  portno = atoi(argv[1]);

  serv_addr.sin_family = AF_INET;

  serv_addr.sin_port = htons(portno);

  serv_addr.sin_addr.s_addr = htonl(0xA000004);

  if (bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
    perror("ERROR on binding");

От админа делал это

# iptables -t mangle -N DIVERT
# iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
# iptables -t mangle -A DIVERT -j MARK --set-mark 1
# iptables -t mangle -A DIVERT -j ACCEPT

# ip rule add fwmark 1 lookup 100
# ip route add local 0.0.0.0/0 dev lo table 100

Если интерфейс с ip 10.0.0.4 не поднят на этой машине, то выдает

ERROR on binding: Cannot assign requested address
Dudraug ★★★★★ ()

Делал такое для эмуляции кучи onvif устройств. Там общение идёт по http, т.е. tcp. Создаёшь на компе кучу ip. На Qt __один__ сервак QTcpServer поднимался вот так: m_server->listen(QHostAddress::Any, port);

И всё. Больше ничего не надо. Через какой ip к серваку обращались, через этот же ему и ответит.

anonymous ()
Ответ на: комментарий от vel

О и правда, чот тупанул. Поставил и понял, что от рута пускать надо.

Dudraug ★★★★★ ()
Ответ на: комментарий от vel

Все равно не работает

int main(int argc, char *argv[])
{
  int fd,portno;

  char buffer[256];
  struct sockaddr_in serv_addr;

  if (argc < 2)
  {
    fprintf(stderr,"ERROR, no port provided");
    exit(1);
  }

  fd = socket(AF_INET, SOCK_STREAM, 0);


  if (fd < 0)
    perror("ERROR opening socket");
  int value = 1;
  if (setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value)) < 0) 
    perror("ERROR setsockopt");

  portno = atoi(argv[1]);

  serv_addr.sin_family = AF_INET;

  serv_addr.sin_port = htons(portno);

  serv_addr.sin_addr.s_addr = htonl(0xA000002);

  if (bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
    perror("ERROR on binding");

  buffer[0] = 1;
  buffer[1] = 2;
  struct sockaddr_in servaddr;
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(8000);
  servaddr.sin_addr.s_addr = htonl(0xA000001);
  printf("11\n");

  if (connect(fd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
     perror("ERROR on connect");
  printf("22\n");
  if (send(fd, &buffer, 2, 0 ) < 0)
    perror("ERROR on sending");

 
  return 0;
}

tcpdump на стороне клиента пишет

14:41:36.016746 ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46
14:41:37.017506 ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46
14:41:38.017616 ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46

10.0.0.4 - фейковый ip, 10.0.0.1 - ip сервака

Все виснет на коннекте.

tcpdump на серваке даже видит входящие пакеты

14:41:36.016746 ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46
14:41:37.017506 ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46
14:41:38.017616 ARP, Request who-has 10.0.0.4 tell 10.0.0.1, length 46
Dudraug ★★★★★ ()
Ответ на: комментарий от Dudraug

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

Зачем использовать адреса из локального сегмента ? Это так необходимо ? Это же тестирование...

Берем блок адресов ( не из локалки ) 172.17.0.0/16 и на сервере добавляем маршрут в него через клиента - ответные пакеты будут возврашаться и tproxy будет работать. При выполнении запроса биндимся на любой адрес из этого блока адресов.

Есть более тонкий вариант - роутить на клиента только ответные пакеты с сервиса, но это нужно на сервере policy-routing городить, а с блоком адресов все намного проще.

vel ★★★★★ ()
Ответ на: комментарий от vel

Берем блок адресов ( не из локалки ) 172.17.0.0/16 и на сервере добавляем маршрут в него через клиента - ответные пакеты будут возврашаться и tproxy будет работать. При выполнении запроса биндимся на любой адрес из этого блока адресов.

хм, опробуемс

Dudraug ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.