RancherOS で構築した k8s クラスタ用に GlusterFS で簡単な分散ファイルシステムを構築
[History] [Last Modified] (2019/01/22 00:55:34)
Recent posts
What is this site?
A platform for makers to share their knowledge.

Share your robots/products with others.
New robots/products

概要

こちらのページで設定した k8s クラスタの各 Node マシンに GlusterFS サーバのコンテナを一つだけ起動して、簡単な分散ファイルシステムを構築します。各 Node へのコンテナ設置のためには DaemonSet が利用できそうですが、ここでは RancherOSrancher.services を利用します。

1台構成

後に rancher.services で起動することを想定して、Debian stretch のイメージでコンテナ内に GlusterFS を設定してみます。GlusterFS は fuse を利用するため適切な権限を付与します。

docker run -h mygluster --cap-add SYS_ADMIN --device /dev/fuse -it --rm debian:stretch /bin/bash

apt インストール

apt update
apt install -y glusterfs-server

サービスの起動および自動起動の設定

/etc/init.d/glusterfs-server start
update-rc.d glusterfs-server defaults

自動起動の設定削除および確認をしたい場合

update-rc.d -f glusterfs-server remove
apt install sysv-rc-conf
sysv-rc-conf

brick を一つだけ作成して、brick をもとに volume を作成

mkdir -p /data/glusterfs/brick0
gluster volume create gv0 mygluster:/data/glusterfs/brick0 force
gluster volume info | grep Status #Status: Created
gluster volume start gv0
gluster volume info | grep Status #Status: Started

マウントして利用できるか確認

mkdir -p /mnt/glusterfs
mount -t glusterfs mygluster:/gv0 /mnt/glusterfs

ログは以下の場所で確認できます

/var/log/glusterfs

ホスト側のディレクトリをマウントしておくとデータを永続化できます。gluster volume create ではディレクトリの内容が削除されません。

docker run -h mygluster --cap-add SYS_ADMIN --device /dev/fuse -it --rm -v /data/glusterfs:/data/glusterfs debian:stretch /bin/bash

ホスト外からマウントするためには更に --net=host を付与します。-h mygluster は付与しません。コンテナのホスト名はホストと同じになります。

docker run --cap-add SYS_ADMIN --device /dev/fuse --net=host -it --rm -v /data/glusterfs:/data/glusterfs debian:stretch /bin/bash
gluster volume create gv0 myhostname:/data/glusterfs/brick0 force

RancherOS の場合

rancher.services の設定は以下のようにできます。

hostname: myhostname
rancher:
  services:
    user-volumes:
      volumes:
      - /home:/home
      - /opt:/opt
      - /var/lib/kubelet:/var/lib/kubelet
      - /data/glusterfs:/data/glusterfs
    glusterfs-server:
      image: my-glusterfs-server:latest
      restart: unless-stopped
      volumes:
      - /data/glusterfs:/data/glusterfs
      cap_add:
      - SYS_ADMIN
      devices:
      - /dev/fuse:/dev/fuse
      environment:
        SERVER_NAME: myhostname
        VOLUME_NAMES: gv0 gv1 gv2
      net: host

Dockerfile

FROM debian:stretch
RUN apt-get update && apt-get install -y glusterfs-server
COPY entrypoint.bash /usr/bin/entrypoint.bash
ENTRYPOINT /usr/bin/entrypoint.bash

entrypoint.bash

#!/bin/bash
set -e

/etc/init.d/glusterfs-server stop || true
/etc/init.d/glusterfs-server start

echo ${VOLUME_NAMES}
VOLUME_NAMES=(`echo $VOLUME_NAMES`)

for VOLUME_NAME in ${VOLUME_NAMES[@]}; do
    echo ${VOLUME_NAME}
    mkdir -p /data/glusterfs/${VOLUME_NAME}
    gluster volume create ${VOLUME_NAME} ${SERVER_NAME}:/data/glusterfs/${VOLUME_NAME} force || true
    gluster volume start ${VOLUME_NAME} || true
done

tail -f /var/log/glusterfs/cmd_history.log

build.bash

#!/bin/bash
set -eu

docker build . -t my-glusterfs-server:latest

動作検証

./build.bash
docker run --cap-add SYS_ADMIN --device /dev/fuse --net=host --rm -v /data/glusterfs:/data/glusterfs \
  -e "SERVER_NAME=`hostname`" \
  -e "VOLUME_NAMES=gv0 gv1 gv2" \
  my-glusterfs-server:latest

Pod からの利用設定

直接 mount する方法もありますが、以下では Persistent Volume として設定しています。

apiVersion: v1
kind: Service
metadata:
  name: glusterfs
