Развертывание приложения на Node.js и MongoDB с помощью Rancher в Ubuntu 16.04

Rancher – это платформа с открытым кодом, которая позволяет легко управлять контейнерами на этапе производства. Rancher является образом Docker, потому сервер Rancher будет работать на любом хосте Linux, где доступен Docker.

Основные функции Rancher:

  • Поддержка межхостовых соединений: все серверы, добавленные в Rancher, связаны между собой, что обеспечивает безопасность соединений между контейнерами.
  • Балансировка нагрузки: Rancher обеспечивает распределение рабочей нагрузки между контейнерами или даже несколькими облаками.
  • Определение сервисов: Rancher предоставляет внутреннюю DNS-систему, с помощью чего контейнеры и сервисы можно определять по имени и использовать внутри других сервисов сети.
  • Управление инфраструктурой: Rancher позволяет добавлять, отслеживать и управлять вычислительными ресурсами любого облачного провайдера.
  • Механизмы оркестровки: Rancher – единственная платформа управления контейнерами, которая поддерживает популярные фреймворки оркестровки Cattle, Swarm, Kubernetes и Mesos.
  • Rancher – свободная и открытая платформа, предоставляющая полный контроль над инфраструктурой.

Данное руководство поможет построить кластер, настроить балансировку нагрузки и развернуть приложение Node.js, данные которого хранятся в MongoDB.

Требования

  • Сервер Ubuntu 16.04 с 1 Гб памяти и предустановленной платформой Rancher (советы по установке вы найдёте в руководстве Многоузловое развёртывание с помощью Rancher и Docker Machine в Ubuntu 16.04).
  • Приложение Node.js на MongoDB. Если у вас пока нет такого приложения, вы можете найти простое приложение в библиотеке Hapi.js. Пример приложения можно также найти в этом репозитории Github (подробности в разделе 1).
  • Git на локальной машине (для клонирования приложения).
  • Docker на локальной машине (описание установки можно найти в официальной документации).
  • Аккаунт на Docker Hub (это свободный реестр образов Docker). Здесь можно разместить код приложения, чтобы затем развернуть его на нескольких хостах с помощью Rancher.
  • Базовые навыки работы с образами и контейнерами Docker. Больше информации – в руководстве Экосистема Docker: базовые компоненты.

1: Приложение Node.js

Для работы подойдёт простое приложение Node.js на основе Hapi.js, которое получает сообщения, регистрирует их и предоставляет список полученных ранее сообщений.

Клонируйте приложение на локальную машину разработки:

git clone https://github.com/do-community/hapi-example

Откройте каталог проекта:

cd hapi-example

Откройте главный файл приложения, server.js. В нём находится описание подключения MongoDB и код для запуска сервера.

const Hapi = require('hapi');
const mongojs = require('mongojs');
// Loads environment variables
// Used only in development
require('dotenv').config({silent: true});
const server = new Hapi.Server();
server.connection({ port: process.env.PORT || 3000 });
// Connect with the database
server.app.db = mongojs(process.env.MONGO_HOST + '/api');
// Add the routes
server.register(require('./routes'), (err) => {
if (err) {
console.error('Failed to load plugin:', err);
}
// Start the server
server.start((err) => {
if (err) {
throw err;
}
console.log('Server running at:', server.info.uri);
});
});

Код маршрутов инкапсулирован как плагин Hapi.js, чтобы сэкономить место в файле (но если вам интересно, вы можете посмотреть файл routes.js).

В файле server.js важна эта строка:

require('dotenv').config({silent: true});

Приложение использует пакет Node.js под названием dotenv, который загружает переменные окружения из файла .env. Документацию пакета dotenv можно найти здесь. Переменные в этом файле сохраняются только для процесса разработки; это проще, чем вручную вводить переменные через терминал. В производстве приложение сможет получить переменные из Docker через Rancher.

Затем нужно указать порт в переменной PORT (укажите резервное значение 3000, если переменная не определена).

server.connection({ port: process.env.PORT || 3000 });

Порт 3000 используется в приложениях Node.js по общему соглашению. Это значение можно изменить в случае необходимости. Единственное требование к порту: он должен находиться в диапазоне от 1023 и до 65535.

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

server.app.db = mongojs(process.env.MONGO_HOST + '/api');

Это значение среды будет определено через Rancher. После создания контейнеров MongoDB оно будет содержать имя хоста сервера MongoDB. Значение api – это имя базы данных, к которой будет подключено приложение (она будет настроена автоматически, если на данный момент её не существует).

2: Создание образа Docker

Rancher использует образы Docker дял развёртывания приложений. Создайте образ Docker для приложения. Для этого нужен файл Dockerfile, содержащий последовательность действий, которые Docker будет выполнять при создании образа. Этот файл уже включен в репозиторий приложения, который вы клонировали ранее. Откройте его в текстовом редакторе.

