Используйте Docker Swarm для создания распределенного кластера поисковых роботов.

сервер Docker рептилия Swarm

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

Иногда сканеру нужно работать только на одном сервере, иногда — на 200 серверах. Как ты так быстро переключился? Один сервер, один переключатель для входа в систему? Или быть умнее, поставить модифицируемую отметку в Redis, и будет работать только краулер на сервере, соответствующем отметке?

Искатель A был развернут на всех серверах, а теперь создан искатель B. Нужно ли вам по очереди входить на каждый сервер для повторного развертывания?

Если да, то вы должны сожалеть, что не увидели эту статью раньше. Прочитав эту статью, вы сможете:

  • Разверните новый сканер на 50 серверах за 2 минуты:
docker build -t localhost:8003/spider:0.01 .
docker push localhost:8002/spider:0.01
docker service create --name spider --replicas 50 --network host 45.77.138.242:8003/spider:0.01
  • Масштабируйте сканер с 50 до 500 серверов за 30 секунд:
docker service scale spider=500
  • Закройте сканеры на всех серверах пакетами в течение 30 секунд:
docker service scale spider=0
  • Пакетное обновление сканеров на всех машинах в течение 1 минуты:
docker build -t localhost:8003/spider:0.02 .
docker push localhost:8003/spider:0.02
docker service update --image 45.77.138.242:8003/spider:0.02 spider

Эта статья не научит вас использовать Docker, поэтому перед чтением этой статьи убедитесь, что вы знакомы с основами Docker.

Что такое Docker Swarm

Docker Swarm — это модуль управления кластером, который поставляется вместе с Docker. Он умеет создавать кластеры Docker и управлять ими.

Строительство окружающей среды

В этой статье для демонстрации будут использоваться 3 сервера Ubuntu 18.04. Три сервера расположены следующим образом:

  • Мастер: 45.77.138.242
  • Раб-1: 199.247.30.74
  • Раб-2: 95.179.143.21

Docker Swarm — это модуль на основе Docker, поэтому сначала установите Docker на 3 сервера. После установки Docker все операции выполняются в Docker.

Установите Докер на мастер

Установите Docker на главный сервер, последовательно выполнив следующие команды.

apt-get update
apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
apt-get update
apt-get install -y docker-ce

Создать узел диспетчера

Для кластера Docker Swarm требуются узлы Manager. Теперь инициализируйте главный сервер в качестве узла диспетчера кластера. Выполните следующую команду.

docker swarm init

После завершения операции вы можете увидеть возвращенный результат, как показано на рисунке ниже.

В этом возвращаемом результате дана команда:

docker swarm join --token SWMTKN-1-0hqsajb64iynkg8ocp8uruktii5esuo4qiaxmqw2pddnkls9av-dfj7nf1x3vr5qcj4cqiusu4pv 45.77.138.242:2377

Эту команду необходимо выполнить на каждом ведомом узле (Slave). Теперь сначала запишите эту команду.

После завершения инициализации получается кластер Docker только с одним сервером. Выполните следующую команду:

docker node ls

Вы можете увидеть текущее состояние кластера, как показано на следующем рисунке.

Создайте частный источник (необязательно)

Создание частного источника не является обязательным действием. Требуются частные источники, поскольку образ Docker проекта может содержать секреты компании и не может быть загружен на общедоступную платформу, такую ​​как DockerHub. Если ваши образы общедоступны на DockerHub или у вас уже есть частный репозиторий образов, вы можете использовать их напрямую, пропустив это и следующее.

Сам частный источник также является образом Docker, сначала потяните его вниз:

docker pull registry:latest

Как показано ниже.

Теперь запустите частный источник:

docker run -d -p 8003:5000 --name registry -v /tmp/registry:/tmp/registry docker.io/registry:latest

Как показано ниже.

В команде запуска открытый порт установлен на порт 8003, поэтому адрес частного источника: 45.77.138.242:8003.

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

Разрешить докеру использовать доверенные частные источники http (необязательно)

Если вы используете команду из предыдущего раздела для создания собственного частного источника, поскольку Docker по умолчанию не разрешает использование частных источников HTTP, вам необходимо настроить Docker, чтобы он доверял ему.

