エラーメッセージこれはよくある悩みの一つです。ステートフルなアプリケーションをデプロイしたものの、PersistentVolumeClaim(PVC)が Pending 状態から一向に動かないことがあります。kubectl describe pvc <pvc-name> を使って詳細を調査すると、次のような壁に突き当たります。
persistentvolumeclaims "my-pvc" is forbidden: no persistent volumes available for this claim and no storage class is set
何が起きているのか?Kubernetesは本質的に、データの保存先をどこに用意すればよいのか分からないと伝えています。PVCを、劇場の座席のチケットだと考えてみてください。劇場側が座席をまだ作っておらず(静的プロビジョニング)、かつ座席を自動で作ってくれる機械もない(動的プロビジョニング)場合、あなたはロビーで立ち尽くすことになります。
このエラーは通常、次の3つの理由で発生します:
- デフォルト設定の欠如: クラスターに「デフォルト(Default)」の StorageClass が指定されていません。- マニフェストの空欄: PVCのYAMLで
storageClassNameが指定されていないため、Kubernetesが判断を保留しています。- 手動設定の不一致: PersistentVolume(PV)を手動で作成したが、そのサイズ(例:5Gi)や AccessMode が、PVCが要求しているもの(例:10Gi)と一致していません。## 解決策1:デフォルトの StorageClass を割り当てるAWS EKS や Google GKE などのマネージドサービスの多くはストレージドライバーがプリインストールされていますが、それらがデフォルトとして設定されていない場合があります。特定のクラスをデフォルトとしてマークすることで、タイプを指定していないPVCは自動的にそのクラスを使用するようになります。 まず、利用可能なクラスを一覧表示します:
kubectl get storageclass
もし gp2 (AWS) や standard (GKE) のようなクラスが表示されているのに、(default) と表示されていない場合は、次のコマンドを実行して修正します:
kubectl patch storageclass gp2 -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
パッチを適用したら、止まっていたPVCを削除して再作成してください。ほぼ瞬時にバインド(Bind)されるはずです。
解決策2:storageClassName を明示的に定義するグローバルなデフォルト設定を望まない場合もあります。例えば、データベースには高性能なSSDが必要だが、ログの保存には安価なHDDストレージを使いたいといったケースです。この場合、PVCに対してどの「テンプレート」を使用するかを正確に伝える必要があります。
pvc.yaml を更新して、storageClassName フィールドを含めます:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: database-storage
spec:
accessModes:
- ReadWriteOnce
storageClassName: premium-r3 # ここに特定のクラス名を指定します
resources:
requests:
storage: 20Gi
更新を適用します。Kubernetesは指定された CSI ドライバー(EBS や Azure Disk ドライバーなど)にアクセスし、その 20Gi のボリュームをプロビジョニングします。
解決策3:ベアメタル環境での手動プロビジョニングホームラボや、クラウドプロバイダーを利用しないベアメタル・クラスターを実行している場合、動的プロビジョニングは標準では利用できません。あなた自身が「ストレージ作成機」になる必要があります。
PVCの要求事項に一致する手動の PersistentVolume を作成します:
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv-01
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
hostPath:
path: "/mnt/data/mysql"
プロのヒント: PVCがこの手動ボリュームを要求できるように、PVC内の storageClassName を空("")にするか、PVに付けたクラス名と一致させてください。
修正の確認いずれかの修正を適用した後、PVCの状態を再度確認します:
kubectl get pvc
Bound ステータスになっていれば成功です。以下のようになります:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
database-storage Bound pvc-8a7b6c... 20Gi RWO premium-r3 15s
ステータスが Bound になれば、Podはついに ContainerCreating から Running へと移行します。

