Контейнер Linux представляет собой группировку процессов, которая изолирована от остальной части системы за счет использования функций безопасности ядра Linux, таких как пространств имен и контрольных групп. Это конструкция похожа на виртуальную машину, но это намного более легкая; вы не имеете накладные расходы на работу дополнительного ядра, или имитируя аппаратное обеспечение. Это означает, что вы можете легко создать несколько контейнеров на одном сервере. Используя контейнеры Linux, вы можете запускать несколько экземпляров целых операционных систем, на том же сервере, или связать приложение и его зависимости в контейнере, не затрагивая остальную часть системы.
Например, представьте, что у вас есть сервер и вы создали несколько сервисов, в том числе веб-сайтов, для ваших клиентов. В традиционной установке, каждый веб-сайт будет виртуальным хостом одного и того же экземпляра веб-сервера Apache или Nginx. Но с контейнерами Linux, каждый веб-сайт будет настроен в своем контейнере, со своим собственным веб-сервером.
Мы можем использовать LXD для создания и управления этими контейнерами. LXD предоставляет услугу гипервизора для управления всем жизненным циклом контейнеров.
В этой статье вы будете использовать LXD для установки двух Nginx на основе веб-сайтов на одном сервере, каждый в пределах своего контейнера. Тогда вы будете устанавливать HAProxy в третьем контейнере, который будет выступать в качестве обратного прокси-сервера. Затем пройдем маршрут движения к контейнеру HAProxy для того, чтобы сделать веб-сайты доступные из Интернета.
Для выполнения этого гида вам понадобится следующее:
lxd
Войдите на сервер, используя учетную запись пользователя, не корень. Мы будем использовать эту учетную запись без пользователя, чтобы выполнить все задачи управления контейнером. Для того, чтобы работать, вы должны сначала добавить пользователя в группу lxd
. Сделайте это с помощью следующей команды:
sudo usermod --append --groups lxd sammy
Выйдите из сервера и снова войдите в систему снова, чтобы ваш новый сеанс SSH обновился с новым составом группы. После того, как вы вошли в систему, вы можете приступить к настройке LXD.
LXD должен быть настроен должным образом, прежде чем использовать его. Самый важное решение конфигурации является тип бэкэнда хранения для хранения контейнеров. Рекомендуемое базовое для хранения LXD является файловая система ZFS, хранится либо в предопределенном файле или с помощью блока хранения. Для того, чтобы использовать поддержку ZFS в LXD, установите пакет zfsutils-linux
:
sudo apt-get update sudo apt-get install zfsutils-linux
Выполните следующие действия для настройки LXD использовать предопределенный файл для хранения контейнеров. Во-первых, выполните следующую команду, чтобы запустить процесс инициализации LXD:
sudo lxd init
Вам будет предложено предоставить несколько частей информации, как показано в следующем выходе. Мы отберем все значения по умолчанию, в том числе предлагаемый размер для предопределенного файла, называется устройство цикла:
Name of the storage backend to use (dir or zfs) [default=zfs]: zfs Create a new ZFS pool (yes/no) [default=yes]? yes Name of the new ZFS pool [default=lxd]: lxd Would you like to use an existing block device (yes/no) [default=no]? no Size in GB of the new loop device (1GB minimum) [default=15]: 15 Would you like LXD to be available over the network (yes/no) [default=no]? no Do you want to configure the LXD bridge (yes/no) [default=yes]? yes Warning: Stopping lxd.service, but it can still be activated by: lxd.socket LXD has been successfully configured.
Предлагаемый размер автоматически вычисляется из доступного дискового пространства сервера.
После того, как устройство сконфигурировано, вы будете конфигурировать сетевые настройки, которые мы рассмотрим после следующего дополнительного раздела.
Если вы собираетесь использовать Block Storage, вам необходимо найти устройство, которое указывает на блок объемом памяти, который вы создали для того, чтобы указать его в конфигурации LXD. Перейдите к вкладке Volumes в панели управления, найдите volume, нажмите на More, а затем нажмите на Config instructions.
Найдите устройство, глядя на команду для форматирования. В частности, обратите внимание на путь, указанный в команде sudo mkfs.ext4 -F
.
В нашем случае имя тома /dev/disk/by-id/scsi-0D0_Volume_volume-fra1-01
, хотя ваш может отличаться.
После того, как вы определите объем, вернитесь к терминалу и введите следующую команду, чтобы начать процесс инициализации LXD.
sudo lxd init
Вам будет представлены ряд вопросов. Ответьте на вопросы, как показано в следующем выводе:
Name of the storage backend to use (dir or zfs) [default=zfs]: zfs Create a new ZFS pool (yes/no) [default=yes]? yes Name of the new ZFS pool [default=lxd]: lxd
При появлении запроса об использовании существующего блока устройства, выберите yes
и укажите путь к вашему устройству:
Would you like to use an existing block device (yes/no) [default=no]? yes Path to the existing block device: /dev/disk/by-id/scsi-0DO_Volume_volume-fra1-01
Затем используйте значение по умолчанию для остальных вопросов:
Would you like LXD to be available over the network (yes/no) [default=no]? no Do you want to configure the LXD bridge (yes/no) [default=yes]? yes Warning: Stopping lxd.service, but it can still be activated by: lxd.socket LXD has been successfully configured.
После завершения процесса, вы будете настраивать сеть.
Процесс инициализации представит нам серию экранов, как на рисунке ниже, которые позволяют нам настроить сетевой мост для контейнеров, таким образом они могут получить частные IP-адреса, общаться друг с другом, и иметь доступ к сети Интернет.
Используйте значение по умолчанию для каждого варианта, но на вопрос о подключении к сети IPv6, выберите NO, так как мы не будем использовать его в этом руководстве.
После завершения настройки сети, вы готовы создавать свои контейнеры.
Мы успешно настроили LXD. Мы определили местонахождение бэкэнда хранения и настроили по умолчанию сеть для всех вновь создаваемых контейнеров. Мы готовы создавать и управлять некоторыми контейнеры, которые мы будем делать с командой lxc
.
Давайте попробуем нашу первую команду, в которой перечислены доступные установленные контейнеры:
lxc list
Вы увидите следующий вывод:
Generating a client certificate. This may take a minute...
If this is your first time using LXD, you should also run: sudo lxd init
To start your first container, try: lxc launch ubuntu:16.04
+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+
Так как это первый раз, когда команда lxc
взаимодействует с LXD гипервизором, вывод позволяет нам знать, что команда автоматически создает сертификат клиента для безопасной связи с LXD. Затем он показывает некоторую информацию о том, как запустить контейнер. Наконец, команда показывает пустой список контейнеров, который, как и ожидается, мы еще не создали каких — либо контейнеров.
Давайте создадим три контейнера. Мы создадим один для каждого веб-сервера, и третий контейнер для обратного прокси-сервера. Цель обратного прокси-сервера, чтобы направлять входящие подключения из Интернета к правильному веб-серверу в контейнере.
Мы будем использовать команду lxc launch
для создания и запуска Ubuntu 16,04 ( ubuntu:x
) контейнера с именем myweb
. Ярлык Х в ubuntu:x
это первая буква, дружественных позывного Ubuntu 16.04. ubuntu:
является идентификатором для предварительно настроенного хранилища LXD изображений.
Примечание : Вы можете найти полный список всех доступных изображений Ubuntu, запустив lxc image list ubuntu:
и в других дистрибутивах, запустив lxc image list images:
Выполните следующие команды для создания контейнеров:
lxc launch ubuntu:x myweb lxc launch ubuntu:x youweb lxc launch ubuntu:x haproxy
Здесь вы можете увидеть пример вывода от создания контейнера myweb
.
Creating myweb
Retrieving image: 100%
Starting myweb
Теперь, когда мы создали три пустые контейнеры, давайте используем команду lxc list
для отображения информации о них:
lxc list
Вывод покажет таблицу с именем каждого контейнера, его текущее состояние, его IP-адрес, его тип, и есть ли сделанные снимки.
+---------+---------+-----------------------+------+------------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+---------+---------+-----------------------+------+------------+-----------+
| haproxy | RUNNING | 5.5.5.5. (eth0) | | PERSISTENT | 0 |
+---------+---------+-----------------------+------+------------+-----------+
| myweb | RUNNING | 5.5.5.5.0 (eth0) | | PERSISTENT | 0 |
+---------+---------+-----------------------+------+------------+-----------+
| youweb | RUNNING | 10.10.10.200 (eth0) | | PERSISTENT | 0 |
+---------+---------+-----------------------+------+------------+-----------+
Обратите внимание на имена контейнеров и их соответствующие IPv4 адреса. Вы будете нуждаться в них, чтобы настроить свои услуги.
Давайте соединимся с контейнером myweb
и настроим первый веб — сервер.
Для подключения, мы используем команду lxc exec
, которая принимает имя контейнера и команды для выполнения. Выполните следующую команду для подключения к контейнеру:
lxc exec myweb -- sudo --login --user ubuntu
--
строка означает , что параметры команды для lxc
должны останавливаться, и будут переданы все остальные строки, так как команда должна быть выполнена внутри контейнера. Команда sudo --login --user ubuntu
, обеспечивает оболочку входа для сконфигурированных аккаунтов ubuntu
внутри контейнера.
Примечание:Если вам необходимо подключить к контейнерам, как рroot, вы можете использовать команду lxc exec myweb — /bin/bash.
Оказавшись внутри контейнера, наша командная строка теперь выглядит следующим образом.
ubuntu@myweb:~$
Пользователь Ubuntu в контейнере имеет предварительно настроенный доступ sudo
, и может работать с командой sudo
без ввода пароля. Эта оболочка ограничена внутри границ контейнера. Все, что мы запускаем в этой оболочке остается в контейнере и не может уйти на хост — сервер.
Давайте обновим список пакетов экземпляра Ubuntu внутри контейнера и установим Nginx:
sudo apt-get update sudo apt-get install nginx
Давайте отредактируем веб — страницу по умолчанию для этого сайта и добавим некоторый текст, который даст понять, что этот сайт размещен в контейнере myweb
. Откроем файл /var/www/html/index.nginx-debian.html
:
sudo nano /var/www/html/index.nginx-debian.html
Выполните следующие изменения в файл:
<!DOCTYPE html> <html> <head> <title>Добро пожаловать в nginx on LXD container myweb!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Добро пожаловать в nginx on LXD container myweb!</h1> <p>Если вы видите эту страницу, веб-сервер nginx успешно установлен и работает. Требуется дополнительная настройка.</p> ...
Мы отредактировали файл в двух местах и , в частности добавлен текст on LXD container myweb
. Сохраните файл и выйдите из редактора.
Теперь выйдите из контейнера и вернитесь обратно на хост-сервер:
logout
Повторите эту процедуру для контейнера youweb
. Войдите, установите Nginx, а затем отредактируйте файл , /var/www/html/index.nginx-debian.html
чтобы добавить youweb
. Затем выйти из контейнера youweb
.
Давайте используем команду curl
чтобы проверить, что веб — серверы в контейнерах работают. Нам нужны IP — адреса веб — контейнеров, которые были показаны ранее.
curl http://5.5.5.5.0/
Вывод должен быть:
<!DOCTYPE html> <html> <head> <title>Добро пожаловать в nginx on LXD container myweb!</title> <style> body { width: 30em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Добро пожаловать в nginx on LXD container myweb!</h1> <p>Если вы видите эту страницу, веб-сервер nginx успешно установлен и работает. Требуется дополнительная настройка.</p> ...
Проверьте второй контейнер, а также, используя команду curl
и его IP — адрес, чтобы проверить правильность установки. Если обои контейнеров настроены правильно, мы можем перейти к настройке HAProxy.
Мы создали HAProxy как прокси перед этими контейнерами. Мы будем направлять трафик каждого контейнера на основе доменного имени, который мы используем. Мы будем использовать домен example.ru
в примере конфигурации, следует, что это специальный домен зарезервированный для документации, как этот учебник. Мы сделаем первый сайт доступным на именах хостов example.ru
и www.example.ru
. Второй сайт будет www2.example.ru
. Подставьте свои собственные доменные имена вместо этих доменных имен.
Войдите в контейнер haproxy
:
lxc exec haproxy -- sudo --login --user ubuntu
Обновите списки пакетов установки и установите HAProxy:
sudo apt-get update sudo apt-get install haproxy
После завершения установки, мы можем настроить HAProxy. Файл конфигурации для HAProxy находится в файле /etc/haproxy/haproxy.cfg
. Откройте файл с помощью вашего любимого текстового редактора.
sudo nano /etc/haproxy/haproxy.cfg
Во-первых, мы сделаем несколько изменений в раздел defaults
. Мы добавим опцию forwardfor
, чтобы мы могли сохранить реальный IP — адрес источника веб — клиента, и мы добавим опцию http-server-close
, которая позволяет повторно использовать сеанс и более низкую латентность.
global ... defaults log global mode http option httplog option dontlognull option forwardfor option http-server-close timeout connect 5000 timeout client 50000 timeout server 50000 ...
Далее, мы настроим внешний интерфейс, чтобы указать два наши серверных контейнеры. Добавим новый раздел frontend
под названием www_frontend
который выглядит следующим образом:
frontend www_frontend bind *:80 # Bind to port 80 (www) on the container # It matches if the HTTP Host: field mentions any of the hostnames (after the '-i'). acl host_myweb hdr(host) -i example.ru www.example.ru acl host_youweb hdr(host) -i youweb.example.ru # Redirect the connection to the proper server cluster, depending on the match. use_backend myweb_cluster if host_myweb use_backend youweb_cluster if host_youweb
Эти команды acl
соответствуют именам хостов веб — серверов и будут перенаправлять запросы к соответствующему разделу backend
.
Затем мы определим два новых раздела backend
, по одному для каждого веб — сервера, и назовем их myweb_cluster
и youweb_cluster
соответственно. Добавьте следующий код в файл, чтобы определить backends:
backend myweb_cluster balance leastconn # We set the X-Client-IP HTTP header. This is useful if we want the web server to know the real client IP. http-request set-header X-Client-IP %[src] # This backend, named here "myweb", directs to container "myweb.lxd" (hostname). server myweb myweb.lxd:80 check backend youweb_cluster balance leastconn http-request set-header X-Client-IP %[src] server youweb youweb.lxd:80 check
Вариант balance
обозначает стратегию балансировки нагрузки. В этом случае мы выбираем наименьшее число соединений. Опция http-request
устанавливает HTTP — заголовок с IP клиентом в режиме реального web client IP. Если мы не ставили этот заголовок, веб — сервер будет записывать HAProxy IP — адрес в качестве источника IP для всех соединений, что делает его более трудным для анализа, от куда ваш трафик происходит. Параметр server
указывает произвольное имя для сервера ( myweb
), а затем имя хоста и порт сервера ..
LXD предоставляет DNS — сервер для контейнеров, поэтому myweb.lxd
разрешается в IP, связанный с контейнером myweb
. Другие контейнеры имеют свои собственные имена хостов, такие как youweb.lxd
и haproxy.lxd
.
Параметр check
указывает HAproxy выполнить проверку работоспособности на веб — сервере, чтобы убедиться, что он доступен.
Чтобы проверить, что конфигурация является допустимой, выполните следующую команду:
/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c
Вывод должен быть таким:
Configuration file is valid
Давайте перезагрузим HAProxy так, чтобы он прочил новую конфигурацию.
sudo systemctl reload haproxy
Теперь выйдите из контейнера для того, чтобы вернуться обратно на хост.
logout
Мы настроили HAProxy действовать в качестве обратного прокси — сервера, который пересылает любые соединения, которые он получает от порта 80
на соответствующий веб — сервер в двух других контейнеров. Давайте сделаем тест, который на haproxy
самом деле удается направить запросы на правильный веб — контейнера. Выполните следующую команду:
curl --verbose --header 'Host: youweb.example.ru' http://5.5.5.5.
Это делает запрос к HAProxy и устанавливает заголовок HTTP host
, который HAProxy следует использовать для перенаправления подключения к соответствующему веб — серверу.
Вывод должен быть такой:
... > GET / HTTP/1.1 > Host: youweb.example.ru > User-Agent: curl/7.47.0 > Accept: */* > ... < <!DOCTYPE html> <html> <head> <title>Добро пожаловать в nginx на LXD в контейнер youweb!</title> <style> ...
HAProxy правильно понял запрос и направила его в контейнер youweb. Веб-сервер обслуживал индексную страницу по умолчанию, что мы редактировали ранее, и показывает текст на контейнере youweb. Теперь давайте зададим маршрут внешних запросов к haproxy, чтобы все могли зайти на наши веб-сайты.
Заключительная часть головоломки, чтобы подключить обратный прокси — сервер в Интернете. Нам нужно настроить наш сервер для передачи каких — либо соединений, которые он может получать из Интернета на порт 80
в контейнер haproxy
.
HAProxy установлен в контейнере, и, по умолчанию, является недоступным из Интернета. Чтобы решить эту проблему, мы создадим правило iptables
для пересылки соединений.
Команда iptables
требует два IP — адреса: публичный IP — адрес сервера ( your_server_ip
) и частный IP — адрес контейнера haproxy
( your_haproxy_ip
), который можно получить с помощью команды lxc list
.
Выполните эту команду, чтобы создать правило:
sudo iptables -t nat -I PREROUTING -i eth0 -p TCP -d your_server_ip/32 --dport 80 -j DNAT --to-destination your_haproxy_ip:80
Вот как команда переводиться:
-t nat
указывает, что мы используем таблицу nat
.-I PREROUTING
указывает, что мы добавляем правило в цепи PREROUTING.-i eth 0
определяет интерфейс eth0, который является публичным интерфейсом по умолчанию.-p TCP
говорит, что мы используем протокол ТСР.-d your_server_ip/32
определяет IP-адрес назначения для правила.--dport 80
: Определяет порт назначения.-j DNAT
говорит, что мы хотим выполнить переход к месту назначения NAT (DNAT).--to-destination your_haproxy_ip:80
говорит, что мы хотим, перейти на IP-адрес контейнера с HAProxy.Наконец, чтобы сохранить команду iptables
так, чтобы она повторно применяется после перезагрузки, мы установим пакет iptables-persistent
:
sudo apt-get install iptables-persistent
При установке пакета, вам будет предложено сохранить текущие правила Iptables. Принять и сохранить все текущие правила iptables
.
Если вы создали два FQDNs, то вы должны иметь возможность подключения к каждому веб-сайту с помощью веб-браузера. Попробуйте это.
Для того, чтобы проверить доступность обоих веб-серверов из интернета, используйте команду curl
:
curl --verbose --header 'Host: example.ru' 'http://your_server_ip' curl --verbose --header 'Host: youweb.example.ru' 'http://your_server_ip'
Эти команды HTTP подключаются к общественному IP — адресу сервера и добавленным полем заголовка HTTP с параметром --header
, который HAProxy будет использовать для обработки запроса, так же как вы делали в шаге 5.
Вот выход из первой команды curl
:
* Trying your_server_ip... * Connected to your_server_ip (your_server_ip) port 80 (#0) > GET / HTTP/1.1 > Host: example.ru > User-Agent: curl/7.47.0 > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.10.0 (Ubuntu) ... <!DOCTYPE html> <html> <head> <title>Добро пожаловать в nginx на LXD в контейнер myweb!</title> <style> body { ...
Вот вывод второй команды curl
:
* Trying your_server_ip... * Connected to your_server_ip (your_server_ip) port 80 (#0) > GET / HTTP/1.1 > Host: youweb.example.ru > User-Agent: curl/7.47.0 > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.10.0 (Ubuntu) ... <!DOCTYPE html> <html> <head> <title>Добро пожаловать в nginx на LXD в контейнер youweb!</title> <style> body { ...
В обоих случаях, правильный сайт показывается.
Вы создали два веб-сайта, каждый в своем контейнере, с управлением HAProxy. Вы можете повторить этот процесс, чтобы настроить многие другие веб-сайты, каждый в пределах своего контейнера.
Можно также добавить MySQL в новый контейнер, а затем установить CMS WordPress для запуска каждого веб — сайта. Вы также можете использовать этот процесс для поддержки старых версий программного обеспечения. Например, если установка CMS требует старую версию программного обеспечения, такую как PHP5, то вы можете установить Ubuntu 14.04 в контейнере ( lxc launch ubuntu:t
), вместо того, чтобы пытаться понизить версию менеджера пакетов, доступных на Ubuntu 16.04.
Наконец, LXD дает возможность делать снимки полного состояния контейнеров, что позволяет легко создавать резервные копии и восстанавливать контейнеры обратно в более позднее время. Кроме того, если мы устанавливаем LXD на двух разных серверах, то можно соединить их и сделать миграцию контейнеров между серверами через Интернет.