Docker: запуск 1000 контейнеров в Swarm кластере в K2 Cloud
О технологиях

Docker: запуск 1000 контейнеров в Swarm кластере в K2 Cloud

851
11 минут

По заверениям разработчиков на сегодняшний день Docker Swarm легко и просто позволяет масштабировать ваши приложения на множество хостов с десятков до тысяч контейнеров. Но выполняется ли это обещание в реальности?

Давайте проверим запуск 1000 контейнеров на трех виртуальных серверах в K2 Cloud и узнаем об этом наверняка.

Внедряем и поддерживаем Kubernetes/DevOps
Развертываем и сопровождаем инфраструктуру для бизнес-приложений на базе микросервисов и контейнеров

Запуск виртуальных машин

Весь эксперимент мы будем проводить на трех виртуальных серверах Ubuntu 16.04 размером m1.large (2 vCPU, 8 Gb RAM). Все серверы подключены к единой виртуальной сети и имеют следующие имена:

  • master.swarm-demo.avmaksimov.ru
  • node-1.swarm-demo.avmaksimov.ru
  • node-2.swarm-demo.avmaksimov.ru

Установка Docker

Разрешаем доступ к виртуальной сети по SSH (22/TCP) и 2376/TCP для управления хостами с Docker Machine.

Установим Docker на каждый из серверов следующими командами:


docker-machine create -d generic  
   --generic-ssh-user ec2-user 
   --generic-ssh-key ~/.ssh/id_rsa 
   --generic-ip-address 185.12.28.100 
   master.swarm-demo.avmaksimov.ru
docker-machine create -d generic 
   --generic-ssh-user ec2-user 
   --generic-ssh-key ~/.ssh/id_rsa 
   --generic-ip-address 185.102.122.120 
   node-1.swarm-demo.avmaksimov.ru
docker-machine create -d generic 
   --generic-ssh-user ec2-user 
   --generic-ssh-key ~/.ssh/id_rsa 
   --generic-ip-address 185.12.28.39 
   node-2.swarm-demo.avmaksimov.ru

Проверим установку:


docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
master.swarm-demo.avmaksimov.ru - generic Running tcp://185.12.28.100:2376 v17.03.1-ce
node-1.swarm-demo.avmaksimov.ru - generic Running tcp://185.102.122.120:2376 v17.03.1-ce
node-2.swarm-demo.avmaksimov.ru - generic Running tcp://185.12.28.39:2376 v17.03.1-ce

Инициализируем Swarm кластер. На master узле выполним команду:


eval $(docker-machine env master.swarm-demo.avmaksimov.ru) && 
   docker swarm init

Команда для выполнения на node-1 и node-2 будет в выводе предыдущей команды. Не забудьте переключить переменные окружения для клиента docker:


eval $(docker-machine env node-1.swarm-demo.avmaksimov.ru) && 
   docker swarm join 
   --token SWMTKN-1-5alztmf6vhq9sbxrlgd6fysdg1xasdfkoxahl7by9q6vt621u-aso816y7t5qk1n5l9qboxfi0g 
   192.168.1.11:2377
This node joined a swarm as a worker.
eval $(docker-machine env node-2.swarm-demo.avmaksimov.ru) && 
   docker swarm join 
   --token SWMTKN-1-5alztmf6vhq9sbxrlgd6fysdg1xasdfkoxahl7by9q6vt621u-aso816y7t5qk1n5l9qboxfi0g 
   192.168.1.11:2377
This node joined a swarm as a worker.

Проверим состояние Swarm кластера:


docker node ls
ID                           HOSTNAME                         STATUS  AVAILABILITY  MANAGER STATUS
co835i5lt8ojqi8av39euuvdp    node-1.swarm-demo.avmaksimov.ru  Ready   Active
jokrnk2o566g6flcim6hlmaow    node-2.swarm-demo.avmaksimov.ru  Ready   Active
o6b0kelc4n6u57ep6xt7bacyj *  master.swarm-demo.avmaksimov.ru  Ready   Active        Leader

