Kubernetes の永続ストレージとして DRBD を使用

DRBD を Kubernetes で使用する FlexVolume プラグインというのは以前からありますが、最近は LINSTOR 経由で使用するプラグインも公開されましたので紹介します。

LINSTOR External Provisioner というのがボリュームの作成と削除を行い、LINSTOR FlexVolume Provisioner というのが、ボリュームの接続、切り離し、マウント、アンマウント、ファイルシステムの作成を行います。

以下に構築例として、Kubernetes の永続ストレージとして DRBDを設定する方法を示します。

前提条件

前提条件として、すでに以下の構成がなされているとします。

  • 3台のホストを用意する。1台を Master(LINSTOR では controller), 残り2台を Worker (LINSTOR では satellite) として使用。
  • すべてのホストに CentOS 7.5、DRBD9, LINSTOR をインストール。
  • すべてのホストに Docker, Kubernetes をインストール。
  • Kubernetes の Master node, Worker node は設定済みである。
  • LINSTOR の node の作成は設定済みである。
# docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.
:

# kubectl get nodes
NAME       STATUS    ROLES     AGE       VERSION
tate-z55   Ready     master    4d        v1.11.1
tate-z56   Ready     <none>    4d        v1.11.1
tate-z57   Ready     <none>    4d        v1.11.1

# linstor --no-utf8 node list 
+----------------------------------------------+
| Node     | NodeType  | IPs          | State  |
|----------------------------------------------|
| tate-z55 | COMBINED  | 10.30.103.55 | Online |
| tate-z56 | SATELLITE | 10.30.103.56 | Online |
| tate-z57 | SATELLITE | 10.30.103.57 | Online |
+----------------------------------------------+

* LINSTOR のインストールは DRBD9 LINSTOR 構築手順書 を参照ください。パッケージを自分でビルドする方法もありますので LINBIT レポジトリなしでも試せます。

ソフトウェア

今回使用したソフトウェア情報を以下に記載します。

  • CentOS 7.5
  • kmod-drbd-9.0.14_3.10.0_862-1
  • drbd-9.5.0-1
  • drbd-utils-9.5.0-1
  • linstor-client-0.2.2-1
  • linstor-server-0.2.6-1
  • python-linstor-0.2.2-1
  • docker-ce-18.06.0.ce-3
  • kubeadm-1.11.1-0
  • kubectl-1.11.1-0
  • kubelet-1.11.1-0

docker パッケージは https://download.docker.com/linux/centos/docker-ce.repo, kubernetes 関連パッケージは https://packages.cloud.google.com/yum/repos/kubernetes-el7-$basearch から取得

LINSTOR External Provisioner の設定

Master ノードで linstor-external-provisioner をビルドします。

# yum install -y git wget
# wget https://dl.google.com/go/go1.10.4.linux-amd64.tar.gz
# tar xzf go1.10.4.linux-amd64.tar.gz
# PATH=$PWD/go/bin:$PATH

# export GOPATH=$HOME
# mkdir -p $GOPATH/src/github.com/LINBIT
# cd $GOPATH/src/github.com/LINBIT/

# git clone https://github.com/LINBIT/linstor-external-provisioner
# (cd linstor-external-provisioner; make)
# cp linstor-external-provisioner/linstor-external-provisioner /bin

端末を一つ用意し、linstor-external-provisioner を起動します。

# linstor-external-provisioner -provisioner=external/linstor -kubeconfig=$HOME/.kube/config &

stdout, stderr がそのまま端末に表示されますので必要に応じてリダイレクトしてください。

LINSTOR FlexVolume Provisioner の設定

全てのノードで LINSTOR FlexVolume Provisioner をビルドします。1つのでノードでビルドしてコピーするでもかまいません。

# cd $GOPATH/src/github.com/LINBIT/
# git clone https://github.com/LINBIT/linstor-flexvolume
# (cd linstor-flexvolume; make)
# mkdir -p /usr/libexec/kubernetes/kubelet-plugins/volume/exec/linbit~linstor-flexvolume
# cp linstor-flexvolume/linstor-flexvolume /usr/libexec/kubernetes/kubelet-plugins/volume/exec/linbit~linstor-flexvolume/

/etc/systemd/system/kubelet.service.d/10-kubeadm.conf を編集し enable-controller-attach-detach=false を追加します。

# vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
:
ExecStart=/usr/bin/kubelet --enable-controller-attach-detach=false $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS

設定後 kubelet を再起動します。

# systemctl daemon-reload; systemctl restart kubelet

設定を確認します。

# cat /proc/$(pgrep kubelet)/cmdline

/etc/linstor/linstor-client.conf の編集

linstor-flexvolume から linstor コマンドが使われるので、Satellite ノードでも linstor コマンドが動作しなければならなりません。以下を Satellite ノードで実行します。

# vi /etc/linstor/linstor-client.conf

[global]
controllers=10.30.103.55

controllers で controller ノードのアドレスを指定します。Satellite ノードでも linstor node list が動作するのを確認してください。

storage pool の準備

Master ノード上で Kubernetes で使用する DRBD storage pool を準備します。ここでは drbd_test とします。

# linstor storage-pool-definition create drbd_test
# linstor storage-pool create tate-z55 drbd_test lvm drbdpool
# linstor storage-pool create tate-z56 drbd_test lvm drbdpool
# linstor storage-pool create tate-z57 drbd_test lvm drbdpool

