0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

k8s, はじめてのデプロイ

Last updated at Posted at 2025-05-05

はじめに

前の記事の続き。構築したk8s クラスタに NGINX をデプロイし、適当なコンテンツにアクセスすることで動作を確かめる。

コンテンツの配備手法に分け、構築パターンは大きく3種類となる。NFSの利用方法はPV/PVCを利用するパターンとCSIを使うパターンで2つあり、今回は両者とも試す。

  1. Worker ノードのローカルディスクに静的なHTMLファイルを配置する
  2. NFSサーバを構築してコンテンツをNFS上に配備する
    2-1. k8sからはPV/PVCを経由でアクセスするパターン
    2-2. k8sからCSIを利用するパターン
  3. CephFSサーバを構築してコンテンツはCephFS上に配備し、CephFSをWorker ノードにマウントして使用する。

今回はCSI利用までとし、CephFSは別にする。

1. Hello k8s! - ローカルディスクに配備

作成順序は以下。

  1. 各 Workerノードに /mnt/data/index.html を作成
  2. hostPath ボリュームでこのファイルをPodにマウント
  3. NodePort を使って外部公開し、curl やブラウザから確認

hostPath?
k8s-workerノード上のディレクトリやファイルを、Pod のコンテナにマウントする仕組み。
言い換えると、コンテナ内で見えるファイルパスを、実際にはホスト側のファイルシステムに接続するというもの。

1-1. 各 Worker ノードでファイル作成

Worker1/2両者で以下を作成する。

mkdir -p /mnt/data
echo "<h1>Hello from $(hostname)</h1>" | sudo tee /mnt/data/index.html

1-2. NGINX Deployment

k8s を実際に利用する上ではあまり使わない設定ではあるが、
hostPath指定+nodeSelectorでk8s-Worker1を明示的に指定する。

yaml nginx-hostpath-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  # Deploymentの名前。NameSpace内ではユニークである必要がある
  name: nginx-hostpath
spec:
  # レプリカ数の指定
  replicas: 1
  selector:
    matchLabels:
      # 管理対象のPodの名前 template.metadata.labels.appとは原則一致させること
      app: nginx-hostpath
  template:
    metadata:
      labels:
        # 実際にデプロイするPodの名前 spec.selector.matchLabelsとは原則一致させること
        app: nginx-hostpath
    spec:
      nodeSelector:
        kubernetes.io/hostname: <worker1のノード名>  # `kubectl get nodes -o wide`で確認
      containers:
      - name: nginx
        image: nginx:stable
        ports:
        - containerPort: 80
        volumeMounts:
        # Pod内コンテナから見えるパス。実態はvolumes.hostpath.pathで指定した/mnt/dataになる
        - mountPath: /usr/share/nginx/html
          name: html-volume
      volumes:
      - name: html-volume
        hostPath:
          # Worker ノード上の絶対パス
          path: /mnt/data
          type: Directory

spec.selector.matchLabelsspec.template.metadata.labels
この二つは原則一致させる。ただし、Job(1回限りの処理)や CronJob(定期処理)、StatefulSet(State を持つ Pod)との共存する際に使わないことがないわけではない模様。

Podコンテナ
厳密にはPod ⊃ コンテナとなり、イコールではない。今回の例では 1 Pod = 1コンテナになっているが、1 Podに複数のコンテナを持たせるケースもある。

containerPort: 80
Pod内でどのポートが開いているかを宣言するためのもの。あくまでも情報提供用のフィードのため、これがなくともコンテナは動作するし、このPort番号でもって外部からアクセスできるわけではない。ただし、Servicekubectl describe podなどの表示上、Podがどのポートで通信しているかを把握するうえで重要なヒントになるため、宣言しておくことが推奨される。

image: nginx:stable
Docker Hubの公式NGINXイメージ をとってくる。実際には docker.io/library/nginx:stable からDownloadすることになる。

1-3.NodePort Service

Podを外部公開するため、Serviceを作成する。

nginx-hostpath-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-hostpath-service
spec:
  type: NodePort
  selector:
    app: nginx-hostpath
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080

1-4. Port ???

Port, targetPort, NodePort, また、NGINX Deploymentで使ったcontainerPort といろいろと出てきて混乱する。まず、対応関係全体図は以下のようになっている。

