[Перевод] Использование GlusterFS с кластером Docker swarm

d628c8bed56d4086aa8ba2bb117561a9.png

В этой статье я описал создание в AWS состоящего из трех нод кластера Docker Swarm и подключение к нему общего для всех нод реплицируемого тома GlusterFS.


Введение


Режим Docker Swarm используется для создания кластера Docker-хостов. При этом, если контейнер A с подключенным к нему именованным томом voldata запущен на node1, все изменения voldata будут сохранены локально на node1. Если контейнер A будет выключен и случится так, что он снова запустится, скажем, на node3, при подключении тома voldata это хранилище окажется пустым и не будет содержать изменений, сделанных на node1.


Как это обойти?


Один из путей решения проблемы — использовать GlusterFS для репликации томов, что позволит сделать данные доступными для всех нод в любое время. При этом для каждого Docker-хоста именованные тома останутся локальными.


Для выполнения этого упражнения я использовал три AWS EC2-инстанса, к каждому из которых было подключено по одному EBS-тому.


Подготовка серверов


В качестве ОС будем использовать Ubuntu 16.04.


Сначала пропишем имена нод в /etc/hosts:


XX.XX.XX.XX    node1
XX.XX.XX.XX    node2
XX.XX.XX.XX    node3

Затем обновим систему:


$ sudo apt update
$ sudo apt upgrade

Перезагрузимся и запустим установку необходимых пакетов на всех нодах:


$ sudo apt install -y docker.io
$ sudo apt install -y glusterfs-server

Запустим сервисы:


$ sudo systemctl start glusterfs-server
$ sudo systemctl start docker

Создадим хранилище GlusterFS:


$ sudo mkdir -p /gluster/data /swarm/volumes

Настройка GlusterFS


На всех нодах подготовим файловую систему для хранилища Gluster:


$ sudo mkfs.xfs /dev/xvdb 
$ sudo mount /dev/xvdb /gluster/data/

На node1:


$ sudo gluster peer probe node2
peer probe: success. 
$ sudo gluster peer probe node3
peer probe: success.

Создадим реплицируемый том:


$ sudo gluster volume create swarm-vols replica 3 node1:/gluster/data node2:/gluster/data node3:/gluster/data force
volume create: swarm-vols: success: please start the volume to access data

Разрешим монтирование только с localhost:


$ sudo gluster volume set swarm-vols auth.allow 127.0.0.1
volume set: success

Запустим том:


$ sudo gluster volume start swarm-vols
volume start: swarm-vols: success

Затем подмонтируем его на каждой ноде Gluster:


$ sudo mount.glusterfs localhost:/swarm-vols /swarm/volumes

Настройка Docker swarm


Наша цель: создать 1 управляющий и 2 рабочих узла.


$ sudo docker swarm init
Swarm initialized: current node (82f5ud4z97q7q74bz9ycwclnd) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-697xeeiei6wsnsr29ult7num899o5febad143ellqx7mt8avwn-1m7wlh59vunohq45x3g075r2h \
    172.31.24.234:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

Получим токен для рабочих узлов:


$ sudo docker swarm join-token worker

To add a worker to this swarm, run the following command:

