Level 2: ステートフルコンテナの実現

目的・ゴール: アプリケーションのデータ永続化を実現

アプリケーションは永続化領域がないとデータの保存ができません。 KubernetesではStatic provisioningとDynamic provisioningの2つの永続化の手法があります。

このレベルではDynamic provisioningを実現するためDynamic provisionerであるTridentをインストールし、 マニフェストファイルを作成しデータの永続化をすることが目標です。

流れ

  1. Dynamic storage provisioningを実現(Tridentのインストール)

  2. StorageClassの作成

  3. PVCをkubernetesマニフェストファイルに追加

    1. 作成したStorageClassを使用する
    2. PVCをkubernetesにリクエストした時点で動的にストレージがプロビジョニングされる
  4. アプリケーションを稼働させて永続化ができていることを確認

コンテナでの永続データのカテゴライズ

コンテナ化されたアプリケーション、環境での永続データは 以下のように分類して考え必要な物をリストアップしました。

  • データベースのデータファイル、ログファイル
  • 各サーバのログファイル
  • 設定ファイル
  • 共有ファイル

Dynamic provisioning

ステートフルコンテナを実現する上でストレージは重要なコンポーネントになります。

Dynamic volume provisiong はオンデマンドにストレージをプロビジョニングするためのものです。

Static provisioning、Dynamic provisioning それぞれを比較します。

Static provisioningの場合、クラスタの管理者がストレージをプロビジョニングして、PersitentVolumeオブジェクトを作成しkubernetesに公開する必要があります。

Dynamic provisioningの場合、Static provisioningで手動で行っていたステップを自動化し、管理者がおこなっていたストレージの事前のプロビジョニング作業をなくすことができます。

StorageClassオブジェクトで指定したプロビジョナを使用し、動的にストレージリソースをプロビジョニングすることができます。

StorageClassには様々なパラメータを指定することができアプリケーションに適したストレージカタログ、プロファイルを作成することができ、物理的なストレージを抽象化するレイヤとなります。

Dynamic Provisioningを実現するために ストレージを制御する Provisioner が必要になります。その標準的なインターフェースとして 2019/1からContainer Storage InterfaceがGAになり、 Kubernetes 1.14からは CSI 1.1がサポートされています。

ネットアップはDynamic provisioningを実現するためのNetApp Tridentというprovisionerを提供しています。

Tridentは CSIを使わない従来同様のTridentと CSIを使う CSI Tridentが提供されていますが、 19.07からは CSI Tridentがデフォルトでインストールされるようになりました。

このレベルではTridentでDynamic provisioningを行い、アプリケーションのデータ永続化を実現します。

NetApp Tridentのインストール

Dynamic storage provisioningを実現するためNetApp Tridentを導入します。 TridentはPodとしてデプロイされ通常のアプリケーションと同様に稼働します。

インストール事前準備

Trident のインストールでk8sクラスタの管理者権限が必要になります。

$ kubectl auth can-i '*' '*' --all-namespaces

バックエンドに登録するストレージのマネジメントIP(配布資料のsvmXXのIPアドレス)にk8sクラスタのコンテナから疎通が取れるかを確認します。

$ kubectl run -i --tty ping --image=busybox --restart=Never --rm --  ping [マネジメントIP]

Tridentインストール(19.07〜)

バイナリをダウンロードしてインストールします。(例はバージョン19.07.0)

$ wget https://github.com/NetApp/trident/releases/download/v19.07.0/trident-installer-19.07.0.tar.gz

$ tar -xf trident-installer-19.07.0.tar.gz

$ cd trident-installer

Tridentの制御にはtridentctlを使います。

tridentctl ユーティリティではドライランモードとデバッグモードがオプションで指定できます。 2つを設定し、実行すると以下のように必要事項を事前チェックし、その内容をすべて標準出力にプリントします。

まずは、ドライランモードで実行し問題ないことを確認します。

Tridentをインストールするネームスペースを作成します。

$ kubectl create ns trident

namespace/trident created

Tridentのインストーラーをドライランモードで実行します。

$ ./tridentctl install --dry-run -n trident -d

