永続ストレージ

本コンテンツは、MAD Workshop Ops Track の内容をベースに、一部変更しています。

演習の概要

OpenShiftの Pod がデータベースをホストするなど、信頼性の高いストレージを必要とする場合があります。
こういった場合は、Pod永続的な(Persistent) Volume を供給する必要があります。なぜならば Pod(コンテナ) 内部に保存されるデータは、Pod が消えると失われてしまうためです。
Persistent Volume は一般的には、外部ストレージシステムから供給され、Pod が消えても存続するストレージです。したがってストレージ内に保存したデータは失われることはありません。

この演習では、この Persistent Volume について学びます。


Persistent Volume Claims

これらの演習を行うには、「コンテナデプロイと管理」の演習で紹介されているアプリケーションがすでにデプロイされている必要があります。

mapit アプリケーションは現在、永続的なストレージを利用していません。Pod が消えると、コンテナ内のすべてのコンテンツも消えてしまいます。
この概念については後で詳しく説明します。

コンテナ内の /app-storage ディレクトリに使う 永続ストレージ(Persistent Storage) を必要とする mapit アプリケーションを想像してみましょう。

コンテナの内部ファイルシステムを構成するディレクトリは、コンテナイメージのread-onlyレイヤーと、イメージからコンテナインスタンスが起動されるとすぐに追加されるwritableな最上位レイヤーを重ね合わせたものです。
writableなレイヤーは、コンテナが削除されると破棄されます。これは動的なコンテナオーケストレーション環境では普通に起きることです。

前のラボで使用した app-management プロジェクトに入っているはずです。確認するために、次のコマンドを実行します。

oc project app-management

OpenShiftに外部の永続ストレージを表す PersistentVolume オブジェクトを作成し、それをコンテナのファイルシステム内に Mount するよう指示する方法を以下に示します。

oc set volume deploy/mapit --add --name=mapit-storage -t pvc --claim-mode=ReadWriteOnce --claim-size=1Gi --claim-name=mapit-storage --mount-path=/app-storage

出力は次のようになります。

deployment.apps/mapit volume updated

最初のステップでは、PersistentVolumeClaim が作成されました。このオブジェクトは、ユーザーからOpenShiftへの一定の容量を持つ特定の種類のストレージのリクエストを表しています。 次に、mapitDeployment を更新して、このストレージを参照し、Pod 内の /app-storage ディレクトリで利用できるようにしています。

このように新しい Deployment が表示されます。

oc get deploy mapit

出力を見ると、ストレージの更新によって新しいリビジョンが作成されたことがわかります。

NAME    READY   UP-TO-DATE   AVAILABLE   AGE
mapit   1/1     1            1           14m

タイミングによっては、新しい Pod が生成されていることがわかるかもしれません。

oc get pod
NAME                     READY   STATUS              RESTARTS   AGE
mapit-649fd997c6-rvntj   0/1     ContainerCreating   0          13s
mapit-79975ccb98-hpw6m   1/1     Running             0          76s

Deployment を見てみましょう。

oc describe deploy mapit

新しいストレージについて、MountsVolumes の両方の詳細が表示されているのがわかります。

...
    Mounts:
      /app-storage from mapit-storage (rw)
  Volumes:
   mapit-storage:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  mapit-storage
    ReadOnly:   false
...

しかし、この裏では何が起こっているのでしょうか?

Storage Classes

OpenShift 4を最初にインストールしたときに、AWS EBS用のダイナミックストレージプロバイダが設定されていました。この StorageClass を見てみましょう。

oc get storageclass

以下のように表示されます。

NAME                PROVISIONER       RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
gp2-csi             ebs.csi.aws.com   Delete          WaitForFirstConsumer   true                   3h36m
gp3-csi (default)   ebs.csi.aws.com   Delete          WaitForFirstConsumer   true                   3h36m

StorageClass を指定していない PersistentVolumeClaim では、デフォルトの StorageClass が使用されます。この場合では、デフォルトはEBS Provisionerで、リクエストされたサイズ(この例では1Gi)のEBS GP2 Volumeを作成します。

gp2-csi もあることに注意してみましょう。これは CSI を実装した StorageClass です。これは "Container Storage Interface" の略です。 CSIの仕様により、ストレージベンダはプラグインを一度開発すれば、様々なコンテナオーケストレーションシステムで動作させることができるようになります。

Persistent Volume (Claims)

先ほど実行した oc set volume コマンドは、claim を参照しています。
Kubernetes環境のストレージは、Volume Claim と Volume のシステムを使用します。ユーザが PersistentVolumeClaim を作成し、Kubernetesはそれにマッチする`PersistentVolume` を見つけようとします。
PersistentVolume が存在しない場合は、要求を満たすことができるDynamic Provisionerがあれば、PersistentVolume が動的に作成されます。

以下を実行します。

oc get persistentvolume

