Config Connector 문제 해결


이 페이지에서는 구성 커넥터 문제와 제품을 사용할 때 발생할 수 있는 일반적인 문제를 해결하는 데 사용할 수 있는 문제 해결 기법을 설명합니다.

기본 문제 해결 기법

구성 커넥터 버전 확인

다음 명령어를 실행하여 설치된 구성 커넥터 버전을 가져오고 출시 노트를 교차 참조하여 실행 중인 버전이 사용할 기능과 리소스를 지원하는지 확인합니다.

kubectl get ns cnrm-system -o jsonpath='{.metadata.annotations.cnrm\.cloud\.google\.com/version}'

리소스 상태 및 이벤트 확인

일반적으로 Kubernetes에서 리소스 상태 검사를 수행하여 구성 커넥터 리소스 문제를 확인할 수 있습니다. 리소스 상태 및 이벤트를 확인하면 구성 커넥터에서 리소스 조정이 실패했는지 여부 그리고 조정이 실패한 이유를 확인하는 데 특히 도움이 됩니다.

구성 커넥터가 실행 중인지 확인

구성 커넥터가 실행 중인지 확인하려면 모든 Pod가 READY 상태인지 확인합니다.

kubectl get pod -n cnrm-system

출력 예시:

NAME                                            READY   STATUS    RESTARTS   AGE
cnrm-controller-manager-0                       1/1     Running   0          1h
cnrm-deletiondefender-0                         1/1     Running   0          1h
cnrm-resource-stats-recorder-77dc8cc4b6-mgpgp   1/1     Running   0          1h
cnrm-webhook-manager-58496b66f9-pqwhz           1/1     Running   0          1h
cnrm-webhook-manager-58496b66f9-wdcn4           1/1     Running   0          1h

namespaced-mode로 구성 커넥터가 설치된 경우 해당 네임스페이스에서 구성 커넥터 리소스 관리를 담당하는 각 네임스페이스에 대해 하나의 컨트롤러(cnrm-controller-manager) Pod가 지정됩니다.

다음을 실행하여 특정 네임스페이스를 담당하는 컨트롤러 Pod의 상태를 확인할 수 있습니다.

kubectl get pod -n cnrm-system \
    -l cnrm.cloud.google.com/scoped-namespace=NAMESPACE \
    -l cnrm.cloud.google.com/component=cnrm-controller-manager

NAMESPACE를 네임스페이스 이름으로 바꿉니다.

컨트롤러 로그 확인

컨트롤러 Pod는 구성 커넥터 리소스 조정과 관련된 정보 및 오류를 로깅합니다.

다음을 실행하여 컨트롤러 Pod의 로그를 확인할 수 있습니다.

kubectl logs -n cnrm-system \
    -l cnrm.cloud.google.com/component=cnrm-controller-manager \
    -c manager

namespaced-mode로 구성 커넥터가 설치된 경우 이전 명령어에서 결합된 모든 컨트롤러 포드의 로그를 표시합니다. 다음을 실행하여 특정 네임스페이스에 대해 컨트롤러 Pod 로그를 확인할 수 있습니다.

kubectl logs -n cnrm-system \
    -l cnrm.cloud.google.com/scoped-namespace=NAMESPACE \
    -l cnrm.cloud.google.com/component=cnrm-controller-manager \
    -c manager

NAMESPACE를 네임스페이스 이름으로 바꿉니다.

구성 커넥터 로그 검사 및 쿼리 방법을 자세히 알아보세요.

리소스 폐기 및 획득

경우에 따라 리소스에서 변경 불가능한 필드를 업데이트해야 할 수도 있습니다. 변경할 수 없는 필드는 수정할 수 없으므로 리소스를 폐기한 후 가져와야 합니다.

  1. 구성 커넥터 리소스의 YAML 구성을 업데이트하고 cnrm.cloud.google.com/deletion-policy 주석을 abandon으로 설정합니다.
  2. 업데이트된 YAML 구성을 적용하여 구성 커넥터 리소스의 삭제 정책을 업데이트합니다.
  3. 구성 커넥터 리소스를 폐기합니다.
  4. YAML 구성에서 변경해야 하는 변경할 수 없는 필드를 업데이트합니다.
  5. 업데이트된 YAML 구성을 적용하여 폐기된 리소스를 가져옵니다.

일반적인 문제

리소스가 5~15분마다 계속 업데이트됨

5~10분마다 구성 커넥터 리소스가 UpToDate 상태에서 Updating 상태로 계속 전환되면 구성 커넥터가 리소스의 원하는 상태와 실제 상태 간에 의도치 않은 차이를 감지하여 구성 커넥터에서 지속적으로 리소스를 업데이트하고 있을 가능성이 있습니다.

먼저 구성 커넥터 또는 Google Cloud 리소스(예: CI/CD 파이프라인, 커스텀 컨트롤러, 크론 작업 등)를 지속적으로 수정하는 외부 시스템이 없는지 확인합니다.

