원시 블록 및 임시 스토리지에 혼합 로컬 SSD 프로비저닝 및 사용

이 문서에서는 동일한 노드에서 표준 임시 스토리지 파일 시스템과 포맷되지 않은 원시 블록 스토리지가 모두 필요한 워크로드를 지원하기 위해 Google Kubernetes Engine (GKE)에서 로컬 SSD를 프로비저닝하고 파티션을 나누는 방법을 보여줍니다.

스테이트풀(Stateful) 애플리케이션과 고도로 최적화된 데이터베이스에 이 구성을 사용합니다. 이러한 워크로드는 성능 향상을 위해 직접 디스크 액세스가 필요한 경우가 많지만 사이드카, 로그 또는 컨테이너 캐시를 위한 표준 임시 파일 스토리지도 필요합니다. 혼합 로컬 SSD 용량을 사용하면 별도의 노드나 전체 디스크를 원시 블록 인프라에만 전용으로 할당할 필요가 없으므로 클러스터 관리 오버헤드를 줄이고 하드웨어 사용률을 극대화할 수 있습니다.

혼합 로컬 SSD 용량으로 클러스터 또는 노드 풀을 만들면 GKE는 물리적으로 연결된 모든 로컬 SSD를 다음과 같이 파티셔닝합니다.

  • 임시 스토리지: 요청된 임시 용량은 로컬 SSD에 균등하게 분할되고 결합되어 노드의 표준 임시 파일 스토리지를 제공합니다. 임시 용량이 여러 로컬 SSD에 파티션으로 나뉘면 스토리지가 RAID-0 배열로 결합됩니다. 표준 emptyDir 볼륨을 사용하여 임시 스토리지에 액세스할 수 있습니다.
  • 원시 블록 스토리지: 각 디스크의 나머지 물리적 용량은 포맷되지 않은 별도의 원시 블록 기기로 노드에 표시됩니다.

이 문서는 특수 워크로드를 위해 GKE에서 하드웨어 사용률과 스토리지 성능을 최적화하려는 플랫폼 관리자, 운영자, DevOps를 대상으로 합니다.

고려사항

Compute Engine 로컬 SSD 제한사항 외에도 혼합 로컬 SSD 모드를 구성하기 전에 다음 GKE 관련 고려사항을 검토하세요.

  • Autopilot 호환성: GKE Autopilot 클러스터는 혼합된 원시 블록 및 임시 스토리지를 지원하지 않습니다. Autopilot에서 표준 임시 스토리지에 로컬 SSD를 사용하는 방법은 Autopilot 클러스터의 로컬 SSD를 참조하세요.
  • 커스텀 ComputeClass: 커스텀 ComputeClass는 혼합 로컬 SSD 구성을 지원하지 않습니다.
  • 운영체제: 혼합 로컬 SSD 모드는 Linux 노드 이미지 (Container-Optimized OS 및 Ubuntu)에서만 지원됩니다. Windows Server 노드 풀은 지원되지 않습니다.
  • 유지보수 이벤트: 스토리지 최적화 Z3 또는 Z4D VM의 원시 블록 스토리지로 로컬 SSD를 사용하지 않는 것이 좋습니다. 이러한 VM의 데이터는 유지보수 이벤트 중에 유지되지 않을 수 있습니다. 자세한 내용은 로컬 SSD 지원 원시 블록 스토리지 프로비저닝 및 사용을 참조하세요.
  • 공유 I/O: 임시 RAID-0 배열과 타겟팅된 원시 블록 파티션이 모두 동일한 기본 물리적 SSD를 사용하므로 한 논리 파티션에서 집약적인 작업을 수행하면 다른 파티션의 처리량에 영향을 미칠 수 있습니다. 최대 처리량 한도에 대한 자세한 내용은 로컬 SSD 성능을 참조하세요.
  • 가격 책정: 혼합 모드를 사용하여 로컬 SSD 용량을 파티셔닝하는 경우 원시 블록 스토리지와 비교하여 임시 스토리지에 할당된 용량과 관계없이 노드에 연결된 총 기본 물리적 로컬 SSD 용량에 대한 요금을 지불합니다. 자세한 내용은 로컬 SSD 가격 책정을 참조하세요.
  • 수동 구성: 로컬 SSD 지원 원시 블록 스토리지를 사용하려면 GKE가 원시 블록 파티션을 포맷하거나 마운트하지 않으므로 기기를 수동으로 구성해야 합니다. 또한 노드 용량을 관리하고 공동 배치 워크로드의 잠재적인 중단을 처리해야 합니다. 로컬 PersistentVolume 객체를 사용하면 통합 포드 예약이 제공됩니다. 워크로드에 포드 수명 주기 동안 데이터를 유지할 필요가 없거나 특별한 성능 요구사항이 없는 경우 대신 완전한 임시 로컬 SSD 구성을 사용하세요. 완전한 임시 구성은 대부분의 사용 사례에 적합합니다.
  • 노드 메모리 스왑: 부팅 디스크 프로필 또는 임시 로컬 SSD 프로필을 사용하여 혼합된 로컬 SSD 용량을 노드 메모리 스왑과 결합할 수 있습니다. 전용 로컬 SSD 프로필은 혼합 로컬 SSD 용량에서 지원되지 않습니다. 자세한 내용은 로컬 SSD 용량이 혼합된 노드 메모리 스왑을 참조하세요.

