1. TOP
  2. BLOG
  3. TECH ARTICLE:連載 第6回
    Kubernetesストレージの理解とEKS環境のCSIドライバーストレージの実習
TECH ARTICLE

2024年05月17日

連載 第6回
Kubernetesストレージの理解とEKS環境のCSIドライバーストレージの実習

今回はクバネティスストレージを確認します。

主な内容:

  • エフェメラルボリューム(Ephemeral Volumes)の理解
  • クバネティスCSIドライバーとEKSアドオンの理解
  • PV(Persistent Claim)、PVC(Persistent Volume Claim)、SC(Storage Class)の理解
  • オンラインPVCボリュームの拡張、可用性ゾーン(AZ、Availability Zone)の制約事項、リクレームポリシー(Reclaim Policy)の理解

実習の課題:

  • ポッドの臨時データ削除のテスト
  • EKS CSI ドライバーとアドオンのインストール
  • ebs-scストレージクラスの生成
  • PVCを使用するポッドの生成

今回の実習で使用するコードのgithubディレクトリは次の通りです。

1. クバネティスエフェメラルボリュームの制約事項の理解

クバネティス環境では基本設定で別枠のストレージ構成でない場合、ポッドが再開すると一緒に使用したデータも削除されます。既存のVM環境ではVMを強制的に削除しない限り、アプリケーションが生成したデータは保管されることとは大きな違いがあります。クバネティス環境ではポッドが実行中のノードは削除されませんでしたが、ポッドの再実行だけでデータも同時に削除されます。これをエフェメラルボリューム(一時的ボリューム)と言います。※1

エフェメラルボリュームはクバネティスで一時的なデータストレージを提供するタイプのボリュームです。エフェメラルという用語は一時的または短期的なことを意味します。エフェメラルボリュームはコンテナのライフサイクルと連動します。つまり、コンテナが生成されるか再開される度にボリュームも同時に初期化されて、コンテナが削除されるとボリュームのデータも同時に削除されます。

それでは、簡単な実習で確認します。

ephermeral-vol-deploy.yaml

1.	apiVersion: apps/v1
2.	kind: Deployment
3.	metadata:
4.	    name: date-pod
5.	    namespace: default
6.	    labels:
7.	        app: date
8.	spec:
9.	    replicas: 1
10.	    selector:
11.	        matchLabels:
12.	            app: date
13.	    template:
14.	        metadata:
15.	            labels:
16.	                app: date
17.	        spec:
18.	            containers:
19.	            - name: date-pod
20.	                image: busybox
21.	                command:
22.	                - "/bin/sh"
23.	                - "-c"
24.	                - "while true; do date >> /pod-out.txt; sleep 5; done"

簡単な ‘busybox’ イメージを実行するDeployment YAMLファイルです。 ‘date’ コマンドを使用して ‘/pod-out.txt’ ファイルに現在の時間情報を保存する設定です。

該当ポッドを実行して ‘/pod-out.txt’ ファイルを確認します。

1.	[(jerry-test:default) pvc]$ k apply -f ephemeral-vol-deploy.yaml
2.	deployment.apps/date-pod created
3.	
4.	[(jerry-test:default) pvc]$ k exec -it date-pod-cd9968dbb-n4gbm -- cat /pod-out.txt
5.	Thu Sep 7 17:29:52 UTC 2023
6.	Thu Sep 7 17:29:57 UTC 2023
7.	Thu Sep 7 17:30:02 UTC 2023

‘/pod-out.txt’ ファイルに現在の時間情報が保存されました。では、以前のデータが保存されているかを確認するためにポッドを再開します。

1.	[(jerry-test:default) pvc]$ k delete pod date-pod-cd9968dbb-n4gbm
2.	pod "date-pod-cd9968dbb-n4gbm" deleted
3.	
4.	[(jerry-test:default) argo-cd-app-of-apps-qa]$ k get pod --selector app=date
5.	NAME READY STATUS RESTARTS AGE
6.	date-pod-cd9968dbb-8zlv9 1/1 Running 0 70s

ポッドを再開しました。デプロイメントリソースポッドを削除すると以前のポッド(date-pod-cd9968dbb-n4gbm)は削除されて、新しいポッド(date-pod-cd9968dbb-8zlv9)が実行されます。