외부 시스템으로 인한 동작이 아닌 경우 Google Cloud가 구성 커넥터 리소스에 지정된 값을 변경하는지 확인합니다. 예를 들어 Google Cloud에서 필드 값의 형식 지정(예: 대문자 사용)을 변경하여 리소스의 원하는 상태와 실제 상태가 달라지는 경우도 있습니다.

REST API(예: ContainerCluster) 또는 Google Cloud CLI를 사용하여 Google Cloud 리소스의 상태를 가져옵니다. 그런 다음 이 상태를 구성 커넥터 리소스와 비교합니다. 값이 일치하지 않는 필드를 찾은 후 일치하도록 구성 커넥터 리소스를 업데이트합니다. 특히 Google Cloud에서 형식이 다시 지정된 값을 찾습니다. 예를 들어 GitHub 문제 #578#294를 참조하세요.

이 방법은 구성 커넥터와 Google Cloud 리소스 모델이 다르기 때문에 완벽한 방법은 아니지만 대부분의 의도치 않은 차이를 포착할 수 있습니다.

문제를 해결할 수 없는 경우 추가 도움말을 참조하세요.

네임스페이스 삭제가 "Terminating" 상태로 중단됨

namespaced-mode로 구성 커넥터가 설치되었고 해당 네임스페이스의 모든 구성 커넥터 리소스가 삭제되기 전 네임스페이스의 ConfigConnectorContext가 삭제된 경우 네임스페이스 삭제가 Terminating 상태로 중단될 수 있습니다. 네임스페이스의 ConfigConnectorContext가 삭제되면 해당 네임스페이스에 대해 구성 커넥터가 사용 중지되어 해당 네임스페이스에 있는 남은 구성 커넥터 리소스가 삭제되지 않습니다.

이 문제를 해결하려면 강제 정리를 수행하고 기본 Google Cloud 리소스를 이후에 수동으로 삭제해야 합니다.

이후에 이 문제가 발생하지 않도록 하려면 해당 네임스페이스의 모든 구성 커넥터 리소스가 Kubernetes에서 삭제된 후에만 ConfigConnectorContext를 삭제합니다. ConfigConnectorContext가 먼저 삭제될 수 있기 때문에 해당 네임스페이스에 있는 모든 구성 커넥터 리소스가 삭제되기 전에는 전체 네임스페이스 삭제를 수행하지 않아야 합니다.

또한 프로젝트 및 해당 하위 요소 또는 폴더 및 해당 하위 요소가 포함된 네임스페이스 삭제가 중단될 수 있는 방법을 참조하세요.

프로젝트가 삭제된 후 리소스 삭제가 "DeleteFailed" 상태로 중단됨

Google Cloud 프로젝트가 먼저 삭제된 경우 클라우드 커넥터 리소스 삭제가 DeleteFailed 상태로 중단될 수 있습니다.

이 문제를 해결하려면 구성 커넥터가 Kubernetes에서 남은 하위 리소스를 삭제할 수 있도록 Google Cloud에서 프로젝트를 복원합니다. 또는 강제 정리를 수행할 수 있습니다.

이후에 이 문제가 발생하지 않도록 하려면 모든 하위 구성 커넥터 리소스가 Kubernetes에서 삭제된 후에만 Google Cloud 프로젝트를 삭제합니다. Project 리소스가 먼저 삭제될 수 있기 때문에 Project 리소스 및 해당 하위 구성 커넥터 리소스가 모두 포함될 수 있는 전체 네임스페이스 삭제를 수행하지 않아야 합니다.

Compute Engine 메타데이터가 정의되지 않음

Compute Engine 메타데이터가 정의되지 않았다는 메시지와 함께 구성 커넥터 리소스가 UpdateFailed 상태로 표시되면 구성 커넥터에 사용되는 IAM 서비스 계정이 존재하지 않기 때문일 수 있습니다.

UpdateFailed 메시지 예시:

Update call failed: error fetching live state: error reading underlying
resource: summary: Error when reading or editing SpannerInstance
"my-project/my-spanner- instance": Get
"https://spanner.googleapis.com/v1/projects/my-project/instances/my-spanner-instance?alt=json":
metadata: Compute Engine metadata "instance/service-accounts/default/token?
scopes=https%!A(MISSING)%!F(MISSING)%!F(MISSING)www.googleapis.com%!F(MISSING)auth%!F(MISSING)compute%!C(MISSING)https%!A(MISSING)%!F(MISSING)%!F(MISSING)www.googleapis.com%!F(MISSIN
G)auth%!F(MISSING)cloud-platform%!C(MISSING)https%!A(MISSING)%!F(MISSING)%!F(MISSING)www.googleapis.com%!F(MISSING)auth%!F(MISSING)cloud-identity%!C(MISSING)https%!A(MISSING)%!F(MISS
ING)%!F(MISSING)www.googleapis.com%!F(MISSING)auth%!F(MISSING)ndev.clouddns.readwrite%!C(MISSING)https%!A(MISSING)%!F(MISSING)%!F(MISSING)www.googleapis.com%!F(MISSING)auth%!F(MISSIN
G)devstorage.full_control%!C(MISSING)https%!A(MISSING)%!F(MISSING)%!F(MISSING)www.googleapis.com%!F(MISSING)auth%!F(MISSING)userinfo.email%!C(MISSING)https%!A(MISSING)%!F(MISSING)%!F
(MISSING)www.googleapis.com%!F(MISSING)auth%!F(MISSING)drive.readonly" not
defined, detail:

