Crossplane 문제 해결하기
Crossplane 문제 해결하기 (Troubleshoot)
Crossplane을 운영하다 보면 리소스가 예상대로 동작하지 않을 때가 있어요. 이 가이드는 흔히 겪는 문제를 진단하고 해결하는 방법을 단계별로 안내해요.
출처: 문서
본문
요청한 리소스를 찾을 수 없음 (Requested resource not found)
Crossplane CLI로 Provider나 Configuration을 설치할 때 the server could not find the requested resource 오류가 나면(예: crossplane xpkg install provider xpkg.crossplane.io/crossplane-contrib/provider-aws-s3:v2.0.0), 대부분 Crossplane CLI를 업데이트해야 한다는 신호예요. 즉 Crossplane이 어떤 API를 알파에서 베타/안정 버전으로 승격시켰는데 기존 플러그인이 이 변경을 알지 못하는 상황이에요.
리소스 상태와 조건 (Resource status and conditions)
대부분의 Crossplane 리소스에는 해당 리소스의 현재 상태를 나타내는 status 섹션이 있어요. Crossplane 리소스에 대해 kubectl describe를 실행하면 해당 조건에 대한 유용한 정보를 자주 얻을 수 있어요. 예를 들어 GCP CloudSQLInstance 관리 리소스의 상태를 확인하려면 리소스에 대해 kubectl describe를 사용하세요.
kubectl describe cloudsqlinstance my-db
Status:
Conditions:
Last Transition Time: 2019-09-16T13:46:42Z
Reason: Creating
Status: False
Type: Ready
대부분의 Crossplane 리소스는 Ready 조건을 설정해요. Ready는 리소스의 가용성(생성 중, 삭제 중, 사용 가능, 사용 불가, 바인딩 중 등)을 나타내요.
리소스 이벤트 (Resource events)
대부분의 Crossplane 리소스는 흥미로운 일이 발생할 때 이벤트를 내보내요. kubectl describe(예: kubectl describe cloudsqlinstance my-db)를 실행하면 리소스와 연결된 이벤트를 볼 수 있어요. kubectl get events로 특정 네임스페이스의 모든 이벤트도 볼 수 있어요.
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning CannotConnectToProvider 16s (x4 over 46s) managed/postgresqlserver.database.azure.crossplane.io cannot get referenced ProviderConfig: ProviderConfig.azure.crossplane.io "default" not found
Kubernetes는 이벤트를 네임스페이스로 묶는 반면, 대부분의 Crossplane 리소스(XR 등)는 클러스터 스코프라는 점을 유의하세요. Crossplane은 클러스터 스코프 리소스에 대한 이벤트를 'default' 네임스페이스로 내보내요.
Crossplane 로그
더 많은 정보를 얻거나 실패를 조사하기 위해 볼 다음 장소는 crossplane-system 네임스페이스에서 실행 중인 Crossplane 파드 로그예요. 현재 Crossplane 로그를 얻으려면 다음을 실행하세요:
kubectl -n crossplane-system logs -lapp=crossplane
Crossplane은 기본적으로 최소한의 로그만 내보낸다는 점을 유의하세요. 어떤 작업을 하는지에 대한 정보는 보통 이벤트가 가장 좋은 장소예요. 찾는 것이 없으면 --debug 플래그로 Crossplane을 재시작해야 할 수도 있어요.
프로바이더 로그
프로바이더가 Crossplane 기능의 상당 부분을 제공한다는 점을 기억하세요. 프로바이더 로그도 kubectl logs로 볼 수 있어요. 관례상 이들도 기본적으로 최소한의 로그만 내보내요.
kubectl -n crossplane-system logs <provider-파드>
Crossplane 커뮤니티가 유지보수하는 모든 프로바이더는 Crossplane의 --debug 플래그 지원을 그대로 따르고 있어요. 프로바이더에 플래그를 설정하는 가장 쉬운 방법은 DeploymentRuntimeConfig를 만들고 이를 Provider에서 참조하는 것이에요:
apiVersion: pkg.crossplane.io/v1beta1
kind: DeploymentRuntimeConfig
metadata:
name: debug-config
spec:
deploymentTemplate:
spec:
selector: {}
template:
spec:
containers:
- name: package-runtime
args:
- --debug
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: crossplane-contrib-provider-aws-s3
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-aws-s3:v2.0.0
runtimeConfigRef:
apiVersion: pkg.crossplane.io/v1beta1
kind: DeploymentRuntimeConfig
name: debug-config
이미 설치된 Provider에 DeploymentRuntimeConfig 참조를 추가하면 해당 Deployment도 그에 따라 업데이트된다는 점을 유의하세요.
Crossplane 일시 중지 (Pausing Crossplane)
때로는 버그를 만났을 때처럼 Crossplane이 리소스를 적극적으로 관리하지 않도록 일시 중지하는 것이 유용할 수 있어요. 모든 리소스를 삭제하지 않고 Crossplane을 일시 중지하려면 다음 명령으로 배포를 축소하세요:
kubectl -n crossplane-system scale --replicas=0 deployment/crossplane
문제를 해결하거나 상황을 정리한 뒤에는 배포를 다시 확장해 Crossplane을 재개할 수 있어요:
kubectl -n crossplane-system scale --replicas=1 deployment/crossplane
프로바이더 일시 중지 (Pausing Providers)
문제 해결 중이거나 복잡한 리소스 마이그레이션을 조정할 때 프로바이더도 일시 중지할 수 있어요. DeploymentRuntimeConfig를 만들고 참조하는 것이 프로바이더를 축소하는 가장 쉬운 방법이며, DeploymentRuntimeConfig를 변경하거나 참조를 제거해 다시 확장할 수 있어요:
apiVersion: pkg.crossplane.io/v1beta1
kind: DeploymentRuntimeConfig
metadata:
name: scale-config
spec:
deploymentTemplate:
spec:
selector: {}
replicas: 0
template: {}
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: crossplane-contrib-provider-aws-s3
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-aws-s3:v2.0.0
runtimeConfigRef:
apiVersion: pkg.crossplane.io/v1beta1
kind: DeploymentRuntimeConfig
name: scale-config
이미 설치된 Provider에 DeploymentRuntimeConfig 참조를 추가하면 해당 Deployment도 그에 따라 업데이트된다는 점을 유의하세요.
리소스가 멈췄을 때 삭제하기 (Deleting when a resource hangs)
Crossplane이 관리하는 리소스는 뒤에 아무것도 남기지 않도록 자동으로 정리돼요. Crossplane은 파이널라이저(finalizer)를 사용해 이를 수행하지만, 특정 시나리오에서는 파이널라이저가 Kubernetes 객체의 삭제를 막을 수 있어요.
이를 처리하려면 객체를 패치해 파이널라이저를 제거하면 Kubernetes가 객체를 삭제할 수 있게 돼요. 다만 이것이 Crossplane이 관리하던 외부 리소스를 반드시 삭제하는 것은 아니므로, 클라우드 공급자 콘솔에서 남아 있는 리소스를 정리해야 해요.
일반적으로 객체에서 파이널라이저를 제거하려면 이 명령을 사용할 수 있어요:
kubectl patch <리소스유형> <이름> -p '{"metadata":{"finalizers": []}}' --type=merge
예를 들어 my-db라는 CloudSQLInstance 관리 리소스(database.gcp.crossplane.io)의 파이널라이저를 제거하려면:
kubectl patch cloudsqlinstance my-db -p '{"metadata":{"finalizers": []}}' --type=merge
재조정 스래싱에 대한 회로 차단기 (Circuit breaker for reconciliation thrashing)
Crossplane에는 재조정 스래싱(reconciliation thrashing)을 방지하는 회로 차단기 메커니즘이 포함되어 있어요. 스래싱은 컨트롤러가 구성된 리소스 상태를 두고 다투거나, 클러스터 성능에 영향을 주는 빡빡한 재조정 루프에 빠질 때 발생해요.
회로 차단기 동작 방식
각 복합 리소스(XR)는 재조정 비율을 모니터링하는 자체 토큰 버킷 기반 회로 차단기를 갖고 있어요:
- 버스트(Burst, 용량): 짧은 시간에 허용되는 최대 이벤트 수 (기본값: 100)
- 보충율(Refill rate): 버스트 용량이 소진된 후의 지속 이벤트 비율 (기본값: 초당 1개 이벤트)
- 쿨다운(Cooldown): 회로가 열린 상태로 유지되어 복구를 시도하기까지의 기간 (기본값: 5분)
XR이 너무 많은 watch 이벤트(버스트와 보충율을 초과)를 받으면 회로 차단기가 열리고 대부분의 재조정 요청을 차단해요. 회로가 열린 동안 Crossplane은 30초마다 한 번의 요청을 허용해 복구를 탐지해요.
회로 차단기 활성화 탐지
XR에는 회로 차단기 상태를 추적하는 Responsive 조건이 있어요. 회로 차단기가 열리면 이 조건이 False로 바뀌어요:
conditions:
- type: Responsive
status: "False"
reason: WatchCircuitOpen
message: "Too many watch events from ConfigMap/my-config (default). Allowing events periodically."
이 메시지는 어떤 리소스가 과도한 watch 이벤트를 유발하는지 식별해 스래싱의 원인을 정확히 짚을 수 있게 해줘요.
근본 원인 파악 및 수정
watch 이벤트는 클러스터에서 리소스가 변경될 때 발생해요. 과도한 watch 이벤트는 보통 리소스가 서로를 주기적으로 업데이트하거나, 외부 시스템이 Crossplane의 변경을 되돌리는 등 루프를 유발하는 구성 패턴을 나타내요.
과도한 watch 이벤트의 원인을 식별하려면:
XR의 Responsive 조건 메시지가 문제 리소스를 식별해 줘요. 이 리소스의 수정 이벤트를 모니터링하세요:
kubectl get <리소스유형> -n <네임스페이스> --output-watch-events --watch-only
흔한 근본 원인과 해결책은 다음과 같아요:
- 패치의 피드백 루프: 변경이 또 다른 변경을 유발하는 순환 업데이트를 만드는 로직이 있는지 Composition 패치를 검토하세요.
- 외부 컨트롤러 충돌: 다른 컨트롤러나 오퍼레이터가 동일한 리소스를 수정하며 Crossplane과 제어권을 다툴 수 있어요.
- 빈번한 연결 세부정보 업데이트: 연결 시크릿에 대한 업데이트가 watch 이벤트를 유발하므로, 모든 필드가 연결 세부정보에 필요할지 고려하세요.
회로 차단기 임계값을 조정하기 전에 근본 원인을 조사하고 수정하세요.
회로 차단기 파라미터 구성
기본 회로 차단기 설정은 대부분의 환경에서 잘 동작해요. 구성 패턴과 클러스터 규모에 따라 조정이 필요할 수 있어요.
예를 들어 XR이 자주 업데이트되는 대규모 배포에서는 버스트와 보충율을 늘리고, 스래싱에 대한 더 엄격한 보호가 필요하면 줄일 수 있어요.
Helm을 통한 Crossplane 시작 인자로 회로 차단기 파라미터를 구성하세요:
helm install crossplane --namespace crossplane-system --create-namespace crossplane-stable/crossplane \
--set args='{"--circuit-breaker-burst=500.0","--circuit-breaker-refill-rate=5.0","--circuit-breaker-cooldown=1m"}'
사용 가능한 파라미터:
--circuit-breaker-burst: 이벤트의 최대 버스트 (기본값: 100.0)--circuit-breaker-refill-rate: 지속 비율의 초당 이벤트 수 (기본값: 1.0)--circuit-breaker-cooldown: 회로를 열어 둘 기간 (기본값: 5m0s)
메트릭으로 모니터링
이 Prometheus 메트릭으로 회로 차단기 활동을 추적하세요. 자세한 메트릭 정보는 Metrics 가이드를 참조하세요.
팁, 트릭, 문제 해결
이 섹션은 복합 리소스(Composite Resources) 작업 시 유용한 몇 가지 일반적인 팁, 트릭, 문제 해결 단계를 다룬다. 복합 리소스가 왜 동작하지 않는지 추적하고 있다면 문제 해결 페이지에도 유용한 정보가 있어요.