新しく実行されたポッドでデータを確認します。

1.	[(jerry-test:default) pvc]$ k exec -it date-pod-cd9968dbb-8zlv9 -- cat /pod-out.txt
2.	Thu Sep 7 17:34:07 UTC 2023
3.	Thu Sep 7 17:34:12 UTC 2023
4.	Thu Sep 7 17:34:17 UTC 2023

以前のポッドで保存された時間情報(Thu Sep 7 17:29:52 UTC 2023)は無く、新しいポッドが実行された時間(Thu Sep 7 17:34:07 UTC 2023)から保存されています。つまり、以前のデータは削除されています(運用経験がある方は理解できると思いますが、これは「データが削除されました」というかなり厳しい事故の発生です)。

データの保存が必須であるDBなどのアプリケーションはこれと同じく基本的にエフェメラルボリューム設定を使用することができません。そのため、クバネティスはストレージシステムを別のリソースで提供します。つまり、PV(Persistent Volume)、PVC(Persistent Volume Claim)とSC(Storage Class)を利用したストレージシステムを構成します。

実習を通して詳細を理解する前に、簡単に名前で推測できる意味から確認します。PVは削除されず、永久(Persistent)に保存されるボリュームを意味するクバネティスリソースです。前の一時的ボリュームと反対の意味でPVに保存したデータはユーザが強制的に削除しないと継続的に保存されます。

PVCはPVをリクエストする(Claim)リソースです。ポッドでPVを使用するにはPV名を直接使用せず、PVC名を使用してコネクションします。クバネティスでよく使用する方式で、このように実際のリソースとこれをリクエストするリソースを分離します。PVを使用するためにはPVを直接使用せず、PVCを利用して使用する程度で理解してください。

SC、ストレージクラスは同じタイプのストレージを纏めたクラスでPVを動的にプロビジョニングするリソースです。例えば、ブロックストレージ、ファイルシステム、オブジェクトストレージなど互いに異なるタイプのストレージを区分する用途で使用します。ユーザは必要なストレージクラス名をPVC YAMLファイルに指定して使用します。一方、ストレージクラスは動的にユーザリクエストのクラスのPVをプロビジョニングします。詳細は実習で確認します。

2. EKS環境ストレージの実習

では、実習でEKS環境のクバネティスストレージシステムを構成する方法を確認します。PV、PVC、ストレージクラスを使用するためには、事前準備が必要です。

オンプレミス環境のネイティブクバネティスは基本クバネティスのインストールと別枠でストレージを使用するには追加でストレージシステムを構成します。そのためにはLonghorn、OpenEBS、Cephなど多様なストレージサービスの中から、クバネティス管理者が環境に合わせて選択してインストールします。

マネジードクバネティスサービス(EKS、AKS、GKEなど)は基本インストールの時に、ストレージ環境を同時に提供します。EKSも基本インストールの時に、ストレージを直ぐに使用できるようにgp2ストレージクラス環境を次のように提供します。

1.	[(jerry-test:default) pvc]$ k get sc
2.	NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
3.	gp2 (default) kubernetes.io/aws-ebs Delete WaitForFirstConsumer false 16d

上記のように ‘k get sc(storage class)’ コマンドを利用すると基本的にインストールされたgp2ストレージクラスを確認できます。ユーザは追加作業なくストレージクラスを利用できます。マネジードクバネティスサービスのメリットですが、クバネティスサービスに自社の多様なリソースを事前に統合させて提供します。

しかし、基本で提供するgp2タイプのストレージはgp3に比べてコストパフォーマンスが劣ります。そのため、基本で提供するgp2タイプのストレージを使用せず、gp3タイプのストレージを使用することをお勧めします(※2 gp2とgp3の比較を参照)。

gp3タイプのストレージを使用するためにEKSはCSI(Container Storage Interface、コンテナストレージインターフェース)ドライバーを使用します。(※3)CSIドライバーはクバネティスと外部ストレージシステム間で標準化されたインターフェースです。CSIはクバネティスコアコンポーネントでストレージ管理システムを分離して、多様なストレージベンダーがスナップショットなどのストレージ追加機能をクバネティスコアコンポーネントの制約がなく自由に開発できる環境を提供します。多くのストレージベンダーはCSI機能を利用してストレージ追加機能を開発しています。

