3.13. NFS を使用した永続ストレージ

OpenShift Container Platform クラスターは、NFS を使用する永続ストレージでプロビジョニングすることが可能です。永続ボリューム (PV) および Persistent Volume Claim (永続ボリューム要求、PVC) は、プロジェクト全体でボリュームを共有するための便利な方法を提供します。PV 定義に含まれる NFS に固有の情報は、Pod 定義で直接定義することも可能ですが、この方法の場合にはボリュームが一意のクラスターリソースとして作成されされないため、ボリュームが競合の影響を受けやすくなります。

3.13.1. プロビジョニング

ストレージは、ボリュームとして OpenShift Container Platform にマウントされる前に基礎となるインフラストラクチャーになければなりません。NFS ボリュームをプロビジョニングするには、NFS サーバーの一覧とエクスポートパスのみが必要です。

手順

  1. PV のオブジェクト定義を作成します。

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv0001 1
    spec:
      capacity:
        storage: 5Gi 2
      accessModes:
      - ReadWriteOnce 3
      nfs: 4
        path: /tmp 5
        server: 172.17.0.2 6
      persistentVolumeReclaimPolicy: Retain 7
    1
    ボリュームの名前。これは、各種の oc <command> pod コマンドの PV アイデンティティーです。
    2
    このボリュームに割り当てられるストレージの量。
    3
    これはボリュームへのアクセスの制御に関連するように見えますが、実際はラベルの場合と同様に、PVC を PV に一致させるために使用されます。現時点では、accessModes に基づくアクセスルールは適用されていません。
    4
    使用されているボリュームタイプ。 この場合は nfs プラグインです。
    5
    NFS サーバーがエクスポートしているパス。
    6
    NFS サーバーのホスト名または IP アドレス
    7
    PV の回収ポリシー。これはボリュームのリリース時に生じることを定義します。
    注記

    各 NFS ボリュームは、クラスター内のスケジュール可能なすべてのノードによってマウント可能でなければなりません。

  2. PV が作成されたことを確認します。

    $ oc get pv
    NAME     LABELS    CAPACITY     ACCESSMODES   STATUS      CLAIM  REASON    AGE
    pv0001   <none>    5Gi          RWO           Available                    31s
  3. 新規 PV にバインドされる Persistent Volume Claim (永続ボリューム要求、PVC) を作成します。

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: nfs-claim1
    spec:
      accessModes:
        - ReadWriteOnce 1
      resources:
        requests:
          storage: 5Gi 2
    1
    PV について前述されているように、accessModes はセキュリティーを実施するのではなく、PV を PVC と一致させるラベルとして機能します。
    2
    この要求は 5Gi 以上の容量を提供する PV を検索します。
  4. Persistent Volume Claim (永続ボリューム要求、PVC) が作成されたことを確認します。

    $ oc get pvc
    NAME         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    nfs-claim1   Bound    pv0001   5Gi        RWO            gp2            2m

3.13.2. ディスククォータの実施

ディスクパーティションを使用して、ディスククォータとサイズ制限を実施することができます。それぞれのパーティションを独自のエクスポートとすることができ、それぞれのエクスポートは 1 つの PV になります。それぞれのエクスポートは 1 つの PV になります。OpenShift Container Platform は PV に固有の名前を適用しますが、NFS ボリュームのサーバーとパスの一意性については管理者に委ねられています。

この方法でクォータを実施すると、開発者は永続ストレージを具体的な量 (10Gi など) で要求することができ、同等かそれ以上の容量の対応するボリュームに一致させることができます。

3.13.3. NFS ボリュームのセキュリティー

このセクションでは、一致するパーミッションや SELinux の考慮点を含む、NFS ボリュームのセキュリティーについて説明します。ユーザーは、POSIX パーミッションやプロセス UID、補助グループおよび SELinux の基礎的な点を理解している必要があります。

開発者は、Pod 定義の volumes セクションで、PVC を名前で参照するか、または NFS ボリュームのプラグインを直接参照して NFS ストレージを要求します。

NFS サーバーの /etc/exports ファイルにはアクセス可能な NFS ディレクトリーが含まれています。ターゲットの NFS ディレクトリーには、POSIX の所有者とグループ ID があります。OpenShift Container Platform NFS プラグインは、同じ POSIX の所有者とエクスポートされる NFS ディレクトリーにあるパーミッションを使って、コンテナーの NFS ディレクトリーをマウントします。ただし、コンテナーは NFS マウントの所有者と同等の有効な UID では実行されません。 これは期待される動作です。