이 문제를 해결하려면 구성 커넥터에 사용되는 IAM 서비스 계정이 존재하는지 확인합니다.

이후에 이 문제가 발생하지 않도록 하려면 구성 커넥터 설치 안내를 참조하세요.

오류 403: 요청의 인증 범위 부족

인증 범위 부족으로 인해 403 오류를 나타내는 메시지와 함께 구성 커넥터 리소스가 UpdateFailed 상태로 표시되면 GKE 클러스터에 워크로드 아이덴티티가 사용 설정되지 않았기 때문일 수 있습니다.

UpdateFailed 메시지 예시:

Update call failed: error fetching live state: error reading underlying
resource: summary: Error when reading or editing SpannerInstance
"my-project/my-spanner-instance": googleapi: Error 403: Request had
insufficient authentication scopes.

문제를 조사하려면 다음 단계를 완료하세요.

  1. 다음 Pod 구성을 wi-test.yaml로 저장합니다.

    apiVersion: v1
    kind: Pod
    metadata:
      name: workload-identity-test
      namespace: cnrm-system
    spec:
      containers:
      - image: google/cloud-sdk:slim
        name: workload-identity-test
        command: ["sleep","infinity"]
      serviceAccountName: cnrm-controller-manager
    

    네임스페이스 모드를 사용하여 구성 커넥터를 설치한 경우 serviceAccountNamecnrm-controller-manager-NAMESPACE여야 합니다. NAMESPACE를 설치 중에 사용한 네임스페이스로 바꿉니다.

  2. GKE 클러스터에 Pod를 만듭니다.

    kubectl apply -f wi-test.yaml
    
  3. 포드에서 대화형 세션을 엽니다.

    kubectl exec -it workload-identity-test \
        --namespace cnrm-system \
        -- /bin/bash
    
  4. ID를 나열합니다.

    gcloud auth list
    
  5. 나열된 ID가 리소스에 결합된 Google 서비스 계정과 일치하는지 확인합니다.

    Compute Engine 기본 서비스 계정이 표시되면 GKE용 워크로드 아이덴티티 제휴가 GKE 클러스터 또는 노드 풀에서 사용 설정되지 않은 것입니다.

  6. 대화형 세션을 종료한 후 GKE 클러스터에서 포드를 삭제합니다.

    kubectl delete pod workload-identity-test \
        --namespace cnrm-system
    

이 문제를 해결하려면 GKE용 워크로드 아이덴티티 제휴가 사용 설정된 GKE 클러스터를 사용합니다.

GKE용 워크로드 아이덴티티 제휴가 사용 설정된 GKE 클러스터에서 계속 동일한 오류가 표시되면 클러스터의 노드 풀에서도 GKE용 워크로드 아이덴티티 제휴를 사용 설정했는지 다시 확인합니다. 기존 노드 풀에서 GKE용 워크로드 아이덴티티 제휴 사용 설정에 대해 자세히 알아보세요. 구성 커넥터가 어디에서든 실행될 수 있기 때문에 모든 클러스터의 노드 풀에서 GKE용 워크로드 아이덴티티 제휴를 사용 설정하는 것이 좋습니다.

403 금지됨: 호출자에게 권한 없음, GKE용 워크로드 아이덴티티 제휴 문서 참조

구성 커넥터 리소스에 GKE용 워크로드 아이덴티티 제휴로 인해 403 오류를 나타내는 메시와 함께 UpdateFailed 상태가 표시되면 구성 커넥터의 Kubernetes 서비스 계정에 IAM 서비스 계정을 GKE용 워크로드 아이덴티티 제휴 사용자로 가장할 수 있는 적합한 IAM 권한이 없기 때문일 수 있습니다.

UpdateFailed 메시지 예시:

