永続ストレージ
本コンテンツは、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への一定の容量を持つ特定の種類のストレージのリクエストを表しています。
次に、mapit
の Deployment
を更新して、このストレージを参照し、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
新しいストレージについて、Mounts
と Volumes
の両方の詳細が表示されているのがわかります。
... 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を作成することで、ファイル、ブロック、さらにはオブジェクトストレージを提供することができます。