[外部PC]
  ↓ http://<NodeIP>:30080     ← nodePort(Serviceが開ける外部ポート)
[Node (kube-proxy)]
  ↓ ルーティング
Service (type: NodePort)
  ↓ port: 80(Service内部ポート)
  ↓ targetPort: 80(PodのPortに転送)
[Pod]
  ↓
containerPort: 80(実際にコンテナ内でアプリがListenしているPort)

一覧にまとめるとこんな感じ。

フィールド名 設定ポイント 意味
containerPort Deployment のコンテナ定義内 Pod内コンテナがListenしているポート 80
targetPort Service Service がトラフィックを Podのどのポートに転送するか 80(name 指定も可能)
port Service Service 自体のポート番号(クラスタ内部で使用) 80
nodePort Service (type: NodePort時) 外部IP + このポートでアクセスできる 30080(範囲:30000〜32767)

1-5. 適用

kubectl apply -f nginx-hostpath-deployment.yaml
kubectl apply -f nginx-hostpath-service.yaml

1-6. 正常性確認

1-6-1. Podが正しく起動したか?

ubuntu@k8s-master:~$ kubectl get pods
NAME                              READY   STATUS    RESTARTS   AGE
nginx-hostpath-7b4445db8d-bsz7l   1/1     Running   1 (145m ago)   6h32m

StatusがRunning になっていればOK.

1-6-2. Serviceが正しく設定されているか?

ubuntu@k8s-master:~$ kubectl get service
NAME                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes               ClusterIP   172.16.0.1       <none>        443/TCP        3d3h
nginx-hostpath-service   NodePort    172.16.246.180   <none>        80:30080/TCP   3d

contaierPort:80とNodePort 30080が紐づいていればOK.

1-6-3. アクセス確認

ubuntu@k8s-master:~$ curl http://192.168.11.122:30080
<h1>Hello from k8s-worker1</h1>

ここで192.168.11.122はk8s-worker1の外部IP。ブラウザでもよいが、最小限の確認としてcurlでとれていることを確認する

1-6-4. Podに入ってみる

実際に動き出した Pod に入り状態を確認してみる。
構文はこんな感じ。
kubectl exec -it コンテナ名 -- コンテナ内で実行するコマンド

ubuntu@k8s-master:~$ kubectl exec -it nginx-hostpath-6f6f977f68-tx8zx -- /bin/sh
# ls 
# ls
bin   dev                  docker-entrypoint.sh  home  lib64  mnt  proc  run   srv  tmp  var
boot  docker-entrypoint.d  etc                   lib   media  opt  root  sbin  sys  usr
# exit

ここで-it は対話モード(インタラクティブ)、 --は UNIX系のオプションでk8s以外にも使われる特殊な記号。具体的にはPod名などのオプションと、Pod内で実行したいコマンドを区切るために使用する。exec -it を利用する際は少なくとも一つのPod 内で実行するコマンドを書く必要がある。/bin/shであって/bin/bashではないのは、コンテナに含まれるパッケージは最低限に絞られており、/bin/bashも含まれていないため(psviも入っていない)。shから抜けるには単にexitでよい。

1-6-5. ダメな例

コンテナ内で何を実行するのかを指定していないと怒られる。

ubuntu@k8s-master:~$ kubectl exec -it nginx-hostpath-7b4445db8d-bsz7l
error: you must specify at least one command for the container

1-6-6. 対話モードでのpod操作の限界

状態確認はできる。設定変更はできない。コンテナにviが含まれていないとかもあるが、それ以前に設定変更したところで Podが再構築されると設定は初期化される。 Podの設定を変更したいのならyamlファイルで行うしかない。

1-7. hostPath の限界

hostPathは検証目的でPodを構築するだけであれば十分だが、
特定のノードに依存するためスケールしない(e.g. worker1/2それぞれのローカルディスクを見ることになる)、セキュリティ的にホストのファイルシステムへアクセスさせるのはリスクがあり、実環境に適用するには心もとない。

マルチノード環境での永続的なストレージを確保するためには、NFSやクラウドプロバイダーのストレージサービスを利用したPersistentVolume(PV)とPersistentVolumeClaim(PVC)の使用が推奨される。これにによって、Podがどのノードで起動しても一貫したストレージアクセスが可能になる。

