Edited at

【IBM Cloud k8s検証メモ】ポッドから永続ストレージのマウント

More than 1 year has passed since last update.

Bluemix の CFコンテナからブロック・ストレージをマウント出来ないため、CMS等の様にクラスタ構成時にファイル共用が必須なケースでは、本番運用に対応できず残念な点でした。 一方 Bluemix k8sでは、Bluemix Infrastructure の ファイル・ストレージをマウントできる様になりました。これにより、前述の問題も解決できる様になり、コンテナ・ベースの本格的な利用ができると思います。

そこで、簡単な構成ですが、次の図の様なコンテナ間のファイル共有する方法について確認しました。


図の説明


  • 外部からアクセスするDNS名は、k8sの標準クラスタ作成時に、Bluemixから付与されるDNS名を利用します。

  • HTTPSでアクセスできる様に、ロードバランサーに、Ingressコントローラを選択します。

  • VIPは、Bluemix Infrastructure の ポータブルサブネットから割り当てられるIPアドレスです。

  • アプリケーションのコンテナは、ポッドとして複数のノード(ワーカー)にデプロイされ、ハードウェア障害に対応します。

  • コンテナから IBM Cloud のストレージ・サービスをNFSマウントして、Read/Write します。


永続ストレージの作成方法

永続ストレージの作成と利用方法には、2つの方法があり、それぞれ、Bluemix Docs に記載があります。 この二つの方法について検証してみたいと思います。

前者を「既存のNFSファイル共有の使用」のパートで、後者を「kubectlを利用した永続ストレージ作成」のパートに書いていきます。


既存のNFSファイル共有の使用

ここでは、IBM Bluemix Container Service における Kubernetes での既存の NFS ファイル共有の使用 の検証を進めていきます。


永続ストレージを準備する場所の確認

既存の状態を再現するために、Bluemix Infrastructure の画面から、先に永続ストレージを作成します。 その前に、何処のデータセンターに永続ストレージを作るべきかを確認するため、k8sクラスタが作成されたデータセンターを確認するために、デバイス・リストの画面を表示します。 kubeから始まるサーバー名が、k8s用に作成されたサーバーのホスト名です。 この例では、ロケーションが Dalas12 となっていますので、同じ場所に、永続ストレージを作成することにします。

NFSやiSCSIなど、ネットワークを介してアクセスするストレージ・サービスは、パケットがネットワークを伝わる時間の影響を受けやすく、サーバーやコンテナとストレージが、遠く離れていると、距離によりパケットの到着時間が長くなる影響を受けて、アクセス速度が遅くなる問題があります。 このため、コンテナとストレージは、可能な限り近い場所に置くことが望ましいと言えます。


永続ストレージの作成

k8sと接続できるストレージのサービスは、ファイル・ストレージ(NFS)となっており、2つの系統があります。 一つは容量と性能の比例型ストレージで、容量が増えるほどIOPS性能が、比例して良くなるタイプのエンデュランス・ストレージ、そして、性能指定型のパフォーマンス・ストレージです。 時間課金を選べるパフォーマンス・ストレージを選択します。

ウェブ画面のガイドに従って、先へ進み、オーダーを確定します。


永続ストレージの作成確認

2〜3分で作成が完了して、ボリューム名の先頭から時計マークが消えます。 そしたら、後にYAMLファイルに設定する項目を得るために、ボリューム名をクリックして詳細を表示します。

次の詳細画面で、ホスト名とマウント・ポイントのパス部分が、kubectlに与えるyamlファイルで必要になりますので、エディタ等にメモしておきます。


大切なもう一つの操作、アクセス権設定

もう一つ、k8sのWorkerノードへのアクセス権を付与する必要があります。 この設定が入っていないと、コンテナが何時迄もスタートできない状態になりますので、忘れいない様に注意ですね。 オレンジの矢印の先をクリックして、許可ホストにWokerノードを追加します。

もう一つの方法として、サブネットを登録する方法があります。 この方法であれば、Workerノードを追加した時にも、追加設定が不要なので、こちらの方が望ましいですね。

これで、永続ストレージの準備完了です。


k8sクラスタ