```docker  
    docker swarm join \
    --token SWMTKN-1-697xeeiei6wsnsr29ult7num899o5febad143ellqx7mt8avwn-1m7wlh59vunohq45x3g075r2h \
    172.31.24.234:2377

На обоих рабочих узлах выполним:


$ sudo docker swarm join --token SWMTKN-1-697xeeiei6wsnsr29ult7num899o5febad143ellqx7mt8avwn-1m7wlh59vunohq45x3g075r2h 172.31.24.234:2377
This node joined a swarm as a worker.

Проверим swarm-кластер:


$ sudo docker node ls
ID                           HOSTNAME          STATUS  AVAILABILITY  MANAGER STATUS
6he3dgbanee20h7lul705q196    ip-172-31-27-191  Ready   Active        
82f5ud4z97q7q74bz9ycwclnd *  ip-172-31-24-234  Ready   Active        Leader
c7daeowfoyfua2hy0ueiznbjo    ip-172-31-26-52   Ready   Active

Тестирование


Будем действовать следующим образом: создадим метки для node1 и node3, создадим контейнер на node1, выключим его, создадим снова на node3, подмонтировав такие же тома, и посмотрим, остались ли в нашем хранилище файлы, созданные во время работы контейнера на node1.


Поставим метки на узлы swarm:


$ sudo docker node update --label-add nodename=node1 ip-172-31-24-234
ip-172-31-24-234
$ sudo docker node update --label-add nodename=node3 ip-172-31-26-52
ip-172-31-26-52

Проверим метки:


$ sudo docker node inspect --pretty ip-172-31-26-52
ID:         c7daeowfoyfua2hy0ueiznbjo
Labels:
 - nodename = node3
Hostname:       ip-172-31-26-52
Joined at:      2017-01-06 22:44:17.323236832 +0000 utc
Status:
 State:         Ready
 Availability:      Active
Platform:
 Operating System:  linux
 Architecture:      x86_64
Resources:
 CPUs:          1
 Memory:        1.952 GiB
Plugins:
  Network:      bridge, host, null, overlay
  Volume:       local
Engine Version:     1.12.1

Создадим на node1 сервис Docker, который будет использоваться для тестирования работы с файлами в общем хранилище:


$ sudo docker service create --name testcon --constraint 'node.labels.nodename == node1' --mount type=bind,source=/swarm/volumes/testvol,target=/mnt/testvol /bin/touch /mnt/testvol/testfile1.txt
duvqo3btdrrlwf61g3bu5uaom

Проверим сервис:


$ sudo docker service ls
ID            NAME     REPLICAS  IMAGE    COMMAND
duvqo3btdrrl  testcon  0/1       busybox  /bin/bash

Убедимся, что он запущен на node1:


$ sudo docker service ps testcon
ID                         NAME           IMAGE          NODE              DESIRED STATE  CURRENT STATE           ERROR
6nw6sm8sak512x24bty7fwxwz  testcon.1      ubuntu:latest  ip-172-31-24-234  Ready          Ready 1 seconds ago     
6ctzew4b3rmpkf4barkp1idhx   \_ testcon.1  ubuntu:latest  ip-172-31-24-234  Shutdown       Complete 1 seconds ago

Также проверим подмонтированные тома:


$ sudo docker inspect testcon
[
    {
        "ID": "8lnpmwcv56xwmwavu3gc2aay8",
        "Version": {
            "Index": 26
        },
        "CreatedAt": "2017-01-06T23:03:01.93363267Z",
        "UpdatedAt": "2017-01-06T23:03:01.935557744Z",
        "Spec": {
            "ContainerSpec": {
                "Image": "busybox",
                "Args": [
                    "/bin/bash"
                ],
                "Mounts": [
                    {
                        "Type": "bind",
                        "Source": "/swarm/volumes/testvol",
                        "Target": "/mnt/testvol"
                    }
                ]
            },
            "Resources": {
                "Limits": {},
                "Reservations": {}
            },
            "RestartPolicy": {
                "Condition": "any",
                "MaxAttempts": 0
            },
            "Placement": {
                "Constraints": [
                    "nodename == node1"
                ]
            }
        },
        "ServiceID": "duvqo3btdrrlwf61g3bu5uaom",
        "Slot": 1,
        "Status": {
            "Timestamp": "2017-01-06T23:03:01.935553276Z",
            "State": "allocated",
            "Message": "allocated",
            "ContainerStatus": {}
        },
        "DesiredState": "running"
    }
]

Выключим сервис и создадим его заново на node3:


$ sudo docker service create --name testcon --constraint 'node.labels.nodename == node3' --mount type=bind,source=/swarm/volumes/testvol,target=/mnt/testvol ubuntu:latest /bin/touch /mnt/testvol/testfile3.txt
5y99c0bfmc2fywor3lcsvmm9q

Убедимся, что теперь он запущен на node3:


$ sudo docker service ps testcon
ID                         NAME           IMAGE          NODE             DESIRED STATE  CURRENT STATE           ERROR
5p57xyottput3w34r7fclamd9  testcon.1      ubuntu:latest  ip-172-31-26-52  Ready          Ready 1 seconds ago     
aniesakdmrdyuq8m2ddn3ga9b   \_ testcon.1  ubuntu:latest  ip-172-31-26-52  Shutdown       Complete 2 seconds ago

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


$ ls -l /swarm/volumes/testvol/
total 0
-rw-r--r-- 1 root root 0 Jan  6 23:59 testfile3.txt
-rw-r--r-- 1 root root 0 Jan  6 23:58 testfile1.txt

Комментарии (1)

  • 7 февраля 2017 в 16:35

    0

    $ sudo gluster peer probe node2
    peer probe: success.
    $ sudo gluster peer probe node3
    peer probe: success.

    А что с безопасностью? Должны же быть какие-то настройки шифрования (как в примере с Docker Swarm).

© Habrahabr.ru