AKS 클러스터의 네트워크 문제 해결

Kubernetes를 새로 설치할 때 또는 Kubernetes 부하를 늘릴 때 네트워크 문제가 발생할 수 있습니다. 네트워킹 문제와 관련된 다른 문제도 발생할 수 있습니다. 항상 AKS 문제 해결 가이드를 확인하여 문제가 설명되어 있는지 확인합니다. 이 문서에서는 네트워크 문제 해결 관점의 추가 세부 정보 및 고려 사항과 발생할 수 있는 특정 문제에 대해 설명합니다.

클라이언트가 API 서버에 연결할 수 없음

이러한 오류에는 Kubernetes 클러스터 명령줄 도구(kubectl) 또는 다른 도구를 통해 AKS(Azure Kubernetes Service) 클러스터의 API 서버에 연결할 수 없을 때 발생하는 연결 문제가 포함됩니다(예: 프로그래밍 언어를 통해 REST API에 연결할 수 없는 경우).

오류

다음과 같은 오류가 표시될 수 있습니다.

Unable to connect to the server: dial tcp <API-server-IP>:443: i/o timeout 
Unable to connect to the server: dial tcp <API-server-IP>:443: connectex: A connection attempt
failed because the connected party did not properly respond after a period, or established 
connection failed because connected host has failed to respond. 

원인 1

API 서버에서 권한을 부여한 IP 범위는 클러스터의 API 서버에서 사용하도록 설정되어 있지만 클라이언트의 IP 주소는 해당 IP 범위에 포함되지 않습니다. IP 범위를 사용할 수 있는지 여부를 확인하려면 Azure CLI에서 다음 az aks show 명령을 사용합니다. IP 범위가 사용하도록 설정된 경우 명령은 IP 범위 목록을 생성합니다.

az aks show --resource-group <cluster-resource-group> \ 
    --name <cluster-name> \ 
    --query apiServerAccessProfile.authorizedIpRanges 

해결 방법 1

클라이언트의 IP 주소가 클러스터의 API 서버에서 권한을 부여한 범위 내에 있는지 확인합니다.

  1. 로컬 IP 주소를 찾습니다. Windows 및 Linux에서 찾는 방법에 대한 자세한 내용은 내 IP를 찾는 방법을 참조하세요.

  2. Azure CLI에서 az aks update 명령을 사용하여 API 서버가 권한을 부여한 범위를 업데이트합니다. 클라이언트의 IP 주소에 권한을 부여합니다. 자세한 내용은 클러스터의 API 서버 권한이 있는 IP 범위 업데이트를 참조하세요.

원인 2

AKS 클러스터가 프라이빗 클러스터인 경우 API 서버 엔드포인트에 공용 IP 주소가 없습니다. AKS 클러스터의 가상 네트워크에 대한 네트워크 액세스 권한이 있는 VM을 사용해야 합니다.

해결 방법 2

이 문제를 해결하는 방법에 대한 자세한 내용은 프라이빗 클러스터에 연결하기 위한 옵션을 참조하세요.

Pod가 IP 주소를 할당하지 못함

오류

Pod가 ContainerCreating 상태에서 중단되고 해당 이벤트가 Failed to allocate address 오류를 보고합니다.

Normal   SandboxChanged          5m (x74 over 8m)    kubelet, k8s-agentpool-00011101-0 Pod sandbox
changed, it will be killed and re-created. 

  Warning  FailedCreatePodSandBox  21s (x204 over 8m)  kubelet, k8s-agentpool-00011101-0 Failed 
create pod sandbox: rpc error: code = Unknown desc = NetworkPlugin cni failed to set up pod 
"deployment-azuredisk6-874857994-487td_default" network: Failed to allocate address: Failed to 
delegate: Failed to allocate address: No available addresses 

not enough IPs available 또는 오류:

Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox 
'ac1b1354613465324654c1588ac64f1a756aa32f14732246ac4132133ba21364': plugin type='azure-vnet' 
failed (add): IPAM Invoker Add failed with error: Failed to get IP address from CNS with error: 
%w: AllocateIPConfig failed: not enough IPs available for 9c6a7f37-dd43-4f7c-a01f-1ff41653609c, 
waiting on Azure CNS to allocate more with NC Status: , IP config request is [IPConfigRequest: 
DesiredIPAddress , PodInterfaceID a1876957-eth0, InfraContainerID 
a1231464635654a123646565456cc146841c1313546a515432161a45a5316541, OrchestratorContext 
{'PodName':'a_podname','PodNamespace':'my_namespace'}]