시작하기 전에

시작하기 전에 다음 태스크를 수행했는지 확인합니다.

  • Google Kubernetes Engine API를 사용 설정합니다.
  • Google Kubernetes Engine API 사용 설정
  • 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화합니다. 이전에 gcloud CLI를 설치했으면 gcloud components update 명령어를 실행하여 최신 버전을 가져옵니다. 이전 gcloud CLI 버전에서는 이 문서의 명령어를 실행하지 못할 수 있습니다.

이 기능을 사용하려면 GKE 노드에서 버전 1.37.0-gke.3570000 이상을 실행해야 합니다.

필요한 역할

혼합 로컬 SSD 용량으로 클러스터 및 노드 풀을 만드는 데 필요한 권한을 얻으려면 관리자에게 프로젝트에 대한 Kubernetes Engine 관리자 (roles/container.admin) IAM 역할을 부여해 달라고 요청하세요. 역할 부여에 대한 자세한 내용은 프로젝트, 폴더, 조직에 대한 액세스 관리를 참조하세요.

커스텀 역할이나 다른 사전 정의된 역할을 통해 필요한 권한을 얻을 수도 있습니다.

혼합 로컬 SSD 스토리지가 있는 클러스터 또는 노드 풀 만들기

--ephemeral-storage-local-ssd 플래그의 capacity 속성을 사용하여 임시 용량을 할당하고 원시 블록 파티션을 예약할 수 있습니다.

--ephemeral-storage-local-ssd 플래그를 사용하여 capacity 하위 필드를 지정하여 클러스터 또는 노드 풀을 만듭니다.

머신 유형에서 구성 가능한 수의 로컬 SSD를 허용하는 경우 count 하위 필드도 지정해야 합니다. 머신 유형에 로컬 SSD 수가 고정되어 있는 경우(예: -lssd 유형) GKE가 VM 형태에 따라 디스크 수를 자동으로 계산하므로 count 하위 필드를 생략할 수 있습니다.

혼합 로컬 SSD 스토리지를 사용하는 클러스터 만들기

새 클러스터를 만들려면 gcloud container clusters create 명령어를 사용합니다. 이 설정은 기본 노드 풀에만 적용됩니다. 후속 노드 풀에 혼합 로컬 SSD 스토리지가 필요한 경우 노드 풀을 만들 때 --ephemeral-storage-local-ssd 플래그를 지정합니다. 연결할 수 있는 최대 디스크 수는 머신 유형 및 리전에 따라 달라집니다.

클러스터 버전이 1.37.0-gke.3570000 이전인 경우 다음 클러스터 생성 명령어에 다음 플래그 중 하나를 추가합니다.

  • 1.37.0-gke.3570000 이상으로 설정된 <var>VERSION</var>가 있는 --cluster-version=<var>VERSION</var> 플래그
  • --release-channel=rapid 플래그