Настройте Docker с помощью следующей команды:

echo '{ "insecure-registries":["45.77.138.242:8003"] }' >> /etc/docker/daemon.json

Затем перезапустите докер с помощью следующей команды.

systemctl restart docker

Как показано ниже.

После завершения перезапуска узел Manager настроен.

Создать сценарий инициализации дочернего узла

Для подчиненного сервера нужно сделать всего три вещи:

  1. Установить Докер
  2. присоединиться к кластеру
  3. надежный источник

Отныне Docker Swarm сам управляет всем остальным, и вам больше не нужно подключаться к этому серверу по SSH.

Чтобы упростить операцию, вы можете написать сценарий оболочки для запуска в пакетном режиме. Создайте один под серверами Slave-1 и Slave-2.init.shфайл со следующим содержимым.

apt-get update
apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
apt-get update
apt-get install -y docker-ce
echo '{ "insecure-registries":["45.77.138.242:8003"] }' >> /etc/docker/daemon.json
systemctl restart docker 
docker swarm join --token SWMTKN-1-0hqsajb64iynkg8ocp8uruktii5esuo4qiaxmqw2pddnkls9av-dfj7nf1x3vr5qcj4cqiusu4pv 45.77.138.242:2377

Сделайте этот файл автономным и запустите:

chmod +x init.sh
./init.sh

Как показано ниже.

Дождавшись завершения работы скрипта, вы можете выйти из SSH на Slave-1 и Slave-2. Нет необходимости заходить снова.

Вернитесь на главный сервер и выполните следующую команду, чтобы убедиться, что в кластере теперь 3 узла:

docker node ls

Посмотрите, что теперь в кластере 3 узла. Как показано ниже.

На этом самый сложный и хлопотный процесс завершен. Осталось только ощутить удобство Docker Swarm.

Создать тестовую программу

Соберите и протестируйте Redis

Поскольку здесь необходимо смоделировать эффект работы распределенного сканера, сначала используйте Docker для создания временной службы Redis:

Выполните следующую команду на главном сервере:

docker run -d --name redis -p 7891:6379 redis --requirepass "KingnameISHandSome8877"

Этот Redis используется извне7891порт, парольKingnameISHandSome8877, IP — это IP-адрес Мастер-сервера.

написать тестовую программу

Напишите простую программу на Python:

import time
import redis


client = redis.Redis(host='45.77.138.242', port='7891', password='KingnameISHandSome8877')

while True:
    data = client.lpop('example:swarm:spider')
    if not data:
        break
    print(f'我现在获取的数据为:{data.decode()}')
    time.sleep(10)

Этот Python считывает число из Redis каждые 10 секунд и печатает его.

Написать Dockerfile

Напишите Dockerfile для создания собственного образа на основе образа Python 3.6:

from python:3.6
label mantainer='contact@kingname.info'

user root
ENV PYTHONUNBUFFERED=0
ENV PYTHONIOENCODING=utf-8

run python3 -m pip install redis

copy spider.py spider.py
cmd python3 spider.py

построить образ

После записи Dockerfile выполните следующую команду, чтобы начать сборку собственного образа:

docker build -t localhost:8003/spider:0.01 .

Здесь необходимо уделить особое внимание.Поскольку мы хотим загрузить это изображение в частный источник для загрузки подчиненным узлом на подчиненном сервере, метод именования изображения должен удовлетворятьlocalhost:8003/自定义名字:版本号такой формат. один из них自定义名字а также版本号Он может быть изменен в соответствии с реальной ситуацией. В примере из этой статьи, поскольку я хочу имитировать программу-краулер, я назвал ее пауком.Поскольку это первая сборка, номер версии — 0,01.

Весь процесс показан на рисунке ниже.

Загружайте изображения в частные источники

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

docker push localhost:8003/spider:0.01

Как показано ниже.

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

Создать сервис

Docker Swarm запускает сервис один за другим, поэтому вам нужно использовать команду docker service для создания сервиса.

docker service create --name spider --network host 45.77.138.242:8003/spider:0.01