Update call failed: error fetching live state: error reading underlying
resource: summary: Error when reading or editing SpannerInstance
"my-project/my-spanner- instance": Get
"https://spanner.googleapis.com/v1/projects/my-project/instances/my-spanner-instance?alt=json":
compute: Received 403 `Unable to generate access token; IAM returned 403
Forbidden: The caller does not have permission
This error could be caused by a missing IAM policy binding on the target IAM
service account.
For more information, refer to the Workload Identity Federation for GKE documentation:
  https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity#creating_a_relationship_between_ksas_and_gsas

이후에 이 문제를 해결하고 이 문제가 발생하지 않도록 하려면 구성 커넥터 설치 안내를 참조하세요.

오류 403: 호출자에게 IAM 권한 없음

구성 커넥터 리소스에 호출자에게 IAM 권한이 없음을 나타내는 메시지와 함께 UpdateFailed 상태가 표시되면 구성 커넥터에서 사용되는 IAM 서비스 계정에 Google Cloud 서비스를 관리하는 데 필요하다고 메시지에 표시된 IAM 권한이 없기 때문일 수 있습니다.

UpdateFailed 메시지 예시:

Update call failed: error fetching live state: error reading underlying
resource: summary: Error when reading or editing SpannerInstance
"my-project/my-spanner- instance": googleapi: Error 403: Caller is missing IAM
permission spanner.instances.get on resource
projects/my-project/instances/my-spanner-instance., detail:

IAM 서비스 계정에 적절한 IAM 권한을 부여한 후에도 동일한 오류가 계속 표시되면 올바른 프로젝트에서 리소스를 생성 중인지 확인합니다. 구성 커넥터 리소스의 spec.projectRef 필드(또는 리소스가 spec.projectRef 필드를 지원하지 않는 경우 해당 cnrm.cloud.google.com/project-id 주석)를 확인하고 리소스가 올바른 프로젝트를 참조하는지 확인합니다. 리소스 또는 네임스페이스 모두 대상 프로젝트가 지정되지 않은 경우 구성 커넥터에서 네임스페이스 이름이 프로젝트 ID로 사용됩니다. 프로젝트 범위 리소스에 대한 대상 프로젝트 구성 방법을 자세히 알아보세요.

계속 동일한 오류가 표시되면 GKE용 워크로드 아이덴티티 제휴가 GKE 클러스터에 사용 설정되었는지 확인합니다.

이후에 이 문제가 발생하지 않도록 하려면 구성 커넥터 설치 안내를 참조하세요.

구성 커넥터 부가기능 설치에서 지원되지 않는 버전

Config Connector 부가기능을 성공적으로 사용 설정할 수 없으면 다음 오류 메시지가 표시됩니다. Node version 1.15.x-gke.x s unsupported. 이 오류를 해결하려면 GKE 클러스터의 버전이 버전 및 기능 요구사항을 충족하는지 확인합니다.

클러스터의 모든 유효 버전을 가져오려면 다음 명령어를 실행합니다.

gcloud container get-server-config --format "yaml(validMasterVersions)" \
    --zone ZONE

ZONE을 Compute Engine 영역으로 바꿉니다.

요구사항을 충족하는 버전을 목록에서 선택합니다.

GKE용 워크로드 아이덴티티 제휴 또는 GKE Monitoring이 사용 중지된 경우에도 오류 메시지가 표시됩니다. 오류를 해결하려면 해당 기능이 사용 설정되었는지 확인합니다.

변경 불가능한 필드를 변경할 수 없음

구성 커넥터는 허용된 상태라도 변경 불가능한 필드에 대한 업데이트를 거부합니다.

예를 들어 변경 불가능한 필드를 kubectl apply로 업데이트하면 명령어가 즉시 실패합니다.

즉, GitOps와 같이 리소스를 계속 다시 적용하는 도구는 허용 오류를 처리할 수 없는 리소스를 업데이트할 때 자체적으로 작업이 중단될 수 있습니다.

구성 커넥터에서는 변경 불가능한 필드에 대한 업데이트가 허용되지 않으므로 이러한 업데이트를 수행하는 유일한 방법은 해당 리소스를 삭제하고 다시 만드는 방법뿐입니다.

업데이트가 없는 경우 변경할 수 없는 필드를 업데이트하는 중에 오류 발생

구성 커넥터를 사용하여 Google Cloud 리소스를 만들거나 가져온 직후에 구성 커넥터 리소스 상태에 다음 오류가 표시될 수 있습니다.

  • Update call failed: error applying desired state: infeasible update: ({true \<nil\>}) would require recreation (예시)

  • Update call failed: cannot make changes to immutable field(s) (예시)

실제로 리소스를 업데이트했다는 의미는 아니지만, Google Cloud API가 구성 커넥터 리소스에서 사용자가 관리하는 변경할 수 없는 필드를 변경했기 때문일 수 있습니다. 이로 인해 변경할 수 없는 필드의 원하는 상태와 라이브 상태가 일치하지 않습니다.

구성 커넥터 리소스에서 이러한 변경할 수 없는 필드의 값을 실시간 상태와 일치하도록 업데이트하여 이 문제를 해결할 수 있습니다. 이를 수행하려면 다음 단계를 완료해야 합니다.

  1. 구성 커넥터 리소스의 YAML 구성을 업데이트하고 cnrm.cloud.google.com/deletion-policy 주석을 abandon으로 설정합니다.
  2. 업데이트된 YAML 구성을 적용하여 구성 커넥터 리소스의 삭제 정책을 업데이트합니다.
  3. 구성 커넥터 리소스를 폐기합니다.
  4. gcloud CLI를 사용하여 해당 Google Cloud 리소스의 실시간 상태를 출력합니다.
  5. gcloud CLI 출력과 구성 커넥터 리소스의 YAML 구성 간의 불일치를 찾고 YAML 구성에서 해당 필드를 업데이트합니다.
  6. 업데이트된 YAML 구성을 적용하여 폐기된 리소스를 가져옵니다.

리소스에 상태 없음

리소스에 status 필드가 없으면 구성 커넥터가 올바르게 작동되지 않을 가능성이 높습니다. 구성 커넥터가 실행 중인지 확인하세요.

'Foo' 종류의 일치 항목 없음

이 오류가 발생했으면 Kubernetes 클러스터에 설치된 Foo 리소스 종류에 대한 CRD가 없기 때문일 수 있습니다.

해당 종류가 구성 커넥터에서 지원되는 리소스 종류인지 확인합니다.

해당 종류가 지원되면 구성 커넥터 설치가 오래되었거나 잘못되었기 때문입니다.

GKE 부가기능을 사용하여 구성 커넥터를 설치한 경우 설치가 자동으로 업그레이드됩니다. 구성 커넥터를 수동으로 설치한 경우에는 수동 업그레이드를 수행해야 합니다.

GitHub 저장소에서 각 구성 커넥터 버전에서 지원되는 리소스 종류를 확인하세요. 예를 들어 여기에서는 구성 커넥터 v1.44.0에서 지원되는 종류를 보여줍니다.

라벨이 Google Cloud 리소스로 전파되지 않음

Config Connector는 metadata.labels에 있는 라벨을 기본 Google Cloud 리소스에 전파합니다. 하지만 일부 Google Cloud 리소스에서는 라벨이 지원되지 않습니다. 리소스의 REST API 문서에서 라벨이 지원되는지 확인합니다. 예를 들어 PubSubTopic의 API 문서를 참조하세요.

웹훅 x509 호출 실패: 인증서에서 기존 일반 이름 필드 사용

다음 예시와 비슷한 오류가 표시되면 인증서에 문제가 있을 수 있습니다.

Error from server (InternalError): error when creating "/mnt/set-weaver-dns-record.yml": Internal error occurred: failed calling webhook "annotation-defaulter.cnrm.cloud.google.com": Post "https://cnrm-validating-webhook.cnrm-system.svc:443/annotation-defaulter?timeout=30s": x509: certificate relies on legacy Common Name field, use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0

이 문제를 해결하려면 관련 인증서와 포드를 삭제합니다.

kubectl delete -n cnrm-system secrets cnrm-webhook-cert-abandon-on-uninstall
kubectl delete -n cnrm-system secrets cnrm-webhook-cert-cnrm-validating-webhook
kubectl delete -n cnrm-system pods -l "cnrm.cloud.google.com/component=cnrm-webhook-manager"

이러한 리소스를 삭제하면 올바른 인증서가 다시 생성됩니다.

이 오류에 대한 자세한 내용은 GitHub 문제를 참조하세요.

리소스 이름의 특수문자로 인한 오류

Kubernetes metadata.name 필드의 특수문자가 유효하지 않습니다. 다음 예시와 비슷한 오류가 표시되면 리소스의 metadata.name에 특수문자가 있는 값이 있을 수 있습니다.

a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')

예를 들어 다음 SQLUser 리소스에는 metadata.name에 잘못된 문자가 포함되어 있습니다.

apiVersion: sql.cnrm.cloud.google.com/v1beta1
kind: SQLUser
metadata:
  name: test.example@example-project.iam
spec:
  instanceRef:
    name: test-cloudsql-db
  type: "CLOUD_IAM_USER"

이 리소스를 만들려고 하면 다음 오류가 발생합니다.

Error from server (Invalid): error when creating "sqlusercrd.yaml": SQLUser.sql.cnrm.cloud.google.com "test.example@example-project.iam" is invalid: metadata.name: Invalid value: "test.example@example-project.iam": a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')

유효한 Kubernetes 이름은 아니지만 유효한 Google Cloud 리소스 이름을 리소스에 지정하려면 다음 예시와 같이 resourceID 필드를 사용하면 됩니다.

apiVersion: sql.cnrm.cloud.google.com/v1beta1
kind: SQLUser
metadata:
  name: 'test'
spec:
  instanceRef:
    name: sqlinstance-sample-postgresql
  host: "%"
  type: CLOUD_IAM_USER
  resourceID: test.example@example-project.iam

이 구성을 사용하면 구성 커넥터가 resourceID 대신 metadata.name을 리소스 이름으로 사용합니다.

리소스 사양에서 필드를 삭제할 수 없음

(리소스의 .yaml 파일을 업데이트하고 다시 적용하거나 kubectl edit를 사용해 리소스 사양을 수정하여) 구성 커넥터 리소스 사양에서 필드를 삭제해도 실제로는 구성 커넥터 리소스의 사양 또는 기본 Google Cloud 리소스에서 이 필드가 삭제되지 않습니다. 대신 사양에서 필드를 삭제하면 해당 필드가 외부에서 관리됩니다.

기본 Google Cloud 리소스에서 필드 값을 비워 두거나 기본값으로 변경하려면 구성 커넥터 리소스 사양의 필드를 0으로 만들어야 합니다.

  • 목록 유형 필드의 경우 []를 사용하여 필드를 빈 목록으로 설정합니다.

    다음 예시에서는 삭제하려는 targetServiceAccounts 필드를 보여줍니다.

    spec:
      targetServiceAccounts:
        - external: "foo-bar@foo-project.iam.gserviceaccount.com"
        - external: "bar@foo-project.iam.gserviceaccount.com"
    

    이 필드를 삭제하려면 값을 빈 값으로 설정합니다.

    spec:
      targetServiceAccounts: []
    
  • 기본 유형 필드의 경우 다음 중 하나를 사용하여 필드를 빈 값으로 설정합니다.

    유형 빈 값
    문자열 ""
    bool "false"
    정수 0

    다음 예시에서는 삭제하려는 identityNamespace 필드를 보여줍니다.

    spec:
      workloadIdentityConfig:
        identityNamespace: "foo-project.svc.id.goog"
    

    이 필드를 삭제하려면 값을 빈 값으로 설정합니다.

    spec:
      workloadIdentityConfig:
        identityNamespace: ""
    
  • 객체 유형 필드의 경우 현재 구성 커넥터에서 전체 객체 유형 필드를 'NULL'로 설정할 수 있는 쉬운 방법은 없습니다. 위의 안내에 따라 객체 유형의 하위 필드를 빈 값 또는 기본값으로 설정하여 작동하는지 확인할 수 있습니다.

KNV2005: syncer가 리소스를 과도하게 업데이트함

구성 동기화를 사용 중이고 구성 커넥터 리소스에 대해 KNV2005 오류가 표시될 경우, 구성 동기화 및 구성 커넥터가 리소스를 두고 경합하고 있을 가능성이 높습니다.

로그 메시지 예:

KNV2005: detected excessive object updates, approximately 6 times per
minute. This may indicate Config Sync is fighting with another controller over
the object.

구성 동기화 및 구성 커넥터에서 동일한 필드를 계속 다른 값으로 업데이트하는 경우 리소스를 놓고 '경합'한다고 표현합니다. 하나가 업데이트되면 다른 하나가 작업을 수행하고 리소스를 업데이트하도록 트리거되고, 그로 인해 다른 하나가 작업을 수행하고 리소스를 업데이트하게 됩니다.

대부분의 필드에서는 경합이 문제가 되지 않습니다. 구성 동기화에 지정된 필드는 구성 커넥터에 의해 변경되지 않는 반면, 구성 동기화에 지정되지 않고 구성 커넥터에서 기본값으로 지정된 필드는 구성 동기화에 의해 무시됩니다. 따라서 대부분의 필드에서 구성 동기화와 구성 커넥터가 동일한 필드를 서로 다른 값으로 업데이트하지 않습니다.

한 가지 예외로 목록 필드가 있습니다. 구성 커넥터가 객체 필드의 하위 필드를 기본값으로 지정하는 방법과 유사하게 구성 커넥터에서 목록 내 객체의 하위 필드를 기본값으로 지정할 수도 있습니다. 그러나 구성 커넥터 리소스의 목록 필드는 원자적이므로 하위 필드의 기본값 지정이 목록 값을 완전히 변경하는 것으로 간주됩니다.

따라서 구성 동기화가 목록 필드를 설정하고 구성 커넥터가 해당 목록 내의 하위 필드를 기본값으로 지정하면 구성 동기화 및 구성 커넥터가 결국 경합하게 됩니다.

이 문제를 해결하려면 다음 옵션을 사용하세요.

  1. 구성 커넥터가 리소스를 설정하려는 항목과 일치하도록 구성 동기화 저장소의 리소스 매니페스트를 업데이트합니다.

    이를 위한 방법 중 하나는 일시적으로 구성 동기화를 중지하고, 구성 커넥터가 리소스 조정을 완료할 때까지 기다린 후 Kubernetes API 서버의 리소스와 일치하도록 리소스 매니페스트를 업데이트하는 것입니다.

  2. client.lifecycle.config.k8s.io/mutation 주석을 ignore로 설정하여 구성 동기화가 Kubernetes API 서버의 리소스 업데이트에 반응하는 것을 중지합니다. 구성 동기화가 객체 변형을 무시하도록 하는 방법을 자세히 알아보세요.

  3. 리소스에서 cnrm.cloud.google.com/state-into-spec 주석을 absent로 설정하여 구성 커넥터가 리소스 사양을 완전히 업데이트하지 못하도록 합니다. 이 주석은 모든 리소스에 지원되지 않습니다. 리소스에서 주석을 지원하는지 확인하려면 해당 리소스 참조 페이지를 확인하세요. 주석에 대해 자세히 알아보세요.

failed calling webhook

구성 커넥터를 제거할 수 없는 상태가 될 수 있습니다. 일반적으로 구성 커넥터 CRD를 삭제하기 전에 구성 커넥터 부가기능을 사용했다가 사용 중지할 때 이러한 상황이 발생합니다. 제거를 시도하면 다음과 비슷한 오류가 표시됩니다.

error during reconciliation: error building deployment objects: error finalizing the deletion of Config Connector system components deployed by ConfigConnector controller: error waiting for CRDs to be deleted: error deleting CRD accesscontextmanageraccesslevels.accesscontextmanager.cnrm.cloud.google.com: Internal error occurred: failed calling webhook "abandon-on-uninstall.cnrm.cloud.google.com": failed to call webhook: Post "https://abandon-on-uninstall.cnrm-system.svc:443/abandon-on-uninstall?timeout=3s": service "abandon-on-uninstall" not found

이 오류를 해결하려면 먼저 웹훅을 수동으로 삭제해야 합니다.

kubectl delete validatingwebhookconfiguration abandon-on-uninstall.cnrm.cloud.google.com --ignore-not-found --wait=true
kubectl delete validatingwebhookconfiguration validating-webhook.cnrm.cloud.google.com --ignore-not-found --wait=true
kubectl delete mutatingwebhookconfiguration mutating-webhook.cnrm.cloud.google.com --ignore-not-found --wait=true

그런 다음 구성 커넥터를 제거하면 됩니다.

IAMPolicy, IAMPartialPolicy, IAMPolicyMember로 오류 업데이트

서비스 계정을 사용하는 IAMPolicy, IAMPartialPolicy, IAMPolicyMember 리소스를 삭제하기 전에 IAMServiceAccount 구성 커넥터 리소스를 삭제하면 구성 커넥터가 조정 중에 IAM 리소스에서 참조된 서비스 계정을 찾을 수 없습니다. 그러면 UpdateFailed 상태가 되며 다음과 같은 오류 메시지가 표시됩니다.

Update call failed: error setting policy member: error applying changes: summary: Request `Create IAM Members roles/[MYROLE] serviceAccount:[NAME]@[PROJECT_ID].iam.gserviceaccount.com for project \"projects/[PROJECT_ID]\"` returned error: Error applying IAM policy for project \"projects/[PROJECT_ID]\": Error setting IAM policy for project \"projects/[PROJECT_ID]\": googleapi: Error 400: Service account [NAME]@[PROJECT_ID].iam.gserviceaccount.com does not exist., badRequest