DEBU Initialized logging.                          logLevel=debug
DEBU Running outside a pod, creating CLI-based client.
DEBU Initialized Kubernetes CLI client.            cli=kubectl flavor=k8s namespace=default version=1.11.0
DEBU Validated installation environment.           installationNamespace=trident kubernetesVersion=
DEBU Parsed requested volume size.                 quantity=2Gi
DEBU Dumping RBAC fields.                          ucpBearerToken= ucpHost= useKubernetesRBAC=true
DEBU Namespace does not exist.                     namespace=trident
DEBU PVC does not exist.                           pvc=trident
DEBU PV does not exist.                            pv=trident
- snip
INFO Dry run completed, no problems found.
- snip

ドライランモードで実施すると問題ない旨(INFO Dry run completed, no problems found.) が表示されれば、インストールに必要な事前要件を満たしていることが確認できます。 バージョン、実行モードによってはログの途中に出力されることもあるためログを確認しましょう。

上記の状態まで確認できたら実際にインストールを実施します。

$ ./tridentctl install -n trident -d

DEBU Initialized logging.                          logLevel=debug
DEBU Running outside a pod, creating CLI-based client.
DEBU Initialized Kubernetes CLI client.            cli=kubectl flavor=k8s namespace=default version=1.11.0
DEBU Validated installation environment.           installationNamespace=trident kubernetesVersion=
DEBU Parsed requested volume size.                 quantity=2Gi
DEBU Dumping RBAC fields.                          ucpBearerToken= ucpHost= useKubernetesRBAC=true
DEBU Namespace does not exist.                     namespace=trident
DEBU PVC does not exist.                           pvc=trident
DEBU PV does not exist.                            pv=trident
- snip
INFO Trident installation succeeded.

「INFO Trident installation succeeded.」が出力されればインストール成功です。

また、問題が発生した場合には tridentctl を使用してtridentに関するログをまとめて確認することが出来ます。

$ ./tridentctl -n trident logs

time="2018-02-15T03:32:35Z" level=error msg="API invocation failed. Post https://10.0.1.146/servlets/netapp.servlets.admin.XMLrequest_filer: dial tcp 10.0.1.146:443: getsockopt: connection timed out"
time="2018-02-15T03:32:35Z" level=error msg="Problem initializing storage driver: 'ontap-nas' error: Error initializing ontap-nas driver. Could not determine Data ONTAP API version. Could not read ONTAPI version. Post https://10.0.1.146/servlets/netapp.servlets.admin.XMLrequest_filer: dial tcp 10.0.1.146:443: getsockopt: connection timed out" backend= handler=AddBackend
time="2018-02-15T03:32:35Z" level=info msg="API server REST call." duration=2m10.64501326s method=POST route=AddBackend uri=/trident/v1/backend

Tridentのバージョン確認

インストールが完了したらtridentのバージョンを確認します。

$ ./tridentctl version -n trident

+----------------+----------------+
| SERVER VERSION | CLIENT VERSION |
+----------------+----------------+
| 19.07.0        | 19.07.0        |
+----------------+----------------+

バージョンが表示されていればインストール成功です。

ヒント

tridentctl は tridentの podと通信をして制御を行います。 このため、各コマンドは tridentの podが存在するネームスペースを 指定する必要があります。

Tridentへのバックエンド登録

Tridentが、その背後で制御するストレージ(バックエンドストレージ)を登録します。

バックエンドストレージを設定するためにjsonファイルを用意します。 サンプルファイルがsample-inputディレクトリにあり、ここではONTAPのNASを設定しますので backend-ontap-nas.jsonをコピーして使います。

backend.jsonの設定パラメータ (NFS ONTAPバックエンド)
パラメータ名 説明 設定内容
managementLIF ONTAPのクラスタ管理LIFまたはSVM管理LIFを設定 192.168.XX.200
dataLIF データ通信LIF 192.168.XX.200
svm tridentから使用するSVM svmXX
username/password クラスタ管理者またはSVM管理者のクレデンシャル SVM管理者を設定: vsadmin/netapp123

編集後は以下の通りとなります。 疎通が取れないIPを設定するとバックエンド登録に失敗します。

$ cat setup/backend.json

