[EKS] Finalizer 이해하기

xgro·2024년 6월 17일
2

EKS

목록 보기
3/4


출처 - https://kubernetes.io/blog/2021/05/14/using-finalizers-to-control-deletion/


📌 Summary

  • Kubernetes와 Argo CD에서 Finalizer를 사용하여 객체 삭제 전 정리 작업을 보장합니다.
  • 디렉토리 변경 시 발생하는 Finalizer 문제를 해결하기 위한 방법을 설명합니다.
  • Argo CD의 App-of-Apps 패턴을 사용할 때 발생할 수 있는 문제와 해결 과정을 다룹니다.



📌 Kubernetes와 Argo CD에서의 Finalizer 이해하기

👉 Finalizer란?

Finalizer는 Kubernetes 객체가 삭제되기 전에 특정 작업을 수행하도록 보장하는 메커니즘입니다. 이는 metadata.finalizers 필드에 키로 추가되며, 객체의 삭제를 지연시켜 자원 정리나 다른 필요한 작업이 완료될 수 있게 합니다. 객체에 Finalizer가 있는 경우, 모든 Finalizer가 제거될 때까지 객체는 실제로 삭제되지 않습니다.

📚 Finalizer 작동 과정:

  1. 객체 생성: 객체가 생성될 때 Finalizer가 설정됩니다.
  2. 삭제 요청: 사용자가 객체 삭제 요청을 하면, Kubernetes는 삭제 타임스탬프를 설정하고 객체를 "삭제 중" 상태로 표시합니다.
  3. Finalizer 실행: Finalizer 자원 정리 작업을 수행합니다. 이 과정에서 외부 시스템과의 상호 작용이나 추가적인 클린업 작업이 포함될 수 있습니다.
  4. Finalizer 제거: 모든 정리 작업이 완료되면 Finalizer가 제거됩니다.
  5. 객체 삭제: Finalizer가 모두 제거되면, 객체가 실제로 삭제됩니다.

📚 Finalizer 사용 예시:

  • PersistentVolumeClaims (PVC): PVC가 삭제될 때 Finalizer를 사용하여 볼륨을 정리하고, 데이터가 손실되지 않도록 합니다.
  • 네트워크 리소스: 네트워크 설정을 해제하거나 특정 네트워크 리소스를 정리하는 데 사용됩니다.

이처럼 Finalizer는 Kubernetes 환경에서 자원 관리의 일관성과 신뢰성을 보장하는 중요한 도구입니다.

예시:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
  finalizers:
    - example.com/my-finalizer



👉 Argo CD에서의 Finalizer

Argo CD는 Kubernetes에 선언적 GitOps 연속 배포를 제공하며, Finalizer를 통해 애플리케이션과 관련 자원 삭제를 관리합니다.

📚 기본 동작:

  • resources-finalizer.argocd.argoproj.io Finalizer는 애플리케이션 삭제 시 관련 자원들을 함께 삭제합니다.
  • 기본적으로 포그라운드 방식의 삭제가 사용됩니다.

📚 Finalizer 사용 시 발생할 수 있는 문제

Finalizer를 사용할 때 몇 가지 일반적인 문제 상황이 발생할 수 있습니다. 다음은 몇 가지 예시와 해결 방법입니다.

  1. Finalizer로 인해 삭제 중 상태에 고착됨:

    • 문제: 네임스페이스나 다른 리소스가 Terminating 상태에 고착되어 삭제되지 않는 경우가 있습니다. 이는 주로 Finalizer가 정리 작업을 완료하지 못했기 때문입니다.
    • 해결 방법: kubectl proxy를 사용하여 Kubernetes API 서버와 직접 상호작용하고, Finalizer를 수동으로 제거할 수 있습니다.
    kubectl proxy &
    kubectl get namespace example-ns -o json > example-ns.json
    # example-ns.json 파일에서 "finalizers" 필드를 빈 배열로 수정
    curl -X PUT --data-binary @example-ns.json http://127.0.0.1:8001/api/v1/namespaces/example-ns/finalize
  2. Finalizer가 제거되지 않음:

    • 문제: Finalizer가 의도한 대로 작동하지 않고, 리소스가 삭제되지 않는 경우가 있습니다.
    • 해결 방법: kubectl patch 명령어를 사용하여 Finalizer를 강제로 제거할 수 있습니다.
    kubectl patch <resource-type>/<resource-name> -p '{"metadata":{"finalizers":[]}}' --type=merge

Finalizer를 사용하면 리소스 정리가 더 확실해지지만, 위와 같은 문제들이 발생할 수 있으므로 주의가 필요합니다. 문제 발생 시에는 해당 리소스의 상태와 Finalizer 설정을 면밀히 확인하고, 필요에 따라 수동으로 정리 작업을 수행해야 합니다.