이 문제를 해결하려면 서비스 계정을 확인하고 해당 IAM 리소스에 필요한 서비스 계정이 삭제되었는지 확인합니다. 서비스 계정이 삭제된 경우 관련 IAM 구성 커넥터 리소스도 정리합니다. IAMPolicyMember의 경우 전체 리소스를 삭제합니다. IAMPolicyIAMParitialPolicy의 경우 삭제된 서비스 계정이 포함된 바인딩만 삭제합니다. 그러나 이를 정리해도 Google Cloud 역할 바인딩이 즉시 삭제되지는 않습니다. 삭제된 서비스 계정이 보관되므로 Google Cloud 역할 바인딩이 60일 동안 보관됩니다. 자세한 내용은 서비스 계정 삭제에 대한 Google Cloud IAM 문서를 참조하세요.

이 문제를 방지하려면 참조된 IAMServiceAccount를 삭제하기 전에 항상 IAMPolicy, IAMPartialPolicy,IAMPolicyMember 구성 커넥터 리소스를 정리해야 합니다.

구성 커넥터에서 삭제한 리소스

구성 커넥터는 외부 원인 없이 리소스를 삭제하지 않습니다. 예를 들어 kubectl delete를 실행하거나, Argo CD와 같은 구성 관리 도구를 사용하거나, 맞춤설정된 API 클라이언트를 사용하면 리소스가 삭제될 수 있습니다.