플러그 인 IPAM 저장소에서 할당된 IP 주소를 확인합니다. 모든 IP 주소가 할당되었지만 이 숫자가 실행 중인 Pod 수보다 훨씬 적을 수 있습니다.

kubenet을 사용하는 경우:

# Kubenet, for example. The actual path of the IPAM store file depends on network plugin implementation. 
chroot /host/
ls -la "/var/lib/cni/networks/$(ls /var/lib/cni/networks/ | grep -e "k8s-pod-network" -e "kubenet")" | grep -v -e "lock\|last\|total" -e '\.$' | wc -l
244

참고 항목

Calico가 없는 kubenet의 경우 경로는 .입니다 /var/lib/cni/networks/kubenet. Calico를 사용하는 kubenet의 경우 경로는 .입니다 /var/lib/cni/networks/k8s-pod-network. 위의 스크립트는 명령을 실행하는 동안 경로를 자동으로 선택합니다.

# Check running Pod IPs
kubectl get pods --field-selector spec.nodeName=<your_node_name>,status.phase=Running -A -o json | jq -r '.items[] | select(.spec.hostNetwork != 'true').status.podIP' | wc -l
7 

동적 IP 할당에 Azure CNI를 사용하는 경우:

kubectl get nnc -n kube-system -o wide
NAME                               REQUESTED IPS  ALLOCATED IPS  SUBNET  SUBNET CIDR   NC ID                                 NC MODE  NC TYPE  NC VERSION
aks-agentpool-12345678-vmss000000  32             32             subnet  10.18.0.0/15  559e239d-f744-4f84-bbe0-c7c6fd12ec17  dynamic  vnet     1
# Check running Pod IPs
kubectl get pods --field-selector spec.nodeName=aks-agentpool-12345678-vmss000000,status.phase=Running -A -o json | jq -r '.items[] | select(.spec.hostNetwork != 'true').status.podIP' | wc -l
21

원인 1

이 오류는 네트워크 플러그 인의 버그로 인해 발생할 수 있습니다. 플러그 인은 Pod가 종료될 때 IP 주소의 할당을 취소하지 못할 수 있습니다.

해결 방법 1

해결 방법 또는 수정 방법은 Microsoft에 문의하세요.

원인 2

종료된 Pod의 가비지를 수집하는 것보다 Pod를 만드는 것이 훨씬 더 빠릅니다.

해결 방법 2

kubelet에 대한 빠른 가비지 수집을 구성합니다. 자세한 내용은 Kubernetes 가비지 수집 설명서를 참조하세요.

Pod 내에서 서비스에 액세스할 수 없음

이 문제를 해결하는 첫 번째 단계는 서비스에 대해 엔드포인트가 자동으로 만들어졌는지 여부를 확인하는 것입니다.

kubectl get endpoints <service-name> 

빈 결과가 표시되면 서비스의 레이블 선택기가 잘못된 것일 수 있습니다. 레이블이 올바른지 확인합니다.

# Query Service LabelSelector. 
kubectl get svc <service-name> -o jsonpath='{.spec.selector}' 

# Get Pods matching the LabelSelector and check whether they're running. 
kubectl get pods -l key1=value1,key2=value2 

위의 단계에서 예상 값을 반환하는 경우:

  • Pod containerPortcontainerPort 서비스와 같은지 확인합니다.

  • podIP:containerPort가 작동하는지 확인합니다.

    # Testing via cURL. 
    curl -v telnet ://<Pod-IP>:<containerPort>
    
    # Testing via Telnet. 
    telnet <Pod-IP>:<containerPort> 
    