# linstor --no-utf8 storage-pool list 
+------------------------------------------------------------------------------+
| StoragePool | Node     | Driver    | PoolName |     Free | SupportsSnapshots |
|------------------------------------------------------------------------------|
| drbd_test   | tate-z55 | LvmDriver | drbdpool | 4.88 GiB | false             |
| drbd_test   | tate-z56 | LvmDriver | drbdpool | 4.88 GiB | false             |
| drbd_test   | tate-z57 | LvmDriver | drbdpool | 4.88 GiB | false             |
+------------------------------------------------------------------------------+

以上で設定は終了です。

StorageClass, PersistentVolumeClaim の準備

あとは StorageClass に登録し (controllers は環境に合わせて書き換える)、

# vi two-replica-sc.yaml

apiVersion: storage.k8s.io/v1beta1
kind: StorageClass
metadata:
  name: two-replica
provisioner: external/linstor
parameters:
  autoPlace: "2"
  filesystem: "xfs"
  storagePool: "drbd_test"
  controllers: "10.30.103.55"

# kubectl create -f two-replica-sc.yaml
# kubectl describe storageclass two-replica

PersistentVolumeClaim でボリュームを割当ます。

# vi my-first-volume-pvc.yaml

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: my-first-volume
  annotations:
    volume.beta.kubernetes.io/storage-class: two-replica
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi

# kubectl create -f my-first-volume-pvc.yaml
# kubectl describe persistentvolumeclaim my-first-volume

正しく動作すると resource, storage-pool は以下のようになります。

# linstor --no-utf8 resource list
+------------------------------------------------------+
| ResourceName            | Node     | Port |    State |
|------------------------------------------------------|
| default-my-first-volume | tate-z55 | 7000 | UpToDate |
| default-my-first-volume | tate-z56 | 7000 | UpToDate |
+------------------------------------------------------+
  *同期中は片方 Inconsistent になってます。

# linstor --no-utf8 storage-pool list
+------------------------------------------------------------------------------+
| StoragePool | Node     | Driver    | PoolName |     Free | SupportsSnapshots |
|------------------------------------------------------------------------------|
| drbd_test   | tate-z55 | LvmDriver | drbdpool | 4.39 GiB | false             |
| drbd_test   | tate-z56 | LvmDriver | drbdpool | 4.39 GiB | false             |
| drbd_test   | tate-z57 | LvmDriver | drbdpool | 4.88 GiB | false             |
+------------------------------------------------------------------------------+

fedora で DRBD を永続ストレージとして使う

最後に、fedoraコンテナを作成し動作確認します。

# vi fedora.yaml

apiVersion: v1
kind: Pod
metadata:
  name: fedora
  namespace: default
spec:
  containers:
  - name: fedora
    image: fedora
    command: [/bin/bash]
    args: ["-c", "while true; do sleep 10; done"]
    volumeMounts:
    - name: default-my-first-volume
      mountPath: /data
    ports:
    - containerPort: 80
  volumes:
  - name: default-my-first-volume
    persistentVolumeClaim:
      claimName: "my-first-volume"

# kubectl create -f fedora.yaml
# kubectl describe pod fedora

ここで、しばらくして、
Unable to mount volumes

と表示される場合は、10-kubeadm.conf にパッチがあっていないか、satellite ノードで linstor コマンドが動作していない可能性がありますので設定を確認します。

問題なければ、fedora pod に接続し、DRBD volume に書き込んでみます。

# kubectl get pod -o wide
NAME      READY     STATUS    RESTARTS   AGE       IP            NODE       NOMINATED NODE
fedora    1/1       Running   0          49s       10.244.2.22   tate-z57   <none>
# kubectl exec fedora -it /bin/bash

/dev/drbd1000 が /data にマウントされているので、ここに書き込み、exit コマンドで fedora pod を抜けます。

[root@fedora /]# mount |grep /data
/dev/drbd1000 on /data type xfs (rw,relatime,attr2,inode64,noquota)
[root@fedora /]# echo "Test1" > /data/Test1
[root@fedora /]# ls -la /data 
total 4
drwxr-xr-x 2 root root 19 Aug 17 04:25 .
drwxr-xr-x 1 root root 29 Aug 17 04:28 ..
-rw-r--r-- 1 root root  6 Aug 18 10:39 Test1
[root@fedora /]# exit

いったん、fedora pod を削除します。前回は tate-z57 に割り当てられていたので、cordon でこれを除外し、再度 fedora pod を作成します。

# kubectl delete pod fedora
# kubectl cordon tate-z57
# kubectl create -f fedora.yaml 
# kubectl get pod -o wide
NAME      READY     STATUS    RESTARTS   AGE       IP           NODE       NOMINATED NODE
fedora    1/1       Running   0          1m        10.244.1.4   tate-z56   <none>

今度は tate-z56 に割り当てられました。再度 fedora pod に接続します。

# kubectl exec fedora -it /bin/bash
[root@fedora /]# ls -la /data/
total 4
drwxr-xr-x 2 systemd-coredump input 19 Aug 16 01:08 .
drwxr-xr-x 1 root             root  29 Aug 16 01:13 ..
-rw-r--r-- 1 root             root   6 Aug 16 01:08 Test1
[root@fedora /]# cat /data/Test1 
Test1

先程の書き込みが確認でき、DRBD が永続ストレージとして使用できるのが確認できました。

参考

以下を参考にしましたので、詳細はこちらを参照ください。