2-1. IRSAとCSIドライバーのインストール

CSIドライバーはEKS外部のAWS EBS(Elastic Block Store)サービスを使用します。クバネティス外部のリソースを制御するためIRSA(※4)の設定が必要です。以前の回と同じくterraformモジュールを利用してCSI用IRSAをインストールします。以下は筆者のgithubファイルです。

1.	module "ebs_csi_irsa_role" {
2.	    source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"
3.	
4.	    role_name = "ebs-csi-jerry-test"
5.	    attach_ebs_csi_policy = true
6.	
7.	    oidc_providers = {
8.	        ex = {
9.	            provider_arn = module.eks.oidc_provider_arn
10.	            namespace_service_accounts = ["kube-system:ebs-csi-controller-sa"]
11.	        }
12.	    }
13.	
14.	    tags = local.tags
15.	}

. role_name

Role名は各自が区別できるように任意の異なった名前を指定します。

上記のようにterraformファイルを生成してCSI用IRSAモジュールを適用します。

1.	$ (⎈ |switch-singapore-test:kube-system) tf init
2.	$ (⎈ |switch-singapore-test:kube-system) tf plan -out planfile
3.	$ (⎈ |switch-singapore-test:kube-system) tf apply planfile

適用が完了するとAWSコンソールでebs-csi Roleを確認できます。参考までに、Role名が同じであれば異なるEKSに使用できないため、もし複数のEKSを運用する場合は各EKSに異なるRole名を適用します。

次に該当Roleを利用してCSI ドライバー用のアドオンを生成します。EKSアドオンとはクバネティスクラスターの機能を拡張し、向上させるためにEKSに追加的にインストールされるコンポーネントです。クラスター運用で一般的に必要な様々な機能を簡略化したり、自動化したりできます。
ここでは既に初期のEKSのインストール時に、 terraformコードに既に‘coredns’、‘kube-proxy’、 ‘vpc-cni’ が含まれているため、該当機能をアドオンで管理しています。

1.	cluster_addons = {
2.	    coredns = {
3.	        preserve = true
4.	        most_recent = true
5.	
6.	        timeouts = {
7.	            create = "25m"
8.	            delete = "10m"
9.	        }
10.	    }
11.	    kube-proxy = {
12.	        most_recent = true
13.	    }
14.	    vpc-cni = {
15.	        most_recent = true
16.	    }
17.	}

EBS CSIドライバーもアドオンで管理できます。アドオンリソースのterraformコードは次のようになります。

eks-addon.tf

1.	variable "aws_account_id" {
2.	    type = string
3.	}
4.	
5.	resource "aws_eks_addon" "aws_ebs_csi_driver" {
6.	    cluster_name = module.eks.cluster_name
7.	    addon_name = "aws-ebs-csi-driver"
8.	    service_account_role_arn = "arn:aws:iam::${var.aws_account_id}:role/ebs-csi-jerry-test"
9.	    addon_version = "v1.20.0-eksbuild.1"
10.	    resolve_conflicts = "OVERWRITE"
11.	
12.	    lifecycle {
13.	        ignore_changes = [
14.	            service_account_role_arn
15.	        ]        
16.	    }
17.	}

. service_account_role_arn

前で追加したEBS CSI ドライバーの Role_Arnを入力します。各自でAWS Account ID情報を変更して入力します。

. addon_version

筆者と同じバージョンを使用しても問題ありません。インストールする時点の最新バージョンも使用できます。

terraformリソースを適用します。

1.	$ (⎈ |switch-singapore-test:kube-system) tf plan -out planfile
2.	$ (⎈ |switch-singapore-test:kube-system) tf apply planfile

正常にインストールされるとAWS EKSコンソールのアドオンメニューに次のようにEBS CSI Driverを確認できます。

アドオンがインストールされると次のようにebs-csi-controllerデプロイメントとebs-csi-node DaemonSetリソースがインストールされます。