以下のように表示されます。

NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                          STORAGECLASS   REASON   AGE
pvc-06b0184f-f4fe-4b7f-838b-33165d694f92   1Gi        RWO            Delete           Bound    app-management/mapit-storage   gp3-csi                 7m26s

これは、先ほどのClaimの結果として作成された Persistent Volume です。この app-management Project に存在するClaimにBindされている(Bound)ことに注意してください。

oc get persistentvolumeclaim -n app-management

以下のように表示されます。

NAME            STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mapit-storage   Bound    pvc-06b0184f-f4fe-4b7f-838b-33165d694f92   1Gi        RWO            gp3-csi        7m53s

永続ストレージのテスト

oc get pods を使って Pod の名前を取得してから、oc クライアントのリモートシェル機能で Pod にログインします。

oc rsh $(oc get pods -l deployment=mapit -o name)

コンテナのシェルセッションにいる状態で、コンテナの名前空間でルートディレクトリの内容をリストアップします。

ls -ahl /

/app-storage という名前のディレクトリがあります。

total 20K
dr-xr-xr-x.   1 root  root         81 Jun 19 06:51 .
dr-xr-xr-x.   1 root  root         81 Jun 19 06:51 ..
-rw-r--r--.   1 root  root        16K Dec 14  2016 anaconda-post.log
drwxrwsr-x.   3 root  1000690000 4.0K Jun 19 06:50 app-storage
lrwxrwxrwx.   1 root  root          7 Dec 14  2016 bin -> usr/bin
drwxrwxrwx.   1 jboss root         45 Aug  4  2017 deployments
drwxr-xr-x.   5 root  root        360 Jun 19 06:51 dev
drwxr-xr-x.   1 root  root         93 Jan 18  2017 etc
drwxr-xr-x.   2 root  root          6 Nov  5  2016 home
lrwxrwxrwx.   1 root  root          7 Dec 14  2016 lib -> usr/lib
lrwxrwxrwx.   1 root  root          9 Dec 14  2016 lib64 -> usr/lib64
drwx------.   2 root  root          6 Dec 14  2016 lost+found
drwxr-xr-x.   2 root  root          6 Nov  5  2016 media
drwxr-xr-x.   2 root  root          6 Nov  5  2016 mnt
drwxr-xr-x.   1 root  root         19 Jan 18  2017 opt
dr-xr-xr-x. 328 root  root          0 Jun 19 06:51 proc
dr-xr-x---.   2 root  root        114 Dec 14  2016 root
drwxr-xr-x.   1 root  root         42 Jun 19 06:51 run
lrwxrwxrwx.   1 root  root          8 Dec 14  2016 sbin -> usr/sbin
drwxr-xr-x.   2 root  root          6 Nov  5  2016 srv
dr-xr-xr-x.  13 root  root          0 Jun 19 03:29 sys
drwxrwxrwt.   1 root  root        120 Jun 19 06:51 tmp
drwxr-xr-x.   1 root  root         69 Dec 16  2016 usr
drwxr-xr-x.   1 root  root         41 Dec 14  2016 var
1 これはコンテナ内の永続ストレージが表示される場所です。

Amazon EBSのVolumeはRead-Write-Onceです。EBSはブロックストレージなので、一度に1つのEC2インスタンスにしかアタッチできません。これは一度に1つのコンテナでしかEBSベースの PersistentVolume を使用できないということを意味します。(この性質をRead-Write-Onceと呼びます)

リモートシェルセッション内で以下を実行します。

echo "Hello World from OpenShift" > /app-storage/hello.txt
exit

次に、ファイルが存在することを確認します。

oc rsh $(oc get pods -l deployment=mapit -o name) cat /app-storage/hello.txt

ここで、永続ストレージが本当に動作するか確認するためにPodを削除してみます。

oc delete pods -l deployment=mapit && oc get pod

しばらくすると、新しい Pod が準備され、実行できるようになります。その名前を探して、もう一度ファイルを確認してください。

oc rsh $(oc get pods -l deployment=mapit -o name) cat /app-storage/hello.txt

ファイルがあることが確認できるでしょう。Pod が消えてもストレージとそのデータは保存されていることが分かります。
新しい Pod は古い Pod と同じノードで実行されていない可能性もありますが、問題なく Persistent Volume は使えています。
これはユーザーが意識しない形で、KubernetesとOpenShiftが自動的に外部ストレージを適切なタイミングで適切な場所にアタッチしたことを意味します。

また、Read-Write-Manyなストレージが必要な場合は、ファイルベースのストレージソリューションが利用できます。
OpenShift Data Foundationは、OpenShiftの内部で動作するハイパーコンバージドなストレージソリューションです。ローカルに接続されたストレージデバイスをストレージプールにして、そこからVolumeを作成することで、ファイル、ブロック、さらにはオブジェクトストレージを提供することができます。