3.11. NFS를 사용하는 영구저장장치

OpenShift Container Platform 클러스터는 NFS를 사용하는 영구 스토리지와 함께 프로비저닝될 수 있습니다. PV(영구 볼륨) 및 PVC(영구 볼륨 클레임)는 프로젝트 전체에서 볼륨을 공유하는 편리한 방법을 제공합니다. PV 정의에 포함된 NFS 관련 정보는 Pod 정의에서 직접 정의될 수 있지만, 이렇게 하면 볼륨이 별도의 클러스터 리소스로 생성되지 않아 볼륨에서 충돌이 발생할 수 있습니다.

3.11.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 ID입니다.
    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에 바인딩하는 영구 볼륨 클레임을 생성합니다.

    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. 영구 볼륨 클레임이 생성되었는지 확인합니다.

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

3.11.2. 디스크 할당량 강제 적용

디스크 파티션을 사용하여 디스크 할당량 및 크기 제약 조건을 적용할 수 있습니다. 각 파티션은 자체 내보내기일 수 있습니다. 각 내보내기는 1개의 PV입니다. OpenShift Container Platform은 PV에 고유한 이름을 적용하지만 NFS 볼륨 서버와 경로의 고유성은 관리자에 따라 다릅니다.

이렇게 하면 개발자가 10Gi와 같은 특정 용량에 의해 영구 스토리지를 요청하고 해당 볼륨과 동등한 용량과 일치시킬 수 있습니다.

3.11.3. NFS 볼륨 보안

이 섹션에서는 일치하는 권한 및 SELinux 고려 사항을 포함하여 NFS 볼륨 보안에 대해 설명합니다. 사용자는 POSIX 권한, 프로세스 UID, 추가 그룹 및 SELinux의 기본 사항을 이해하고 있어야 합니다.

개발자는 Pod 정의의 볼륨 섹션에서 직접 PVC 또는 NFS 볼륨 플러그인을 참조하여 NFS 스토리지를 요청합니다.

NFS 서버의 /etc/exports 파일에 액세스할 수 있는 NFS 디렉터리가 있습니다. 대상 NFS 디렉터리에는 POSIX 소유자 및 그룹 ID가 있습니다. OpenShift Container Platform NFS 플러그인은 내보낸 NFS 디렉터리에 있는 동일한 POSIX 소유권 및 권한과 함께 컨테이너의 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 레이블과 일치하고 65534, nfsnobody 소유자 또는 디렉터리에 액세스하려면 추가 그룹의 5555와 함께 실행해야 합니다.

참고

65534의 소유자 ID는 예시와 같이 사용됩니다. NFS의 root_squash는 UID가 0루트를 UID가 65534nfsnobody로 매핑하지만, NFS 내보내기에는 임의의 소유자 ID가 있을 수 있습니다. NFS를 내보내려면 소유자 65534가 필요하지 않습니다.

3.11.3.1. 그룹 ID

NFS 내보내기 권한 변경 옵션이 아닐 경우 NFS 액세스를 처리하는 권장 방법은 추가 그룹을 사용하는 것입니다. OpenShift Container Platform의 추가 그룹은 공유 스토리지에 사용되며 NFS가 그 예입니다. 반면 iSCSI와 같은 블록 스토리지는 Pod의 securityContext에 있는 fsGroup SCC 전략과 fsGroup 값을 사용합니다.

참고

영구 스토리지에 액세스하려면, 일반적으로 추가 그룹 ID vs 사용자 ID를 사용하는 것이 좋습니다.

예시의 대상 NFS 디렉터리의 그룹 ID가 5555이므로 Pod는 Pod의 securityContext 정의에서 supplementalGroups를 사용하여 해당 그룹 ID를 정의할 수 있습니다. 예를 들면 다음과 같습니다.

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 범위 확인이 적용되며, 5555 그룹 ID가 허용될 수 있습니다.

참고

사용자 정의 SCC를 사용하려면 먼저 적절한 서비스 계정에 추가해야 합니다. 예를 들어, Pod 사양에 다른 값이 지정된 경우를 제외하고 지정된 프로젝트에서 기본 서비스 계정을 사용하십시오.

3.11.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이고 SCC가 restricted라고 가정하면 Pod에서 요청한 대로 65534의 사용자 ID가 허용되지 않습니다. 따라서 Pod가 다음과 같은 이유로 실패합니다.

  • 65534가 사용자 ID로 요청되었습니다.
  • Pod에서 사용 가능한 모든 SCC를 검사하여 어떤 SCC에서 65534의 사용자 ID가 허용되는지 확인합니다. SCC의 모든 정책을 확인하는 동안 여기에는 중요한 사항은 사용자 ID입니다.
  • 사용 가능한 모든 SCC는 runAsUser 전략에서 MustRunAsRange를 사용하므로 UID 범위 검사가 필요합니다.
  • 65534는 SCC 또는 프로젝트의 사용자 ID 범위에 포함되어 있지 않습니다.