FROM node:6
MAINTAINER James Kolce <contact@jameskolce.com>
RUN mkdir -p /usr/api
COPY . /usr/api
WORKDIR /usr/api
RUN npm install --production
ENV PORT 3000
EXPOSE  $PORT
CMD ["npm", "start"]

Рассмотрим подробнее содержимое файла, чтобы понять, как он работает.

FROM node:6

Это значит, что образ будет собран на основе версии 6 официального образа Node.js на Docker Hub (поскольку приложение использует некоторые функции ES6, доступные только в этой или более новых версиях). Рекомендуется указать конкретную версию, а не просто использовать самую новую версию: так вы сможете избежать тех обновлений, которые могут привести к конфликтам и сбоям приложения.

Следующие стоки определяют рабочий каталог:

RUN mkdir -p /usr/api
COPY . /usr/api
WORKDIR /usr/api

Сначала Docker запускает команду mkdir, чтобы создать каталог /usr/api (в котором хранится приложение). Флаг –p создаст все необходимые промежуточные каталоги. Затем Docker скопирует содержимое образа в этот каталог и определит этот новый каталог как рабочий каталог (поэтому последующие команды будут запускаться из этого каталога).

Следующая строка запускает npm и устанавливает зависимости приложения для производства.

RUN npm install --production

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

ENV PORT 3000
EXPOSE  $PORT

Первая строка определяет переменную среды PORT, указанный здесь порт будет прослушиваться приложением. Если эта переменная не определена, устанавливается порт по умолчанию 3000. Затем нужно открыть этот порт, чтобы иметь доступ к нему извне контейнера. С помощью переменной среды его легче изменить, при этом не придётся переписывать код приложения. В дальнейшем приложение сможет использовать эти переменные среды.

Последняя строка Dockerfile запускает сервер Node.js с помощью команды npm start.

CMD ["npm", "start"]

Чтобы создать образ Docker из этого файла, перейдите в каталог hapi-example и введите:

docker build -t your_dockerhub_username/hapi-example .

Эта команда создаст образ Docker с помощью Dockerfile.

Обратите внимание на точку в конце команды. Она указывает путь к Dockerfile, который находится в текущей папке. Флаг -t устанавливает тег для образа; в качестве тега используется your_dockerhub_username/hapi-example. В дальнейшем этот тег можно использовать для создания экземпляров контейнера на основе этого образа. В качестве префикса используется имя пользователя Docker Hub, поскольку после тестирования этот образ нужно опубликовать, а локальный тег образа Docker должен соответствовать имени репозитория в Docker Hub.

Примечание: Если при запуске последней команды вы получили такое сообщение:

Cannot connect to the Docker daemon. Is the docker daemon running on this host?

убедитесь, что Docker запущен и работает без ошибок. После этого попробуйте ещё раз запустить команду.

Протестируйте собранный образ. Создайте контейнер MongoDB, с которым приложение сможет взаимодействовать и сохранять данные. Чтобы создать и запустить контейнер MongoDB на основе официального образа, введите команду:

docker run --name testdb -p 27017:27017 -d mongo:3

Присвойте контейнеру временное имя с помощью опции –name. С помощью этого имени можно остановить контейнер после тестирования. Свяжите порт 27017 с открытым портом контейнера, чтобы проверить работу MongoDB в браузере на локальной машине. Также нужно указать образ, на основе которого будет собран контейнер. Рекомендуется использовать ту же версию MongoDB, на которой создавалось приложение.

После этого посетите в браузере страницу:

http://localhost:27017

Вы увидите следующее сообщение:

It looks like you are trying to access MongoDB over HTTP on the native driver port

Это значит, что MongoDB работает.

Запустите контейнер приложения и свяжите его с контейнером MongoDB:

docker run --name hapi-app -p 3000:3000 -d -e MONGO_HOST=testdb --link testdb your_dockerhub_username/hapi-example

Эта команда похожа на ту, с помощью которой был запущен контейнер MongoDB, но в этот раз нужно указать образ приложения (your_dockerhub_username/hapi-example) и порт 3000 (он указан в Dockerfile). Также нужно добавить переменную среды MONGO_HOST, которая указывает имя контейнера MongoDB (его приложение будет использовать для подключения к БД). Параметр –link testdb позволяет использовать контейнер БД как хост внутри контейнера приложения.

Протестируйте приложение. Откройте ссылку:

http://localhost:3000

Должна появиться пустая страница без сообщений об ошибке.

Примечание: Браузер Firefox может вывести пустой массив ([ ]) или JSON. Оба эти вывода значат, что всё работает верно.

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