hostPath 実環境での利用は、物理ハードウェアやUSB機器など、ホストにしか存在しない特殊デバイスとの連携 などにとどめることが推奨される。

2. PV/PVCを使ってみる。

NGINXが参照するファイルをWorker Pod上に直接配備する例では当然ながらスケールしない。Podを増やしていったとしても、すべてのPodが共通のコンテンツにアクセスできる(RWX = Read Write Many)よう、共通のディスク領域を用意する必要がある。
k8s ではこれを実現するためにPV(Persistent Volume)という仕組みが用意されている。

2-1. NFS を構築する

ストレージをどのように作るかの議論は非常に奥深いものがあるが、ここでは最も簡単なNFSを用いる手法を試す。

2-1-1. NFSの用意(サーバサイド)

今回のラボ構成ではk8s-master ノード上でNFSを動作させる。

# NFSインストールし、/srv/nfs/htdocを共有ディレクトリにする。
sudo apt update
sudo apt install -y nfs-kernel-server
sudo mkdir -p /srv/nfs/htdocs
sudo chmod -R 777 /srv/nfs/htdocs

# exports設定(例)
echo "/srv/nfs/htdocs *(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports
sudo exportfs -rav # /exc/exports の内容を再度読み込み
sudo systemctl restart nfs-server

2-1-1-1. Export 設定のオプション

オプション 2
rw 読み書きを許可(Read/Write)
sync 書き込み操作はすぐにディスクへ同期(安全だが遅くなる)
no_subtree_check サブディレクトリのチェックを行わない(高速化)
no_root_squash クライアント側の root ユーザを、そのままサーバ上でも root として扱う

no_root_squash
通常は安全性を考えてroot_squash(= root を nobody に変換)が推奨される。今回の NFS 検証ではアクセス権周りの問題回避のため no_root_squashを使用するとした。

2-1-2. NFSの用意(Workerノード側)

用意としてはNFS-commonをインストールするだけ。実際にどのNFS領域をマウントするかはk8s側から行うため、ノード側での永続マウントは不要

sudo apt update
sudo apt install -y nfs-common

2-2. k8s マニフェスト作成

2-2-1. そも、PV/PVC とは?

  • PV とは、k8s管理者やCSIドライバによってあらかじめ提供される ストレージリソース
  • PVC とは、ユーザ/Podからのストレージ要求

PV(実際に利用できるストレージ量)/PVC(クライアントが利用したい容量)を、k8sがバインドさせる。ユーザサイドでPVCを出すと、デフォルトではk8sが最適なPVを選んでくれる。しかし、PVが複数ある本番環境においては、事故防止のため明示的に紐づけを行うことが推奨される。この例では自動でマッチングする手法を採用。

2-2-2. PersistentVolume/PersistentVolumeClaim を作成

nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  nfs:
    path: /srv/nfs/htdocs
    server: <MASTER_NODE_IP>
  persistentVolumeReclaimPolicy: Retain
フィールド 意味
capacity.storage 確保したストレージサイズをk8sに宣言
accessModes ReadWriteMany は同一クラスタの複数Podからなら同時に読み書き可能
nfs.path / server 実際のNFSマウント先(K8sノードから見たパス)
persistentVolumeReclaimPolicy: Retain PVCが削除されても実体は保持(上書きや消去防止)

capacity.storage
この例では1Gi 確保したとしているが、実際にNFS側がこの容量に制限されるわけではない。あくまでも宣言。この辺りを厳密にやろうとすると、NFSでは無理が出てくる。

nfs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
フィールド 意味
accessModes ReadWriteMany を要求。PVと一致する必要あり
resources.requests.storage このPVCが最低限必要とする容量(例:1Gi)

2-2-3. サンプルスクリプト

touch /srv/nfs/htdocs/index.htmlでindex.htmlを空でよいので作成。

/srv/nfs/htdocs/start.sh
#!/bin/sh
HOSTNAME=$(hostname)
echo "<html><body><h1>Hello from $HOSTNAME</h1></body></html>" > /usr/share/nginx/html/index.html
nginx -g 'daemon off;'
chmod +x /srv/nfs/htdocs/start.sh

2-3. NGINXのデプロイ