1.	$ (⎈ |switch-singapore-test:kube-system) k get deployments.apps ebs-csi-controller -n kube-system
2.	NAME READY UP-TO-DATE AVAILABLE AGE
3.	ebs-csi-controller 2/2 2 2 8h
4.	
5.	$ (⎈ |switch-singapore-test:kube-system) k get ds ebs-csi-node -n kube-system
6.	NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
7.	ebs-csi-node 2 2 2 2 2 kubernetes.io/os=linux 8h

DaemonSetとは、クバネティスの全てのノードで自動的に実行されるコントローラポッドです。主な用途はモニタリング、ログ収集で、ストレージポッドがDaemonSetを利用します。ノードの特定ディレクトリを使用するか特定コンポーネントを実行する用途でノードが追加されると、追加設定しなくても自動的にDaemonSetポッドが実行されるので便利です。

EBS CSIコントローラポッドはクラスターでPV生成をリクエストすると、リクエストを受けてクバネティス外部のEBSにボリュームを生成してコネクションする機能を担当します。もし、ボリュームの構成に問題があればebs-csi-controllerポッドのログを確認してトラブルシューティングを行います。

2-2. SC(Storage Class)の生成

準備したCSI ドライバー基準でストレージクラス(SC)を生成します。SCもクバネティスリソースで、マニュフェストファイルで作成できます。下記は筆者のgithubファイルです。

1.	apiVersion: storage.k8s.io/v1
2.	kind: StorageClass
3.	metadata:
4.	    name: ebs-sc
5.	    annotations:
6.	        storageclass.kubernetes.io/is-default-class: "true"
7.	allowVolumeExpansion: true
8.	provisioner: ebs.csi.aws.com
9.	volumeBindingMode: WaitForFirstConsumer
10.	    parameters:
11.	        type: gp3

. metadata.name: ebs-sc

ストレージクラス名です。任意に指定できますが、基本で提供される ‘ebs-sc’ をそのまま使用することをお勧めします。この後、ストレージクラス名をPVCに指定してストレージを生成します。

. metadata.annotations.storageclass.kubernetes.io/is-default-class: “true”

既存のgp2タイプのストレージクラスの代わりにCSIドライバーで作成したストレージクラスを基本ストレージクラスに指定します。PVC生成時に、別途、ストレージクラス名を指定しない場合はデフォルトで指定した ‘ebs-sc’ 基準でボリュームを生成します。

. allowVolumeExpansion: true

運用環境でボリュームを拡張する場合が偶に発生します。ストレージクラスで‘allowVolumeExpansion’機能を有効にすると、既存ボリュームを削除するかSnapshotでコピーせず、オンラインでボリューム拡張ができます。ebs-scストレージクラスはオンラインボリューム拡張をサポートします。

. provisioner: ebs.csi.aws.com

CSI ドライバーを利用してボリュームを生成します。

. parameters.type: gp3

コストパフォーマンスに優れたgp3タイプのストレージを使用します。

マニュフェストを適用してストレージクラスリソースを生成します。

1.	$ (⎈ |switch-singapore-test:kube-system) k apply -f ebs-default-storageclass.yaml 
2.	storageclass.storage.k8s.io/ebs-sc created

新たに生成したストレージクラスが確認できます。

1.	[(jerry-test:default) aws-ebs-csi]$ k get sc
2.	NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
3.	ebs-sc (default) ebs.csi.aws.com Delete WaitForFirstConsumer true 3s
4.	gp2 (default) kubernetes.io/aws-ebs Delete WaitForFirstConsumer false 19d

ebs-sc名で新しいストレージクラスが生成されましたが、確認するとdefaultのストレージクラスが2つあります。既存のgp2ストレージクラスのdefaultストレージクラス設定を無効にします。2つのdefaultストレージクラスを使用すると求める設定通りに動作しません。 ‘kubectl patch’ コマンドを使用すると既存リソースの属性を変更できます。

1.	kubectl patch storageclass gp2 -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'

再度確認すると意図したようにebs-scのみがdefaultストレージクラスに指定されました。