일반적으로 사전 정의된 SCC를 수정하지 않는 것이 좋습니다. 이 상황을 해결하기 위해 선호되는 방법은 사용자 정의 SCC를 생성하는 것입니다. 따라서 최소 및 최대 사용자 ID가 정의되고 UID 범위 검사가 여전히 적용되며, 65534의 UID가 허용됩니다.

참고

사용자 정의 SCC를 사용하려면 먼저 적절한 서비스 계정에 추가해야 합니다. 예를 들어, Pod 사양에 다른 값이 지정된 경우를 제외하고 지정된 프로젝트에서 기본 서비스 계정을 사용하십시오.

3.11.3.3. SELinux

RHEL(Red Hat Enterprise Linux) 및 RHCOS(Red Hat Enterprise Linux CoreOS) 시스템은 기본적으로 원격 NFS 서버에서 SELinux를 사용하도록 구성됩니다.

RHEL 이외 및 비RHCOS 시스템의 경우 SELinux는 Pod에서 원격 NFS 서버로 쓰기를 허용하지 않습니다. NFS 볼륨이 올바르게 마운트되지만 읽기 전용입니다. 다음 절차에 따라 올바른 SELinux 권한을 활성화해야 합니다.

사전 요구 사항

  • container-selinux 패키지가 설치되어 있어야 합니다. 이 패키지는 virt_use_nfs SELinux 부울을 제공합니다.

절차

  • 다음 명령을 사용하여 virt_use_nfs 부울을 활성화합니다. -P 옵션을 사용하면 재부팅할 때 이 부울을 지속적으로 사용할 수 있습니다.

    # setsebool -P virt_use_nfs 1

3.11.3.4. 내보내기 설정

컨테이너 사용자가 볼륨을 읽고 쓸 수 있도록 하려면 NFS 서버의 내보낸 각 볼륨은 다음 조건을 준수해야 합니다.

  • 모든 내보내는 다음 형식을 사용하여 내보내야 합니다.

    /<example_fs> *(rw,root_squash)
  • 마운트 옵션으로 트래픽을 허용하도록 방화벽을 구성해야 합니다.

    • NFSv4의 경우 기본 포트 2049(nfs)를 구성합니다.

      NFSv4

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

    • NFSv3의 경우 2049(nfs), 20048(mountd) 및 111(portmapper)의 포트 3개가 있습니다.

      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
  • 대상 Pod에서 액세스할 수 있도록 NFS 내보내기 및 디렉터리를 설정해야 합니다. 컨테이너의 기본 UID에 표시된 대로 내보내기를 컨테이너의 기본 UID로 설정하거나 위 그룹 ID에 표시된 대로 supplementalGroups를 사용하여 Pod 그룹 액세스 권한을 제공합니다.

3.11.4. 리소스 회수

NFS는 OpenShift Container Platform Recyclable 플러그인 인터페이스를 구현합니다. 자동 프로세스는 각 영구 볼륨에 설정된 정책에 따라 복구 작업을 처리합니다.

기본적으로 PV는 Retain으로 설정됩니다.

PVC에 대한 클레임이 삭제되고 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: "/"

사용자가 PVC1을 생성하여 nfs1에 바인딩합니다. 그리고 사용자가 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를 삭제하고 동일한 이름으로 다시 생성하는 것은 권장되지 않습니다. Released에서 Available로 PV의 상태를 수동으로 변경하면 오류가 발생하거나 데이터가 손실될 수 있습니다.

3.11.5. 추가 구성 및 문제 해결

사용되는 NFS 버전과 구성 방법에 따라 적절한 내보내기 및 보안 매핑에 필요한 추가 구성 단계가 있을 수 있습니다. 다음은 적용되는 몇 가지입니다.

NFSv4 마운트에서 소유권이 nobody:nobody인 모든 파일이 올바르게 표시되지 않습니다.

  • 이는 NFS의 /etc/idmapd.conf에 있는 ID 매핑 설정으로 인한 것일 수 있습니다.
  • 이 Red Hat 해결책을 참조하십시오.

NFSv4에서 ID 매핑 비활성화

  • NFS 클라이언트 및 서버 모두에서 다음을 실행합니다.

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