{
    "version": 1,
    "storageDriverName": "ontap-nas",
    "backendName": "userXXBackendName",
    "managementLIF": "192.168.XX.200",
    "dataLIF": "192.168.XX.200",
    "svm": "svmXX",
    "username": "vsadmin",
    "password": "netapp123"
}

「XX」はラボ環境にあわせて設定してください。

編集したjsonファイルと``tridentctl create backend``を使ってバックエンドを登録します。

$ ./tridentctl -n trident create backend -f setup/backend.json

+-------------------+----------------+--------+---------+
|       NAME        | STORAGE DRIVER | ONLINE | VOLUMES |
+-------------------+----------------+--------+---------+
| userXXBackendName | ontap-nas      | true   |       0 |
+-------------------+----------------+--------+---------+

問題発生時に実施: Tridentをアンインストールする

トラブルシューティング時にTridentをアンインストールする必要が出てくるケースがあります。 その際には tridentctl ユーティリティのアンインストール用のサブコマンドを使用してアンインストールします。

インストール実行時に失敗したときなど、クリーンに再インストールしたい場合に使います。

$ ./tridentctl uninstall -n trident

ヒント

続けて trident namespaceも削除したい場合は、trident namespace 内に残るオブジェクトが完全になくなった事を確認する事をおすすめします。

Related Issue

Tridentインストールのバージョン間の差異

インストール時の動作が19.0xで何度か変化しているので整理しておきます。

Version インストール時backend.json 初回バックエンド登録
〜19.01 必要 されない
19.04 必要 される
19.07〜 不要 されない

インストール時のbackend.json

19.01/04では Tridentが構成情報を保存する Persistent Volumeを Provisioningするために setup/backend.jsonファイルを作成してから tridentctl install をする必要があります。

19.01では Trident Install後に改めて バックエンド登録をする必要がありました。 19.04では Trident Install時点で backend.jsonで指定したストレージがバックエンド登録されます。

19.07では インストール時に setup/backend.jsonが不要になりました。これはCustom Resource Definition を利用してTridentの構成情報を保存するように変更になった事によります。 ただし、これにより 19.07では インストール完了後にバックエンドの自動登録がされないため注意してください。 また、tridentctl installを実行するときのカレントパスに setup ディレクトリが必要なため注意してください。

過去のバージョンのインストール手順は下記を参考にしてください。

StorageClassの定義

StorageClassを定義して、ストレージのサービスカタログを作りましょう。

Trident v19.07 ではStorageClassを作成するときに以下の属性を設定できます。 これらの属性のパラメータを組み合わせてストレージサービスをデザインします。

StorageClass の parameters に設定可能な属性
設定可能な属性
性能に関する属性 メデイアタイプ(hdd, hybrid, ssd)、プロビジョニングのタイプ(シン、シック)、IOPS
データ保護・管理に関する属性 スナップショット有無、クローニング有効化、暗号化の有効化
バックエンドのストレージプラットフォーム属性 ontap-nas, ontap-nas-economy, ontap-nas-flexgroup, ontap-san, solidfire-san, eseries-iscsi

全てのパラメータ設定については以下のURLに記載があります。

NFSバックエンドのONTAPでのStorageClass

ストレージ構成は以下の通りです。 今回、意識する必要があるところは異なるメディアタイプ(HDDとSSD)のアグリゲートを保有しているところです。

  • 各SVMにHDD, SSDのアグリゲートを割り当て済み

    • aggr1_01:SSDのアグリゲート
    • aggr2_01:HDDのアグリゲート

以下のようなイメージでStoageClassを作成しましょう。

  • DB 用の高速領域: SSD を使ったストレージサービス
  • Web コンテンツ用のリポジトリ: HDDを使ったストレージサービス

以下は上記の「DB 用の高速領域」のStorageClass作成方法のサンプルです。

高速ストレージ用のマニフェストファイル例 StorageClassFastest.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ontap-gold
provisioner: netapp.io/trident
reclaimPolicy: Retain
parameters:
  backendType: "ontap-nas"
  media: "ssd"
  provisioningType: "thin"
  snapshots: "true"

ストレージクラスを作成します。

$ kubectl create -f StorageClassFastest.yml