前回の[Bluemix k8s検証メモ] アプリをHTTPSとドメイン名でアクセスするで作成したk8sクラスタのコンテナに、永続ディスクをマウントしたいと思います。 標準クラスタが作れていれば、この時点で、デプロイメントが無くても、読み進めれば、永続ストレージをマウントしていけますので、ご参照いただければ幸いです。

次のコマンドで、現在の状態を確認します。 po/express-app-188xxxx の PODの各コンテナへ、永続ストレージをマウントします。

$ kubectl get all

NAME READY STATUS RESTARTS AGE
po/express-app-1882574706-pfhjv 1/1 Running 0 4d
po/express-app-1882574706-pqmf2 1/1 Running 0 4d
po/express-app-1882574706-xlgr4 1/1 Running 0 4d

NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc/express-svc 10.10.10.57 <nodes> 3000:31514/TCP 4d
svc/kubernetes 10.10.10.1 <none> 443/TCP 4d

NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deploy/express-app 3 3 3 3 4d

NAME DESIRED CURRENT READY AGE
rs/express-app-1882574706 3 3 3 4d


永続ボリュームへのマッピング

エディタで次のファイルを作成します。 ここで、server, path の部分は、前述のストレージ画面のメモを利用します。 パスの部分は、ホスト名部分を除外してパスだけをセットします。 各項目の説明は、IBM Bluemix Container Service における Kubernetes での既存の NFS ファイル共有の使用を参照願います。 また、Kubernetesドキュメント Persistent Volumes も参考にすると、理解が深まります。


t050_stg.yml

apiVersion: v1

kind: PersistentVolume
metadata:
name: mypv
spec:
capacity:
storage: "20Gi"
accessModes:
- ReadWriteMany
nfs:
server: "fsf-dal1201a-fz.adn.networklayer.com"
path: "/IBM02SV289550_1/data01"

yamlファイルを反映させて、永続ボリュームを作成済みの永続ストレージへマッピングします。

$ kubectl apply -f t050_stg.yml 

persistentvolume "mypv" created

永続ボリュームが出来ていることを確認します。

$ kubectl get pv

NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM REASON AGE
mypv 20Gi RWX Retain Available 11s

詳細に見るには、次のコマンドを利用します。

$ kubectl describe pv mypv

Name: mypv
Labels: <none>
StorageClass:
Status: Bound
Claim: default/mypvc
Reclaim Policy: Retain
Access Modes: RWX
Capacity: 20Gi
Message:
Source:
Type: NFS (an NFS mount that lasts the lifetime of a pod)
Server: fsf-dal1201a-fz.adn.networklayer.com
Path: /IBM02SV289550_1/data01
ReadOnly: false
No events.


永続ボリュームクレームの設定

今度は、コンテナにマウントする際に利用するクレームを定義します。 前述同様に、個々の項目の説明は避けますが、ポイントだけ補足します。

storage:accessModes の値が、前述の永続ボリュームと一致する様にします。


t051_stg.yml

kind: PersistentVolumeClaim

apiVersion: v1
metadata:
name: mypvc
annotations:
volume.beta.kubernetes.io/storage-class: ""
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: "20Gi"

yamlを反映します。

$ kubectl apply -f t051_stg.yml 

persistentvolumeclaim "mypvc" created

永続ボリュームクレームを確認します。 永続ボリュームとバインドされている状態になっています。

$ kubectl get pvc

NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
mypvc Bound mypv 20Gi RWX 12s

同様に詳細も見ておきます。

$ kubectl describe pvc mypvc

Name: mypvc
Namespace: default
StorageClass:
Status: Bound
Volume: mypv
Labels: <none>
Capacity: 20Gi
Access Modes: RWX
No events.


コンテナの再作成と永続ボリュームクレームのマウント

前回、アプリ・コンテナとIngressをデプロイした時の YAMLファイルがあれば、それを利用して一度、削除します。

$ kubectl delete -f publish.yml

もう一つの方法としては、以下のコマンドを実行して削除します。

$ kubectl delete deployment express-app

$ kubectl delete service express-svc
$ kubectl delete ingress express-ingress

前回のpublish.ymlを修正して、次のファイルを準備します。 主な違いは、'volumeMount:' と 'volumes:' を加えたことです。 コンテナをビルドした時に利用した Dockerfileを編集する必要はありません。 次のYAMLファイルだけで、コンテナに永続ストレージをマウントできる様になります。