1.	[(jerry-test:default) aws-ebs-csi]$ k get sc
2.	NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
3.	ebs-sc (default) ebs.csi.aws.com Delete WaitForFirstConsumer true 3m8s
4.	gp2 kubernetes.io/aws-ebs Delete WaitForFirstConsumer false 19d

2-3. PVC(Persistent Volume Claim)生成

次は新しく作成したCSI ドライバー基盤のebs-scストレージクラスを使用するPVCとPVCを利用したポッドを生成します。方法はPVCリソースを先に作成し該当PVCをポッドでマウントするタイプです。

簡単に図で表現すると下記のようになります。

ストレージクラスを先に作成し、そのストレージクラスの名前をPVC YAMLファイルに指定します。そしてPOD YAMLファイルにPVC名を指定するとストレージの関連設定が完了します。

では先ず、PVC マニュフェストです。

ebs-pvc.yaml

1.	apiVersion: v1
2.	kind: PersistentVolumeClaim
3.	metadata:
4.	    name: ebs-claim
5.	    namespace: default
6.	spec:
7.	    accessModes:
8.	        - ReadWriteOnce
9.	    storageClassName: ebs-sc
10.	    resources:
11.	        requests:
12.	            storage: 4Gi

. metadata.name: ebs-claim

任意のPVC名を指定します。その名前をポッドのマニュフェストに指定し、ポッドでボリュームをコネクションします。

. metadata.namespace: default

PVCはネームスペース単位にリソースを割当てると、ネームスペースのポッドはPVCを使用できます。

. spec.accessModes: ReadWriteOnce

EBSブロックストレージは一つのノード(ポッド)だけRead、Writeが可能です。もし、複数のポッドを同時に読み込みと書き込みができる環境が必要であれば、EBSブロックストレージではないEFSファイルシステムを使用します。EFSファイルシステムはReadWriteManyアクセスモードをサポートします。

. spec.storageClassName: ebs-sc

PVCはストレージクラス名を指定して動的にボリュームを割当てます。ストレージクラスを使用しないと毎回手動でPVを先に指定して生成する必要があるため、面倒です。PVC マニュフェストでストレージクラスを指定して容量とaccessModesだけ指定すると、ポッドが生成されるとボリュームも同時に生成される動的ボリュームが有効となります。

. spec.resources.requests.storage: 4Gi

ポッドで必要なボリューム容量を指定します。

マニュフェストを適用してPVCを生成します。

1.	$ (⎈ |switch-singapore-test:default) k apply -f ebs-pvc.yaml 
2.	persistentvolumeclaim/ebs-claim created

生成されたPVCを確認します。

1.	$ (⎈ |switch-singapore-test:default) k get pvc
2.	NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
3.	ebs-claim Pending ebs-sc 24s

ここで、STATUS(状態)が未だ ‘Pending’ は要注意です。詳細を確認するために ‘describe’ コマンドを利用します。予想外の問題が発生したらクバネティスでは先ず ‘k describe’ コマンドで確認します。

$ (⎈ |switch-singapore-test:default) k describe pvc ebs-claim
(省略)
Events:
Type Reason Age From Message
—- —— —- —- ——-
Normal WaitForFirstConsumer 11s (x3 over 30s) persistentvolume-controller waiting for first consumer to be created before binding

上記で内容を確認すると「最初のユーザのコネクションを待っている状態(waiting for first consumer to be created before binding)」です。ebs-scストレージクラスの属性を確認すると‘VOLUMEBINDINGMODE – WaitForFirstConsumer’ で、「最初のユーザを待っている」状態です。最初のユーザであるポッドが未だPVCをコネクションしてないためPVCが生成できない遅延(‘Pending’)の状態です。

1.	$ (⎈ |switch-singapore-test:default) k get sc
2.	NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
3.	ebs-sc (default) ebs.csi.aws.com Delete WaitForFirstConsumer true 5h10m

では次に、生成したPVCをポッドで使用します。

pvc-pod.yaml

1.	apiVersion: v1
2.	kind: Pod
3.	metadata:
4.	    name: pvc-pod
5.	    namespace: default
6.	spec:
7.	    containers:
8.	    - name: app
9.	        image: centos
10.	        command: ["/bin/sh"]
11.	        args: ["-c", "while true; do echo $(date -u) >> /data/out.txt; sleep 5; done"]
12.	        volumeMounts:
13.	        - name: date-vol
14.	            mountPath: /data
15.	    volumes:
16.	    - name: date-vol
17.	        persistentVolumeClaim:
18.	            claimName: ebs-claim