구성 커넥터가 클러스터의 일부 리소스를 시작하고 삭제했다고 오해하는 경우가 많습니다. 예를 들어 구성 커넥터를 사용하는 경우, 컨테이너 로그 메시지 또는 Kubernetes 클러스터 감사 로그에서 특정 리소스에 대한 구성 커넥터 컨트롤러 관리자의 삭제 요청이 표시될 수 있습니다. 이러한 삭제 요청은 외부 트리거의 결과이며 구성 커넥터는 삭제 요청을 조정하려고 시도합니다.

리소스가 삭제된 이유를 확인하려면 해당 리소스로 전송된 첫 번째 삭제 요청을 살펴봐야 합니다. 이를 살펴보는 가장 좋은 방법은 Kubernetes 클러스터 감사 로그를 조사하는 것입니다.

예를 들어 GKE를 사용하는 경우 GKE 클러스터 감사 로그에 Cloud Logging을 사용하여 쿼리할 수 있습니다. 예를 들어 네임스페이스 bar에서 foo라는 BigQueryDataset 리소스에 대한 초기 삭제 요청을 찾으려면 다음과 같은 쿼리를 실행합니다.

resource.type="k8s_cluster"
resource.labels.project_id="my-project-id"
resource.labels.cluster_name="my-cluster-name"
protoPayload.methodName="com.google.cloud.cnrm.bigquery.v1beta1.bigquerydatasets.delete"
protoPayload.resourceName="bigquery.cnrm.cloud.google.com/v1beta1/namespaces/bar/bigquerydatasets/foo"