서비스 문제의 다른 몇 가지 잠재적 원인은 다음과 같습니다.

  • 컨테이너가 지정된 containerPort를 수신 대기하지 않습니다. (Pod 설명을 확인합니다.)
  • CNI 플러그 인 오류 또는 네트워크 경로 오류가 발생했습니다.
  • kube-proxy가 실행되고 있지 않거나 iptables 규칙이 올바르게 구성되지 않았습니다.
  • 네트워크 정책이 트래픽을 삭제하고 있습니다. 네트워크 정책 적용 및 테스트에 대한 자세한 내용은 Azure Kubernetes 네트워크 정책 개요를 참조하세요.
    • Calico를 네트워크 플러그 인으로 사용하는 경우 네트워크 정책 트래픽도 캡처할 수 있습니다. 구성에 대한 자세한 내용은 Calico 사이트를 참조하세요.

노드가 API 서버에 연결할 수 없음

많은 추가 항목 및 컨테이너가 Kubernetes API에 액세스해야 합니다(예: kube-dns 및 연산자 컨테이너). 이 프로세스 중에 오류가 발생하는 경우 다음 단계를 통해 문제의 원인을 확인할 수 있습니다.

먼저 Pod 내에서 Kubernetes API에 액세스할 수 있는지 확인합니다.

kubectl run curl --image=mcr.microsoft.com/azure-cli -i -t --restart=Never --overrides='[{"op":"add","path":"/spec/containers/0/resources","value":{"limits":{"cpu":"200m","memory":"128Mi"}}}]' --override-type json --command -- sh

그런 다음, 이제 셸에 액세스된 컨테이너 내에서 다음을 실행합니다.

# If you don't see a command prompt, try selecting Enter. 
KUBE_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) 
curl -sSk -H "Authorization: Bearer $KUBE_TOKEN" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1/namespaces/default/pods

정상적인 출력은 다음과 유사합니다.

{ 
  "kind": "PodList", 
  "apiVersion": "v1", 
  "metadata": { 
    "selfLink": "/api/v1/namespaces/default/pods", 
    "resourceVersion": "2285" 
  }, 
  "items": [ 
   ... 
  ] 
} 

오류가 발생하면 kubernetes-internal 서비스 및 해당 엔드포인트가 정상인지 확인합니다.

kubectl get service kubernetes-internal
NAME                TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE 
kubernetes-internal ClusterIP   10.96.0.1    <none>        443/TCP   25m 
kubectl get endpoints kubernetes-internal
NAME                ENDPOINTS          AGE 
kubernetes-internal 172.17.0.62:6443   25m 

두 테스트 모두 앞의 응답과 같은 응답을 반환하고 반환된 IP 및 포트가 컨테이너에 대한 응답과 일치하는 경우 kube-apiserver가 실행되고 있지 않거나 네트워크에서 차단되었을 수 있습니다.

액세스가 차단되는 주요 이유는 네 가지가 있을 수 있습니다.

컨테이너 인사이트를 사용하여 kube-apiserver 로그를 확인할 수도 있습니다. kube-apiserver 로그 쿼리 및 기타 많은 쿼리에 대한 자세한 내용은 Container Insights에서 로그를 쿼리하는 방법을 참조하세요.

마지막으로 클러스터 자체에서 kube-apiserver 상태 및 해당 로그를 확인할 수 있습니다.

# Check kube-apiserver status. 
kubectl -n kube-system get pod -l component=kube-apiserver 

# Get kube-apiserver logs. 
PODNAME=$(kubectl -n kube-system get pod -l component=kube-apiserver -o jsonpath='{.items[0].metadata.name}')
kubectl -n kube-system logs $PODNAME --tail 100

403 - Forbidden 오류가 반환되는 경우 kube-apiserver는 RBAC(역할 기반 액세스 제어)로 구성되어 있고 컨테이너의 ServiceAccount에 리소스에 액세스할 수 있는 권한이 없는 것일 수 있습니다. 이 경우 적절한 RoleBindingClusterRoleBinding 개체를 만들어야 합니다. 역할 및 역할 바인딩에 대한 자세한 내용은 액세스 및 ID를 참조하세요. 클러스터에서 RBAC를 구성하는 방법에 대한 예제는 RBAC 권한 부여 사용을 참조하세요.

참가자

Microsoft에서 이 문서를 유지 관리합니다. 원래 다음 기여자가 작성했습니다.

보안 주체 작성자:

기타 기여자:

다음 단계