spec:
  ports:
  - port: 1
---
apiVersion: v1
kind: Endpoints
metadata:
  name: glusterfs
subsets:
- addresses:
  - ip : 10.0.2.15 # myhostname IP
  ports:
  - port: 1
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: gv0-pv
  labels:
    name: gv0-pv
spec:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 32Gi
  glusterfs:
    endpoints: glusterfs
    path: gv0
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: gv0-pvc
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 32Gi
  selector:
    matchLabels:
      name: gv0-pv
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  volumes:
  - name: external
    persistentVolumeClaim:
      claimName: gv0-pvc
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - mountPath: /external
      name: external

複数台構成

手動で設定を把握

複数台構成を把握する目的で、以下のようにコンテナを三つ同じ docker ネットワーク内に起動してみます。実際には別々のサーバで一つのコンテナを --net=host を付与して起動します。

docker network create --subnet=172.18.0.0/16 mygluster
docker run -h mygluster1 --name mygluster1 --net mygluster --ip 172.18.0.101 --cap-add SYS_ADMIN --device /dev/fuse -it --rm debian:stretch /bin/bash
docker run -h mygluster2 --name mygluster2 --net mygluster --ip 172.18.0.102 --cap-add SYS_ADMIN --device /dev/fuse -it --rm debian:stretch /bin/bash
docker run -h mygluster3 --name mygluster3 --net mygluster --ip 172.18.0.103 --cap-add SYS_ADMIN --device /dev/fuse -it --rm debian:stretch /bin/bash

apt update
apt install -y glusterfs-server
/etc/init.d/glusterfs-server start
mkdir -p /data/glusterfs/gv0

例えば mygluster1 から mygluster2 と mygluster3 を追加する場合

gluster peer probe mygluster2
gluster peer probe mygluster3
gluster peer status

mygluster1 と mygluster2 および mygluster3 は同じ扱いで主従関係はありません。以下のコマンドはいずれのホストで実行しても動作します。

gluster volume create gv0 replica 3 mygluster1:/data/glusterfs/gv0 mygluster2:/data/glusterfs/gv0 mygluster3:/data/glusterfs/gv0 force
gluster volume start gv0
gluster volume info

実行例

root@mygluster1:/# gluster volume info

Volume Name: gv0
Type: Replicate
Volume ID: 0216131f-643f-485c-a35e-3775d3c9c25b
Status: Started
Snapshot Count: 0
Number of Bricks: 1 x 3 = 3
Transport-type: tcp
Bricks:
Brick1: mygluster1:/data/glusterfs/gv0
Brick2: mygluster2:/data/glusterfs/gv0
Brick3: mygluster3:/data/glusterfs/gv0
Options Reconfigured:
transport.address-family: inet
performance.readdir-ahead: on
nfs.disable: on

ボリュームのタイプ

冗長性なし

gluster volume create gv0 mygluster1:/data/glusterfs/gv0 mygluster2:/data/glusterfs/gv0 mygluster3:/data/glusterfs/gv0 mygluster4:/data/glusterfs/gv0 force

すべて同じデータを保持

gluster volume create gv0 replica 4 mygluster1:/data/glusterfs/gv0 mygluster2:/data/glusterfs/gv0 mygluster3:/data/glusterfs/gv0 mygluster4:/data/glusterfs/gv0 force

同じデータを二つのサーバで保持

gluster volume create gv0 replica 2 mygluster1:/data/glusterfs/gv0 mygluster2:/data/glusterfs/gv0 mygluster3:/data/glusterfs/gv0 mygluster4:/data/glusterfs/gv0 force

新規にサーバを追加した場合のオペレーション例

mygluster1 と mygluster2 で volume create して start

gluster pool list
gluster peer status
gluster volume list
gluster volume create gv0 replica 2 mygluster1:/data/glusterfs/gv0 mygluster2:/data/glusterfs/gv0 force
gluster volume start gv0
gluster volume info gv0
gluster volume status gv0
#gluster volume stop gv0
#gluster volume delete gv0

mygluster3 と mygluster4 を pool に追加

gluster peer probe mygluster3
gluster peer probe mygluster4
gluster pool list
gluster volume add-brick gv0 mygluster3:/data/glusterfs/gv0 mygluster4:/data/glusterfs/gv0 force
gluster volume info gv0
gluster volume rebalance gv0 start #force
gluster volume rebalance gv0 status
#gluster volume rebalance gv0 stop

RancherOS の場合の簡単な設定例

簡単のため便宜的な master とその他で設定を分けてみます。SERVER_NAMES 等の環境変数を変更すると docker コンテナ自体が再作成されますが、brick ディレクトリ内のデータは削除されずに引き継がれます。