👉 App-of-Apps 디렉토리 변경으로 인한 Finalizer 문제와 해결 과정

처음 EKS에서 ArgoCD GitOps 패턴을 사용하여 App-of-Apps를 운영하던 중 argocd 부트스트랩 디렉토리 구조 변경으로 인해 Finalizer가 제거되지 않는 문제에 빠진 경험이 있습니다.

다행(?)스럽게도 애플리케이션이 올바르게 삭제되지 않아서, 장애가 발생할 수 있는 상황을 대처 할 수 있었습니다. ( 본문에서는 다행이라고 했지만, 원래 동작사항은 어플리케이션이 모두 삭제 되어야 하는 상황입니다. )


🔥 문제 상황:

기존에 구성되어 있던 App-of-Apps 디렉토리를 변경하면서, 이전 경로를 참조하는 Finalizer가 제대로 제거되지 않아 애플리케이션이나 네임스페이스가 삭제되지 않는 문제 발생.


📕 원인 분석:

  1. 잘못된 경로 참조: 디렉토리 경로 변경으로 인해 ArgoCD가 기존 리소스를 찾지 못해 Finalizer가 정리 작업을 완료하지 못함.
  2. 동기화 문제: ArgoCD가 새로운 경로를 인식하지 못해 애플리케이션 상태가 OutOfSync 상태로 남아 있음.
  3. 캐시 문제: ArgoCD 캐시가 갱신되지 않아 이전 상태가 유지됨.

✅ Case 해결 과정:

올바른 프로젝트 구조를 적용한 뒤, 리소스에 적용되어있는 finalizer 관련 내용을 제거하여 Argocd가 다시 싱크를 맞출 수 있도록 구성하여 장애상황을 회피할 수 있었습니다.

kubectl patch some-resource/some-name \
    --type json \
    --patch='[ { "op": "remove", "path": "/metadata/finalizers" } ]'

✅ 올바른 해결 과정:

  1. 애플리케이션 경로 업데이트:

    • 변경된 디렉토리 경로를 반영하도록 values.yaml 파일을 수정합니다.
    repoURL: https://github.com/your-repo
    path: new-folder-path
  2. 기존 애플리케이션 삭제:

    • 문제가 있는 애플리케이션을 강제로 삭제하여 Finalizer를 제거합니다.
    kubectl patch application <application-name> -n argocd -p '{"metadata":{"finalizers":[]}}' --type=merge
  3. 네임스페이스 강제 삭제:

    • 네임스페이스가 Terminating 상태에 고착된 경우, Finalizer를 수동으로 제거합니다.
    kubectl proxy &
    kubectl get namespace example-ns -o json > example-ns.json
    # example-ns.json 파일에서 "finalizers" 필드를 빈 배열로 수정
    curl -X PUT --data-binary @example-ns.json http://127.0.0.1:8001/api/v1/namespaces/example-ns/finalize
  4. 새로운 App-of-Apps 생성:

    • 새로운 경로로 업데이트된 App-of-Apps를 생성합니다.
    argocd app create app-of-apps \
        --repo https://github.com/your-repo \
        --path new-folder-path \
        --dest-server https://kubernetes.default.svc \
        --dest-namespace argocd
  5. 동기화 상태 확인 및 갱신:

    • ArgoCD 대시보드에서 각 애플리케이션의 동기화 상태를 확인하고 필요한 경우 수동으로 동기화합니다.
    argocd app sync app-of-apps
  6. 캐시 갱신:

    • 문제가 지속될 경우, ArgoCD 서버를 재시작하여 캐시를 갱신합니다.
    kubectl rollout restart deployment/argocd-server -n argocd



📌 Conclusion

Kubernetes와 Argo CD에서 Finalizer를 이해하고 사용하는 방법에 대해서 정리해 보았습니다.

Finalizer는 객체 삭제 전 정리 작업을 보장하며, 특히 App-of-Apps 패턴을 사용할 때 유용합니다.

디렉토리 변경으로 인해 발생할 수 있는 문제를 해결하기 위해, 애플리케이션 경로를 업데이트하고, 강제로 Finalizer를 제거하며, 새로운 App-of-Apps를 생성하는 과정을 통해 문제를 해결할 수 있습니다.

이러한 절차를 통해 Argo CD를 안정적으로 운영하고, GitOps 환경에서 효율적으로 리소스를 관리할 수 있습니다.



🔗 Reference

profile
안녕하세요! DevOps 엔지니어 이재찬입니다. 블로그에 대한 피드백은 언제나 환영합니다! 기술, 개발, 운영에 관한 다양한 주제로 함께 나누며, 더 나은 협업과 효율적인 개발 환경을 만드는 과정에 대해 인사이트를 나누고 싶습니다. 함께 여행하는 기분으로, 즐겁게 읽어주시면 감사하겠습니다! 🚀

0개의 댓글