리소스 경합 문제 해결

이 페이지에서는 Google Distributed Cloud 환경에서 리소스 경합 문제를 식별하고 해결하는 방법을 설명합니다.

추가 지원이 필요하면 Cloud Customer Care에 문의하세요.

개요

경우에 따라 Google Distributed Cloud에 리소스 경합이 발생하여 컨테이너의 속도가 느려지거나 성능이 저하되거나 종료될 수 있습니다. 이 문제는 컨테이너의 높은 CPU 또는 메모리 소비로 인해 발생할 수 있습니다.

CPU 및 메모리 관리 방식

  • CPU:

    • 포드가 포드의 컨테이너에 지정된 CPU 요청에 따라 노드에 예약됩니다.
    • 포드의 컨테이너는 컨테이너에 지정된 한도보다 많은 CPU를 사용할 수 없습니다.
    • 컨테이너의 CPU 사용량은 CPU 한도로 제한됩니다.
    • CPU 사용량이 노드 수준에서 제한되면 요청에 비례하는 CPU 주기가 컨테이너에 자동으로 할당됩니다.

    리소스 요청이 있는 포드 예약 방법에 대해 자세히 알아보세요.

  • 메모리:

    • 포드가 포드의 컨테이너에 지정된 메모리 요청에 따라 노드에 예약됩니다.
    • 컨테이너는 컨테이너에서 지정한 한도보다 더 많은 메모리를 사용할 수 없습니다.
    • 메모리 한도를 지정하지 않으면 컨테이너는 노드에서 사용 가능한 모든 메모리를 사용할 수 있습니다. 그러면 시스템이 OOM-Killer(메모리 부족 종료)를 트리거하고 우선순위가 낮은 포드를 제거할 수 있습니다.

자세한 내용은 CPU 리소스 할당, Kubernetes에서 메모리 리소스 할당, GKE Enterprise 측정항목을 참조하세요.

문제

컨테이너 속도 저하

CPU 경합 문제로 인해 컨테이너가 느려질 수 있습니다. 가능한 이유는 다음과 같습니다.

컨테이너의 높은 CPU 사용률:

CPU 요청에 비례하는 CPU 주기가 할당되지 않거나 CPU 요청이 컨테이너에 필요한 것보다 너무 낮게 설정되면 컨테이너가 느려질 수 있습니다. 컨테이너의 CPU 사용률에 대한 CPU 한도의 비율을 확인하세요.

Google Cloud 콘솔 > Monitoring > 측정항목 탐색기MQL 편집기에서 다음 쿼리를 실행합니다.

  fetch k8s_container
  | metric 'kubernetes.io/anthos/container/cpu/limit_utilization'
  | group_by 1m, [value_limit_utilization_mean: mean(value.limit_utilization)]
  | filter resource.cluster_name == 'CLUSTER_NAME'
  | filter resource.container_name == 'CONTAINER_NAME'
  | filter resource.pod_name == 'POD_NAME'
  | filter resource.namespace_name == 'NAMESPACE_NAME'
  | every 1m

그런 후 다음 중 하나를 수행합니다.

노드의 높은 CPU 사용률