. spec.containers.volumeMounts:-name: date-vol

ボリュームマウント(volumeMounts)名で、任意の名前を指定できます。複数のボリュームマウント名を指定できます。名前を基準に区分してPVC(またはConfigMap)とコネクションします。

. spec.volumes.-name: date-vol

上記で指定したボリュームマウント名を指定します。

. spec.volumes.persistentVolumeClaim:claimName: ebs-claim

ボリュームマウントが使用するPVC名です。前で生成したPVC名をclaimNameに指定します。この設定でポッドとPVCをコネクションできます。

ポッドで永久ボリュームを使用するためには上記のようにポッドがボリュームを使用するマウントポイントを指定し、そのマウントポイントを外部PVCとコネクションするためのPVC名を指定します。マウントポイントとPVC名だけ指定すれば、全ての設定が完了します。

互いに異なる性格のストレージを使用するために複数のストレージクラスを設定すると、同一のマニュフェストを活用できるため大変便利です。クバネティスはこのようにストレージの使用方法を抽象化してユーザの利便性を向上させました。

次にマニュフェストを適用してポッドを生成します。

1.	$ (⎈ |switch-singapore-test:default) k apply -f pvc-pod.yaml 
2.	pod/pvc-pod created
3.	
4.	$ (⎈ |switch-singapore-test:default) k get pod pvc-pod 
5.	NAME READY STATUS RESTARTS AGE
6.	pvc-pod 1/1 Running 0 97s

ポッドが正常に生成されてストレージが割当てられたかを確認します。

1.	$ (⎈ |switch-singapore-test:default) k exec -it pvc-pod -- cat /data/out.txt 
2.	Wed Jul 19 15:12:10 UTC 2023
3.	Wed Jul 19 15:12:15 UTC 2023
4.	(省略)

ボリュームマウントに指定した /data/out.txtファイルが生成されて該当ファイルに現在の時間情報(date)が正常に入力されています。それでは、既存ポッドを削除し、再度生成して既存データが保存されるか確認します。

1.	$ (⎈ |switch-singapore-test:default) k delete -f pvc-pod.yaml 
2.	pod "pvc-pod" deleted

クバネティスリソースを削除するには上記のように-f(file)オプションを使用してマニュフェストファイルで削除することができます。結果、次のようにpvc-podポッドが削除されました。

1.	$ (⎈ |switch-singapore-test:default) k get pod pvc-pod
2.	Error from server (NotFound): pods "pvc-pod" not found

既存PVC(ebs-claim)を使用するポッドを再度生成します。今回は既存データが削除されず、そのまま保存されるか確認します。

1.	$ (⎈ |switch-singapore-test:default) k apply -f pvc-pod.yaml 
2.	pod/pvc-pod created
3.	
4.	$ (⎈ |switch-singapore-test:default) k exec -it pvc-pod -- cat /data/out.txt
5.	Wed Jul 19 15:12:10 UTC 2023
6.	Wed Jul 19 15:12:15 UTC 2023
7.	(省略)

結果は以前のデータが削除されず、そのまま保存されています。以前実習でPVCを使用しないでデータを保存すると、ポッドが再開されるとそのデータも同時に削除されましたが、PVCを使用すると既存データは削除されません。

PVCを利用するとポッドのライフサイクル(削除、生成)と関係なくデータを保存できます。

2-4. PV、PVC、SCの関係

実習で使用したPV、PVCとSCの関係を確認します。 ‘k get pvc’ コマンドを利用してPVC情報を確認すると下記のようにPV名(pvc-5f4f2824-adb9-452d-969b-f9c127d2eb29)とストレージクラスebs-scがあります。

1.	$ (⎈ |switch-singapore-test:default) k get pvc
2.	NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
3.	ebs-claim Bound pvc-5f4f2824-adb9-452d-969b-f9c127d2eb29 4Gi RWO ebs-sc 25m