Эта команда создаетspiderоказание услуг. По умолчанию запускает 1 контейнер. Операция показана на рисунке ниже.

Конечно, вы также можете использовать множество контейнеров для запуска сразу же после их создания.В этом случае вам нужно добавить только один--replicasпараметры. Например, для запуска с 50 контейнерами сразу после создания службы:

docker service create --name spider --replicas 50 --network host 45.77.138.242:8003/spider:0.01

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

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

docker service ps spider

Как показано ниже.

Просмотр журнала узла

По результату выполнения на приведенном выше рисунке видно, что идентификатор этого работающего контейнера равенrusps0ofwids, затем выполните следующую команду для динамического просмотра журнала:

docker service logs -f 容器ID

На этом этапе журнал этого контейнера будет постоянно отслеживаться. Как показано ниже.

Масштабирование

Теперь контейнер запущен только на 1 сервере, я хочу использовать 3 сервера для запуска этого краулера, тогда мне нужно выполнить команду:

docker service scale spider=3

Эффект операции показан на рисунке ниже.

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

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

Вы можете видеть, что на нем действительно работает контейнер. Это автоматически назначается Docker Swarm.

Теперь мы используем следующую команду, чтобы принудительно закрыть Docker на slave-1, и посмотрим на эффект.

systemctl stop docker

Вернитесь к главному серверу и снова проверьте работу сканера, как показано на следующем рисунке.

Видно, что после того, как Docker Swarm обнаружит, что Slave-1 находится в автономном режиме, он автоматически найдет новую машину для запуска задачи, чтобы гарантировать, что всегда выполняются 3 задачи. В этом примере Docker Swarm автоматически запускает 2 контейнера-паука на главном компьютере.

Если производительность машины лучше, вы даже можете запустить еще несколько контейнеров на каждой машине:

docker service scale spider=10

На данный момент запущено 10 контейнеров для запуска этих сканеров. Эти 10 рептилий изолированы друг от друга.

Что делать, если вы хотите остановить все поисковые роботы? Очень просто, одна команда:

docker service scale spider=0

Это остановит все сканеры.

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

Что делать, если вы хотите видеть все контейнеры одновременно? Вы можете просмотреть последние 20 строк журналов для всех контейнеров с помощью следующей команды:

docker service ps robot | grep Running | awk '{print $1}' | xargs -i docker service logs --tail 20 {}

Таким образом, журналы будут отображаться по порядку. Как показано ниже.

Обновите сканер

Если ваш код изменен. Затем нужно обновить сканер.

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

Следующий шаг — обновить зеркало в сервисе. Есть два способа обновить изображение. Один из них — сначала закрыть все сканеры, а затем обновить.

docker service scale spider=0
docker service update --image 45.77.138.242:8003/spider:0.02 spider
docker service scale spider=3

Второй — выполнить команду обновления напрямую.

docker service update --image 45.77.138.242:8003/spider:0.02 spider

Разница между ними в том, что при непосредственном выполнении команды обновления запущенные контейнеры обновляются один за другим.

Эффект операции показан на рисунке ниже.

Вы можете сделать больше с Docker Swarm

В этой статье используется пример симулированного сканера, но очевидно, что любая программа, которую можно запускать в пакетном режиме, может быть запущена с помощью Docker Swarm, независимо от того, используете ли вы Redis или Celery для связи, нужна ли вам связь или нет, до тех пор, пока вы можете запускать в пакетном режиме вы можете использовать Docker Swarm.

В одном и том же кластере Swarm можно запускать несколько разных сервисов, и каждый сервис не влияет друг на друга. Вы действительно можете создать кластер Docker Swarm один раз, и тогда вам больше не придется о нем беспокоиться, вам нужно только запустить на сервере, где находится узел Manager, для всех последующих операций.

коммерческое время

Эта статья представляет собой один из различных методов развертывания распределенных сканеров.Чтобы узнать о других методах, вы можете обратиться к моей новой книге "Разработка поисковых роботов на Python: от начала работы до реальных боевых действий". Теперь он доступен на JD.com, Dangdang и Amazon.

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