Остановите контейнер БД:

docker stop testdb

После этого контейнер можно удалить:

docker rm testdb

Затем остановите и удалите контейнер приложения:

docker stop hapi-app && docker rm hapi-app

3: Загрузка образа на Docker Hub

Чтобы развернуть приложение с помощью Rancher, нужно выбрать реестр Docker и создать в нем репозиторий для хранения образа. В руководстве для этого используется официальный реестр Docker Hub.

Откройте учётную запись Docker Hub. Выберите Create Repository. Заполните форму:

  • Name (required): Имя репозитория (в данном случае это hapi-example).
  • Description: Краткое описание образа, с помощью которого вы быстро сможете отличить его от других образов.
  • Full Description: Здесь вы можете добавить документ markdown (это поле можно пропустить).
  • Visibility: Вы можете создавать частные и публичные репозитории (частные доступны только вам, публичные доступны всем пользователям). В данном случае нужно создать публичный репозиторий.

Примечание: Создавая частный репозиторий, нужно добавить учётные данные Docker Hub на страницу Infrastructure → Registries через интерфейс Rancher.

Заполнив форму, нажмите Create. После этого на экране появится страница репозитория.

Чтобы загрузить в него образ Docker, подключитесь к Docker Hub с помощью команды docker. Вернитесь в терминал и введите команду:

docker login

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

Чтобы загрузить образ в репозиторий Docker Hub, введите команду:

docker push your_dockerhub_username/hapi-example

Процесс может занять несколько минут.

4: Создание хостов Rancher

С помощью Rancher создайте все хосты, необходимые для развёртывания сервисов: два для приложения Node.js, один для MongoDB и один для балансировки нагрузки.

Откройте интерфейс Rancher в браузере:

http://your_rancher_ip_address

  • Откройте Infrastructure → Hosts и нажмите Add Host.
  • Выберите хостинг-провайдера.
  • В поле Access Token укажите токен доступа (можно получить у хостинг-провайдера) и нажмите Next.
  • Присвойте хосту имя (введите host, а интерфейс автоматически сгенерирует имена от host1 до host4).
  • В Quantity выберите 4.
  • В Image используйте стандартное значение Ubuntu 16.04.1 x64.
  • В Size оставьте стандартное значение 1gb RAM, 30gb Disk, 1 vCPU.
  • В SSH User можно оставить root.
  • Нажмите кнопку Create и подождите пару минут.

После того как Rancher создаст хосты, можно добавить метки, чтобы указать их типы и предназначение. Также метки позволяют масштабировать хосты в зависимости от их типов. Rancher может автоматически увеличить количество хостов того или иного типа и развернуть все необходимые им контейнеры. Создайте метки loadbalancer, application и database.

Чтобы создать метку loadbalancer:

  • Откройте Infrastructure → Hosts и выберите host1.
  • Нажмите кнопку Options (кнопка с тремя точками в верхне части страницы) и выберите Edit.
  • Нажмите +Add Label, введите в поле Key слово type, а в Value – loadbalancer.
  • Нажмите Save.

Примечание: Имена хостов могут отображаться в формате host1.localdomain. Это нормальное поведение (формат может изменяться в зависимости от среды).

Чтобы создать следующую метку, повторите описанный выше процесс, выберите два свободных хоста и введите application в поле Value.

Чтобы создать метку для БД, выберите последний свободный хост и укажите database в Value.

5: Развёртывание сервера MongoDB

Разверните сервер MongoDB с помощью официального образа Docker. Контейнер MongoDB будет также иметь сторонний контейнер для хранения всех данных. Оба контейнера будут развёрнуты на хосте с меткой database.

Откройте интерфейс Rancher и выполните такие действия:

  • Выберите Stacks → User → Define a Service.
  • На странице Add Service слайдер Scale должен указывать Run 1 container.
  • Укажите имя сервиса: MongoDB.
  • Укажите образ: mongo:3
  • Нажмите кнопку Add Sidekick Container.
  • Назовите новый контейнер Data. Он будет работать как том для хранения данных MongoDB.
  • Поскольку новый контейнер нужен только для хранения данных, используйте образ busybox.
  • Во вкладке Command переключите опцию Autorestart на Never (Start Once).
  • Откройте вкладку Volumes и добавьте новый том, нажав Add Volume. В появившемся поле укажите /data/db (это стандартный путь MongoDB дял хранения данных).
  • Откройте вкладку Scheduling и нажмите Add Schedule Rule. Введите следующие параметры: The Host must have a host label of type = database.
  • Откройте вкладку сервиса MongoDB, прокрутите до вкладки Command и убедитесь, что опция Autorestart установлена на Always.
  • Во вкладке Volumes найдите Volumes From и выберите Data.
  • Во вкладке Scheduling добавьте новое правило: The Host must have a host label of type = database.
  • Нажмите Create.

