동적 리소스의 관측 가능성

동적 리소스의 관측 가능성 (Observability of Dynamic Resources)

이 페이지는 DRA로 동적으로 할당된 리소스의 상태와 건강을 관찰하는 방법을 설명해요.

출처: 문서

본문

동적 리소스의 관측 가능성 (Observability of dynamic resources)

다음 방법 중 하나를 사용해 동적으로 할당된 리소스의 상태를 확인할 수 있어요:

  • kubelet 디바이스 메트릭 (#monitoring-resources)
  • ResourceClaim 상태 (#resourceclaim-device-status)
  • 디바이스 건강 모니터링 (#device-health-monitoring)

kubelet 디바이스 메트릭 (#monitoring-resources)

PodResourcesLister kubelet gRPC 서비스는 사용 중인 디바이스를 모니터링하게 해줘요. DynamicResource 메시지는 디바이스 이름과 클레임 이름 같은 동적 리소스 할당에 특화된 정보를 제공해요. 자세한 내용은 디바이스 플러그인 리소스 모니터링을 참고해요.

ResourceClaim 디바이스 상태 (#resourceclaim-device-status)

DRA 드라이버는 ResourceClaim의 status.devices 필드에서 각 할당된 디바이스에 대해 드라이버별 디바이스 상태 데이터를 보고할 수 있어요. 예를 들어 드라이버는 네트워크 인터페이스 디바이스에 할당된 IP 주소를 나열할 수 있어요. 이 필드를 업데이트하려면 특정 합성 RBAC 권한이 필요해요. 하드닝 가이드 - 동적 리소스 할당클러스터에서 동적 리소스 할당 하드닝하기를 참고해요.

드라이버가 ResourceClaim의 status.devices 필드에 추가하는 정보의 정확성은 드라이버에 달려 있어요. 이 필드를 디바이스 정보의 유일한 소스로 신뢰할 수 있는지 결정하려면 드라이버를 평가해요.

DRAResourceClaimDeviceStatus 기능 게이트를 비활성화하면 ResourceClaim을 저장할 때 status.devices 필드가 자동으로 지워져요. DRA 드라이버에서 status.devices 필드가 설정된 기존 ResourceClaim을 업데이트하는 것이 가능할 때 ResourceClaim 디바이스 상태가 지원돼요.

다음 예시에서 ResourceClaim의 status.devices 필드는 할당된 디바이스 관리를 담당하는 드라이버(resource-driver.example.com)로 채워졌어요:

apiVersion: resource.k8s.io/v1
kind: ResourceClaim
metadata:
  name: macvlan-eth0
spec:
...
status:
  allocation:
    devices:
      results:
      - device: eth0
        driver: resource-driver.example.com
        pool: nic-worker-a
        request: macvlan-eth0
        shareID: 8e7acdf9-0290-4ecd-a801-a654b021d2b7
        consumedCapacity:
          resource-driver.example.com/bandwidth: 1G
  devices:
  - conditions:
    - lastTransitionTime: "2025-10-21T08:38:17Z"
      message: Device successfully allocated and assigned to the pod
      reason: NetworkReady
      status: "True"
      type: NetworkReady
    device: eth0
    driver: resource-driver.example.com
    networkData:
      hardwareAddress: 00:01:ec:84:fb:51
      interfaceName: net1
      ips:
      - 10.10.1.2/24
      - 2001:db8::1/64
    pool: nic-worker-a
    shareID: 8e7acdf9-0290-4ecd-a801-a654b021d2b7

디바이스가 할당되지 않았다면 그 디바이스로 ResourceClaim의 status.devices 필드를 업데이트하려는 드라이버의 요청은 거부돼요. 디바이스가 할당 해제되면(status.allocation.devices에서 제거되면) status.devices의 해당 항목이 자동으로 제거돼요.

status.devices 필드에 대한 자세한 내용은 ResourceClaim API 참조를 참고해요.

디바이스 건강 모니터링 (#device-health-monitoring)

Kubernetes는 동적으로 할당된 인프라 리소스의 건강을 모니터링하고 보고하는 메커니즘을 제공해요. 특수 하드웨어에서 실행되는 유상태 애플리케이션의 경우 디바이스가 실패했거나 건강하지 않게 되었을 때 아는 것이 중요해요. 디바이스가 복구되는지 알아내는 것도 도움이 돼요.

이 기능을 사용하려면 ResourceHealthStatus 기능 게이트가 활성화되어야 하고(v1.36부터 베타이며 기본 활성화됨), DRA 드라이버가 DRAResourceHealth gRPC 서비스를 구현해야 해요.

DRA 드라이버가 할당된 디바이스가 건강하지 않게 되었음을 감지하면 이 상태를 kubelet에 다시 보고해요. 이 건강 정보는 파드의 status에 직접 노출돼요. kubelet은 각 컨테이너의 status에서 allocatedResourcesStatus 필드를 채우며, 그 컨테이너에 할당된 각 디바이스의 건강을 상세히 설명해요. 각 리소스 건강 항목은 건강 상태에 대한 추가 사람이 읽을 수 있는 맥락(오류 세부 정보나 실패 이유 같은 것)이 있는 선택적 message 필드를 포함할 수 있어요.

kubelet이 제한 시간 내에 DRA 드라이버로부터 건강 업데이트를 받지 못하면 디바이스의 건강 상태가 "Unknown"으로 표시돼요. DRA 드라이버는 DeviceHealth gRPC 메시지에서 health_check_timeout_seconds 필드를 설정해 이 제한 시간을 디바이스별로 구성할 수 있어요. 지정되지 않으면 kubelet은 기본 제한 시간 30초를 사용해요. 이것은 다른 하드웨어 유형(예: GPU, FPGA, 스토리지 디바이스)이 건강 보고 특성에 따라 적절한 제한 시간 값을 사용할 수 있게 해줘요.

이것은 사용자와 컨트롤러가 하드웨어 실패에 반응할 수 있게 하는 중요한 가시성을 제공해요. 실패 중인 파드의 경우 이 상태를 검사해 실패가 건강하지 않은 디바이스와 관련되었는지 결정할 수 있어요.

리소스 풀 상태 (Resource pool status)

ResourcePoolStatusRequest API를 사용해 리소스 풀의 디바이스 가용성을 조회할 수 있어요. 이것은 클러스터의 DRA 리소스 풀 전체에서 얼마나 많은 디바이스가 가용하거나, 할당되었거나, 사용 불가한지에 대한 가시성을 제공해요.

리소스 풀 상태를 확인하려면:

  • 드라이버 이름(필수)과 선택적으로 반환된 풀 수에 대한 제한을 지정해 ResourcePoolStatusRequest를 만들어요. 풀 이름을 지정해 단일 풀로 제한할 수도 있어요.
  • 컨트롤러가 요청을 처리할 때까지 기다려요.
  • 상태를 읽어 풀 가용성을 봐요. 상태는 다음을 포함해요: poolCount: 필터와 일치하는 총 풀 수(제한으로 잘린 경우 나열된 풀 수를 초과할 수 있음). pools: 각각 다음을 포함하는 풀 세부 정보 목록: driverpoolName: 풀을 식별함. generation: ResourceSlice 전체에서 관찰된 최신 풀 세대. resourceSliceCount: 풀을 구성하는 ResourceSlice 수. totalDevices: 풀의 총 디바이스. allocatedDevices: 현재 클레임에 할당된 디바이스. availableDevices: 할당에 사용 가능한 디바이스(totalDevices - allocatedDevices - unavailableDevices). unavailableDevices: 테인트나 다른 조건으로 인해 사용 불가한 디바이스. nodeName: 해당하는 경우 풀과 연결된 노드. validationError: 풀의 데이터를 완전히 검증할 수 없을 때 설정됨(예: 세대 롤아웃 중). 설정되면 디바이스 수 필드가 설정되지 않을 수 있음. partitionSummary: 파티셔너블 풀에 대해 파티션 유형별 할당 가능성(아래 파티션 요약 참고). shareableSummary: 공유 가능한 디바이스가 있는 풀에 대해 총 용량 사용률(아래 공유 가능 요약 참고). conditions: Complete(성공) 또는 Failed(오류) 조건 유형을 포함함.
  • 완료되면 요청을 삭제해요.

ResourcePoolStatusRequest 객체는 kube-controller-manager의 컨트롤러에 의해 한 번 처리돼요. spec은 생성되면 불변이고, status가 채워지면 전체 객체가 불변이 돼요. 업데이트된 가용성 데이터를 얻으려면 요청을 삭제하고 다시 만들어요. 완료된 요청은 1시간 후 자동으로 정리돼요.

이 기능은 ResourcePoolStatusRequest 리소스에 대한 명시적 RBAC 권한이 필요해요. 기본 ClusterRole에는 이 권한이 포함되지 않아요.

리소스 풀 상태는 kube-apiserver와 kube-controller-manager의 DRAResourcePoolStatus 기능 게이트로 제어돼요.

파티션 요약 (#resource-pool-partition-summary)

GPU 같은 단일 물리 디바이스는 같은 공유 카운터에서 끌어오는 여러 파티션 유형(예: 전체 GPU 대 절반 크기의 MIG 슬라이스)으로 광고될 수 있어요. 이러한 파티션들이 같은 기본 용량을 두고 경쟁하기 때문에 단순한 디바이스 수로는 각 유형을 몇 개 더 할당할 수 있는지 알 수 없어요. 파티셔너블 풀에 대해 partitionSummary 뷰가 그 질문에 답해요. 각 파티션 유형에 대해 보고해요:

  • attribute: 이 항목을 그룹화하는 값을 가진 디바이스 속성의 정규화된 이름. ResourceSlice의 spec.partitionTypeAttribute이거나, 슬라이스가 아무것도 선언하지 않을 때 요청의 spec.defaultPartitionTypeAttribute이에요.
  • type: 디바이스에서 그 속성의 값(예: Full 또는 Half).
  • total: 풀에서 이 파티션 유형의 디바이스 수.
  • allocatable: 현재 공유 카운터 소비를 고려할 때 이 파티션 유형의 추가 디바이스를 더 할당할 수 있는 수.

명명된 속성은 문자열 속성이어야 해요. 파티셔너블 디바이스의 파티션 유형 속성이 없거나 문자열이 아니면(예: 정수, 불리언, 버전 값) 풀은 파티션 요약 대신 검증 오류를 보고해요. 목록 유형 속성에 대한 특별 처리는 없어요. 문자열이 아닌 속성은 단순히 유효한 파티션 유형 속성이 아니에요.

이 뷰를 생성하려면 드라이버가 각 파티셔너블 디바이스에 값이 파티션 유형을 명명하는 문자열 속성으로 레이블을 지정하고, ResourceSlice의 partitionTypeAttribute 필드에서 그 속성을 명명해요:

apiVersion: resource.k8s.io/v1
kind: ResourceSlice
# ...
spec:
  # Every partitionable device in this slice carries this attribute; devices
  # that share a value share the same shared-counter cost.
  partitionTypeAttribute: gpu.example.com/profile

드라이버가 아직 partitionTypeAttribute를 선언하도록 업데이트되지 않았다면, 요청은 그 spec에서 대체 속성을 명명함으로써 파티션 요약을 얻을 수 있어요. 슬라이스의 자체 partitionTypeAttribute가 항상 우선하며, 요청 수준 기본값은 슬라이스가 하나를 선언하지 않는 디바이스에만 적용돼요:

apiVersion: resource.k8s.io/v1alpha3
kind: ResourcePoolStatusRequest
metadata:
  name: check-gpu-partitions
spec:
  driver: gpu.example.com
  # Fallback grouping attribute for slices that don't declare one themselves.
  defaultPartitionTypeAttribute: gpu.example.com/profile

슬라이스도 요청도 속성을 명명하지 않으면 파티셔너블 풀은 partitionSummary를 보고하지 않아요.

partitionSummary 뷰는 kube-apiserver와 kube-controller-manager의 DRAPartitionableDevicesType 기능 게이트로 제어되며, 이는 차례로 DRAResourcePoolStatusDRAPartitionableDevices 기능 게이트가 활성화되어야 해요.

공유 가능 요약 (#resource-pool-shareable-summary)

공유 가능한 디바이스(allowMultipleAllocations를 설정하고 여러 클레임이 소비할 수 있는 디바이스)를 포함하는 풀에 대해 shareableSummary는 풀 전체의 총 용량 사용률을 보고해요:

  • fullyAvailableDevices: 용량이 전혀 소비되지 않은 공유 가능한 디바이스.
  • partiallyAvailableDevices: 용량 중 일부는 소비되었지만 전부는 아닌 공유 가능한 디바이스.
  • capacity: 용량 이름별로 풀 전체의 총 total, consumed, available(total에서 consumed를 뺀 값, 절대 음수가 아님) 양.

shareableSummary는 풀에 최소 하나의 디바이스가 공유 가능할 때만 채워져요. 이것은 리소스 풀 상태 기능(DRAResourcePoolStatus 기능 게이트)의 일부이며 DRAPartitionableDevicesType을 요구하지 않아요. 요약하는 공유 가능한 디바이스는 소비 가능 용량 기능에서 온 것이에요.

컨테이너의 DRA 디바이스 메타데이터 (#device-metadata)

DRA 드라이버는 디바이스 속성(PCI 버스 주소나 중재된 디바이스 UUID 같은 것)과 네트워크 구성 같은 디바이스 메타데이터를 JSON 파일로 컨테이너에 직접 노출할 수 있어요. 이것은 애플리케이션이 Kubernetes API를 조회하거나 커스텀 컨트롤러를 사용하지 않고 할당된 디바이스에 대한 정보를 발견하게 해줘요.

KEP-5304는 드라이버가 따라야 하는 디바이스 메타데이터 프로토콜(#device-metadata-protocol)을 정의해 애플리케이션이 드라이버와 클러스터 전반에 걸쳐 일관된 레이아웃을 보도록 해줘요. DRA kubelet 플러그인 라이브러리(https://pkg.go.dev/k8s.io/dynamic-resource-allocation/kubeletplugin)가 이 프로토콜을 구현해요.

디바이스 메타데이터는 디바이스 접근과 같은 규칙을 따라요: 컨테이너가 디바이스를 요청할 때만 컨테이너 내부에서 사용 가능해요. 자세한 내용은 DRA로 워크로드에서 디바이스 요청하기를 참고해요.

디바이스 메타데이터 프로토콜 (#device-metadata-protocol)

프로토콜은 네 가지 규칙으로 구성돼요:

  • 파일 경로 (File paths): 메타데이터 파일은 컨테이너 내부의 /var/run/kubernetes.io/dra-device-attributes 아래에 존재해요. 직접 참조된 ResourceClaim의 경우 경로는 resourceclaims/<claimName>/<requestName>/<driverName>-metadata.json이에요. ResourceClaimTemplate에서 만들어진 클레임의 경우 경로는 resourceclaimtemplates/<podClaimName>/<requestName>/<driverName>-metadata.json이며, 여기서 podClaimNamepod.spec.resourceClaims[].name이에요. 요청이 우선순위 목록을 사용할 때 최상위 요청 이름만 <requestName> 경로 세그먼트에 사용돼요. 파일의 requests[].name 필드는 gpu/high-memory 같은 전체 <request>/<subrequest> 참조를 포함해요. 경로 상수는 k8s.io/dynamic-resource-allocation/api/metadata(https://pkg.go.dev/k8s.io/dynamic-resource-allocation/api/metadata)에 정의돼 있어요.
  • JSON API: 각 파일은 하나 이상의 DeviceMetadata 객체의 스트림이에요. 각 객체는 Kubernetes API 규칙을 따라 apiVersionkind를 가져요. 같은 메타데이터가 드라이버가 선택한 순서대로 구성된 API 버전마다 한 번 인코딩돼요. 소비자는 디코드할 수 있는 첫 버전을 사용하고 알 수 없는 버전을 건너뛰어요. 알려진 버전의 잘못된 객체는 오류예요.
  • 세대 (Generation): 초기 파일은 metadata.generation이 1로 설정돼 있어요. 각 업데이트는 소비자가 변경을 감지할 수 있도록 세대를 증가시켜요.
  • 컨테이너 노출 (Container exposure): DRA kubelet 플러그인 라이브러리는 CDI를 사용해 각 파일을 읽기 전용으로 바인드 마운트해요. 다른 구현은 파일이 필요 경로에 나타나고 읽기 전용인 한 다른 메커니즘을 사용할 수 있어요.

드라이버에서 디바이스 메타데이터 활성화 (#device-metadata-enable)

디바이스 메타데이터는 드라이버 측 기능이에요. Kubernetes 기능 게이트가 없고 DRA kubelet 플러그인 라이브러리에서 기본적으로 비활성화돼 있어요. 드라이버는 기능을 활성화하고 쓰는 버전을 명시적으로 선택해야 해요:

kubeletplugin.EnableDeviceMetadata(true, []schema.GroupVersion{
	metadatav1beta1.SchemeGroupVersion,
	metadatav1alpha1.SchemeGroupVersion,
})

v1beta1 버전이 필요해요. 드라이버는 더 오래된 소비자와의 호환성을 위해 v1alpha1도 쓸 수 있어요. 슬라이스의 순서가 메타데이터 스트림의 순서이며 프레임워크는 버전을 정렬하지 않아요. 드라이버는 최신 버전을 앞에 두어야 해요. 버전 없이, v1beta1 없이, 또는 알 수 없는 버전으로 디바이스 메타데이터를 활성화하면 플러그인이 시작 중에 실패해요.

각 준비된 디바이스에 대해 드라이버는 Device.Metadatakubeletplugin.DeviceMetadata로 채울 수 있어요. 드라이버는 그 디바이스에 대해 ResourceSlice에서 게시하는 속성을 포함해야 워크로드가 런타임에 같은 정보를 보게 됩니다. 드라이버는 런타임에만 관련되는 속성도 포함할 수 있어요. 네트워크 디바이스의 경우 드라이버는 CNI 구성 후 UpdateRequestMetadata를 호출해 인터페이스 이름, IP 주소, 하드웨어 주소를 추가할 수 있어요.

위의 kubelet 플러그인 API 링크는 드라이버 작성자를 위한 통합을 설명해요. DRA 프레임워크는 보편적인 명령줄 플래그를 정의하지 않으므로 클러스터 운영자는 드라이버가 제공하는 배포 구성을 통해 기능을 활성화해요.

활성화되면 DRA kubelet 플러그인 라이브러리가 할당된 디바이스를 준비하는 동안 메타데이터 파일을 써요. 또한 기본적으로 CDI 사양을 /var/run/cdi에 써요. 컨테이너 런타임은 그 디렉터리에서 CDI 사양을 발견하도록 구성되어야 해요. 라이브러리는 생성된 각 사양에 필요한 최소 CDI 사양 버전을 결정해요.

하나의 요청이 여러 DRA 드라이버에서 디바이스를 할당할 때 각 드라이버가 자체 메타데이터 파일을 써요. 드라이버 이름을 아는 소비자는 클레임, 요청, 드라이버 이름에서 정확한 경로를 구성해야 해요. Go 소비자는 ReadResourceClaimMetadata 또는 ReadResourceClaimTemplateMetadata를 사용해 요청에 대한 모든 드라이버별 파일을 읽고 병합할 수 있어요.

메타데이터 스키마 (#device-metadata-schema)

메타데이터 파일의 각 객체는 DeviceMetadata API(metadata.resource.k8s.io/v1beta1)를 준수해요.

스키마는 다음을 포함해요:

  • 이름, 네임스페이스, UID, 메타데이터 세대를 포함한 ResourceClaim에 대한 표준 객체 메타데이터.
  • ResourceClaimTemplate에서 생성된 클레임에 대한 선택적 podClaimName.
  • 요청 목록. 각 요청은 필수 name과 할당된 디바이스 목록을 가져요.
  • 각 디바이스에 대한 driver, pool, name.
  • 선택적 디바이스 속성과 네트워크 데이터.

속성 값은 ResourceSlice 디바이스 속성과 같은 표현을 사용해요. 각 속성은 정확히 하나의 스칼라 값(int, bool, string, version) 또는 목록 값(ints, bools, strings, versions)을 가져요. 디바이스 용량 값은 디바이스 메타데이터에 포함되지 않아요.

네트워크 데이터는 interfaceName, ips, hardwareAddress를 포함할 수 있어요. 필드 제약에 대해서는 DeviceMetadata API 문서를 참고해요.

다음 예시는 ResourceClaimTemplate을 통해 할당된 GPU 디바이스에 대한 메타데이터 스트림의 한 객체를 보여줘요:

{
  "kind": "DeviceMetadata",
  "apiVersion": "metadata.resource.k8s.io/v1beta1",
  "metadata": {
    "name": "pod0-gpu-2kqrd",
    "namespace": "gpu-test1",
    "uid": "c7e7b22e-239b-4498-b27c-7f1344481e14",
    "generation": 1
  },
  "podClaimName": "gpu",
  "requests": [
    {
      "name": "gpu",
      "devices": [
        {
          "driver": "gpu.example.com",
          "pool": "worker-0",
          "name": "gpu-0",
          "attributes": {
            "driverVersion": {
              "version": "1.0.0"
            },
            "index": {
              "int": 0
            },
            "model": {
              "string": "LATEST-GPU-MODEL"
            },
            "uuid": {
              "string": "gpu-18db0e85-99e9-c746-8531-ffeb86328b39"
            }
          }
        }
      ]
    }
  ]
}

DRA kubelet 플러그인은 쓰기 전에 메타데이터를 검증하지 않아요. Go 소비자는 스트림을 디코딩할 때 생성된 검증에 선택적으로 참여할 수 있어요. 디코딩과 검증은 별개의 결과를 가져요: 검증 오류는 성공적으로 디코딩된 객체가 반환되는 것을 막지 않아요. 사용법은 DRA 디바이스 메타데이터에 접근하기를 참고해요.

즉시 및 지연 메타데이터 (#device-metadata-lifecycle)

즉시 메타데이터의 경우 드라이버는 클레임을 준비하는 동안 속성 또는 네트워크 데이터를 제공해요. DRA kubelet 플러그인은 소비 컨테이너가 시작되기 전에 세대 1의 파일을 써요.

지연 메타데이터의 경우 드라이버는 속성이나 네트워크 데이터 없이 디바이스를 준비할 수 있어요. 초기 세대 1 파일에는 디바이스 신원이 포함돼요. 드라이버는 나중에 UpdateRequestMetadata를 호출해 전체 스트림을 원자적으로 교체하고 세대를 증가시켜요. 업데이트에는 초기 파일이 존재해야 해요. 디바이스 준비가 요청에 대해 디바이스를 반환하지 않으면 프레임워크는 그 요청에 대해 메타데이터 파일도 메타데이터 CDI 디바이스도 만들지 않아요.

메타데이터는 각 소비 컨테이너의 수명 동안 그 컨테이너에 사용 가능하게 유지돼요. 프레임워크는 클레임이 준비 해제된 후 메타데이터 파일과 CDI 사양을 제거해요.

워크로드에서 디바이스 메타데이터를 사용하는 방법을 배우려면 DRA 디바이스 메타데이터에 접근하기를 참고해요.

커스텀 드라이버 (#device-metadata-custom-drivers)

DRA kubelet 플러그인 라이브러리를 사용하지 않는 커스텀 드라이버는 디바이스 메타데이터 프로토콜(#device-metadata-protocol)을 스스로 구현해야 해요. 이것은 올바른 경로에 버전이 있는 DeviceMetadata 스트림을 쓰고, 모든 업데이트에서 metadata.generation을 증가시키고, CDI 또는 동등한 메커니즘으로 파일을 읽기 전용으로 노출하는 것을 포함해요.

더 알아보기 (Learn more)