ターゲットの NFS ディレクトリーが NFS サーバーに表示される場合を例に取って見てみましょう。

$ ls -lZ /opt/nfs -d
drwxrws---. nfsnobody 5555 unconfined_u:object_r:usr_t:s0   /opt/nfs

$ id nfsnobody
uid=65534(nfsnobody) gid=65534(nfsnobody) groups=65534(nfsnobody)

次に、コンテナーは SELinux ラベルに一致し、ディレクトリーにアクセスするために UID の 65534nfsnobody 所有者、または補助グループの 5555 のいずれかで実行される必要があります。

注記

所有者 ID 65534 は一例として使用されています。NFS の root_squashroot、uid 0nfsnobody、uid 65534 にマップしても、NFS エクスポートは任意の所有者 ID を持つことができます。所有者 65534 は NFS エクスポートには必要ありません。

3.13.3.1. グループ ID

NFS アクセスに対応する際の推奨される方法として、補助グループを使用することができます (NFS エクスポートのパーミッションを変更するオプションがないことを前提としています)。OpenShift Container Platform の補助グループは共有ストレージに使用されます (例: NFS)。これとは対照的に、iSCSI などのブロックストレージは、Pod の securityContextfsGroup SCC ストラテジーと fsGroup の値を使用します。

注記

永続ストレージへのアクセスを取得するには、通常はユーザー ID ではなく、補助グループ ID を使用することが推奨されます。

ターゲット NFS ディレクトリーの例で使用したグループ ID は 5555 なので、Pod は、supplementalGroups を使用してグループ ID を Pod の securityContext 定義の下で定義することができます。以下は例になります。

spec:
  containers:
    - name:
    ...
  securityContext: 1
    supplementalGroups: [5555] 2
1
securityContext は特定のコンテナーの下ではなく、この Pod レベルで定義される必要があります。
2
Pod 向けに定義される GID の配列。この場合、配列には 1 つの要素があります。追加の GID はカンマで区切られます。

Pod の要件を満たすカスタム SCC が存在しない場合、Pod は restricted SCC に一致する可能性があります。この SCC では、supplementalGroups ストラテジーが RunAsAny に設定されています。 これは、指定されるグループ ID は範囲のチェックなしに受け入れられることを意味します。

その結果、上記の Pod は受付をパスして起動します。しかし、グループ ID の範囲をチェックすることが望ましい場合は、カスタム SCC の使用が推奨されます。カスタム SCC は、最小および最大のグループ ID が定義され、グループ ID の範囲チェックが実施され、グループ IDの 5555 が許可されるように作成できます。

注記

カスタム SCC を使用するには、まずこれを適切なサービスアカウントに追加する必要があります。たとえば、Pod 仕様に指定がない場合には、指定されたプロジェクトで default サービスアカウントを使用します。

3.13.3.2. ユーザー ID

ユーザー ID は、コンテナーイメージまたは Pod 定義で定義することができます。

注記

永続ストレージへのアクセスを取得する場合、通常はユーザー ID ではなく、補助グループ ID を使用することが推奨されます。

上記のターゲット NFS ディレクトリーの例では、コンテナーは UID を 65534 (ここではグループ ID を省略します) に設定する必要があります。 したがって以下を Pod 定義に追加することができます。

spec:
  containers: 1
  - name:
  ...
    securityContext:
      runAsUser: 65534 2
1
Pod には、各コンテナーに固有の securityContext と、その Pod で定義されたすべてのコンテナーに適用される Pod の securityContext が含まれます。
2
65534nfsnobody ユーザーです。

default プロジェクトと restricted SCC を前提とする場合は、Pod が要求するユーザー ID 65534 は許可されず、Pod は失敗します。Pod が失敗する理由は以下の通りです。

  • 65534 をそのユーザー ID として要求する。
  • ユーザー ID 65534 を許可する SCC を確認するために Pod で利用できるすべての SCC が検査される。SCC のすべてのポリシーがチェックされますが、ここでのフォーカスはユーザー ID になります。
  • 使用可能なすべての SCC が独自の runAsUser ストラテジーとして MustRunAsRange を使用しているため、UID の範囲チェックが要求される。
  • 65534 は SCC またはプロジェクトのユーザー ID 範囲に含まれていない。