이 쿼리를 사용하여 첫 번째 삭제 요청을 찾은 다음 해당 삭제 로그 메시지의 authenticationInfo.principalEmail을 확인하여 삭제 원인을 파악합니다.

컨트롤러 포드 OOMKilled

구성 커넥터 컨트롤러 포드에 OOMKilled 오류가 표시되면 컨테이너 또는 전체 포드가 허용된 것보다 많은 메모리를 사용했기 때문에 종료되었다는 의미입니다. 이는 kubectl describe 명령어를 실행하여 확인할 수 있습니다. 포드 상태가 OOMKilled 또는 Terminating로 표시될 수 있습니다. 또한 포드의 이벤트 로그를 조사하면 OOM 관련 이벤트 발생을 확인할 수 있습니다.

kubectl describe pod POD_NAME -n cnrm-system

POD_NAME을 문제를 해결하려는 포드로 바꿉니다.

이 문제를 해결하려면 ControllerResource 커스텀 리소스를 사용하여 포드의 메모리 요청과 메모리 한도를 늘리면 됩니다.

PodSecurityPolicy의 업그레이드 차단

구성 커넥터 부가기능에서 수동 설치로 전환하고 구성 커넥터를 새 버전으로 업그레이드한 후 PodSecurityPolicy를 사용하면 cnrm 포드의 업데이트가 차단될 수 있습니다.