Создадим для запуска тестовых контейнеров отдельную сеть:

eval $(docker-machine env master.swarm-demo.avmaksimov.ru) && 
   docker network create --driver overlay --subnet 10.0.0.0/20 
   --attachable swarm-scale-test-net
bx2idzv2629ed8mlfnvi4v6pj

Эта сеть будет использоваться всеми контейнерами для коммуникации друг с другом. Сетевая маска /20 даст нам возможность запускать в этой сети до 4 тысяч контейнеров. Ключ —attachable дает нам возможность запускать в этой сети не управляемые Docker Swarm (обычные) контейнеры, запускаемые при помощи команды docker run.

Настройка хостов

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

ARP кеш

Самое первое сообщение, которое вы увидите в выводе dmesg, если оставить sysctl настройки по умолчанию — neighbour: arp_cache: neighbor table overflow!. Эта проблема вызвана слишком маленьким ARP кешом по умолчанию, который будет не успевать очищаться.

Каждый запускаемый вами контейнер подключается к трем сетям:

  • swarm-scale-test-net — общая сеть, которую мы настроили
  • ingress — сеть, откуда поступает трафик с опубликованного порта на сервис
  • docker_gwbridge — публичная интернет сеть

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

ARP кешем управляют следующие настройки:


sysctl -w net.ipv4.neigh.default.gc_thresh1=8096
sysctl -w net.ipv4.neigh.default.gc_thresh2=12288
sysctl -w net.ipv4.neigh.default.gc_thresh3=16384
  • gc_thresh1 — минимальное количество данных, которое необходимо хранить в ARP кеше
  • gc_thresh2 — мягкое максимальное количество данных кеша
  • gc_thresh3 — жесткое максимальное количество данных

      Вообще говоря, работа с ARP кешем документирована слабо, поэтому обычно эти значения подбирают, умножая предыдущие значения на 2, до тех пор, пока система не начнет чувствовать себя нормально.

Другие важные настройки

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


# Определить большее количество портов (диапазон) для подключения
net.ipv4.ip_local_port_range=1024 65000

# Быстрее переиспользовать закрытые сокеты
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_fin_timeout=15

# Максимальное количество "накопившихся" сокетов.  По умолчанию 128.
net.core.somaxconn=4096
net.core.netdev_max_backlog=4096

# 16MB на сокет - скорее всего не будет 
# использоваться так много
net.core.rmem_max=16777216
net.core.wmem_max=16777216

# Общий сетевой тюнинг
net.ipv4.tcp_max_syn_backlog=20480
net.ipv4.tcp_max_tw_buckets=400000
net.ipv4.tcp_no_metrics_save=1
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_syn_retries=2
net.ipv4.tcp_synack_retries=2
net.ipv4.tcp_wmem=4096 65536 16777216

# Отслеживание соединений для предотвращения отбрасывания пакетов 
# (обычно проблема на балансировщиках)
net.netfilter.nf_conntrack_max=262144
net.ipv4.netfilter.ip_conntrack_generic_timeout=120
net.netfilter.nf_conntrack_tcp_timeout_established=86400

# Настройки ARP кеша для высоко нагруженного docker swarm-а
net.ipv4.neigh.default.gc_thresh1=8096
net.ipv4.neigh.default.gc_thresh2=12288
net.ipv4.neigh.default.gc_thresh3=16384

Запуск реплицированного сервиса

После того, как был произведен тюнинг хостов, давайте попробуем запустить наш сервис на 1000 контейнеров в Docker Swarm кластере. В качестве сервиса будет использоваться очень маленький образ titpetric/sonyflake, предназначенный для генерации ID-шников и отдачи их по HTTP. Исходный код сервиса доступен на GitHub


docker service create 
   --replicas 1000 
   --network swarm-scale-test-net 
   --update-parallelism 5 
   --name sonyflake 
   -p 80:80 
   titpetric/sonyflake

Пара минут и все контейнеры запустились!


docker service ls

ID NAME MODE REPLICAS IMAGE
uxtfzjy7q203 sonyflake replicated 1000/1000 titpetric/sonyflake:latest

