Thank you for reading this post, don't forget to subscribe!
Если необходимо чтобы одни и те же данные были доступны на разных серверах, и уже установлен ceph как блочное устройство и вы решили установить glusterfs то у вас это не получится из-за того, что ceph и gluster используют одну и ту же библиотеку, но разных версий. (решить данную проблему мне не удалось, поэтому встречайте следующий костыль:)
Поднимаем gluster в docker контейнерах, для этого нам понадобится уже собранный swarm кластер.
Опишу ручную установку:
на swarm master создаём оverlay сеть:
docker network create -d overlay --attachable netgfs
на всех нодах выполняем следующие команды:
mkdir /etc/glusterfs
mkdir /var/lib/glusterd
mkdir /var/log/glusterfs
mkdir -p /bricks/brick1/gv0
mkdir /datavol
mount --bind /datavol /datavol
mount --make-shared /datavol
далее запускаем контейнеры на соответствующих нодах:
docker run --restart=always --name gfsc1 -v /bricks:/bricks -v /etc/glusterfs:/etc/glusterfs:z -v /var/lib/glusterd:/var/lib/glusterd:z -v /var/log/glusterfs:/var/log/glusterfs:z -v /sys/fs/cgroup:/sys/fs/cgroup:ro --mount type=bind,source=/datavol,target=/datavol,bind-propagation=rshared -d --privileged=true --net=netgfs -v /dev/:/dev gluster/gluster-centos
docker run --restart=always --name gfsc2 -v /bricks:/bricks -v /etc/glusterfs:/etc/glusterfs:z -v /var/lib/glusterd:/var/lib/glusterd:z -v /var/log/glusterfs:/var/log/glusterfs:z -v /sys/fs/cgroup:/sys/fs/cgroup:ro --mount type=bind,source=/datavol,target=/datavol,bind-propagation=rshared -d --privileged=true --net=netgfs -v /dev/:/dev gluster/gluster-centos
docker run --restart=always --name gfsc3 -v /bricks:/bricks -v /etc/glusterfs:/etc/glusterfs:z -v /var/lib/glusterd:/var/lib/glusterd:z -v /var/log/glusterfs:/var/log/glusterfs:z -v /sys/fs/cgroup:/sys/fs/cgroup:ro --mount type=bind,source=/datavol,target=/datavol,bind-propagation=rshared -d --privileged=true --net=netgfs -v /dev/:/dev gluster/gluster-centos
после чего с одной из нод присоединяемся к контейнеру, добавляем пиров создаём volume, стартуем его и монтируем директорию:
docker exec -it gfsc1 bash
gluster peer probe gfsc2
gluster peer probe gfsc3
gluster volume create gv0 replica 3 gfsc1:/bricks/brick1/gv0 gfsc2:/bricks/brick1/gv0 gfsc3:/bricks/brick1/gv0
gluster volume start gv0
mount.glusterfs gfsc1:/gv0 /datavol
По сути всё, 3 мастера можно их использовать, директория для хранения данных /datavol клиентов подключаем следующим образом:
Создаём директорию scripts в ней файл run.sh со следующим содержимым:
#!/bin/bash
echo $$
trap 'trap - TERM; umount /datavol; kill -s TERM -- -$$' TERM
while true; do
mount.glusterfs $1:/gv0 /datavol
if [ $? -eq 0 ]
then
break
fi
sleep 1
done
tail -f /dev/null & wait
exit 0
контейнеры запускаем следующим образом:
docker run --restart=always --name gfsm1 -v $(pwd)/scripts:/scripts --mount type=bind,source=/datavol,target=/datavol,bind-propagation=rshared -d --privileged=true --net=netgfs gluster/glusterfs-client /scripts/run.sh gfsc1
docker run --restart=always --name gfsm2 -v $(pwd)/scripts:/scripts --mount type=bind,source=/datavol,target=/datavol,bind-propagation=rshared -d --privileged=true --net=netgfs gluster/glusterfs-client /scripts/run.sh gfsc2
docker run --restart=always --name gfsm3 -v $(pwd)/scripts:/scripts --mount type=bind,source=/datavol,target=/datavol,bind-propagation=rshared -d --privileged=true --net=netgfs gluster/glusterfs-client /scripts/run.sh gfsc3
Готово.
##################################################################################
Данный скрипт необходимо запускать на swarm master. В нём имеется 3 основные переменные которые мы добавляем, это:
datadir - директория которой у нас будут расшаренные файлы,
gluster_server - перечисленные через пробел gluster сервера(рекомендовано использовать нечётное количество, чтобы образовался кворум)
name_glusternet - имя оверлей подсети(влияет только на визуальную составляющую, чтоб знать какая сеть на что отвечает)
контейнеры будут называться следующим образом: glusterИМЯНОДЫ
клиенты будут монтироваться к первому серверу в списке gluster_server
для запуска, создаём файл gluster.sh на сварм мастере с ниже указанным содержими и запускаем его:
[codesyntax lang="bash" blockstate="collapsed"]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
<strong> cat gluster.sh</strong> #!/bin/bash p=`pwd` datadir='/hostdata' gluster_server='node2 node3' name_glusternet='gluster' ################################################################ BLACK='\033[0;30m' # ${BLACK} # чёрный цвет знаков RED='\033[0;31m' # ${RED} # красный цвет знаков GREEN='\033[0;32m' # ${GREEN} # зелёный цвет знаков YELLOW='\033[0;33m' # ${YELLOW} # желтый цвет знаков BLUE='\033[0;34m' # ${BLUE} # синий цвет знаков MAGENTA='\033[0;35m' # ${MAGENTA} # фиолетовый цвет знаков CYAN='\033[0;36m' # ${CYAN} # цвет морской волны знаков GRAY='\033[0;37m' # ${GRAY} # серый цвет знаков NORMAL='\033[0m' # ${NORMAL} # все атрибуты по умолчанию WHITE='\033[1;37m' # ${WHITE} ################################################################# net=`docker network ls | awk '{print $2}' | grep ^"$name_glusternet"$` if [[ $net != "$name_glusternet" ]]; then docker network create -d overlay --attachable $name_glusternet fi echo -e "${WHITE}Создаём директорию в которой будут размещаться реплицируемые файлы:${RED} $datadir ${NORMAL}" for i in `docker node ls | grep -v 'ENGINE VERSION' |sed 's|*||'| awk '{print $2}'`; do echo "Create dir: $datadir in $i" && ssh -t $i "mkdir -p "$datadir" /bricks/brick1/gv0 /etc/glusterfs /var/lib/glusterd /var/log/glusterfs" 2>&1 |grep -v 'Connection to'; done echo "_____________________________________________" echo -e "${WHITE}Производим mount${NORMAL}" for i in `docker node ls | grep -v 'ENGINE VERSION' |sed 's|*||'| awk '{print $2}'`; do ssh -t $i "mount --bind "$datadir" "$datadir" && mount --make-shared "$datadir""; done echo "_____________________________________________" echo -e "${WHITE}Запускаем контейнеры на всех нодах ${NORMAL}" for i in `docker node ls | grep -v 'ENGINE VERSION' |sed 's|*||'| awk '{print $2}'`; do echo "Run container gluster"$i" on node $i" && ssh -t $i "docker run -dit --net "$name_glusternet" --privileged --name gluster`echo $i|sed 's|_||g'` -v /bricks:/bricks -v /etc/glusterfs:/etc/glusterfs:z -v /var/lib/glusterd:/var/lib/glusterd:z -v /var/log/glusterfs:/var/log/glusterfs:z -v /sys/fs/cgroup:/sys/fs/cgroup:ro --mount type=bind,source="$datadir",target="$datadir",bind-propagation=rshared -d --privileged=true -v /dev/:/dev gluster/gluster-centos" 2>&1 |grep -vi 'Connection to' && echo ""; done echo "_____________________________________________" echo -e "${WHITE}Проверка.${NORMAL}" echo -e "Вывод ${YELLOW} id${NORMAL} контейнеров и их ${YELLOW}названий ${NORMAL}, должно быть:${RED} `docker node ls | grep -v 'ENGINE VERSION' |sed 's|*||'| awk '{print $2}'| wc -l` ${NORMAL} штук:" for i in `docker node ls | grep -v 'ENGINE VERSION' |sed 's|*||'| awk '{print $2}'`; do ssh -t $i "docker ps | grep `echo $i | sed 's|_||g'`" 2>&1 | grep -vi 'Connection to' | awk '{print $1,$NF}'; done echo "_____________________________________________" echo -e "${WHITE}Добавляем peer'ов в кластер ${NORMAL}" for i in `echo $gluster_server`; do echo "gluster_$i" | sed 's|_||g' >> $p/node; done dockername=`cat $p/node | sort |uniq` for i in `echo $dockername`; do ssh -t `echo $gluster_server | awk '{print $1}'` "docker exec -ti `echo gluster_$gluster_server | awk '{print $1}'|sed 's|_||g'` gluster peer probe $i"; done echo "_____________________________________________" echo -e "${WHITE}Проверяем добавились ли peer:${NORMAL}" ssh -t `echo $gluster_server | awk '{print $1}'` "docker exec -ti `echo gluster_$gluster_server | awk '{print $1}' | sed 's|_||g'` gluster peer status" for i in `cat $p/node | sort | uniq`; do echo "$i:/bricks/brick1"; done | tr -s '\r\n' ' ' > $p/node_brik echo "ssh -t `echo $gluster_server | awk '{print $1}'` \"docker exec -ti `echo gluster_$gluster_server | awk '{print $1}' | sed 's|_||g'` gluster volume create gv0 replica `echo $gluster_server | wc -w` transport tcp `cat $p/node_brik`force\"" >$p/comand_for_run echo "_____________________________________________" echo "" echo -e "${WHITE}Создаём и стартуем volume ${RED}gv0 ${NORMAL}" echo "ssh -t `echo $gluster_server | awk '{print $1}'` \"docker exec -ti `echo gluster_$gluster_server | awk '{print $1}' | sed 's|_||g'` gluster volume start gv0\"" >> $p/comand_for_run /bin/bash $p/comand_for_run for i in `echo $gluster_server`; do echo "ssh -t $i \"docker exec -ti `echo gluster_$i |sed 's|_||g'` mount.glusterfs localhost:/gv0 "$datadir"\""; done >> $p/mountdir echo "_____________________________________________" echo "" echo -e "${WHITE}mount директории ${RED} $datadir ${NORMAL}" bash $p/mountdir echo "" echo "_____________________________________________" echo -e "${WHITE}Проверяем pool list ${NORMAL}" ssh -t `echo $gluster_server | awk '{print $1}'` "docker exec -ti `echo gluster_$gluster_server | awk '{print $1}' | sed 's|_||g'` gluster pool list" echo "" echo "_____________________________________________" echo -e "${WHITE}Проверяем peer status ${NORMAL}" ssh -t `echo $gluster_server | awk '{print $1}'` "docker exec -ti `echo gluster_$gluster_server | awk '{print $1}' | sed 's|_||g'` gluster peer status" echo "" echo "_____________________________________________" echo -e "${WHITE}Проверяем peer status ${NORMAL}" ssh -t `echo $gluster_server | awk '{print $1}'` "docker exec -ti `echo gluster_$gluster_server | awk '{print $1}' | sed 's|_||g'` gluster volume info all" rm -rf $p/comand_for_run $p/node $p/node_brik $p/mountdir ######################## # клиентская часть # ######################## docker node ls | grep -v 'ENGINE VERSION' |sed 's|*||'| awk '{print $2}' > $p/all_node echo $gluster_server | sed 's| |\n|g' | grep -v ^$ > $p/glusterServer grep -vf $p/glusterServer $p/all_node > $p/glusterClient echo "_____________________________________________" echo -e "${WHITE}Добавляем ${RED}client ${WHITE}peer'ов в кластер${NORMAL}" for i in `cat $p/glusterClient`; do echo "gluster_$i" | sed 's|_||g' >> $p/client_node; done dockername=`cat $p/client_node | sort |uniq` clientnode=`cat $p/glusterClient` for i in `echo $dockername`; do for j in `echo $clientnode`; do echo "ssh -t $j \"docker exec -ti $i gluster peer probe $i"\" '2>/dev/null'; done; done > $p/addpeerclinet /bin/bash $p/addpeerclinet echo "_____________________________________________" echo -e "${WHITE}Монтируем ${RED}client'ов${WHITE} к мастер серверу ${RED}`echo $gluster_server | awk '{print $1}'` ${NORMAL}" for i in `echo $dockername`; do for j in `echo $clientnode`; do echo "ssh -t $j \"docker exec -ti $i mount.glusterfs `echo gluster_$gluster_server | awk '{print $1}'| sed 's|_||g'`:/gv0 "$datadir" $i"\" '2>/dev/null'; done; done> $p/mountclinet /bin/bash $p/mountclinet rm -rf $p/all_node $p/glusterServer $p/glusterClient $p/client_node $p/addpeerclinet $p/mountclinet |
[/codesyntax]
чтобы удалить все данные и контейнеры, то запускаем следующий скрипт:
[codesyntax lang="bash"]
1 2 3 4 5 6 7 8 9 |
cat del_gluster.sh #!/bin/bash datadir='/hostdata' for i in `docker node ls | grep -v 'ENGINE VERSION' |sed 's|*||'| awk '{print $2}'`; do echo $i && ssh -t $i "docker rm -f `echo gluster_$i |sed 's|_||g'`";done for i in `docker node ls | grep -v 'ENGINE VERSION' |sed 's|*||'| awk '{print $2}'`; do echo $i && ssh -t $i "umount $datadir"; done for i in `docker node ls | grep -v 'ENGINE VERSION' |sed 's|*||'| awk '{print $2}'`; do echo $i && ssh -t $i "docker container prune -f && echo """; done for i in `docker node ls | grep -v 'ENGINE VERSION' |sed 's|*||'| awk '{print $2}'`; do echo $i && ssh -t $i "rm -rf /bricks/* /etc/glusterfs/* /var/lib/glusterd/* /var/log/glusterfs/* "$datadir"/*"; done |
[/codesyntax]