GlusterFS Docker
GlusterFS и Docker
Тут краткое описание о "докеризации" GlusterFS
Постановка Задачи
Есть 3 хардварных ноды, на каждой из которых будет запущено приложение. Для организации общего хранилища требуется настроить GlusterFS. Требования от заказчика - все процессы запускать в докер-контейнерах
- Базовая система - CentOS 7
- Docker 1.10
- ??
Имеется три ноды (именование сквозное потому номера идут не с 1)
- node-3
- node-4
- node-6
На кадой из них установлен CentOS 7
# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core)
Хранилище будет подмонтированно на всех 3-х нодах.
Устновка Docker
Установка докера хорошо описана в документации: https://docs.docker.com/engine/installation/linux/centos/
# rpm -qa | grep docker docker-engine-selinux-1.10.2-1.el7.centos.noarch docker-engine-1.10.2-1.el7.centos.x86_64
Включить в автозагрузку
# systemctl enable docker
Запустить:
# service docker start
GlusterFS в докере
Существует пре-собранный образ (а точнее 2 образа) которые содержат все что нужно для GlusterFS.
Однако к минусам этих образов я отнесу то, что на хост-системе Centos 6.5 (в том числе и со свежим ядром из elrepo) эти образа не работают. Проблема в том что для systemd который работает внутри нужны "капабилитез" (https://www.opennet.ru/man.shtml?topic=capabilities) котоые внутрь контейнера не пробрасываются. Беглый просмотр образов наводит на мысль что исправить это можно, нагородив костылей вместо использования родного для Centos 7 systemd однако практического смысла в этом нет, а на хост-стстеме с Centos 7 проблема не воспроизводится.
Установка
Установка предельно проста (потому мы и используме докер!)
- Скачать образ
# docker pull gluster/gluster-centos
- Запустить контейнер
#!/bin/bash docker run \ --privileged \ -d \ -p 10022:22 \ -p 111:111 \ -p 24007:24007 \ -p 24008:24008 \ -p 24009:24009 \ -p 24010:24010 \ -p 24011:24011 \ -p 24012:24012 \ -p 24013:24013 \ -p 24014:24014 \ -p 24015:24015 \ -p 24016:24016 \ -p 24017:24017 \ -p 24018:24018 \ -p 24019:24019 \ -p 24020:24020 \ -p 24021:24021 \ -p 24022:24022 \ -p 24023:24023 \ -p 24024:24024 \ -p 24025:24025 \ -p 24026:24026 \ -p 24027:24027 \ -p 24028:24028 \ -p 24029:24029 \ -p 24030:24030 \ -p 24031:24031 \ -p 24032:24032 \ -p 24033:24033 \ -p 24034:24034 \ -p 24035:24035 \ -p 24036:24036 \ -p 24037:24037 \ -p 24038:24038 \ -p 24039:24039 \ -p 24040:24040 \ -p 24041:24041 \ -p 24042:24042 \ -p 24043:24043 \ -p 24044:24044 \ -p 24045:24045 \ -p 24046:24046 \ -p 24047:24047 \ -p 24048:24048 \ -p 24049:24049 \ -p 24050:24050 \ -p 49152:49152 \ -p 49153:49153 \ -p 49154:49154 \ -p 49155:49155 \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ -v /gluster_file:/var/lib/glusterd \ -v /gluster_storage:/gluster_storage \ -v /etc/hosts:/etc/hosts \
На параметрах запуска остановлюсь подробнее:
- --privileged : For systemd to run without crashing it is necessary to run the container in the privileged mode since systemd requires CAP_SYS_ADMIN capability.
- -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ - проброс sysfs
- -v /gluster_file:/var/lib/glusterd - вся конфигурация GlusterFS будет храниться на хост системе (gluster_file), для того что бы контейнер можно было смело пересоздавать или обновлять. По-хорошему никакие данные не следует хранить внутри контейнера.
- -v /gluster_storage:/gluster_storage: Мортируем внутрь контейнера папку которая будет использоваться для данных
- -v /etc/hosts:/etc/hosts - для простоты работы вся информация вноситься в хосты что бы упростить конфигурацию
На этом моменте нужно остановиться подробнее - тут существует тонкость.
Напомню, в нашей схеме учавствуют три хоста (host-4, host-5 и host-6).
На каждом из них создаем нужные записи, причем информация о самом хосте указывает на localhost.
Например, для host-6:
192.168.56.101 node-4 127.0.0.1 node-6 192.168.56.102 node-5
Если это не сделать, то возникает проблема с хождением через nat да и в целом конфигурация выглядит логично.
- Проброс портов -p ... - список портов (что бы не заморачиваться) взят с официальной документации (http://www.gluster.org/community/documentation/index.php/Basic_Gluster_Troubleshooting)
Насройка GlusterFS
Базовую настройку производим изнутри контейнеров
Для подключения к контейнеру
- Уточнить ID контейнера
docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b9ebafb93e82 gluster/gluster-centos "/usr/sbin/init" 21 hours ago Up 5 hours 245/tcp, 443/tcp, 2049/tcp, 6010-6012/tcp, 0.0.0.0:111->111/tcp, 8080/tcp, 38465-38466/tcp, 0.0.0.0:24007-24050->24007-24050/tcp, 38468-38469/tcp, 0.0.0.0:49152-49155->49152-49155/tcp, 49156-49162/tcp, 0.0.0.0:10022->22/tcp desperate_raman
- Подключиться к контейнеру
docker exec -it b9ebafb93e82 /bin/bash
Далее внутри контейнера доступна утилита gluster
Создаем кластер:
gluster peer probe node-5 gluster peer probe node-4
Проверить результат:
# gluster peer status Number of Peers: 2 Hostname: node-4 Uuid: c82db9d5-230f-4d79-a466-c62e0b82d74d State: Peer in Cluster (Connected) Hostname: node-5 Uuid: 4038195f-d9e8-4fcd-b7ba-d9a66e6d3518 State: Peer in Cluster (Connected)
2 ноды (плюс третья - та на которой выполняется команда) - как и ожидалось.
Следующий шаг - создание volume
gluster volume create replicated_data replica 3 transport tcp node-4:/gluster_storage node-5:/gluster_storage node-6:/gluster_storage force
В этой команде параметры означают следующее:
- replicated_data - имя volume - может быть любым
- replica - тип volume, в нашем случае - это аналог "зеркала" RAID1 (другие типы нас в данной момент не интересуют - наша цель отказоустойчивость)
- 3 - "replication factor" - количество копий. У нас - по одной копии на ноду, хотя при наличии нескольких физических дисков можно "размазать" данные и более по-другому, например в соотношении 2-2-1 или еще как-то :)
- tcp - протокол который использовать для этого volume (кстати надо уточнить - только для репликации или и для монтирования?)
- node-4:/gluster_storage node-5:/gluster_storage node-6:/gluster_storage - список нод и директорий которые будут хранить данные. В нашем случае - это проброшенная внутрь контейнера директория с хост-системы, таким образом все данные будут храниться на хост-системе.
- force - принудительное создание (папки, а не выделеные диски - не то о чем мечтает GlusterFS но force заставляет работать с папками)
Старт volume
gluster volume start replicated_data
Проверить статус: (вроде-бы все выглядит нормально)
gluster volume status Status of volume: replicated_data Gluster process TCP Port RDMA Port Online Pid ------------------------------------------------------------------------------ Brick node-4:/gluster_storage 49152 0 Y 399 Brick node-5:/gluster_storage 49152 0 Y 398 Brick node-6:/gluster_storage 49152 0 Y 398 NFS Server on localhost N/A N/A N N/A Self-heal Daemon on localhost N/A N/A Y 393 NFS Server on node-5 N/A N/A N N/A Self-heal Daemon on node-5 N/A N/A Y 393 NFS Server on node-4 N/A N/A N N/A Self-heal Daemon on node-4 N/A N/A Y 416 Task Status of Volume replicated_data ------------------------------------------------------------------------------ There are no active volume tasks
gluster volume info Volume Name: replicated_data Type: Replicate Volume ID: 6462ffa2-7378-4d5f-a302-a2734fbcfcaa Status: Started Number of Bricks: 1 x 3 = 3 Transport-type: tcp Bricks: Brick1: node-4:/gluster_storage Brick2: node-5:/gluster_storage Brick3: node-6:/gluster_storage Options Reconfigured: performance.readdir-ahead: on
Подключение volumе к хост-системе
/etc/rc.local
mount.glusterfs $(hostname):/replicated_data /www-data/
Эта команда подключит volume replicated_data в www-data.
Естественно что никакого нового места такое подключение не принесет - но данные записаные в /www-data будут копироваться на все три ноды кластера
# df -h Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos-root 41G 4.9G 36G 13% / devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.9G 0 1.9G 0% /dev/shm tmpfs 1.9G 8.4M 1.9G 1% /run tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup /dev/mapper/centos-home 20G 33M 20G 1% /home /dev/sda1 497M 164M 334M 33% /boot tmpfs 380M 0 380M 0% /run/user/0 node-6:/replicated_data 41G 4.9G 36G 13% /www-data [root@node-6 ~]#
Известные проблемы
Starting with GlusterFS 3.3, one change has been the check to see if a directory (or any of it's ancestors) is already part of a volume. This is causing many support questions in #gluster.
This was implemented because if you remove a brick from a volume and continue to use the volume, you can get file into a state where re-adding a former brick can cause all sort of problems, many of which can result in data loss.
If you're going to reuse a brick, make sure you know what you're doing.
The Solution
For the directory (or any parent directories) that was formerly part of a volume, simply:
Don't worry if it says that the attribute does not exist. As long as it doesn't exist, you're in good shape.
Finally, restart glusterd to ensure it's not "remembering" the old bricks.
See the bugzilla entry for more details and see Jeff Darcy's article for more information about how GlusterFS uses extended attributes.
setfattr -x trusted.glusterfs.volume-id $brick_path setfattr -x trusted.gfid $brick_path rm -rf $brick_path/.glusterfs