6: Развёртывание приложения Node.js

Аналогичным образом можно развернуть приложение Node.js. Образ, хранящийся на Docker Hub, будет развёрнут на хостах с меткой application и подключится к сервису MongoDB.

Откройте интерфейс Rancher и выполните такие действия:

  • Выберите Stacks → User, в стеке Default нажмите Add Service.
  • В Scale выберите Always run one instance of this container on every host.
  • Укажите имя сервиса: NodeJS.
  • Укажите образ с Docker Hub: your_dockerhub_username/hapi-example.
  • Выберите Service Links → Destination Service и укажите MongoDB. Затем выберите As name и введите db. Теперь сервис NodeJS получит доступ к MongoDB.
  • Во вкладке Command нажмите Add Environment Variable, добавьте переменную MONGO_HOST и присвойте ей значение db. С помощью этой переменной приложение сможет найти сервер БД.
  • Откройте вкладку Scheduling и нажмите Add Scheduling Rule. Введите следующие параметры: The Host must have a host label of type = application.
  • Нажмите Create.

Запуск контейнеров займет некоторое время. После этого откройте меню Infrastructure, нажмите Hosts и вы увидите два хоста с меткой application.

7: Развёртывание балансировщика нагрузки

Балансировщик нагрузки нужно подключить к сервисам NodeJS.

Чтобы создать балансировщик нагрузки:

  • Выберите Stacks → User → Add Service и выберите Add Load Balancer.
  • Укажите имя сервиса: LoadBalancer.
  • Найдите раздел Port Rules. В Request Host Port укажите 80, а в Target Port – порт 3000.
  • В Target Service выберите NodeJS.
  • Откройте вкладку Scheduling и нажмите Add Scheduling Rule. Введите следующие параметры: The Host must have a host label of type = loadbalancer.
  • Нажмите Create.

8: Тестирование приложения

Чтобы протестировать приложение, нужно узнать адрес хоста балансировщика нагрузки. Выберите сервис LoadBalancer; IP-адрес будет указан во вкладке Ports.

Теперь, чтобы убедиться, что всё работает, выполните следующую команду:

curl your_load_balancer_ip

Эта команда отправит серверу запрос GET. В качестве ответа вы получите пустой массив ([]), потому что в БД пока нет данных.

С помощью следующей команды добавьте в БД сообщение:

curl -i -X POST -H "Content-Type:application/json" your_load_balancer_ip -d '{"message":"This is a test"}'

Команда отправит на сервер запрос POST с JSON-объектом, который содержит ключ message со значением This is a test. Отправив запрос, вы должны увидеть это сообщение с присвоенным ему _id. Если это так, значит, приложение может подключаться к MongoDB и хранить там данные.

Это приложение примет только ключ message. Остальные ключи будут сброшены.

Чтобы проверить работу приложения, снова запустите первую команду:

curl your_load_balancer_ip

Вы должны получить добавленное в БД сообщение:

HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
cache-control: no-cache
content-length: 61
Date: Wed, 05 Jan 2017 20:07:02 GMT
Connection: keep-alive
{"message":"This is a test","_id":"e64d85579aee7d1000b075a2"}

Важно! Это тестовое приложение небезопасно! Любой пользователь, который знает адрес и API, может добавить сообщение. После тестирования рекомендуется отключить приложение, удалив сервис в Rancher.

9: Масштабирование приложения Node.js

Когда приложение начнёт получать большой объём трафика, серверы перестанут справляться с нагрузкой. В таком случае нужно увеличить количество серверов Node.js, и нагрузка будет автоматически распределена между хостами приложения.

Чтобы выполнить масштабирование приложения:

  • Выберите Infrastructure → Hosts и нажмите Add Host.
  • Добавьте токен в поле Access Token.
  • Укажите имя нового хоста: host5. Rancher автоматически присвоит имя host6 следующему хосту.
  • Выберите количество хостов, которые нужно создать (в данном случае это 2).
  • В Image оставьте значение по умолчанию Ubuntu 16.04.1 x64.
  • В Size оставьте значение по умолчанию 1gb RAM, 30gb Disk, 1 vCPU.
  • Нажмите кнопку Add Label. В поле Key введите type, в поле Value укажите application.
  • Нажмите Create.

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

Заключение

Теперь вы знаете, как подготовить приложение NodeJS к развёртыванию, развернуть и масштабировать его, а также подключить его к хранилищу данных MongoDB. Rancher легко справляется со всеми этими задачами. Кроме того, Rancher умеет автоматически распределять нагрузку.

Tags: , , , , ,

Добавить комментарий