nginx-nfs-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-nfs
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-nfs
  template:
    metadata:
      labels:
        app: nginx-nfs
    spec:
      securityContext:
        appArmorProfile:
          type: Unconfined    
      containers:
      - name: nginx
        image: nginx:stable
        command: ["/bin/sh", "-c", "/mnt/start.sh"]
        volumeMounts:
        - mountPath: /mnt
          name: nfs-volume
      volumes:
      - name: nfs-volume
        persistentVolumeClaim:
          claimName: nfs-pvc

特徴的なのが(当然だが)volumes.persistentVolumeClaimnfs-pvcを指定しているところ。

Excuse
spec.securityContext.appArmorProfile.type は正直なところおまじない。今回の検証ではAppArmorについてはデフォルトからは変更していないため、本来は不要のはず。ただ、ラボ環境のAppArmor周りがどこかおかしくなってしまった様子で、W/Aとして入れている。

nginx-nfs-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-nfs-service
spec:
  type: NodePort
  selector:
    app: nginx-nfs
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080

2-3-1. デプロイしてみる

kubectl apply -f nfs-pv.yaml
kubectl apply -f nfs-pvc.yaml
kubectl apply -f nginx-nfs-deployment.yaml
kubectl apply -f nginx-nfs-service.yaml

2-3-2. 正常性確認

ubuntu@k8s-master:~$ kubectl get pods
NAME                              READY   STATUS    RESTARTS   AGE
nginx-hostpath-7b4445db8d-bsz7l   1/1     Running   0          3h28m
nginx-nfs-77bbfbb487-mqwvq        1/1     Running   0          2m32s
nginx-nfs-77bbfbb487-wgmnk        1/1     Running   0          2m24s

nginx-nfs-***が running であること

ubuntu@k8s-master:~$ kubectl get pvc
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
nfs-pvc   Bound    nfs-pv   1Gi        RWX                           <unset>                 99m

PVC が Bound になっていること。

ubuntu@k8s-master:~$ curl http://192.168.11.122:30180
<html><body><h1>Hello from nginx-nfs-c8544878d-jnpwb</h1></body></html>
ubuntu@k8s-master:~$ curl http://192.168.11.122:30180
<html><body><h1>Hello from nginx-nfs-c8544878d-vm976</h1></body></html>
ubuntu@k8s-master:~$ curl http://192.168.11.122:30180
<html><body><h1>Hello from nginx-nfs-c8544878d-vm976</h1></body></html>
ubuntu@k8s-master:~$ curl http://192.168.11.122:30180
<html><body><h1>Hello from nginx-nfs-c8544878d-jnpwb</h1></body></html>

実際にアクセスして別々の Pod から応答が得られること。

2-4. PV/PVC の限界

PV/PVCの仕組みによって宣言的なリソース管理が可能になる。しかし、PVは実態としてのストレージデバイスごとの違い、またオンプレ、クラウドの違いもすべて手動で吸収する必要がある。CSIを導入することでこの辺りを抽象化、Storage Classとして共通な Interfaceを使用できるようになる。

3. CSI を使ってみる

3-1. CSIとStorageClass?

**CSI(Container Storage Interface)**は、Kubernetesが外部のストレージシステムと連携するための標準インターフェースのこと。k8s v1.13 から利用できるようになった。
CSIを利用することで、統一的な仕組みで Storage へアクセスできるようになった。ストレージベンダーから見ると、k8s のコアコードを変更することなく、自社のストレージをk8sに統合できるようになった。

CSIを利用することで、PVCの作成時に必要な Storageが自動的にプロビジョニングされるようになり、手動でのPV作成が不要になった。このほか、スナップショットなどの高度なStorage機能の利用、Security やAccess制御の高度化が可能になる。

StorageClassは、k8sで異なるストレージの Class を定義するリソースのこと。各StorageClassは、特定のCSIドライバー(provisioner)を指定し、そのドライバーに渡すパラメータを含められる。

この関係により、ユーザーはStorageClassを通じて、必要なストレージの種類や特性を抽象的に指定し、実際のストレージのプロビジョニングや管理はCSIドライバーが担う構造となっている。

この規模ではあまりメリットはないが、NFSをPVの代わりにCSI を利用して領域を割り当てることにする。

3-2. CSIドライバの導入