사용률에 대한 CPU 비율이 포드의 개별 컨테이너에 부족하다면 노드에서 실행 중인 컨테이너 집합에 할당할 CPU 주기가 충분하지 않기 때문일 수 있습니다. 따라서 다음 단계를 수행하여 노드에서 할당 가능한 CPU에 대한 실제 CPU 사용량의 비율을 확인합니다.

  1. 느리게 작동하는 포드의 노드를 가져옵니다.

    kubectl get pod –kubeconfig CLUSTER_KUBECONFIG --namespace NAMESPACE POD --output wide
    
  2. Google Cloud 콘솔 > Monitoring > 측정항목 탐색기MQL 편집기에서 다음 쿼리를 실행합니다.

    fetch k8s_node
    | metric 'kubernetes.io/anthos/node/cpu/allocatable_utilization'
    | group_by 1m,
        [value_allocatable_utilization_mean: mean(value.allocatable_utilization)]
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.node_name == 'NODE_NAME'
    | every 1m
    

    이 비율이 높으면(>=0.8) 노드에 CPU 주기가 부족하고 초과 구독되었음을 의미합니다. 이 단계에 따라 해당 노드에서 다른 모든 포드의 CPU 사용량을 확인하고 CPU를 더 사용하는 다른 컨테이너가 있는지 조사합니다.

    1. 노드의 모든 포드를 가져옵니다.
    kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=NODE_NAME
    
    1. 각 컨테이너의 CPU 사용률을 확인합니다.
    fetch k8s_container
    | metric 'kubernetes.io/anthos/container/cpu/limit_utilization'
    | group_by 1m, [value_limit_utilization_mean: mean(value.limit_utilization)]
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.container_name == 'CONTAINER_NAME'
    | filter resource.pod_name == 'POD_NAME'
    | filter resource.namespace_name == 'NAMESPACE_NAME'
    | every 1m
    

    노드에서 많은 CPU를 사용하는 다른 컨테이너가 있는 경우 느리게 작동하는 컨테이너의 CPU 요청 및 한도를 늘립니다. 그러면 필요한 CPU 주기를 가져오기 위해 다른 노드에 포드가 다시 생성됩니다.

시스템 포드가 느리게 작동하는 경우 Google 지원팀에 문의하세요.

vSphere 수준에서 CPU 초과 구독

노드 또는 포드에서 CPU 소비량이 많지 않은데도 컨테이너가 느리다면 vSphere 수준에서 VM이 초과 구독되었을 수 있습니다. 따라서 노드가 기본 가상화에서 예상되는 CPU 주기를 가져올 수 없습니다.

다음 단계를 수행하여 VM이 초과 구독되었는지 확인합니다. 초과 구독이 감지되면 다음을 시도합니다.

  • 일부 VM을 다른 호스트로 이동합니다.
  • 호스트의 VM당 vCPU 수를 평가하고 줄입니다.
  • GKE Enterprise VM에 리소스를 더 할당합니다.
  • 컨테이너의 CPU 요청과 한도를 늘립니다. 그러면 필요한 CPU 주기를 가져오기 위해 다른 노드에 포드가 다시 생성됩니다.

포드에 OOMKilled(메모리 부족-종료)가 발생함

메모리 누수 또는 컨테이너의 메모리 요청 및 한도 구성으로 인해 포드에 OOMKilled가 발생할 수 있습니다. 가능한 이유는 다음과 같습니다.

컨테이너의 높은 메모리 사용량

포드의 컨테이너가 할당된 총 메모리를 과도하게 사용하면 포드에 OOMKilled가 발생할 수 있습니다. 컨테이너의 메모리 한도에 대한 메모리 요청의 비율을 확인하세요.

Google Cloud 콘솔 > Monitoring > 측정항목 탐색기MQL 편집기에서 다음 쿼리를 실행합니다.

fetch k8s_container
| metric 'kubernetes.io/anthos/container/memory/limit_utilization'
| filter (metric.memory_type == 'non-evictable')
| group_by 1m, [value_limit_utilization_mean: mean(value.limit_utilization)]
| filter resource.cluster_name == 'CLUSTER_NAME'
| filter resource.container_name == 'CONTAINER_NAME'
| filter resource.pod_name == 'POD_NAME'
| filter resource.namespace_name == 'NAMESPACE_NAME'
| every 1m

그런 후 다음 중 하나를 수행합니다.

노드의 높은 메모리 사용량