storageclass "ontap-gold" created

$ kubectl get sc

NAME         PROVISIONER         AGE
ontap-gold   netapp.io/trident   10s

注釈

デフォルトのStorageClassの設定

StorageClassは記載がないときに使用するStorageClassを指定できます。

kubectl patch storageclass ストレージクラス名 -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

Persistent Volume Claimの作成

アプリケーションで必要とされる永続化領域の定義をします。 PVCを作成時に独自の機能を有効化することができます。

データの保管ポリシー、データ保護ポリシー、SnapShotの取得ポリシー、クローニングの有効化、暗号化の有効化などを設定できます。

一覧については以下のURLに記載があります。 metadata.annotation 配下に記述することで様々な機能を使用することが可能となります。

デプロイ用のマニフェストファイルにPVCを追加

Level1で作成したマニフェストファイルにPVCの項目を追加し、ダイナミックプロビジョニングを使用しデータを永続化出来るアプリケーションを定義します。

高速ストレージ用の定義ファイルの例 PVCFastest.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sample-pv-claim
  labels:
    app: アプリケーション名
  annotations:
    trident.netapp.io/exportPolicy: "default"
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
  storageClassName: ontap-gold

ここでやることは主に以下の2つを実施してください。 このセクションはどうやって実現するかを考えていただくためあえて答えは書いてありません。

  1. 上記PVCマニフェストファイルを作成し、PVCオブジェクトを作成
  2. Level1で作成したアプリケーションの永続化

ヒント

Level1で作成したマニフェストにはストレージの定義がありません。 どうやってストレージの定義をし永続化するかを考えてみましょう。 また、Level1のサンプルでは永続化する対象はデータベース(MySQL)になります。 MySQLのデータファイルはデフォルトでは /var/lib/mysql になります。

デプロイメント実施

上記のPVCの設定が終わったら再度アプリケーションをデプロイします。

その後、アプリケーションからデータを保存するようオペレーションを行います。 WordPressであれば記事を投稿することで簡単に確認ができます。

永続化できていることを確認するためアプリケーションの停止・起動を実施

永続化されていることを確認するため、一度アプリケーションを停止します。

Deploymentで必要となるポッドは起動するような設定になっているため、 簡単にアプリケーションの停止・起動を行う方法として Deployment 配下の Pod を削除する方法がとれます。

$ kubectl delete pod -l "ラベル名"

$ kubectl get deploy

実行例は以下の通りです。

$ kubectl delete pod -l app=wordpress # app=wordpress が付与されているポッドをすべて削除

pod "wordpress-5bc75fd7bd-kzc5l" deleted
pod "wordpress-mysql-565494758-jjdl4" deleted

$ kubectl get deploy # Podはデプロイメントで管理されているため、すぐ再起動される

NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
wordpress         1         1         1            0           31d
wordpress-mysql   1         1         1            0           31d

DeploymentによってPodの起動数は管理されるため新たにPodが起動します。 AVAILABLE の数が正常になるまで待ちましょう。

$ kubectl get deploy

NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
wordpress         1         1         1            1           31d
wordpress-mysql   1         1         1            1           31d

再デプロイメント後の確認

再起動したPodに対して永続化されたデータが使用されていることを確認します。 2つの視点から確認したいと思います。

  1. アプリケーションであれば再度ログインして保存したデータを確認します。
  2. バックエンドストレージに動的にボリュームが作成されていることを確認します。
$ ssh vsadmin@192.168.XX.200 vol show

Password:
Vserver   Volume       Aggregate    State      Type       Size  Available Used%
--------- ------------ ------------ ---------- ---- ---------- ---------- -----
tridentsvm root        aggr1        online     RW          1GB    972.2MB    5%
tridentsvm trident_trident aggr1    online     RW       1.86GB     1.77GB    5%
tridentsvm trident_trident_basic_f4048 aggr1 online RW     1GB    972.4MB    5%
3 entries were displayed.

Tridentの特徴的な機能: Volume Cloningのストレージオフロード

NetAppのストレージOSは FlexCloneや Cloneと呼ばれるストレージオフロード可能な、 高速データ複製機能=クローニングテクノロジーを利用できます。[1]

