IKSとはIBM Cloud Kubernetes Service の略で、CNCFの認証を取得した Kubernetes サービスです。
この記事は、IKSのポッドからブロック・ストレージを利用方法と、ファイルストレージとの違いの確認したものです。
IKSの永続ストレージ
IKSから利用できる永続ストレージは、IBM Cloud IaaS (旧称 SoftLayer) のストレージサービスの一つ エンデュランス ストレージ (Endurance Storage)と パフォーマンス ストレージ (Performance Storage) を利用することができます。 エンデュランス ストレージはストレージ容量に比例して、秒間あたり受け入れる命令数(IOPS)が増加するという容量と性能が比例するタイプのサービスです。 従って、容量を多く確保すれば、それに伴ってアクセス速度の性能が向上します。 また、パフォーマンスストレージでは、容量だけでなく、IOPS性能指定して買うことができます。
このストレージサービスの提供形態には、2種類あり、ファイル・ストレージという名称でNFSサービス、そして、ブロック・ストレージという名称でiSCSIサービスが提供されています。 以下2つのリンクは、これらサービスのマニュアルです。
- ブロック・ストレージ https://console.bluemix.net/docs/infrastructure/BlockStorage/index.html
- ファイル・ストレージ https://console.bluemix.net/docs/infrastructure/FileStorage/index.html
エンデュランス ストレージのストレージ容量とIOPS性能の比例の関係には、次の3つのクラスがあり、k8sのマニフェストで指定することができます。
クラス | 性能 | 容量範囲 |
---|---|---|
ブロンズ (デフォルト) | 2 IOPS/GB | 20 から 12000 Gi |
シルバー | 4 IOPS/GB | 20 から 12000 Gi |
ゴールド | 10 IOPS/GB | 20 から 4000 Gi |
ブロックストレージのセットアップ
ブロックストレージを利用するために、ストレージクラスに、ブロック・ストレージのプロビジョナーをインストールする必要があります。 これは、次のリンクのマニュアルにしたがって、Helmからインストールできます。
前提準備
もし、IKS上にk8sクラスタを未作成、そして、CLIをインストールしていない場合は、以下のリンクを参照して、k8sクラスタのセットアップ、そして、kubectlコマンド、helmコマンドを利用できる様にする必要があります。
- IBM Cloud CLIインストール https://console.bluemix.net/docs/containers/cs_cli_install.html#cs_cli_install
- k8s クラスタの作成 https://console.bluemix.net/docs/containers/cs_clusters.html#clusters_cli
- kubectl を実行するように CLI を構成する https://console.bluemix.net/docs/containers/cs_cli_install.html#cs_cli_configure
- Kubernetes Service での Helm のセットアップ https://console.bluemix.net/docs/containers/cs_integrations.html#helm
- マニュアルのリンク: クラスターへの IBM Cloud Block Storage プラグインのインストール https://console.bluemix.net/docs/containers/cs_storage.html#install_block
ブロックストレージ・プラグインのインストール
最初に、Helmを利用するためにHelmのサーバーを動かします。 そのためにサーバーのサービスアカウントを作成して、アクセス権を付与します。
apiVersion: v1
kind: ServiceAccount
metadata:
name: tiller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system
上記のYAMLを適用します。
$ kubectl apply -f rbac-config.yml
これでHelmが動作するようになったので、HELM初期化、HELMリポジトリの追加、ブロック・ストレージのプラグインをインストールを行います。最後に、kubectl get sc として ibm-block-* のエントリーが表示されたら、ストレージクラスの準備完了です。
$ helm init --service-account tiller
$ helm repo add ibm https://registry.bluemix.net/helm/ibm
$ helm install ibm/ibmcloud-block-storage-plugin
$ kubectl get sc
NAME PROVISIONER AGE
default ibm.io/ibmc-file 2d
ibmc-block-bronze ibm.io/ibmc-block 25s
ibmc-block-custom ibm.io/ibmc-block 25s
ibmc-block-gold ibm.io/ibmc-block 25s
ibmc-block-retain-bronze ibm.io/ibmc-block 25s
ibmc-block-retain-custom ibm.io/ibmc-block 25s
ibmc-block-retain-gold ibm.io/ibmc-block 25s
ibmc-block-retain-silver ibm.io/ibmc-block 25s
ibmc-block-silver ibm.io/ibmc-block 25s
ibmc-file-bronze (default) ibm.io/ibmc-file 2d
ibmc-file-custom ibm.io/ibmc-file 2d
ibmc-file-gold ibm.io/ibmc-file 2d
ibmc-file-retain-bronze ibm.io/ibmc-file 2d
ibmc-file-retain-custom ibm.io/ibmc-file 2d
ibmc-file-retain-gold ibm.io/ibmc-file 2d
ibmc-file-retain-silver ibm.io/ibmc-file 2d
ibmc-file-silver ibm.io/ibmc-file 2d
これで、ブロックストレージを利用するための準備が整いました。
エンデュランス・ストレージのPVC設定
ブロックストレージのサービスを注文するYAMLを作成して適用します。 このYAMLを適用すると、クラウドの利用料金が発生するので、注意が必要です。 料金に関係する部分は、 billingType と storage の2箇所で請求額が変わります。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc-block
annotations:
volume.beta.kubernetes.io/storage-class: "ibmc-block-bronze"
labels:
billingType: "hourly" # 時間課金
spec:
accessModes:
- ReadWriteOnce # ブロックストレージは共有できない
resources:
requests:
storage: 20Gi
上記のYAMLを適用すると、PVCとPVが作成されます。 後はマウントして利用するだけです。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
10.132.253.17 Ready <none> 2d v1.11.2+IKS
10.132.253.30 Ready <none> 2d v1.11.2+IKS
$ kubectl apply -f my-pvc-block.yml
persistentvolumeclaim/mypvc-block created
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc-block Pending ibmc-block-bronze 6s
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc-block Bound pvc-7946602b-ba1d-11e8-b2ac-72d65ed87e6b 20Gi RWO ibmc-block-bronze 1m
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-7946602b-ba1d-11e8-b2ac-72d65ed87e6b 20Gi RWO Delete Bound default/mypvc-block ibmc-block-bronze 1m
コンテナからストレージのマウント
デプロイメントのポッドから、エンデュランス・ストレージのPVCを設定して、コンテナからマウントします。
PVCをマウントするポッドの設定YAML
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: dep-block
labels:
app: dep-block
spec:
selector:
matchLabels:
app: dep-block
template:
metadata:
labels:
app: dep-block
spec:
containers:
- image: ubuntu
name: ubuntu
volumeMounts:
- name: pvc-block
mountPath: /mnt # マウントポイント
args:
- tail
- -f
- /dev/null
volumes: # ポッドボリューム設定
- name: pvc-block
persistentVolumeClaim:
claimName: mypvc-block
次が実行結果です。 起動したポッドに対話型でシェルを起動して、以下を確認しました。
- ブロックストレージを指定したのですが、ファイルシステムが作成されていて、コンテナから利用できています。
- /mntのデバイスは、デバイスマッパーになっていて、ブロックストレージとしてマウントされたことがわかります。
- 書き込んだデータのハッシュを取得しておき、再度、ポッドを作り直して、同じデータが参照できるか確認してします。
$ kubectl apply -f deploy-block.yml
deployment.apps/dep-block created
$ kubectl get -f deploy-block.yml
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
dep-block 1 1 1 0 8s
$ kubectl get -f deploy-block.yml
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
dep-block 1 1 1 1 1m
$ kubectl get po
NAME READY STATUS RESTARTS AGE
dep-block-84bd59b989-j6f8j 1/1 Running 0 2m
$ kubectl exec -it dep-block-84bd59b989-j6f8j bash
root@dep-block-84bd59b989-j6f8j:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 99G 3.6G 90G 4% /
tmpfs 64M 0 64M 0% /dev
tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup
/dev/mapper/docker_data 99G 3.6G 90G 4% /etc/hosts
shm 64M 0 64M 0% /dev/shm
/dev/mapper/3600a09803830446d323f4c3066433164 20G 44M 20G 1% /mnt
tmpfs 2.0G 12K 2.0G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 2.0G 0 2.0G 0% /proc/acpi
tmpfs 2.0G 0 2.0G 0% /sys/firmware
tmpfs 2.0G 0 2.0G 0% /proc/scsi
root@dep-block-84bd59b989-j6f8j:/# ps -ax > /mnt/test.dat
root@dep-block-84bd59b989-j6f8j:/# md5sum /mnt/test.dat
fad2f2ab592130112ff5af57881e0fb5 /mnt/test.dat
完了したらデプロイメントを削除します。 この時、永続ストレージが無くならないことを確認しています。
$ kubectl delete -f deploy-block.yml
deployment.apps "dep-block" deleted
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
dep-block-84bd59b989-j6f8j 1/1 Terminating 0 35m
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc-block Bound pvc-7946602b-ba1d-11e8-b2ac-72d65ed87e6b 20Gi RWO ibmc-block-bronze 41m
再度、永続ストレージをマウントするポッドをデプロイして、前述の書き込んだデータを確認します。
$ kubectl apply -f deploy-block.yml
deployment.apps/dep-block created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
dep-block-84bd59b989-m2p7s 0/1 ContainerCreating 0 15s
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
dep-block-84bd59b989-m2p7s 1/1 Running 0 1m
ポッドが起動したので、対話型シェルを起動して、ハッシュを確認します。 確かに、同じハッシュの値でした。
$ kubectl exec -it dep-block-84bd59b989-m2p7s bash
root@dep-block-84bd59b989-m2p7s:/# md5sum /mnt/test.dat
fad2f2ab592130112ff5af57881e0fb5 /mnt/test.dat
ファイル・ストレージとブロック・ストレージの比較
同じエンデュランスのファイルストレージを利用して、比較して見ます。
次はファイルサービスを利用するYAMLです。
my-pvc-file.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc-file
annotations:
volume.beta.kubernetes.io/storage-class: "ibmc-file-bronze"
labels:
billingType: "hourly"
spec:
accessModes:
- ReadWriteMany # NFSなので 複数のポッドからもアクセスできる
resources:
requests:
storage: 20Gi
このYAMLをデプロイして、ストレージが追加されるのを待ちます。 約3分後には、ストレージが起動していました。
$ kubectl apply -f my-pvc-file.yml
persistentvolumeclaim/mypvc-file created
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc-block Bound pvc-7946602b-ba1d-11e8-b2ac-72d65ed87e6b 20Gi RWO ibmc-block-bronze 45m
mypvc-file Pending ibmc-file-bronze 4s
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc-block Bound pvc-7946602b-ba1d-11e8-b2ac-72d65ed87e6b 20Gi RWO ibmc-block-bronze 49m
mypvc-file Bound pvc-dcb4dbf1-ba23-11e8-b2ac-72d65ed87e6b 20Gi RWX ibmc-file-bronze 3m
次は、ファイルストレージを利用するデプロイメントのYAMLです。
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: dep-file
labels:
app: dep-file
spec:
selector:
matchLabels:
app: dep-file
template:
metadata:
labels:
app: dep-file
spec:
containers:
- image: ubuntu
name: ubuntu
volumeMounts:
- name: pvc-file
mountPath: /mnt
args:
- tail
- -f
- /dev/null
volumes:
- name: pvc-file
persistentVolumeClaim:
claimName: mypvc-file
前述のYAMLを適用して、ポッドに対話シェルを立ち上げて、確認します。
- /mntのデバイスは、表示内容からホスト名とエクスポートディレクトリになっていて、NFSであることが判別できます。
$ kubectl apply -f deploy-file.yml
deployment.apps/dep-file created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
dep-block-84bd59b989-m2p7s 1/1 Running 0 8m
dep-file-6c8ff6fc87-zlgdh 1/1 Running 0 6s
$ kubectl exec -it dep-file-6c8ff6fc87-zlgdh bash
root@dep-file-6c8ff6fc87-zlgdh:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 99G 3.6G 90G 4% /
tmpfs 64M 0 64M 0% /dev
tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup
/dev/mapper/docker_data 99G 3.6G 90G 4% /etc/hosts
shm 64M 0 64M 0% /dev/shm
fsf-tok0201a-fz.service.softlayer.com:/IBM02SEV289550_7/data01 20G 0 20G 0% /mnt
tmpfs 2.0G 12K 2.0G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 2.0G 0 2.0G 0% /proc/acpi
tmpfs 2.0G 0 2.0G 0% /sys/firmware
tmpfs 2.0G 0 2.0G 0% /proc/scsi
iSCSIを利用する場合は、コンテナにイニシエーターを設定する必要があるのですが、IKSのブロックストレージのクラスは、NFSサーバーのストレージをマウントする時と変わらない手軽さで利用できることがわかりました。 あまりにも簡単に使えたので、ファイルストレージを立ち上げて比較して、ブロックストレージであることを確かめてしまいました。(^_^);
パフォーマンスストレージ XFSとしてマウント
もう一つ、IBM Cloud IaaSで、重宝なパフォーマンス・ストレージも試して見ます。
こちらも、ブロックストレージなのですが、前述のブロックストレージと同様に、プロビジョナーがmkfsまでを実行して、コンテナからマウントできるところまで、セットアップしてくれます。特に高速ストレージの性能を発揮できるファイルシステム XFSでマウントします。 こちらは、XFSでマウントするストレージクラスの設定は、手作業で実施する必要があります。 次のYAMLを適用して、ストレージクラスを追加します。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ibmc-block-custom-xfs
labels:
addonmanager.kubernetes.io/mode: Reconcile
provisioner: ibm.io/ibmc-block
parameters:
type: "Performance"
sizeIOPSRange: |-
[20-39]Gi:[100-1000]
[40-79]Gi:[100-2000]
[80-99]Gi:[100-4000]
[100-499]Gi:[100-6000]
[500-999]Gi:[100-10000]
[1000-1999]Gi:[100-20000]
[2000-2999]Gi:[200-40000]
[3000-3999]Gi:[200-48000]
[4000-7999]Gi:[300-48000]
[8000-9999]Gi:[500-48000]
[10000-12000]Gi:[1000-48000]
fsType: "xfs"
reclaimPolicy: "Delete"
classVersion: "2"
次は、適用結果です。ibmc-block-custom-xfs が追加されています。
$ vi stg-class-perf.yml
$ kubectl apply -f stg-class-perf.yml
storageclass.storage.k8s.io/ibmc-block-custom-xfs created
$ kubectl get sc
NAME PROVISIONER AGE
default ibm.io/ibmc-file 2d
ibmc-block-bronze ibm.io/ibmc-block 4h
ibmc-block-custom ibm.io/ibmc-block 4h
ibmc-block-custom-xfs ibm.io/ibmc-block 5s <--- 追加
ibmc-block-gold ibm.io/ibmc-block 4h
ibmc-block-retain-bronze ibm.io/ibmc-block 4h
ibmc-block-retain-custom ibm.io/ibmc-block 4h
ibmc-block-retain-gold ibm.io/ibmc-block 4h
ibmc-block-retain-silver ibm.io/ibmc-block 4h
ibmc-block-silver ibm.io/ibmc-block 4h
ibmc-file-bronze (default) ibm.io/ibmc-file 2d
ibmc-file-custom ibm.io/ibmc-file 2d
ibmc-file-gold ibm.io/ibmc-file 2d
ibmc-file-retain-bronze ibm.io/ibmc-file 2d
ibmc-file-retain-custom ibm.io/ibmc-file 2d
ibmc-file-retain-gold ibm.io/ibmc-file 2d
ibmc-file-retain-silver ibm.io/ibmc-file 2d
ibmc-file-silver ibm.io/ibmc-file 2d
永続ストレージのPVCのYAMLを作成します。 ポイントはコメントした5箇所です。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc-block-xfs
annotations:
volume.beta.kubernetes.io/storage-class: "ibmc-block-custom-xfs" # ストレージクラス
labels:
billingType: "hourly" # 時間課金
spec:
accessModes:
- ReadWriteOnce # <-- ブロックなので一つのポッドからしか利用できない
resources:
requests:
storage: 20Gi # <-- 容量の設定単位は、IaaSのマニュアル参照のこと
iops: "400" # <-- IOPSを指定
1分程度でプロビジョニング完了でした。
$ kubectl apply -f my-pvc-block-xfs.yml
persistentvolumeclaim/mypvc-block-xfs created
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc-block Bound pvc-7946602b-ba1d-11e8-b2ac-72d65ed87e6b 20Gi RWO ibmc-block-bronze 1h
mypvc-block-xfs Pending ibmc-block-custom-xfs 5s
mypvc-file Bound pvc-dcb4dbf1-ba23-11e8-b2ac-72d65ed87e6b 20Gi RWX ibmc-file-bronze 16m
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc-block Bound pvc-7946602b-ba1d-11e8-b2ac-72d65ed87e6b 20Gi RWO ibmc-block-bronze 1h
mypvc-block-xfs Bound pvc-2e4c6204-ba26-11e8-b2ac-72d65ed87e6b 20Gi RWO ibmc-block-custom-xfs 1m
mypvc-file Bound pvc-dcb4dbf1-ba23-11e8-b2ac-72d65ed87e6b 20Gi RWX ibmc-file-bronze 17m
シェルを起動して確認した結果です。 /dev/mapperでブロックストレージで接続されています。
$ kubectl exec -it dep-block-xfs-6fb49dd86f-2g4xr bash
root@dep-block-xfs-6fb49dd86f-2g4xr:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 99G 3.5G 90G 4% /
tmpfs 64M 0 64M 0% /dev
tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup
/dev/mapper/docker_data 99G 3.5G 90G 4% /etc/hosts
shm 64M 0 64M 0% /dev/shm
/dev/mapper/3600a09803830446d445d4c3066664755 20G 33M 20G 1% /mnt
tmpfs 2.0G 12K 2.0G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 2.0G 0 2.0G 0% /proc/acpi
tmpfs 2.0G 0 2.0G 0% /sys/firmware
tmpfs 2.0G 0 2.0G 0% /proc/scsi
ポッド内の二つのコンテナから一つのブロックストレージを利用できるか?
ブロック・ストレージは、下位レイヤーがiSCSIで実装されているため、NFSのように複数のクライアントからマウントして利用することはできません。しかし、YAMLファイルでは、ポッドのレベルにボリューム書いて、コンテナのレベルでマウントポイントを書くことになっていますから、複数のコンテナを持つポッドの場合、ポッド上の複数のコンテナがブロック・ストレージをマウントしてデータを共有できるように思われます。
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: dep-block2
labels:
app: dep-block2
spec:
selector:
matchLabels:
app: dep-block2
template:
metadata:
labels:
app: dep-block2
spec:
containers:
- name: c1 # コンテナ1
image: ubuntu
volumeMounts:
- name: pvc-block
mountPath: /mnt
args:
- tail
- -f
- /dev/null
- name: c2 # コンテナ2
image: ubuntu
volumeMounts:
- name: pvc-block
mountPath: /mnt
args:
- tail
- -f
- /dev/null
volumes: # ポッドレベルのボリューム定義
- name: pvc-block
persistentVolumeClaim:
claimName: mypvc-block
ポッド上の二つのコンテナから、/mntにマウントしたストレージをアクセスして、動作を確認します。
以下の通り、二つのコンテナから、同じボリュームをアクセスできることが確認できました。
$ kubectl apply -f deploy-block2.yml
deployment.apps/dep-block2 created
$ kubectl get po
NAME READY STATUS RESTARTS AGE
dep-block2-5c56f8cb8f-pf544 2/2 Running 0 1m
# 二つのコンテナは、同一ポッドで同じホスト名
$ kubectl exec -it dep-block2-5c56f8cb8f-pf544 -c c1 hostname
dep-block2-5c56f8cb8f-pf544
$ kubectl exec -it dep-block2-5c56f8cb8f-pf544 -c c2 hostname
dep-block2-5c56f8cb8f-pf544
# 書き込み、読み取りテスト
$ kubectl exec -it dep-block2-5c56f8cb8f-pf544 -c c1 -- bash -c "date > /mnt/date.dat"
$ kubectl exec -it dep-block2-5c56f8cb8f-pf544 -c c1 -- bash -c "cat /mnt/date.dat"
Mon Sep 17 06:07:48 UTC 2018
$ kubectl exec -it dep-block2-5c56f8cb8f-pf544 -c c2 -- bash -c "cat /mnt/date.dat"
Mon Sep 17 06:07:48 UTC 2018
ブロックストレージをレプリカセットで共有できるか?
結論はできない。 ブロック・ストレージは、複数のポッドからアクセスはできないので、プロビジョニングが成功しない。
複数のポッドから永続ストレージをマウントしたい場合は、ファイルサービスを利用すること。
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: dep-block
labels:
app: dep-block
spec:
replicas: 3 ## <-- ここで3を指定
selector:
matchLabels:
app: dep-block
template:
metadata:
labels:
app: dep-block
spec:
containers:
- image: ubuntu
name: ubuntu
volumeMounts:
- name: pvc-block
mountPath: /mnt
args:
- tail
- -f
- /dev/null
volumes:
- name: pvc-block
persistentVolumeClaim:
claimName: mypvc-block
最初にブロックストレージを掴んだポッドだけが起動して、残りは保留になる。
imac:test-iks maho$ kubectl apply -f deploy-block.yml
deployment.apps/dep-block created
$ kubectl get po
NAME READY STATUS RESTARTS AGE
dep-block-84bd59b989-48hz9 0/1 ContainerCreating 0 2s
dep-block-84bd59b989-jk8nb 0/1 ContainerCreating 0 2s
dep-block-84bd59b989-mr7cp 0/1 ContainerCreating 0 2s
$ kubectl get po
NAME READY STATUS RESTARTS AGE
dep-block-84bd59b989-48hz9 0/1 ContainerCreating 0 19m
dep-block-84bd59b989-jk8nb 0/1 ContainerCreating 0 19m
dep-block-84bd59b989-mr7cp 1/1 Running 0 19m
以上