t043_cluster_disk.yml

apiVersion: extensions/v1beta1

kind: Deployment
metadata:
name: express-app
spec:
replicas: 3
template:
metadata:
labels:
app: express-app
spec:
containers:
- name: express-container
image: registry.ng.bluemix.net/takara/express-app
ports:
- containerPort: 3000
volumeMounts:
- mountPath: /app/public
name: myvol
volumes:
- name: myvol
persistentVolumeClaim:
claimName: mypvc
---
apiVersion: v1
kind: Service
metadata:
name: express-svc
spec:
type: NodePort
selector:
app: express-app
ports:
- protocol: TCP
port: 3000
nodePort: 31514
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: express-ingress
spec:
tls:
- hosts:
- mycluster3.us-south.containers.mybluemix.net
secretName: mycluster3
rules:
- host: mycluster3.us-south.containers.mybluemix.net
http:
paths:
- path: /
backend:
serviceName: express-svc
servicePort: 3000

次のコマンドで、アプリ・コンテナとIngressをデプロイします。

$ kubectl create -f t043_cluster_disk.yml


コンテナでのマウント状態の確認

`kubectl get pod で、podのリストを取得して、その中の一つにログインして、マウント状態を確認した結果が以下です。

外からのYAMLファイルだけの操作で、コンテナにファイルシステムをマウントできる点は、とっても便利ですね。

$ kubectl exec -it express-app-943621608-0k35n /bin/bash

root@express-app-943621608-0k35n:/# df
Filesystem 1K-blocks Used Available Use% Mounted on
overlay 101330012 6063956 95249672 6% /
tmpfs 2048016 0 2048016 0% /dev
tmpfs 2048016 0 2048016 0% /sys/fs/cgroup
/dev/xvda2 101330012 6063956 95249672 6% /etc/hosts
fsf-dal1201a-fz.adn.networklayer.com:/IBM02SV289550_1/data01 20971264 0 20971264 0% /app/public
shm 65536 0 65536 0% /dev/shm
tmpfs 2048016 12 2048004 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 2048016 0 2048016 0% /sys/firmware


kubectlを利用した永続ストレージ作成

永続ストレージを利用するためのもう一つの方法について、IBM Bluemix Container Service での永続ストレージの作成 の内容を検証していきます。

$ kubectl get storageclasses

NAME TYPE
default ibm.io/ibmc-file
ibmc-file-bronze (default) ibm.io/ibmc-file
ibmc-file-custom ibm.io/ibmc-file
ibmc-file-gold ibm.io/ibmc-file
ibmc-file-retain-bronze ibm.io/ibmc-file
ibmc-file-retain-custom ibm.io/ibmc-file
ibmc-file-retain-gold ibm.io/ibmc-file
ibmc-file-retain-silver ibm.io/ibmc-file
ibmc-file-silver ibm.io/ibmc-file

$ kubectl describe storageclasses ibmc-file-bronze 

Name: ibmc-file-bronze
IsDefaultClass: Yes
Annotations: kubectl.kubernetes.io/last-applied-configuration={"kind":"StorageClass","apiVersion":"storage.k8s.io/v1beta1","metadata":{"name":"ibmc-file-bronze","creationTimestamp":null,"labels":{"addonmanager.kubernetes.io/mode":"Reconcile","kubernetes.io/cluster-service":"true"},"annotations":{"storageclass.beta.kubernetes.io/is-default-class":"true"}},"provisioner":"ibm.io/ibmc-file","parameters":{"iopsPerGB":"2","reclaimPolicy":"Delete","sizeRange":"20Gi,40Gi,80Gi,100Gi,250Gi,500Gi,1000Gi,2000Gi,4000Gi,8000Gi,12000Gi","type":"Endurance"}},storageclass.beta.kubernetes.io/is-default-class=true
Provisioner: ibm.io/ibmc-file
Parameters: iopsPerGB=2,reclaimPolicy=Delete,sizeRange=20Gi,40Gi,80Gi,100Gi,250Gi,500Gi,1000Gi,2000Gi,4000Gi,8000Gi,12000Gi,type=Endurance
Events: <none>

次のYAMLファイルで、Bluemix Infrastructure エンデュランス・ストレージ(月額)を作成して、コンテナにマウントできる状態になります。 このケースでは、永続ボリュームを作ったり、Bluemix Infrastructure のウェブ画面から、ファイル・ストレージを作成する必要はありません。


t053_stg.yml

apiVersion: v1

kind: PersistentVolumeClaim
metadata:
name: mypvc2
annotations:
volume.beta.kubernetes.io/storage-class: "ibmc-file-bronze"
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 20Gi

適用します。

$ kubectl apply -f t053_stg.yml

persistentvolumeclaim "mypvc2" created

2〜3分すると、mypvc2 の列の様に、永続ボリューム・クレームが利用できる様になります。

$ kubectl get pvc

NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
mypvc Bound mypv 20Gi RWX 7h
mypvc2 Bound pvc-70563956-9949-11e7-8559-9694aad01573 20Gi RWX 2m

永続ボリュームも確認すると、次の様になっています。 RECLAIMPOLICY が違うことに要注意です。

$ kubectl get pv

NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM REASON AGE
mypv 20Gi RWX Retain Bound default/mypvc 7h
pvc-70563956-9949-11e7-8559-9694aad01573 20Gi RWX Delete Bound default/mypvc2 1m


永続ボリュームクレームのマウント

次のYAMLファイルで、前述の方法で作成した永続ボリューム・クレームをマウントするコンテナを作成します。


t044_cluster_endurance.yml

apiVersion: extensions/v1beta1

kind: Deployment
metadata:
name: express-app2
spec:
replicas: 1
template:
metadata:
labels:
app: express-app2
spec:
containers:
- name: express-container2
image: registry.ng.bluemix.net/takara/express-app
ports:
- containerPort: 3000
volumeMounts:
- mountPath: /app/public
name: myvol
volumes:
- name: myvol
persistentVolumeClaim:
claimName: mypvc2

kubectl を実行して、内容を反映させます。

$ kubectl create -f t044_cluster_endurance.yml

deployment "express-app2" created
service "express-svc2" created

PODを確認すると、exporess-app2-* という名前で、PODが稼働していることが解ります。

kubectl get pod

NAME READY STATUS RESTARTS AGE
express-app-943621608-3bfps 1/1 Running 0 21h
express-app-943621608-70z2s 1/1 Running 0 21h
express-app-943621608-7l6tm 1/1 Running 0 21h
express-app2-3198649982-14p53 1/1 Running 0 13s
mypod 1/1 Running 0 1d

実際にログインして、dfコマンドでマウント状態を確認します。 /app/publicのファイル・システムは、Bluemix IaaSのファイル・システムであることが確認できます。

$ kubectl exec -it express-app2-3198649982-14p53 /bin/bash

root@express-app2-3198649982-14p53:/# df
Filesystem 1K-blocks Used Available Use% Mounted on
overlay 101330012 5718424 95595204 6% /
tmpfs 2048016 0 2048016 0% /dev
tmpfs 2048016 0 2048016 0% /sys/fs/cgroup
fsf-dal1201b-fz.adn.networklayer.com:/IBM02SEV289550_1/data01 20971328 0 20971328 0% /app/public
/dev/xvda2 101330012 5718424 95595204 6% /etc/hosts
shm 65536 0 65536 0% /dev/shm
tmpfs 2048016 12 2048004 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 2048016 0 2048016 0% /sys/firmware

ファイルが入っていませんが、/app/public で ls を実行して、ファイルシステムが動作していることが確認できます。

root@express-app2-3198649982-14p53:/# ls -al /app/public

total 8
drwxr-xr-x 2 nobody 4294967294 4096 Sep 14 12:37 .
drwxr-xr-x 7 root root 4096 Sep 9 16:10 ..
root@express-app2-3198649982-14p53:/#


まとめ

Bluemix Infrastructure ファイル・サービス で提供される NFSサーバーを kubectl を使って コンテナの内容を変えることなく、マウントできることが確認できました。 また、kubectl から Bluemix Infrastructure のエンデュランス・ストレージを作成して、同様にマウントできることも確認できました。 これで、複数のコンテナ間でファイルが共有でき、コンテナで、永続的な情報としてファイルへ書き込みことができる事が確認できました。


参考資料