구성 가능한 로컬 SSD 수가 있는 머신 유형의 경우 다음을 실행합니다.

gcloud container clusters create CLUSTER_NAME \
    --machine-type=MACHINE_TYPE \
    --ephemeral-storage-local-ssd count=NUMBER_OF_DISKS,capacity=CAPACITY

로컬 SSD 수가 고정된 머신 유형의 경우 다음을 실행합니다.

gcloud container clusters create CLUSTER_NAME \
    --machine-type=MACHINE_TYPE \
    --ephemeral-storage-local-ssd capacity=CAPACITY

다음을 바꿉니다.

  • CLUSTER_NAME: 만들려는 클러스터의 이름입니다.
  • MACHINE_TYPE: 사용할 머신 유형입니다. 지원되는 머신 유형 목록은 머신 시리즈 지원을 참조하세요. 공유 코어 머신 유형은 로컬 SSD를 지원하지 않으므로 기본 e2-medium 머신 유형으로 로컬 SSD를 사용할 수 없습니다.
  • NUMBER_OF_DISKS: 구성 가능한 로컬 SSD 수가 있는 머신 유형의 경우 각 노드에서 프로비저닝할 로컬 SSD 디스크 수입니다.
  • CAPACITY: 임시 스토리지에 포맷할 총 로컬 SSD 용량입니다. 이 값은 0보다 크고 총 실제 로컬 SSD 용량(디스크 수 × 디스크당 크기)보다 작아야 합니다(예: 200GB). 다음에 유의하세요.

    • 클러스터를 만든 후에는 값을 변경할 수 없습니다.
    • GKE는 이 용량의 일부를 시스템용으로 예약하므로 할당 가능한 임시 스토리지는 CAPACITY 미만입니다. 자세한 내용은 로컬 임시 스토리지 예약을 참조하세요.

혼합 로컬 SSD 스토리지를 사용하여 노드 풀 만들기

기존 클러스터에 노드 풀을 추가하려면 gcloud container node-pools create 명령어를 사용합니다.

노드 풀 버전이 1.37.0-gke.3570000 이전인 경우 다음을 수행해야 합니다.

  • <var>VERSION</var>를 1.37.0-gke.3570000 이상으로 설정하여 다음 노드 풀 생성 명령어에 --node-version=<var>VERSION</var> 플래그를 추가합니다.
  • 클러스터 컨트롤 플레인이 버전 1.37.0-gke.3570000 이상인지 확인합니다.

구성 가능한 로컬 SSD 수가 있는 머신 유형의 경우 다음을 실행합니다.

gcloud container node-pools create POOL_NAME \
    --cluster=CLUSTER_NAME \
    --machine-type=MACHINE_TYPE \
    --ephemeral-storage-local-ssd count=NUMBER_OF_DISKS,capacity=CAPACITY

로컬 SSD 수가 고정된 머신 유형의 경우 다음을 실행합니다.

gcloud container node-pools create POOL_NAME \
    --cluster=CLUSTER_NAME \
    --machine-type=MACHINE_TYPE \
    --ephemeral-storage-local-ssd capacity=CAPACITY

다음을 바꿉니다.

  • POOL_NAME: 만들려는 새 노드 풀의 이름입니다.
  • CLUSTER_NAME: 클러스터의 이름입니다.
  • MACHINE_TYPE: 사용할 머신 유형입니다. 지원되는 머신 유형 목록은 머신 시리즈 지원을 참조하세요. 공유 코어 머신 유형은 로컬 SSD를 지원하지 않으므로 기본 e2-medium 머신 유형으로 로컬 SSD를 사용할 수 없습니다.
  • NUMBER_OF_DISKS: 구성 가능한 로컬 SSD 수가 있는 머신 유형의 경우 각 노드에서 프로비저닝할 로컬 SSD 디스크 수입니다.
  • CAPACITY: 임시 스토리지에 포맷할 총 로컬 SSD 용량입니다. 이 값은 0보다 크고 총 실제 로컬 SSD 용량(디스크 수 × 디스크당 크기)보다 작아야 합니다(예: 200GB). 다음에 유의하세요.

    • 노드 풀이 생성된 후에는 값을 변경할 수 없습니다.
    • GKE는 이 용량의 일부를 시스템용으로 예약하므로 할당 가능한 임시 스토리지는 CAPACITY 미만입니다. 자세한 내용은 로컬 임시 스토리지 예약을 참조하세요.