マニュフェストファイルを利用してPVCを生成すると、そのPVCが指定したSCが自動的にPVを生成します。

次はPVです。

1.	$ (⎈ |switch-singapore-test:default) k get pv pvc-5f4f2824-adb9-452d-969b-f9c127d2eb29
2.	NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
3.	pvc-5f4f2824-adb9-452d-969b-f9c127d2eb29 4Gi RWO Delete Bound default/ebs-claim ebs-sc 13m

PVを確認すると ‘CLAIM – default/ebs-claim’ を確認できます。そのPVをリクエスト(claim)するPVC名がebs-claimであることが分かります。つまり、PVは ‘default/ebs-claim’ で生成したPVであることを表しています。そして、PVCと同じくPVを生成したストレージクラスも ‘ebs-sc’ であることを ‘STORAGECLASS’ から確認できます。

整理すると、PVC マニュフェストにストレージクラスを指定してPVCを生成すると、ストレージクラスが自動的にPVを生成します。PVを先に生成する必要がなく、マニュフェストの指定でPVCを生成すると動的にPVを生成します。

図で表現すると下記のようになります。

管理者が事前にサービス要求事項で必要なストレージクラスを生成します。開発担当者は必要なストレージクラスだけを指定すれば動的にボリュームを割当ててアプリケーションで使用できます。ストレージの種類によりアプリケーションコードを変更しないで、単純にPVC名だけで変更できるため、かなり便利です。

3. ストレージ運用のヒント

円滑なストレージシステムの運用のために ① ボリュームの拡張(Volume Expansion)、② 可用性ゾーン(AZ、Availability Zone)の制約事項、③ リクレームポリシー(Reclaim Policy)を確認します。

システム運用時、ボリュームを拡張する場合が発生します。ボリューム不足で拡張する必要があるが、既存ボリュームをバックアップして新しいボリュームに既存データを復元すると、時間が掛かることとデータ流失のリスクもあるため、かなり難しい作業です。幸いにも、EKS CSI ドライバーで生成したボリュームはオンラインボリューム拡張機能をサポートします。クバネティスで使用できるストレージには、オンラインボリューム拡張機能をサポートするストレージがあります。ボリューム拡張のサポートの有無はストレージクラス属性で確認できます。

1.	[(jerry-test:default) ~]$ k get sc
2.	NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
3.	ebs-sc (default) ebs.csi.aws.com Delete WaitForFirstConsumer true 2d21h
4.	gp2 kubernetes.io/aws-ebs Delete WaitForFirstConsumer false 22d

‘ALLOWVOLUMEEXPANSION’ 属性を確認すると新しく生成したebs-scストレージクラスは‘true’ です。しかし、基本で提供するgp2のストレージクラスは ‘false’ です。つまり ebs-scで生成したボリュームは拡張が可能ですがgp2で生成したボリュームはボリューム拡張機能がありません。

‘k edit pvc’ コマンドを使用して簡単にボリュームを拡張できます。既存で作成されたリソースの属性を変更するためには ‘k patch’ コマンドと ‘k edit’ コマンドが使用できます。

1.	[(jerry-test:default) ~]$ k edit pvc ebs-claim
2.	(省略)
3.	spec:
4.	    accessModes:
5.	    - ReadWriteOnce
6.	    resources:
7.	        requests:
8.	            storage: 10Gi # 4Gi to 10Gi
9.	storageClassName: ebs-sc
10.	volumeMode: Filesystem
11.	volumeName: pvc-8283283c-a2f3-4a59-bf84-9ac2ffbedbad
12.	(省略)

既存の4Giの容量を10Giに変更し、保存(:wq利用)します。 ‘k edit’ コマンドはviと同じく ‘:wq’ コマンドを使用して変更事項を保存できます。

1.	[(jerry-test:default) ~]$ k edit pvc ebs-claim
2.	persistentvolumeclaim/ebs-claim edited

容量を変更して、再度PVC属性を確認すると容量の増加が確認できます。

1.	[(jerry-test:default) ~]$ k get pvc
2.	NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
3.	ebs-claim Bound pvc-283283c-a2f3-a59-bf84-ac2ffbedbad 10Gi RWO ebs-sc 3h1m