노드에서 실행되는 모든 포드의 메모리 사용량이 사용 가능한 메모리를 초과하면 포드에 OOMKilled가 발생할 수 있습니다. 따라서 노드의 MemoryPressure 조건이 True인지 확인합니다.

  1. 다음 명령어를 실행하고 Conditions 섹션을 검사합니다.

    kubectl describe nodes --kubeconfig CLUSTER_KUBECONFIG NODE-NAME
    
  2. MemoryPressure 조건이 True이면 노드의 메모리 사용률을 확인합니다.

    fetch k8s_node
    | metric 'kubernetes.io/anthos/node/memory/allocatable_utilization'
    | filter (metric.memory_type == 'non-evictable')
    | group_by 1m,
        [value_allocatable_utilization_mean: mean(value.allocatable_utilization)]
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.node_name = 'NODE_NAME'
    | every 1m
    

    이 비율이 높으면(0.8 이상) 포드에 할당할 충분한 메모리가 노드에 없는 것입니다. 메모리를 많이 사용하는 일부 프로세스 또는 다른 포드 때문일 수 있습니다.

  3. Google Cloud 콘솔 > Monitoring > 측정항목 탐색기MQL 편집기에서 다음 쿼리를 실행하여 노드의 컨테이너에 대한 메모리 사용량을 확인합니다.

    fetch k8s_node
    | metric 'kubernetes.io/anthos/container_memory_usage_bytes'
    | filter resource.cluster_name == 'CLUSTER_NAME'
    | filter resource.node_name == 'NODE_NAME'
    | group_by 1m,
        [value_container_memory_usage_bytes_mean:
          mean(value.container_memory_usage_bytes)]
    | every 1m
    

    많은 메모리를 사용하는 컨테이너가 있는 경우 컨테이너 작동을 조사하거나 필요한 경우 컨테이너의 메모리 요청을 늘립니다.

시스템 포드가 많은 메모리를 소비하는 경우 Google 지원팀에 문의하세요.

또한 Google Distributed Cloud 클러스터에서 자동 확장 기능을 사용 설정하여 워크로드 요구사항에 따라 노드 풀을 자동으로 확장하거나 축소할 수 있습니다.

자동 확장 처리 사용 설정 방법을 알아보세요.

Etcd 문제

etcd 서버 문제로 인해 VMware용 Anthos 클러스터에서 컨테이너 오류가 발생할 수 있으며 이 경우 다음과 같은 문제가 나타날 수 있습니다.

  • 반복되는 다음 형식의 API 서버 로그:

    etcdserver: request timed out, etcdserver: leader changed

  • 다음 형식의 반복되는 etcd 로그:

    W | wal: sync duration of 2.466870869s, expected less than 1s, W | etcdserver: read-only range request * took too long

가능한 이유는 다음과 같습니다.

CPU 제한

etcd 서버 포드 또는 etcd 서버가 실행되는 노드에서 CPU 제한으로 인해 etcd 서버가 느려질 수 있습니다. CPU 경합 문제가 있는지 확인하려면 컨테이너 속도 저하 섹션의 단계를 참조하세요.

ectd 서버 포드나 노드에서 CPU 경합이 감지되면 사용자 클러스터의 제어 영역 노드에 CPU를 추가합니다. gkectl update를 사용하여 사용자 클러스터 구성 파일에서 cpus 필드를 수정합니다.

Etcd 포드에 OOMKilled 발생

리소스 경합 문제로 인해 etcd 포드에 OOMKilled가 발생할 수 있습니다. etcd 서버 포드 또는 etcd 서버가 실행되는 노드에 메모리 경합 문제가 있는지 확인하려면 포드에 OOMKilled(메모리 부족-종료)가 발생함 섹션의 단계를 참조하세요.

etcd 포드에서 OOMKill 오류가 감지되면 사용자 클러스터의 제어 영역 노드에서 사용 가능한 메모리를 늘립니다. gkectl update를 사용하여 사용자 클러스터 구성 파일에서 memoryMB 필드를 수정합니다.

디스크 속도 저하

etcd 서버 포드나 노드의 CPU 또는 메모리 소비에 문제가 없다면 기본 데이터 스토어가 느리거나 제한된 경우에도 etcd 속도가 저하될 수 있습니다.

