파이널라이저

파이널라이저 (Finalizers)

삭제를 요청한 리소스가 즉시 사라지지 않고 특정 조건을 기다리는 경우가 있어요. 바로 파이널라이저(Finalizer) 때문입니다. 이 페이지는 파이널라이저가 무엇이고, 어떻게 동작하며, 왜 리소스 삭제가 지연되는지 설명해 드립니다. 삭제가 안 되는 리소스를 만났을 때 이 개념을 알고 있으면 큰 도움이 돼요.

출처: Kubernetes 공식 문서 — Finalizers

파이널라이저(Finalizers) 는 삭제 표시가 된 리소스를 쿠버네티스가 완전히 삭제하기 전에 특정 조건이 충족될 때까지 기다리도록 지시하는 네임스페이스 키예요. 파이널라이저는 컨트롤러에게 삭제된 객체가 소유했던 리소스를 정리하라고 알려줍니다.

파이널라이저가 지정된 객체를 삭제하라고 쿠버네티스에 알리면, API가 .metadata.deletionTimestamp를 채워 객체를 삭제 표시하고 202 상태 코드(HTTP "Accepted")를 반환해요. 컨트롤 플레인 또는 다른 컴포넌트가 파이널라이저가 정의한 조치를 취하는 동안 대상 객체는 terminating 상태로 남습니다. 이런 조치가 완료되면 컨트롤러는 대상 객체에서 관련 파이널라이저를 제거해요. metadata.finalizers 필드가 비워지면 쿠버네티스는 삭제가 완료된 것으로 보고 객체를 삭제합니다.

파이널라이저를 사용해 리소스의 가비지 컬렉션을 제어할 수 있어요. 예를 들어, 컨트롤러가 파이널라이징되는 객체를 삭제하기 전에 관련 API 리소스나 인프라를 정리하도록 파이널라이저를 정의할 수 있습니다.

파이널라이저는 보통 실행할 코드를 지정하지 않아요. 대신 어노테이션과 비슷하게 특정 리소스에 대한 키 목록인 경우가 많습니다. 쿠버네티스는 일부 파이널라이저를 자동으로 지정하지만, 직접 지정할 수도 있어요.

파이널라이저가 동작하는 방식 (How finalizers work)

매니페스트 파일로 리소스를 만들 때 metadata.finalizers 필드에 파이널라이저를 지정할 수 있어요. 리소스를 삭제하려 하면 삭제 요청을 처리하는 API 서버가 finalizers 필드의 값을 확인하고 다음을 수행합니다:

  • 삭제를 시작한 시간으로 metadata.deletionTimestamp 필드를 추가하도록 객체를 수정.
  • metadata.finalizers 필드에서 모든 항목이 제거될 때까지 객체가 제거되지 않도록 방지.
  • 202 상태 코드(HTTP "Accepted") 반환.

해당 파이널라이저를 관리하는 컨트롤러는 metadata.deletionTimestamp가 설정된 객체 업데이트를 감지해 객체 삭제가 요청되었음을 파악해요. 컨트롤러는 해당 리소스에 지정된 파이널라이저의 요구 사항을 충족하려고 합니다. 파이널라이저 조건이 충족될 때마다 컨트롤러는 리소스 finalizers 필드에서 해당 키를 제거해요. finalizers 필드가 비워지면 deletionTimestamp가 설정된 객체는 자동으로 삭제됩니다. 파이널라이저를 사용해 관리되지 않는 리소스의 삭제를 방지할 수도 있어요.

파이널라이저의 흔한 예는 kubernetes.io/pv-protection으로, PersistentVolume 객체의 실수 삭제를 방지해요. PersistentVolume 객체가 팟에서 사용 중이면 쿠버네티스는 pv-protection 파이널라이저를 추가합니다. PersistentVolume을 삭제하려 하면 Terminating 상태가 되지만, 파이널라이저가 존재하므로 컨트롤러는 삭제할 수 없어요. 팟이 PersistentVolume 사용을 중단하면 쿠버네티스가 pv-protection 파이널라이저를 제거하고 컨트롤러가 볼륨을 삭제합니다.

참고:

  • 객체를 DELETE하면 쿠버네티스는 해당 객체에 삭제 타임스탬프를 추가하고, 삭제 대기 중인 객체의 .metadata.finalizers 필드 변경을 즉시 제한하기 시작해요. 기존 파이널라이저는 제거할 수 있지만(finalizers 목록에서 항목을 삭제), 새 파이널라이저를 추가할 수는 없어요. 또한 한번 설정된 deletionTimestamp는 수정할 수 없습니다.
  • 삭제가 요청된 후에는 이 객체를 되살릴 수 없어요. 유일한 방법은 삭제하고 유사한 새 객체를 만드는 것입니다.

참고: 커스텀 파이널라이저 이름은 반드시 공개적으로 자격을 갖춘(qualified) 이름이어야 해요. 예: example.com/finalizer-name. 쿠버네티스는 이 형식을 강제하며, API 서버는 변경이 커스텀 파이널라이저에 qualified 이름을 사용하지 않으면 쓰기를 거부합니다.

소유자 참조, 라벨, 파이널라이저 (Owner references, labels, and finalizers)

라벨과 마찬가지로 소유자 참조(owner references)도 쿠버네티스 객체 간의 관계를 설명하지만, 목적은 다릅니다. 컨트롤러가 팟 같은 객체를 관리할 때 라벨을 사용해 관련 객체 그룹의 변경을 추적해요. 예를 들어 Job이 하나 이상의 팟을 만들면, Job 컨트롤러는 그 팟들에 라벨을 적용하고 같은 라벨을 가진 클러스터의 모든 팟 변경을 추적합니다.

Job 컨트롤러는 또한 그 팟들에 Job을 가리키는 소유자 참조를 추가해요. 이 팟들이 실행되는 동안 Job을 삭제하면, 쿠버네티스는 클러스터에서 어떤 팟을 정리해야 하는지 결정할 때 라벨이 아니라 소유자 참조를 사용합니다.

쿠버네티스는 삭제 대상 리소스에서 소유자 참조를 식별할 때도 파이널라이저를 처리해요.

어떤 상황에서는 파이널라이저가 종속 객체의 삭제를 차단해 대상 소유자 객체가 예상보다 오래 완전히 삭제되지 않고 남을 수 있어요. 이런 상황에서는 대상 소유자와 종속 객체의 파이널라이저 및 소유자 참조를 확인해 원인을 해결해야 합니다.

참고: 객체가 deleting 상태에 갇힌 경우, 삭제가 계속되도록 파이널라이저를 수동으로 제거하는 것을 피하세요. 파이널라이저는 보통 이유가 있어 리소스에 추가되므로, 강제로 제거하면 클러스터에 문제가 생길 수 있어요. 이는 파이널라이저의 목적을 이해하고 다른 방식으로 달성됐을 때만(예: 일부 종속 객체를 수동으로 정리) 해야 합니다.

더 알아보기 (Learn more)