原本はこちら。Helm からのインストールが推奨のようだが、今回はkubectl ベースでのインストール(Helmは検証前...)

ubuntu@k8s-master:~$ curl -skSL https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/v4.11.0/deploy/install-driver.sh | bash -s v4.11.0 --
Installing NFS CSI driver, version: v4.11.0 ...
serviceaccount/csi-nfs-controller-sa created
serviceaccount/csi-nfs-node-sa created
clusterrole.rbac.authorization.k8s.io/nfs-external-provisioner-role created
clusterrolebinding.rbac.authorization.k8s.io/nfs-csi-provisioner-binding created
clusterrole.rbac.authorization.k8s.io/nfs-external-resizer-role created
clusterrolebinding.rbac.authorization.k8s.io/nfs-csi-resizer-role created
csidriver.storage.k8s.io/nfs.csi.k8s.io created
deployment.apps/csi-nfs-controller created
daemonset.apps/csi-nfs-node created
NFS CSI driver installed successfully.

3-2-1. 正常性確認

CSIドライバをインストールするとcsi-nfs-controller(NFS CSI ドライバのコントローラー側)とcsi-nfs-node(各ノードに1つずつ常駐するドライバ)がkube-systemにインストールされる。確認方法は以下。

ubuntu@k8s-master:~$ kubectl -n kube-system get pod
NAME                                      READY   STATUS    RESTARTS         AGE
(snip)
csi-nfs-controller-5bf646f7cc-f7nkp       5/5     Running   0                24m
csi-nfs-node-8gwp2                        3/3     Running   0                24m
csi-nfs-node-c8f2k                        3/3     Running   3 (17m ago)      24m
csi-nfs-node-mvrc9                        3/3     Running   0                24m
(snip)
ubuntu@k8s-master:~$ kubectl -n kube-system get pod -o wide -l app=csi-nfs-controller
NAME                                  READY   STATUS    RESTARTS   AGE   IP               NODE          NOMINATED NODE   READINESS GATES
csi-nfs-controller-5bf646f7cc-f7nkp   5/5     Running   0          19m   192.168.11.123   k8s-worker2   <none>           <none>
ubuntu@k8s-master:~$ 
ubuntu@k8s-master:~$ kubectl -n kube-system get pod -o wide -l app=csi-nfs-node
NAME                 READY   STATUS    RESTARTS      AGE   IP               NODE          NOMINATED NODE   READINESS GATES
csi-nfs-node-8gwp2   3/3     Running   0             20m   192.168.11.123   k8s-worker2   <none>           <none>
csi-nfs-node-c8f2k   3/3     Running   3 (19m ago)   20m   192.168.11.122   k8s-worker1   <none>           <none>
csi-nfs-node-mvrc9   3/3     Running   0             20m   192.168.11.121   k8s-master    <none>           <none>

3-2. NFSをCSIから使ってみる。

3-2-1. StorageClass

CSI を利用する場合、PVを定義せず、代わりに StorageClassを利用する。StorageClassを利用すればPVを個別に定義することなく、新しいPodが作られるたびに自動でStorageが作られていく。

nfs-sc.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-csi
provisioner: nfs.csi.k8s.io
parameters:
  server: 192.168.11.121
  share: /exported/path
reclaimPolicy: Retain
volumeBindingMode: Immediate
nfs-sc-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-dynamic-pvc
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: nfs-csi
  resources:
    requests:
      storage: 1Gi

nfs-pvc.yamlとの差分はstorageClassName: nfs-csiが追加されたことのみ。ストレージクラス名はnfs-sc.yamlで定義したものとそろえる

3-2-1. 正常性確認

kubectl get pvc で新しく定義したPVのStatusがBoundとなっていればOK

ubuntu@k8s-master:~$ kubectl get storageClass
NAME      PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-csi   nfs.csi.k8s.io   Retain          Immediate           false                  3s
ubuntu@k8s-master:~$ kubectl get pvc
NAME              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
nfs-dynamic-pvc   Bound    pvc-342392a4-28d7-4aa2-8d3f-56406398277b   1Gi        RWX            nfs-csi        <unset>                 7s

ここでpvc-342392a4-28d7-4aa2-8d3f-56406398277bができているが、NFSサーバ上に同名のディレクトリが作成されていることが確認できる。