便宜的な master

rancher.services の設定は以下のようにできます。

hostname: myhostname-master
rancher:
  services:
    user-volumes:
      volumes:
      - /home:/home
      - /opt:/opt
      - /var/lib/kubelet:/var/lib/kubelet
      - /data/glusterfs:/data/glusterfs
    glusterfs-server:
      image: my-glusterfs-server-master:latest
      restart: unless-stopped
      volumes:
      - /data/glusterfs:/data/glusterfs
      cap_add:
      - SYS_ADMIN
      devices:
      - /dev/fuse:/dev/fuse
      environment:
        SERVER_NAMES: myhostname-master myhostname1
        VOLUME_NAMES: gv0 gv1 gv2
      net: host

Dockerfile

FROM debian:stretch
RUN apt-get update && apt-get install -y glusterfs-server
COPY entrypoint-master.bash /usr/bin/entrypoint-master.bash
ENTRYPOINT /usr/bin/entrypoint-master.bash

entrypoint-master.bash

replica 2 としているため、SERVER_NAMES で指定した先頭から二つずつが組になります。以下の例では myhostname-master myhostname1 が組です。SERVER_NAMES: myhostname-master myhostname1 myhostname2 myhostname3 とした場合は更に myhostname2 myhostname3 が組になります。

the order in which bricks are specified has a great effect on data protection.
https://docs.gluster.org/en/latest/Administrator%20Guide/Setting%20Up%20Volumes/#creating-distributed-replicated-volumes

#!/bin/bash
set -e

/etc/init.d/glusterfs-server stop || true
/etc/init.d/glusterfs-server start

VOLUME_NAMES=(`echo $VOLUME_NAMES`)
SERVER_NAMES=(`echo $SERVER_NAMES`)

while [ `gluster pool list | grep Connected | wc -l` -ne ${#SERVER_NAMES[@]} ]; do
    for SERVER_NAME in ${SERVER_NAMES[@]}; do
        echo ${SERVER_NAME}
        gluster peer probe ${SERVER_NAME} || true
    done
done

for VOLUME_NAME in ${VOLUME_NAMES[@]}; do
    echo ${VOLUME_NAME}
    mkdir -p /data/glusterfs/${VOLUME_NAME}
    CMD="gluster volume create ${VOLUME_NAME} replica 2"
    for SERVER_NAME in ${SERVER_NAMES[@]}; do
        CMD="${CMD} ${SERVER_NAME}:/data/glusterfs/${VOLUME_NAME}"
    done
    ${CMD} force || true
    gluster volume start ${VOLUME_NAME} || true
    gluster volume rebalance ${VOLUME_NAME} start || true
done

tail -f /var/log/glusterfs/cmd_history.log

build.bash

#!/bin/bash
set -eu

docker build . -t my-glusterfs-server-master:latest

その他のホスト

hostname: myhostname1
rancher:
  services:
    user-volumes:
      volumes:
      - /home:/home
      - /opt:/opt
      - /var/lib/kubelet:/var/lib/kubelet
      - /data/glusterfs:/data/glusterfs
    glusterfs-server:
      image: my-glusterfs-server:latest
      restart: unless-stopped
      volumes:
      - /data/glusterfs:/data/glusterfs
      cap_add:
      - SYS_ADMIN
      devices:
      - /dev/fuse:/dev/fuse
      environment:
        VOLUME_NAMES: gv0 gv1 gv2
      net: host

Dockerfile

FROM debian:stretch
RUN apt-get update && apt-get install -y glusterfs-server
COPY entrypoint.bash /usr/bin/entrypoint.bash
ENTRYPOINT /usr/bin/entrypoint.bash

entrypoint.bash

#!/bin/bash
set -e

/etc/init.d/glusterfs-server stop || true
/etc/init.d/glusterfs-server start

echo ${VOLUME_NAMES}
VOLUME_NAMES=(`echo $VOLUME_NAMES`)

for VOLUME_NAME in ${VOLUME_NAMES[@]}; do
    echo ${VOLUME_NAME}
    mkdir -p /data/glusterfs/${VOLUME_NAME}
done

tail -f /var/log/glusterfs/cmd_history.log

build.bash

#!/bin/bash
set -eu

docker build . -t my-glusterfs-server:latest

IO の状態を確認

マウントしているクライアント

gluster volume status gv0 clients

各 brick における読み出し、書き込み、ファイルオープン回数の調査

gluster volume top gv0 read
gluster volume top gv0 write
gluster volume top gv0 open

各 brick のプロファイリング

gluster volume profile gv0 start
gluster volume profile gv0 info
gluster volume profile gv0 stop
Related pages