Azure Kubernetes Services에서 API 서버 및 기타 문제 해결
이 가이드는 AKS(대규모 Microsoft Azure Kubernetes Services) 배포의 API 서버 내에서 발생할 수 있는 예상치 못한 문제를 식별하고 해결하는 데 도움이 되도록 설계되었습니다.
Microsoft는 5,000개의 노드와 200,000개의 Pod 규모로 API 서버의 안정성과 성능을 테스트했습니다. API 서버를 포함하는 클러스터에는 Kubernetes SLO(서비스 수준 목표)를 자동으로 스케일 아웃하고 제공하는 기능이 있습니다. 대기 시간이 길거나 시간이 초과되는 경우 분산 etc
디렉터리(etcd)에 리소스가 누출되거나 잘못된 클라이언트에 과도한 API 호출이 있기 때문일 수 있습니다.
필수 조건
Kubernetes kubectl 도구입니다. Azure CLI를 사용하여 kubectl을 설치하려면 az aks install-cli 명령을 실행합니다.
사용하도록 설정되고 Log Analytics 작업 영역으로 전송되는 AKS 진단 로그(특히 kube-audit 이벤트)입니다. 리소스별 또는 Azure 진단 모드를 사용하여 로그가 수집되는지 확인하려면 Azure Portal에서 진단 설정 블레이드를 확인합니다.
AKS 클러스터의 표준 계층입니다. 무료 계층을 사용하는 경우 API 서버 및 etcd에는 제한된 리소스가 포함됩니다. 무료 계층의 AKS 클러스터는 고가용성을 제공하지 않습니다. 이는 종종 API 서버 및 etcd 문제의 근본 원인입니다.
Kubernetes 컨트롤 플레인을 사용하지 않고 AKS 노드에서 직접 명령을 실행하기 위한 kubectl-aks 플러그 인입니다.
기본 상태 검사
Resource Health 이벤트
AKS는 중요한 구성 요소 가동 중지 시간을 위한 리소스 상태 이벤트를 제공합니다. 계속하기 전에 Resource Health에 보고된 중요한 이벤트가 없는지 확인합니다.
문제 진단 및 해결
AKS는 클러스터 및 컨트롤 플레인 가용성 및 성능에 대한 전용 문제 해결 범주를 제공합니다.
증상
다음 표에서는 API 서버 오류의 일반적인 증상에 대해 간략하게 설명합니다.
증상 | 설명 |
---|---|
API 서버의 시간 제한 | AKS API 서버 SLA의 보장을 넘어서는 빈번한 시간 제한입니다. 예를 들어 kubectl 명령 제한 시간이 초과됩니다. |
높은 대기 시간 | Kubernetes SLO를 실패하게 만드는 대기 시간이 깁니다. 예를 들어 명령은 Pod를 kubectl 나열하는 데 30초 이상 걸립니다. |
상태 또는 웹후크 호출 실패에 CrashLoopbackOff 직면한 API 서버 Pod |
API 서버에 대한 호출을 차단하는 사용자 지정 허용 웹후크(예: Kyverno 정책 엔진)가 없는지 확인합니다. |
문제 해결 검사 목록
대기 시간이 긴 경우 다음 단계에 따라 잘못된 클라이언트 및 실패한 API 호출 유형을 정확히 파악합니다.
1단계: 요청 수로 상위 사용자 에이전트 식별
가장 많은 요청(그리고 잠재적으로 가장 많은 API 서버 로드)을 생성하는 클라이언트를 식별하려면 다음 코드와 유사한 쿼리를 실행합니다. 다음 쿼리는 전송된 API 서버 요청 수별로 상위 10개 사용자 에이전트를 나열합니다.
AKSAudit
| where TimeGenerated between(now(-1h)..now()) // When you experienced the problem
| summarize count() by UserAgent
| top 10 by count_
| project UserAgent, count_
참고 항목
쿼리에서 결과가 반환되지 않으면 진단 로그를 쿼리하기 위해 잘못된 테이블을 선택했을 수 있습니다. 리소스별 모드에서 데이터는 리소스의 범주에 따라 개별 테이블에 기록됩니다. 진단 로그는 테이블에 기록 AKSAudit
됩니다. Azure 진단 모드에서는 모든 데이터가 테이블에 기록 AzureDiagnostics
됩니다. 자세한 내용은 Azure 리소스 로그를 참조하세요.
가장 높은 요청 볼륨을 생성하는 클라이언트를 아는 것이 유용하지만 높은 요청 볼륨만으로는 문제가 되지 않을 수 있습니다. 각 클라이언트가 API 서버에서 생성하는 실제 로드의 더 나은 지표는 해당 클라이언트가 경험하는 응답 대기 시간입니다.
2단계: 사용자 에이전트당 API 서버 요청의 평균 대기 시간 식별 및 차트
시간 차트에 표시된 대로 사용자 에이전트당 API 서버 요청의 평균 대기 시간을 식별하려면 다음 쿼리를 실행합니다.
AKSAudit
| where TimeGenerated between(now(-1h)..now()) // When you experienced the problem
| extend start_time = RequestReceivedTime
| extend end_time = StageReceivedTime
| extend latency = datetime_diff('millisecond', end_time, start_time)
| summarize avg(latency) by UserAgent, bin(start_time, 5m)
| render timechart
이 쿼리는 "요청 수로 상위 사용자 에이전트 식별" 섹션의 쿼리에 대한 후속 작업입니다. 시간이 지남에 따라 각 사용자 에이전트에 의해 생성되는 실제 부하에 대한 더 많은 인사이트를 제공할 수 있습니다.
팁
이 데이터를 분석하여 AKS 클러스터 또는 애플리케이션에서 문제를 나타낼 수 있는 패턴 및 변칙을 식별할 수 있습니다. 예를 들어 특정 사용자에게 높은 대기 시간이 발생하는 것을 알 수 있습니다. 이 시나리오는 API 서버 또는 etcd에서 과도한 부하를 유발하는 API 호출 유형을 나타낼 수 있습니다.
3단계: 지정된 사용자 에이전트에 대한 잘못된 API 호출 식별
다음 쿼리를 실행하여 지정된 클라이언트에 대한 여러 리소스 유형에서 API 호출의 99번째 백분위수(P99) 대기 시간을 테이블화합니다.
AKSAudit
| where TimeGenerated between(now(-1h)..now()) // When you experienced the problem
| extend HttpMethod = Verb
| extend Resource = tostring(ObjectRef.resource)
| where UserAgent == "DUMMYUSERAGENT" // Filter by name of the useragent you are interested in
| where Resource != ""
| extend start_time = RequestReceivedTime
| extend end_time = StageReceivedTime
| extend latency = datetime_diff('millisecond', end_time, start_time)
| summarize p99latency=percentile(latency, 99) by HttpMethod, Resource
| render table
이 쿼리의 결과는 업스트림 Kubernetes SLO에 실패하는 API 호출의 종류를 식별하는 데 유용할 수 있습니다. 대부분의 경우 잘못된 클라이언트가 너무 큰 개체 또는 개체 집합에 대해 너무 많은 LIST
호출을 할 수 있습니다. 아쉽게도 사용자에게 API 서버 확장성에 대해 안내하는 하드 확장성 제한은 없습니다. API 서버 또는 기타 확장성 제한은 Kubernetes 확장성 임계값에 설명된 다양한 요인에 따라 달라집니다.
원인 1: 네트워크 규칙은 에이전트 노드에서 API 서버로의 트래픽을 차단합니다.
네트워크 규칙은 에이전트 노드와 API 서버 간의 트래픽을 차단할 수 있습니다.
잘못 구성된 네트워크 정책이 API 서버와 에이전트 노드 간의 통신을 차단하는지 확인하려면 다음 kubectl-aks 명령을 실행합니다.
kubectl aks config import \
--subscription <mySubscriptionID> \
--resource-group <myResourceGroup> \
--cluster-name <myAKSCluster>
kubectl aks check-apiserver-connectivity --node <myNode>
구성 가져오기 명령은 클러스터의 모든 노드에 대한 Virtual Machine Scale Set 정보를 검색합니다. 그런 다음 check-apiserver-connectivity 명령은 이 정보를 사용하여 API 서버와 지정된 노드 간의 네트워크 연결, 특히 기본 확장 집합 인스턴스에 대한 네트워크 연결을 확인합니다.
참고 항목
명령의 출력에 check-apiserver-connectivity
메시지가 포함된 Connectivity check: succeeded
경우 네트워크 연결에 방해가 되지 않습니다.
해결 방법 1: 네트워크 정책을 수정하여 트래픽 차단 제거
명령 출력에 연결 오류가 발생했음을 나타내는 경우 에이전트 노드와 API 서버 간의 트래픽을 불필요하게 차단하지 않도록 네트워크 정책을 다시 구성합니다.
원인 2: 잘못된 클라이언트가 etcd 개체를 누출하여 etcd가 느려지는 경우
일반적인 문제는 etcd 데이터베이스에서 사용되지 않는 개체를 삭제하지 않고 개체를 지속적으로 만드는 것입니다. 따라서 etcd가 모든 형식의 개체(10,000개 이상)를 너무 많이 처리할 때 성능 문제가 발생할 수 있습니다. 이러한 개체에 대한 변경이 급격히 증가하면 에칭된 데이터베이스 크기(기본적으로 4기가바이트)를 초과할 수도 있습니다.
etcd 데이터베이스 사용량을 확인하려면 Azure Portal에서 진단 및 문제 해결로 이동합니다. 검색 상자에서 "etcd"를 검색하여 Etcd 가용성 문제 진단 도구를 실행합니다. 진단 도구는 사용량 분석 및 총 데이터베이스 크기를 보여 줍니다.
etcd 데이터베이스의 현재 크기를 바이트 단위로 빠르게 보려면 다음 명령을 실행합니다.
kubectl get --raw /metrics | grep -E "etcd_db_total_size_in_bytes|apiserver_storage_size_bytes|apiserver_storage_db_total_size_in_bytes"
참고 항목
이전 명령의 메트릭 이름은 Kubernetes 버전에 따라 다릅니다. Kubernetes 1.25 이하의 etcd_db_total_size_in_bytes
경우 . Kubernetes 1.26~ 1.28의 apiserver_storage_db_total_size_in_bytes
경우 .
해결 방법 2: etcd에서 개체 만들기, 개체 삭제 또는 개체 수명 제한에 대한 할당량 정의
etcd가 용량에 도달하고 클러스터 가동 중지 시간을 발생시키는 것을 방지하기 위해 생성된 최대 리소스 수를 제한할 수 있습니다. 리소스 인스턴스에 대해 생성된 수정 버전 수를 늦출 수도 있습니다. 만들 수 있는 개체 수를 제한하려면 개체 할당량을 정의할 수 있습니다.
더 이상 사용되지 않지만 리소스를 사용하는 개체를 식별한 경우 삭제하는 것이 좋습니다. 예를 들어 완료된 작업을 삭제하여 공간을 확보할 수 있습니다.
kubectl delete jobs --field-selector status.successful=1
자동 정리를 지원하는 개체의 경우 TTL(Time to Live) 값을 설정하여 이러한 개체의 수명을 제한할 수 있습니다. 레이블 선택기를 사용하여 특정 형식의 모든 개체를 대량으로 삭제할 수 있도록 개체에 레이블을 지정할 수도 있습니다. 개체 간에 소유자 참조를 설정하면 부모 개체가 삭제된 후 종속 개체가 자동으로 삭제됩니다.
원인 3: 잘못된 클라이언트가 과도한 LIST 또는 PUT 호출을 수행합니다.
etcd가 너무 많은 개체로 오버로드되지 않는다고 판단되면 잘못된 클라이언트가 너무 많이 LIST
만들거나 PUT
API 서버를 호출할 수 있습니다.
솔루션 3a: API 호출 패턴 조정
컨트롤 플레인의 압력을 줄이기 위해 클라이언트의 API 호출 패턴을 조정하는 것이 좋습니다.
솔루션 3b: 컨트롤 플레인을 압도하는 클라이언트 제한
클라이언트를 조정할 수 없는 경우 Kubernetes의 우선 순위 및 공정성 기능을 사용하여 클라이언트를 제한할 수 있습니다. 이 기능은 컨트롤 플레인의 상태를 유지하고 다른 애플리케이션의 실패를 방지하는 데 도움이 될 수 있습니다.
다음 절차에서는 5개의 동시 호출로 설정된 잘못된 클라이언트의 LIST PodS API를 제한하는 방법을 보여 줍니다.
잘못된 클라이언트의 API 호출 패턴과 일치하는 FlowSchema 를 만듭니다.
apiVersion: flowcontrol.apiserver.k8s.io/v1beta2 kind: FlowSchema metadata: name: restrict-bad-client spec: priorityLevelConfiguration: name: very-low-priority distinguisherMethod: type: ByUser rules: - resourceRules: - apiGroups: [""] namespaces: ["default"] resources: ["pods"] verbs: ["list"] subjects: - kind: ServiceAccount serviceAccount: name: bad-client-account namespace: default
클라이언트의 잘못된 API 호출을 제한하는 낮은 우선 순위 구성을 만듭니다.
apiVersion: flowcontrol.apiserver.k8s.io/v1beta2 kind: PriorityLevelConfiguration metadata: name: very-low-priority spec: limited: assuredConcurrencyShares: 5 limitResponse: type: Reject type: Limited
API 서버 메트릭에서 제한된 호출을 관찰합니다.
kubectl get --raw /metrics | grep "restrict-bad-client"
원인 4: 사용자 지정 웹후크가 API 서버 Pod에서 교착 상태를 일으킬 수 있습니다.
Kyverno와 같은 사용자 지정 웹후크가 API 서버 Pod 내에서 교착 상태를 일으킬 수 있습니다.
API 서버와 관련된 이벤트를 확인합니다. 다음 텍스트와 유사한 이벤트 메시지가 표시될 수 있습니다.
내부 오류 발생: webhook "mutate.kyverno.svc-fail"를 호출하지 못했습니다. webhook를 호출하지 못했습니다. "https://kyverno-system-kyverno-system-svc.kyverno-system.svc:443/mutate/fail?timeout=10s": unix @-/tunnel-uds>/proxysocket 쓰기: 쓰기: 깨진 파이프
이 예제에서는 유효성 검사 웹후크가 일부 API 서버 개체의 생성을 차단하고 있습니다. 이 시나리오는 부트스트랩 시간 동안 발생할 수 있으므로 API 서버 및 Konnectivity Pod를 만들 수 없습니다. 따라서 웹후크는 해당 Pod에 연결할 수 없습니다. 이 이벤트 시퀀스는 교착 상태와 오류 메시지를 발생합니다.
솔루션 4: 웹후크 구성 삭제
이 문제를 해결하려면 웹후크 구성의 유효성 검사 및 변경 작업을 삭제합니다. Kyverno에서 이러한 웹후크 구성을 삭제하려면 Kyverno 문제 해결 문서를 검토하세요.
타사 연락처 고지
이 문서에 포함된 타사의 연락처 정보는 이 항목에 대한 추가 정보를 찾는 데 도움을 주기 위한 것입니다. 이 연락처 정보는 공지 없이 변경될 수 있습니다. Microsoft는 타사 연락처 정보의 정확성을 보증하지 않습니다.
타사 정보 고지 사항
이 문서에 나와 있는 다른 공급업체 제품은 Microsoft와 무관한 회사에서 제조한 것입니다. Microsoft는 이들 제품의 성능이나 안정성에 관하여 명시적이든 묵시적이든 어떠한 보증도 하지 않습니다.
도움을 요청하십시오.
질문이 있거나 도움이 필요한 경우 지원 요청을 생성하거나Azure 커뮤니티 지원에 문의하세요. Azure 피드백 커뮤니티에 제품 피드백을 제출할 수도 있습니다.