노드 라벨 확인

프로비저닝 후 노드에 임시 및 원시 블록 스토리지 모두에 대한 올바른 라벨이 있는지 확인하려면 다음 명령어를 실행합니다.

kubectl describe node NODE_NAME

출력에는 다음 노드 라벨이 모두 포함되어야 합니다.

  • cloud.google.com/gke-ephemeral-storage-local-ssd: "true"
  • cloud.google.com/gke-local-nvme-ssd-partition: "true"

임시 용량에 액세스

다른 GKE 임시 볼륨과 마찬가지로 emptyDir 볼륨을 통해 예약된 임시 스토리지에 액세스합니다.

원시 블록 용량에 액세스

원시 블록 용량에 액세스하려면 StorageClass 객체를 만들고 로컬 PersistentVolume 객체를 프로비저닝하고 PersistentVolumeClaim 객체를 사용하여 이를 요청합니다.

StorageClass 만들기

커뮤니티 정적 프로비저닝 도구 없이 PersistentVolume 객체를 프로비저닝하므로 volumeBindingMode: WaitForFirstConsumer 필드를 사용하여 StorageClass 객체를 만드는 것이 좋습니다. 이렇게 하면 포드 예약까지 바인딩이 지연되어 Kubernetes가 포드를 실행할 수 있는 적절한 노드에서 로컬 SSD를 선택합니다.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: "local-storage"
provisioner: "kubernetes.io/no-provisioner"
volumeBindingMode: "WaitForFirstConsumer"

PersistentVolume 만들기

로컬 PersistentVolume 객체에는 노드 업그레이드, 확장, 클러스터 자동 확장과 관련된 중요한 제한사항이 있습니다. 볼륨을 만들기 전에 로컬 PersistentVolume 제한사항을 검토하여 수명 주기 이벤트가 데이터에 미치는 영향을 파악하세요.

PersistentVolume 객체를 만들려면 다음 단계를 완료하여 로컬 SSD 파티션에 대한 심볼릭 링크 경로를 찾고, 정확한 잔여 용량을 확인하고, 매니페스트를 구성합니다.

파티션 용량 찾기

대상 노드에서 다음 명령어를 실행하여 파티션에 남은 정확한 원시 블록 용량을 찾습니다.

kubectl debug node/NODE_NAME -it --image=ubuntu -- \
    sh -c 'ls -l /host/dev/disk/by-id/ | grep partition; lsblk -o NAME,SIZE,TYPE'

NODE_NAME을 로컬 SSD가 연결된 노드의 이름으로 바꿉니다.

출력에는 기기 이름과 파티션 심볼릭 링크 간의 매핑이 표시되므로 어떤 파티션이 어떤 기기에 해당하는지 확인할 수 있습니다. 또한 노드에 연결된 블록 기기와 그 크기도 나열합니다.

예를 들어 노드에 로컬 SSD 2개를 연결하고 임시 스토리지 (capacity=200GB)에 200GB를 할당하는 경우 출력은 다음과 유사합니다.

google-local-ssd-partition0 -> /dev/nvme0n1p2
google-local-ssd-partition1 -> /dev/nvme0n2p2
NAME          SIZE TYPE
...
nvme0n1       375G disk
|-nvme0n1p1   100G part
| `-md0     199.9G raid0
`-nvme0n1p2   275G part
nvme0n2       375G disk
|-nvme0n2p1   100G part
| `-md0     199.9G raid0
`-nvme0n2p2   275G part

google-local-ssd-partition 심볼릭 링크와 기본 기기 이름 간의 매핑과 해당 파티션의 크기를 확인합니다. PersistentVolume 매니페스트에서 크기를 PARTITION_SIZE로, 심볼릭 링크 경로를 LOCAL_SSD_SYMLINK_PATH로 사용합니다.