実際、ポッドで確認するとボリュームの拡張が確認できます。

1.	[(jerry-test:default) ~]$ k exec -it pvc-pod -- sh
2.	sh-4.4# df -h
3.	Filesystem Size Used Avail Use% Mounted on
4.	overlay 100G 7.8G 93G 8% /
5.	tmpfs 64M 0 64M 0% /dev
6.	tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
7.	/dev/nvme1n1 9.8G 84K 9.7G 1% /data
8.	/dev/nvme0n1p1 100G 7.8G 93G 8% /etc/hosts
9.	(省略)

上記のようにボリューム拡張が必要な場合に簡単な作業で拡張できます。緊急の状況でも使用できる大変有用な機能です。

次にAWS EBSボリュームの可用性ゾーン(Availability Zone、AZ)の制約事項を確認します。EBSボリュームは可用性ゾーンに属するリソースです。そのため、EBSを使用するためにはAZでノードが実行される必要があります。異なる可用性ゾーンにあるEBSを使用できないため、ポッドが実行できないエラーが発生します。詳細メッセージでポッドがEBSボリュームをマウントできないか先に可用性ゾーンを確認します。

PVの詳細情報を下記のように確認するとPVが配布されたAZ情報を確認できます。

1.	$ (⎈ |switch-singapore-test:default) k get pv pvc-c84491be-5a51-464d-bc93-fdfaf199685c -ojson |jq '.spec.nodeAffinity.required.nodeSelectorTerms[].matchExpressions[]'
2.	{
3.	    "key": "topology.ebs.csi.aws.com/zone",
4.	    "operator": "In",
5.	    "values": [
6.	        "ap-northeast-2c"
7.	    ]
8.	}

PVは上記のように ‘ap-northeast-2c’ に割当てられて異なる可用性ゾーンにあるポッドはそのPVを使用できません。実際の運用環境でポッドにPVを割当てできないエラーが発生しますが、これは該当AZのノードを実行できずに発生する問題です。ノードがAZで実行するまで少し待機すると解決する場合があります。

次はリクレームポリシーですが、回収や再利用のポリシーのことで、Delete(削除)、Retain(維持)の2つのオプションがあります。PVCを削除するときPVも同時に削除(Delete)するか、維持(Retain)するかを選択するオプションです。

一般的にDeleteオプションを使用してPVCを削除するとPVも同時に削除して、管理の利便性を考慮します。しかし、データを特別に保存する必要がある場合、DeleteオプションではないRetainポリシーを使用します。

では、ポッドとPVCを削除して実際にPVが削除されるかを確認します。

1.	$ (⎈ |switch-singapore-test:default) k delete pod pvc-pod 
2.	pod "pvc-pod" deleted
3.	
4.	$ (⎈ |switch-singapore-test:default) k delete pvc ebs-claim
5.	persistentvolumeclaim "ebs-claim" deleted

ポッドとPVCを削除するとPVCにコネクションされたPVも同時に削除されます。リクレームポリシーでDeleteを使用すると、このようにPVCを削除すると自動的にPVも削除します。

1.	$ (⎈ |switch-singapore-test:default) k get pv pvc-5f4f2824-adb9-452d-969b-f9c127d2eb29 
2.	Error from server (NotFound): persistentvolumes "pvc-5f4f2824-adb9-452d-969b-f9c127d2eb29" not found

以上、クバネティス環境のストレージサービスについて確認しました。


※1 クバネティスエフェメラルボリュームの追加説明
https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/

※2 gp2と gp3の比較
https://docs.aws.amazon.com/ja_jp/emr/latest/ManagementGuide/emr-plan-storage-compare-volume-types.html

※3 EKSもストレージ構成のための追加作業が必要で、ネイティブクバネティスと類似します。

※4 terraform github IRSA for EKS
https://github.com/terraform-aws-modules/terraform-aws-iam/blob/master/examples/iam-role-for-service-accounts-eks/main.tf

お気軽にお問い合わせください

製品に関する事やご不明な点など、お気軽にご相談ください。
また、ジェニファーソフトでは2週間の無償トライアルを提供しています。

詳しく知りたい方は
導入や費用のご相談は