CSI Tridentでは PersistentVolumeClaimの dataSourceにコピー元となる PVC/Snapshotを指定する事で 巨大なボリュームでも容量消費せずに超高速にデータをコピーする クローニングテクノロジーが使用されます。

注釈

Volume Data Source Feature Gate Kubernetesで CSI Tridentを使って dataSourceを指定してCloningをするには featuregateを有効にする必要があります。

Feature Gates 機能 Kubernetes Support Feature Gate指定 Trident Support
VolumePVCDataSource PersistentVolumeClaimを指定してClone
Kubernetes 1.15 αサポート
Kubernetes 1.16 βサポート
必要
不要
19.10〜
19.10〜
VolumeSnapshotDataSource VolumeSnapshotを指定してClone Kubernetes 1.12 αサポート 必要 19.07〜

kindにデータソースの種類(VolumeSnapshot/PersistentVolumeClaim)とnameにデータソースの名前を指定します。

CSI Trident- dataSourceを持つPVCの例 csidatasource.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: clone-of-pvc-1
  namespace: myns
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  dataSource: (このフィールドにオブジェクトの種類と名前を記述)
    kind: PersistentVolumeClaim
    name: pvc-1

従来の Tridentでも、PVCアノテーションである、trident.netapp.io/cloneFromPVC を介してクローニングテクノロジーを利用できます。

引数にPVC名を指定します。

Trident- アノテーションを持ったPVCの例 pvccloning.yml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: basicclone
  annotations:
    trident.netapp.io/cloneFromPVC: database (<-ここにクローンしたい既存のPVC名(ボリューム名)を記述)
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
  storageClassName: ontap-gold

ここではサンプルでPVC Cloning を活用したOracle Databaseを複数デプロイするデモ動画をご覧ください。

[1]必要な機能が利用できるモデル/ライセンスである事をご確認ください。

クローニング技術によって実現可能なこと

クローニング技術はシンプルですが非常に多く用途で使用することができます。 例としてあげられるのが以下の用途です。

  • プレビルド環境の高速展開
  • 本番環境に影響せずに大規模な並列テスト
  • 運用時のデータリストアの高速化、瞬時に論理障害を戻す

Tridentのアップグレード方法

TridentはKubernetesのアップデートと同じサイクルでリリースされています。 Kubernetesのバージョンがあがってから約1ヶ月以内くらいにTridentがリリースされます。

kubernetesのバージョンにサポートの有無があります。

バージョンに対応したTridentを確認するには以下のページを参照ください。

https://netapp-trident.readthedocs.io/en/stable-v19.07/support/requirements.html

すでにインストールされているTridentをアップグレードするには以下のようにアンインストール、インストールをくりかえすことで実現できます。

$ ./tridentctl uninstall -n <namespace>
$ ./tridentctl install   -n <namespace>

アンインストールコマンドのデフォルトの挙動はTridentでデプロイされたPVC,PVは削除しません。 Tridentの状態をそのままにしているため、アンインストール後にインストールをすることでアップグレードとして機能させることができます。

Tridentアップグレード時の注意

アップグレード時に Kubernetesのバージョンによっては考慮が必要な場合があります。

また、19.07では etcdから CRDへと Tridentの構成情報の記録場所が変更になったため、アップグレード時には、そのコピーが行われます。

アップグレード中の動作等、詳細は下記のアップグレードについてのオフィシャルドキュメントを参照してください。

https://netapp-trident.readthedocs.io/en/stable-v19.07/kubernetes/upgrading.html

まとめ

アプリケーションに対して動的に永続化領域をプロビジョニングしデータの永続化を実現しました。

今回はStorageClassの作成からアプリケーションにPersistentVolumeを割り当てるところまでを一連の流れで実現しました。

運用を考えた場合、それぞれのコンポーネントで担当が異なるため以下のような分担になるかと思います。

  • StorageClassの作成: インフラ・kubernetesクラスタの管理者
  • PersistentVolumeClaimの作成: アプリケーション開発者

今後障害時の動作が気になると思いますが、 Level 4: 運用編 での検討事項とします。

ここまでで Level2 は終了です。