PodSecurityPolicy가 업그레이드를 막는지 확인하려면 config-connector-operator 이벤트를 확인하고 다음과 유사한 오류를 찾습니다.

create Pod configconnector-operator-0 in StatefulSet configconnector-operator failed error: pods "configconnector-operator-0" is forbidden: PodSecurityPolicy: unable to admit pod: [pod.metadata.annotations[seccomp.security.alpha.kubernetes.io/pod]: Forbidden: seccomp may not be set pod.metadata.annotations[container.seccomp.security.alpha.kubernetes.io/manager]: Forbidden: seccomp may not be set]

이 문제를 해결하려면 오류에 언급된 주석에 해당하는 PodSecurityPolicy에서 주석을 지정해야 합니다. 이전 예시에서 주석은 seccomp.security.alpha.kubernetes.io입니다.

강제 정리

구성 커넥터 리소스가 삭제 중 중단되었고 이를 단순히 Kubernetes 클러스터에서 없애고 싶으면 해당 종료자를 삭제하여 강제로 삭제할 수 있습니다.

kubectl edit를 사용하여 리소스를 수정하고, metadata.finalizers 필드를 삭제해서 리소스 종료자를 삭제하고 Kubernetes API 서버에 대해 변경 사항을 보존할 수 있도록 파일을 저장할 수 있습니다.

리소스의 종료자를 삭제하면 Kubernetes 클러스터에서 리소스가 즉시 삭제되기 때문에 구성 커넥터가 기본 Google Cloud 리소스 삭제를 완료할 기회를 얻지 못할 수 있습니다(반드시 그럴 필요는 없음). 즉, 이후에 Google Cloud 리소스를 수동으로 삭제해야 할 수 있습니다.

모니터링

측정항목

Prometheus를 사용하여 구성 커넥터에서 측정항목을 수집하고 표시할 수 있습니다.

로깅

모든 구성 커넥터 Pod가 JSON 형식으로 구조화된 로그를 출력합니다.

컨트롤러 Pod의 로그는 특히 리소스 조정으로 문제를 디버깅하는 데 유용합니다.

로그 메시지에서 다음 필드로 필터링하여 특정 리소스의 로그를 쿼리할 수 있습니다.

  • logger: 소문자로 표시된 리소스 종류를 포함합니다. 예를 들어 PubSubTopic 리소스에는 pubsubtopic-controllerlogger가 포함됩니다.
  • resource.namespace: 리소스의 네임스페이스를 포함합니다.
  • resource.name: 리소스 이름을 포함합니다.

고급 로그 쿼리를 위한 Cloud Logging 사용

GKE를 사용하는 경우 다음 쿼리를 사용하여 특정 리소스에 대해 Cloud Logging을 사용하여 로그를 쿼리할 수 있습니다.

# Filter to include only logs coming from the controller Pods
resource.type="k8s_container"
resource.labels.container_name="manager"
resource.labels.namespace_name="cnrm-system"
labels.k8s-pod/cnrm_cloud_google_com/component="cnrm-controller-manager"

# Filter to include only logs coming from a particular GKE cluster
resource.labels.cluster_name="GKE_CLUSTER_NAME"
resource.labels.location="GKE_CLUSTER_LOCATION"

# Filter to include only logs for a particular Config Connector resource
jsonPayload.logger="RESOURCE_KIND-controller"
jsonPayload.resource.namespace="RESOURCE_NAMESPACE"
jsonPayload.resource.name="RESOURCE_NAME"

다음을 바꿉니다.

  • GKE_CLUSTER_NAME은 Config Connector를 실행하는 GKE 클러스터의 이름입니다.
  • GKE_CLUSTER_LOCATION을 Config Connector를 실행하는 GKE 클러스터 위치로 바꿉니다. 예를 들면 us-central1입니다.
  • RESOURCE_KIND: 리소스 종류가 소문자로 표시됩니다. 예를 들면 pubsubtopic입니다.
  • RESOURCE_NAMESPACE을 리소스의 네임스페이스로 바꿉니다.
  • RESOURCE_NAME을 리소스의 이름으로 바꿉니다.

추가 도움말

추가 도움을 받으려면 GitHub에 문제를 제출하거나 Google Cloud 지원팀에 문의하세요.