Небольшой тест

В качестве теста будет использоваться Wrk — современный инструмент тестирования производительности HTTP, способный генерировать значительную нагрузку при работе даже с одним многоядерным процессором. Он сочетает в себе многопоточный дизайн с масштабируемыми системами уведомления о событиях, такими как epoll и kqueue.


docker run 
   --net=swarm-scale-test-net 
   --rm williamyeh/wrk 
   -t 6 
   -c 30 
   http://sonyflake

Running 10s test @ http://sonyflake
  6 threads and 30 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.69ms    1.87ms  45.42ms   91.81%
    Req/Sec     2.55k     0.88k    8.27k    80.97%
  152568 requests in 10.08s, 29.79MB read
Requests/sec:  15137.45
Transfer/sec:      2.96MB

Уменьшим количество запущенных контейнеров до 30.

docker service scale sonyflake=30

Проверить статус операции можно командой


docker ps -a --format "{{.Status}}"  | sort | uniq -c

 470 Dead
   181 Removal In Progress
   8 Exited (2) About a minute ago
   8 Up 56 minutes
   3 Up 58 minutes
   3 Up 59 minutes
   8 Up About an hour

Как только количество контейнеров в статусе «Removal in Progress» станет равно нулю и docker service ls будет показывать 30/30, проведем тест еще раз


docker run 
   --net=swarm-scale-test-net 
   --rm williamyeh/wrk 
   -t 6 
   -c 30 
   http://sonyflake

Running 10s test @ http://sonyflake
  6 threads and 30 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.36ms    1.06ms  18.20ms   80.58%
    Req/Sec     2.64k     1.26k    7.63k    83.67%
  157952 requests in 10.09s, 30.84MB read
Requests/sec:  15651.65
Transfer/sec:      3.06MB


Результаты теста показывают примерно 30% увеличение времени ответа каждого отдельного контейнера при увеличении количества запускаемых контейнеров в 30 раз (с 30 до 1000), обуславливаемое контекстным переключением CPU каждого сервера кластера, затрачиваемое на обслуживание работы каждого отдельного docker процесса.

Мы успешно протестировали возможности Docker Swarm кластера и запустили в нем 1000 контейнеров. Создать и запустить для этого теста виртуальную инфраструктуру в K2 Cloud заняло у меня считанные минуты, а производительности даже таких небольших виртуальных серверов с лихвой хватило на обслуживание работы такого количества контейнеров. Само собой, чтобы запустить еще большее количество микросервисных контейнеров на одном виртуальном сервере, нужно еще чуть-чуть увеличить параметры sysctl.

15 ноября 2022
OpenShift остался без поддержки – как решить проблему российским клиентам
Интерес к семейству ПО для контейнеризации OpenShift был довольно высоким в корпоративном сегменте в прежние годы. По данным мониторинговой службы Datadog, только за прошлый год во всем мире количество пользователей платформ от RedHat увеличилось на 28%. Весной IBM объявил об уходе из России и прекращении поддержки всех программных продуктов для текущих клиентов. Разберемся, насколько критичной оказалась данная ситуация для заказчиков, и какие варианты действий существуют, чтобы минимизировать возможные риски отключения от сервиса.
0 минут
624
25 февраля 2021
Свидетели DevOps: мифы и байки про девопсов и тех, кто их нанимает
Те, кто решил стать девопсом, видят в этой профессии заманчивые перспективы. Это новый уровень мышления, это творчество и возможность создавать, это безграничные просторы для самосовершенствования. Не секрет также, что девопсам хорошо платят. Вместе с тем, вокруг понятия DevOps сформировался некий культ, овеянный мифами и легендами.
0 минут
843
4 декабря 2020
Дайджест обновлений К2 Облака осень 2020 г.
За осень в К2 Облаке многое изменилось. Мы активно писали код и не успевали сообщать обо всех переменах. Постараемся исправиться и информировать вас ASAP, чтобы вы могли сразу же использовать новые фичи.
1 минута
256
scrollup