예를 들어 이전 출력에서 /dev/disk/by-id/google-local-ssd-partition0 심볼릭 링크는 크기가 275G인 nvme0n1p2 파티션을 가리킵니다.

kubectl debug 명령어는 기본 네임스페이스에서 임시 포드를 실행 상태로 둡니다. 리소스가 소모되지 않도록 하려면 다음 명령어를 실행하여 이 포드를 삭제합니다.

kubectl delete pod DEBUG_POD_NAME

DEBUG_POD_NAME을 kubectl debug 명령어로 생성된 포드의 이름으로 바꿉니다. 이 이름은 명령어를 실행할 때 출력됩니다.

PersistentVolume 매니페스트 구성

찾은 파티션 크기로 볼륨 매니페스트를 구성합니다. 로컬 볼륨에는 nodeAffinity 필드가 필요합니다. 이렇게 하면 Kubernetes가 이 볼륨을 요청하는 포드를 로컬 SSD가 물리적으로 연결된 특정 노드에 예약할 수 있습니다. 다음 예시에서는 원시 블록 로컬 SSD 파티션의 매니페스트를 보여줍니다.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: "example-local-pv"
spec:
  capacity:
    storage: PARTITION_SIZE
  accessModes:
  - "ReadWriteOnce"
  volumeMode: "Block"
  persistentVolumeReclaimPolicy: "Retain"
  storageClassName: "local-storage"
  local:
    path: "LOCAL_SSD_SYMLINK_PATH"
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: "kubernetes.io/hostname"
          operator: "In"
          values:
          - "NODE_NAME"

다음을 바꿉니다.

  • PARTITION_SIZE: 첫 번째 단계에서 찾은 실제 원시 블록 용량입니다. 값이 파티션 용량과 정확히 일치하도록 Gi 서픽스 (예: 275Gi)를 사용합니다.
  • NODE_NAME: 로컬 SSD가 연결된 노드의 이름입니다.
  • LOCAL_SSD_SYMLINK_PATH: 첫 번째 단계에서 찾은 포맷되지 않은 로컬 SSD 파티션의 심볼릭 링크 경로입니다. 노드 풀에 연결된 로컬 SSD마다 호스트 OS는 남은 원시 블록 용량에 액세스하는 심볼릭 링크를 만듭니다. 경로는 0 색인 생성 패턴을 따릅니다. 예를 들어 로컬 SSD 3개를 연결하는 경우 파티션의 원시 블록 경로는 다음과 같습니다.
    • /dev/disk/by-id/google-local-ssd-partition0
    • /dev/disk/by-id/google-local-ssd-partition1
    • /dev/disk/by-id/google-local-ssd-partition2

PersistentVolumeClaim 만들기

PersistentVolumeClaim 객체를 만들어 볼륨을 요청합니다. 해당 사양은 다음과 같습니다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: "example-local-pvc"
spec:
  accessModes:
  - "ReadWriteOnce"
  volumeMode: "Block"
  storageClassName: "local-storage"
  resources:
    requests:
      storage: PARTITION_SIZE

포드에서 볼륨 사용

volumeDevices 사양에서 PersistentVolumeClaim 객체를 참조하여 포드에서 PersistentVolume 객체를 사용할 수 있습니다. 다음은 example-local-pvc 클레임을 사용하는 샘플 포드 매니페스트입니다.

apiVersion: v1
kind: Pod
metadata:
  name: "example-pod"
spec:
  containers:
  - name: "app"
    image: "ubuntu:22.04"
    command: ["/bin/sh", "-c"]
    args: ["tail -f /dev/null"]
    volumeDevices:
    - name: "raw"
      devicePath: "/dev/xvda"
  volumes:
  - name: "raw"
    persistentVolumeClaim:
      claimName: "example-local-pvc"

kubernetes.io/no-provisioner 프로비저닝 도구를 사용하므로 GKE는 로컬 볼륨을 자동으로 정리하지 않습니다. PersistentVolume 객체를 삭제하는 경우 디스크를 안전하게 재사용하려면 먼저 기본 디스크에서 데이터를 수동으로 삭제해야 합니다.

문제 해결

문제 해결 안내는 GKE에서 스토리지 문제 해결을 참조하세요.

다음 단계