다음 문제를 확인합니다.

  • etcd 서버가 기본 디스크를 읽고 쓰는 데 너무 오래 걸리는지 확인하려면 다음 안내를 따르세요.

    1. etcd 로그를 가져옵니다.

      kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG logs -n ETCD_POD_NAMESPACE ETCD_POD
      
    2. 다음 패턴의 항목을 찾아 etcd가 디스크에서 읽는 데 시간이 너무 오래 걸리는지 확인합니다.

      W | etcdserver: read-only range request "key:\"/registry/configmaps/default/clusterapi-vsphere-controller-manager-leader-election\" " with result "range_response_count:1 size:685" took too long (6.893127339s) to execute

    3. 다음 패턴의 항목을 찾아 etcd가 디스크에 쓰는 데 시간이 너무 오래 걸리는지 확인합니다.

      W | wal: sync duration of 2.466870869s, expected less than 1s

    위 로그 패턴 중 일부 또는 둘 다 etcd 로그에 자주 표시되는 경우 디스크 속도가 느려졌음을 나타냅니다. 그러면 데이터 스토어와 디스크의 성능을 확인합니다.

  • etcd 측정항목을 확인하려면 다음 안내를 따르세요.

    1. etcd 미리 쓰기 로깅 동기화 지연 시간을 가져옵니다.

      Google Cloud 콘솔 > Monitoring > 측정항목 탐색기MQL 편집기에서 다음 쿼리를 실행합니다.

      fetch k8s_container::kubernetes.io/anthos/etcd_disk_wal_fsync_duration_seconds
      | every 1m
      | filter resource.cluster_name == 'CLUSTER_NAME'
      | filter resource.pod_name == 'POD_NAME'
      | filter resource.namespace_name == 'NAMESPACE_NAME'
      | percentile 99
      
    2. etcd 쓰기 지연 시간을 가져옵니다.

      Google Cloud 콘솔 > Monitoring > 측정항목 탐색기MQL 편집기에서 다음 쿼리를 실행합니다.

      fetch k8s_container::kubernetes.io/anthos/etcd_disk_backend_commit_duration_seconds
      | every 1m
      | filter resource.cluster_name == 'CLUSTER_NAME'
      | filter resource.pod_name == 'POD_NAME'
      | filter resource.namespace_name == 'NAMESPACE_NAME'
      | percentile 99
      

    etcd_disk_wal_fsync_duration_secondsp99가 계속 10ms를 초과하거나 etcd_disk_backend_commit_duration_secondsp99가 계속 25ms를 초과하면 디스크 속도가 느려졌다는 의미입니다. 그러면 데이터 스토어와 디스크의 성능을 확인합니다.

VM 디스크의 읽기/쓰기 지연 시간

다음 단계를 수행하여 VM 가상 디스크에서 읽기/쓰기 지연 시간을 확인합니다.

  1. 느린 etcd 포드의 노드를 식별합니다.

    kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG get pods -n ETCD_POD_NAMESPACE ETCD_POD -owide
    
  2. vSphere에 로그인하고 위 단계에서 식별된 VM을 선택합니다. vSphere에서 모니터 > 성능 > 고급으로 이동하고 섹션에서 가상 디스크를 선택하여 가상 디스크의 읽기 및 쓰기 지연 시간을 식별합니다.

    가상 디스크 읽기/쓰기 지연 시간이 높은 경우 다음 안내를 따르세요.

    • 데이터 스토어에서 실행 중인 다른 VM을 검사하여 초당 입출력 작업 수(IOPS) 사용량이 높은지 확인합니다. VM에서 IOPS가 급증하는 경우 해당 VM의 작동을 평가합니다.
    • 실험실/인프라팀에 문의하여 읽기 및 쓰기 대역폭이 특정 시점에 제한되거나 제한되지 않는지 확인합니다.
    • 실험실/인프라팀에 문의하여 디스크 성능스토리지 성능 문제(있는 경우)를 식별합니다.

자세한 내용은 리소스 확장 권장사항을 참조하세요.

API 서버 문제

API 서버와 통신하는 동안 Google Distributed Cloud의 컨테이너에 지연 시간이 발생하거나 Kubectl 명령어가 실패하거나 응답하는 데 시간이 너무 오래 걸린다면 API 서버에 문제가 있을 수 있습니다.

가능한 이유는 다음과 같습니다.

많은 API 요청

요청 빈도와 양이 너무 많으면 API 서버의 응답 속도가 느려질 수 있습니다. API 서버에서 요청을 제한하기 시작한 후에도 느린 응답 시간이 지속될 수 있습니다. API 서버에서 API 요청 비율을 확인하세요.

Google Cloud 콘솔 > Monitoring > 측정항목 탐색기MQL 편집기에서 다음 쿼리를 실행합니다.