ubuntu@k8s-master:~$ ls /srv/nfs/htdocs/
index.html  pvc-342392a4-28d7-4aa2-8d3f-56406398277b  start.sh

3-3. コンテンツの準備

前の正常性確認で、nfs-dynamic-pvcが/srv/nfs/htdocsの配下にpvc-342392a4-28d7-4aa2-8d3f-56406398277bが作られたことが確認できた。このディレクトリに先ほど作ったstart.shをコピーする。
NFS をexport する際、no_root_squashを指定して作成したため、PVCのアクセス権限はroot:root で作成されているのに注意。

ubuntu@k8s-master:/srv/nfs/htdocs$ pwd
/srv/nfs/htdocs
ubuntu@k8s-master:/srv/nfs/htdocs$ sudo cp ./index.html ./pvc-342392a4-28d7-4aa2-8d3f-56406398277b/
ubuntu@k8s-master:/srv/nfs/htdocs$ sudo cp ./start.sh ./pvc-342392a4-28d7-4aa2-8d3f-56406398277b/

3-4. Deployment と Service

差分が出てくるのはspec.template.spec.volumes.persistentVolumeClaim.claimNameがnfs-sc-pvc.yamlで指定したnfs-dynamic-pvcとなっている点。ほかはpodの名称を変更したのみ。

nginx-nfs-csi-service.yamlもnodePort の番号を少しずらした。

nginx-nfs-csi-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-nfs-csi
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-nfs-csi
  template:
    metadata:
      labels:
        app: nginx-nfs-csi
    spec:
      containers:
      - name: nginx
        image: nginx:stable
        command: ["/bin/sh", "-c", "/mnt/start.sh"]
        volumeMounts:
        - mountPath: /mnt
          name: nfs-volume
      volumes:
      - name: nfs-volume
        persistentVolumeClaim:
          claimName: nfs-dynamic-pvc
/nginx-nfs-csi-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-nfs-csi-service
spec:
  type: NodePort
  selector:
    app: nginx-nfs-csi
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30280

3-5. 適用と正常性確認

ubuntu@k8s-master:~$ kubectl apply -f ./nginx-nfs-csi-deployment.yaml
deployment/nginx-nfs-csi-deployment created
ubuntu@k8s-master:~$ kubectl apply -f ./nginx-nfs-csi-service.yaml
service/nginx-nfs-csi-service created

3-5-1. Service の確認

ubuntu@k8s-master:~$ kubectl get service
NAME                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes               ClusterIP   172.16.0.1       <none>        443/TCP        3d3h
(snip)
nginx-nfs-csi-service    NodePort    172.16.9.152     <none>        80:30280/TCP   4s

3-5-2. Pod の確認

ubuntu@k8s-master:~$ kubectl get pod
NAME                              READY   STATUS    RESTARTS       AGE
(snip
nginx-nfs-csi-6b564979c-ftw92     1/1     Running   0              12m
nginx-nfs-csi-6b564979c-n9ndv     1/1     Running   0              12m

3-5-3. NodePort での応答を確認する

正しく応答してくれる。

ubuntu@k8s-master:~$ curl http://192.168.11.122:30280
<html><body><h1>Hello from nginx-nfs-csi-6b564979c-ftw92</h1></body></html>
ubuntu@k8s-master:~$ curl http://192.168.11.122:30280
<html><body><h1>Hello from nginx-nfs-csi-6b564979c-n9ndv</h1></body></html>
ubuntu@k8s-master:~$ curl http://192.168.11.122:30280
<html><body><h1>Hello from nginx-nfs-csi-6b564979c-ftw92</h1></body></html>

3-6. NFSの限界

PVでspec.capacity.storageで用意するディスクサイズを、PVCでspec.resources.requests.storageで必要なディスクサイズを宣言している。では、宣言した量を超えてpodがデータを使うとなるとどうなるかというと、実は監視されておらず、k8sの範囲の中では利用できてしまう。実際に絞ろうとすると、xfs_quotaedquotaなどを使ってNFS側で頑張るしかない。この辺り、k8sの宣言型で進めるという理想と、実際のStorage 実装のはざまに落ちる。

k8s側からCSIを通じて容量管理をもくろんだ場合、CephFS などといった別のソリューションを探ることになる。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?