一般に、事前定義された SCC は変更しないことが勧められています。ただし、この状況を改善するには、カスタム SCC を作成することが推奨されます。 カスタム SCC は、最小および最大のユーザー ID が定義され、UID 範囲のチェックの実施が設定されており、UID 65534 が許可されるように作成できます。

注記

カスタム SCC を使用するには、まずこれを適切なサービスアカウントに追加する必要があります。たとえば、Pod 仕様に指定がない場合には、指定されたプロジェクトで default サービスアカウントを使用します。

3.13.3.3. SELinux

デフォルトでは、SELinux は Pod からリモートの NFS サーバーへの書き込みを許可していません。NFS ボリュームは正常にマウントされますが、読み取り専用です。

リモート NFS サーバーへの書き込みを有効にするには、以下の手順に従ってください。

前提条件

  • container-selinux パッケージがインストールされている必要があります。このパッケージは virt_use_nfs SELinux ブール値を提供します。

手順

  • 以下のコマンドを使用して virt_use_nfs ブール値を有効にします。-P オプションを使用すると、再起動後もこのブール値を永続化できます。

    # setsebool -P virt_use_nfs 1

3.13.3.4. エクスポート設定

任意のコンテナーユーザーにボリュームの読み取りと書き出しを許可するには、NFS サーバーにエクスポートされる各ボリュームは以下の条件を満たしている必要があります。

  • すべてのエクスポートは、次の形式を使用してエクスポートする必要があります。

    /<example_fs> *(rw,root_squash)
  • ファイアウォールは、マウントポイントへのトラフィックを許可するように設定する必要があります。

    • NFSv4 の場合、デフォルトのポート 2049 (nfs) を設定します。

      NFSv4

      # iptables -I INPUT 1 -p tcp --dport 2049 -j ACCEPT

    • NFSv3 の場合、以下の 3 つのポートを設定します。2049 (nfs)、20048 (mountd)、111 (portmapper)。

      NFSv3

      # iptables -I INPUT 1 -p tcp --dport 2049 -j ACCEPT
      # iptables -I INPUT 1 -p tcp --dport 20048 -j ACCEPT
      # iptables -I INPUT 1 -p tcp --dport 111 -j ACCEPT

  • NFS エクスポートとディレクトリーは、ターゲット Pod からアクセスできるようにセットアップされる必要があります。この場合、エクスポートをコンテナーのプライマリー UID で所有されるように設定するか、または上記のグループ ID に示されるように supplementalGroups を使用して Pod にグループアクセスを付与します。

3.13.4. リソースの回収

NFS は OpenShift Container Platform の Recyclable プラグインインターフェースを実装します。回収タスクは、それぞれの永続ボリュームに設定されるポリシーに基づいて自動プロセスによって処理されます。

デフォルトで、PV は Retain に設定されます。

PV への要求が削除され、PV がリリースされると、PV オブジェクトを再利用できません。代わりに、新規の PV が元のボリュームと同じ基本ボリュームの情報を使って作成されます。

たとえば、管理者は nfs1 という名前の PV を作成するとします。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs1
spec:
  capacity:
    storage: 1Mi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 192.168.1.1
    path: "/"

ユーザーは、nfs1 にバインドされる PVC1 を作成します。次にユーザーは PVC1 を削除し、nfs1 への要求を解除します。これにより、nfs1Released になります。管理者が同じ NFS 共有を利用可能にする必要がある場合には、同じ NFS サーバー情報を使って新規 PV を作成する必要があります。 この場合、PV の名前は元の名前とは異なる名前にします。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs2
spec:
  capacity:
    storage: 1Mi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 192.168.1.1
    path: "/"

元の PV を削除して、PV を同じ名前で再作成することは推奨されません。PV のステータスを Released から Available に手動で変更しようとすると、エラーが発生し、データが失われる可能性があります。

3.13.5. その他の設定とトラブルシューティング

適切なエクスポートとセキュリティーマッピングを行うため、使用している NFS のバージョンおよびその設定方法に応じて追加の設定が必要になることがあります。以下は例になります。

NFSv4 のマウントにすべてのファイルの所有者が nobody:nobody と誤って表示される。

NFSv4 の ID マッピングが無効になっている

  • NFS クライアントとサーバーの両方で以下を実行してください。

    # echo 'Y' > /sys/module/nfsd/parameters/nfs4_disable_idmapping