fetch k8s_container::kubernetes.io/anthos/apiserver_request_total
| filter resource.cluster_name == 'CLUSTER_NAME'
| filter resource.pod_name == 'APISERVER_POD_NAME'
| filter resource.namespace_name == 'NAMESPACE_NAME'
| align rate(1m)
| every 1m
| group_by [metric.verb]

API 요청이 예기치 않게 증가하면 Cloud Audit Logging을 사용하여 API 서버를 너무 자주 쿼리하는 포드를 식별합니다.

  • 시스템 포드인 경우 Google 지원팀에 문의하세요.
  • 사용자 포드라면 추가 조사를 통해 API 요청이 예상대로인지 확인합니다.

CPU 제한

API 서버의 요청 비율이 높으면 CPU가 제한될 수 있습니다. 그러면 API 서버 포드 또는 노드에서의 CPU 경합으로 인해 API 서버가 느려질 수 있습니다.

포드 또는 노드에 CPU 경합 문제가 있는지 확인하려면 컨테이너 속도 저하 섹션을 참조하세요.

API 서버 포드에 OOMKilled 발생

리소스 경합 문제로 인해 API 서버 포드에 OOMKilled가 발생할 수 있습니다. 포드 또는 노드에 메모리 경합 문제가 있는지 확인하려면 포드에 OOMKilled(메모리 부족-종료)가 발생함 섹션의 단계를 참조하세요.

느린 etcd 응답

API 서버는 etcd 클러스터와 통신하여 클라이언트에 대한 읽기/쓰기 요청을 처리합니다. etcd가 느리거나 응답하지 않으면 API 서버도 느려집니다.

etcd 문제로 인해 API 서버가 느려졌는지 확인하려면 API 서버 로그를 가져옵니다.

kubectl –kubeconfig ADMIN_CLUSTER_KUBECONFIG logs -n APISERVER_NAMESPACE APISERVER_POD_NAME

etcdserver: request timedout 또는 etcdserver: leader changed와 같이 반복되는 로그가 관찰되면 Etcd 문제 단계를 수행하여 디스크 관련 문제를 해결합니다.

클러스터에서 측정항목을 내보내지 않는 경우

이 문서의 앞부분에 표시된 기술은 클러스터에서 Google Cloud 프로젝트로 내보내는 측정항목에 의존합니다.

클러스터가 측정항목을 내보내지 않으면 명령줄을 사용하여 리소스 경합을 조사할 수 있습니다. 다음은 측정항목을 보기 위해 관리자 워크스테이션에서 실행할 수 있는 몇 가지 명령어입니다.

노드의 측정항목을 봅니다.

kubectl --kubeconfig CLUSTER_KUBECONFIG get --raw \
    /apis/metrics.k8s.io/v1beta1/nodes/NODE_NAME | jq

다음을 바꿉니다.

  • CLUSTER_KUBECONFIG: 클러스터 kubeconfig 파일 경로
  • NODE_NAME: 노드 이름

포드의 측정항목을 봅니다.

kubectl --kubeconfig CLUSTER_KUBECONFIG get --raw \
    /apis/metrics.k8s.io/v1beta1/namespaces/NAMESPACE/pods/POD_NAME | jq

다음을 바꿉니다.

  • NAMESPACE: 포드의 네임스페이스
  • POD_NAME: 포드의 이름

모든 노드의 측정항목을 봅니다.

kubectl --kubeconfig CLUSTER_KUBECONFIG top node

네임스페이스에서 모든 포드의 측정항목을 봅니다.

kubectl --kubeconfig CLUSTER_KUBECONFIG top pod --namespace NAMESPACE

네임스페이스에서 모든 포드에 있는 컨테이너의 측정항목을 봅니다.

kubectl --kubeconfig CLUSTER_KUBECONFIG top pod --containers --namespace NAMESPACE

자세한 내용은 kubectl top podkubectl top node를 참조하세요.

노드에서 실행 중인 컨테이너 내에서 top 명령어를 실행할 수도 있습니다.

컨테이너 내에서 명령어를 실행하는 방법은 두 가지입니다.

다음 단계

추가 지원이 필요하면 Cloud Customer Care에 문의하세요.