목록으로

Programming Notes

Kubernetes v1.35: 가변형 PersistentVolume 노드 어피니티 (알파)

PersistentVolume 노드 어피니티 API는 Kubernetes v1.10부터 존재했습니다. 이 API는 클러스터의 모든 노드에서 볼륨에 동등하게 접근할 수 없을 수 있음을 표현하기 위해 널리 사용됩니다. 이 필드는 이전에는 변경 불가능했지만, Kubernetes...

PersistentVolume 노드 어피니티 API는 Kubernetes v1.10부터 존재했습니다. 이 API는 클러스터의 모든 노드에서 볼륨에 동등하게 접근할 수 없을 수 있음을 표현하기 위해 널리 사용됩니다. 이 필드는 이전에는 변경 불가능했지만, Kubernetes v1.35(알파)부터 변경 가능해졌습니다. 이 변경은 보다 유연한 온라인 볼륨 관리의 문을 엽니다.

왜 노드 어피니티를 변경 가능하게 만들었는가?

이는 명백한 질문을 제기합니다: 왜 지금 노드 어피니티를 변경 가능하게 만들었을까요? 디플로이먼트와 같은 스테이트리스(stateless) 워크로드는 자유롭게 변경할 수 있으며 모든 파드를 다시 생성하여 변경 사항이 자동으로 롤아웃되지만, PersistentVolume(PV)은 스테이트풀(stateful)이며 데이터 손실 없이 쉽게 다시 생성할 수 없습니다.

그러나 스토리지 공급자는 진화하고 스토리지 요구 사항은 변화합니다. 특히, 현재 여러 공급자가 지역 디스크(regional disks)를 제공하고 있습니다. 일부는 워크로드 중단 없이 영역 디스크(zonal disks)에서 지역 디스크로 라이브 마이그레이션(live migration)까지 지원합니다. 이러한 변경은 최근 1.34에서 GA로 승격된 VolumeAttributesClass API를 통해 표현할 수 있습니다. 하지만 볼륨이 지역 스토리지로 마이그레이션되더라도, Kubernetes는 PV 객체에 기록된 노드 어피니티 때문에 다른 존(zone)으로 파드를 스케줄링하는 것을 여전히 방지합니다. 이 경우, PV 노드 어피니티를 다음과 같이 변경하고 싶을 수 있습니다.

spec:
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: topology.kubernetes.io/zone
          operator: In
          values:
          - us-east1-b

로 변경합니다.

spec:
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: topology.kubernetes.io/region
          operator: In
          values:
          - us-east1

또 다른 예시로, 공급업체는 때때로 새로운 세대의 디스크를 제공합니다. 새로운 디스크는 클러스터 내의 오래된 노드에 항상 연결될 수 없습니다. 이러한 접근성은 PV 노드 어피니티를 통해서도 표현될 수 있으며, 파드가 올바른 노드에 스케줄링되도록 보장합니다. 하지만 디스크가 업그레이드될 때, 이 디스크를 사용하는 새로운 파드는 여전히 오래된 노드에 스케줄링될 수 있습니다. 이를 방지하기 위해 PV 노드 어피니티를 다음과 같이 변경하고 싶을 수 있습니다.

spec:
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: provider.com/disktype.gen1
          operator: In
          values:
          - available

로 변경합니다.

spec:
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: provider.com/disktype.gen2
          operator: In
          values:
          - available

따라서 이제 변경 가능해졌으며, 이는 더 유연한 온라인 볼륨 관리를 향한 첫걸음입니다. API 서버에서 하나의 유효성 검사를 제거하는 간단한 변경이지만, Kubernetes 생태계와 잘 통합하기까지는 아직 갈 길이 멉니다.

시도해 보기

이 기능은 Kubernetes 클러스터 관리자이며, 스토리지 공급자가 온라인 업데이트를 허용하고 이를 활용하려 하지만, 해당 업데이트가 볼륨 접근성에 영향을 미칠 수 있는 경우에 유용합니다.

PV 노드 어피니티를 변경하는 것만으로는 실제 기저 볼륨의 접근성이 변경되지 않는다는 점에 유의하십시오. 이 기능을 사용하기 전에, 먼저 스토리지 공급자에서 기저 볼륨을 업데이트하고, 업데이트 후 어떤 노드가 해당 볼륨에 접근할 수 있는지 이해해야 합니다. 그런 다음 이 기능을 활성화하고 PV 노드 어피니티를 동기화 상태로 유지할 수 있습니다.

현재 이 기능은 알파 상태입니다. 기본적으로 비활성화되어 있으며, 변경될 수 있습니다. 이 기능을 사용해 보려면 APIServer에서 MutablePVNodeAffinity 피처 게이트를 활성화한 다음, PV의 spec.nodeAffinity 필드를 편집할 수 있습니다. 일반적으로 관리자만 PV를 편집할 수 있으므로, 적절한 RBAC 권한이 있는지 확인하십시오.

업데이트와 스케줄링 사이의 경쟁 조건

파드 외부에서 스케줄링 결정에 영향을 미칠 수 있는 요소는 거의 없으며, PV 노드 어피니티가 그중 하나입니다. 노드 어피니티를 완화하여 더 많은 노드가 볼륨에 접근하도록 허용하는 것은 괜찮지만, 노드 어피니티를 강화하려고 할 때 경쟁 조건(race condition)이 발생할 수 있습니다. 스케줄러가 캐시에서 수정된 PV를 어떻게 볼지 불분명하므로, 스케줄러가 더 이상 볼륨에 접근할 수 없는 오래된 노드에 파드를 배치할 수 있는 작은 시간 간격이 존재합니다. 이 경우 파드는 ContainerCreating 상태에서 멈출 것입니다.

현재 논의 중인 완화책 중 하나는 PersistentVolume의 노드 어피니티가 위반될 경우 kubelet이 파드 시작에 실패하도록 하는 것입니다. 이는 아직 구현되지 않았습니다. 따라서 지금 이 기능을 시도하고 있다면, 업데이트된 PV를 사용하는 후속 파드들을 주시하고, 볼륨에 접근할 수 있는 노드에 스케줄링되는지 확인하십시오. 스크립트에서 PV를 업데이트하고 즉시 새 파드를 시작하면 의도대로 작동하지 않을 수 있습니다.

CSI (컨테이너 스토리지 인터페이스)와의 향후 통합

현재는 클러스터 관리자가 PV의 노드 어피니티와 스토리지 공급자의 기저 볼륨을 모두 수정해야 합니다. 그러나 수동 작업은 오류 발생 가능성이 높고 시간이 많이 소요됩니다. 궁극적으로는 이 기능을 VolumeAttributesClass와 통합하여, 권한이 없는 사용자도 PersistentVolumeClaim(PVC)을 수정하여 스토리지 측 업데이트를 트리거하고, 클러스터 관리자의 개입 없이 PV 노드 어피니티가 적절하게 자동으로 업데이트되도록 하는 것이 바람직합니다.

사용자 및 스토리지 드라이버 개발자의 피드백을 환영합니다

앞서 언급했듯이, 이것은 단지 첫걸음에 불과합니다.

Kubernetes 사용자라면, PV 노드 어피니티를 어떻게 사용하고 있는지(또는 사용할 것인지) 배우고 싶습니다. 귀하의 경우 온라인 업데이트가 유익한가요?

CSI 드라이버 개발자라면, 이 기능을 구현할 의향이 있으신가요? API가 어떤 모습이기를 바라시나요?

피드백은 다음을 통해 제공해 주십시오:

이 기능과 관련된 문의사항이나 특정 질문은 SIG Storage 커뮤니티에 문의해 주십시오.