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 서버에서 권한을 부여한 범위 내에 있는지 확인합니다.
로컬 IP 주소를 찾습니다. Windows 및 Linux에서 찾는 방법에 대한 자세한 내용은 내 IP를 찾는 방법을 참조하세요.
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
containerPort
가containerPort
서비스와 같은지 확인합니다.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가 실행되고 있지 않거나 네트워크에서 차단되었을 수 있습니다.
액세스가 차단되는 주요 이유는 네 가지가 있을 수 있습니다.
- 네트워크 정책. API 관리 평면에 대한 액세스가 차단되고 있을 수 있습니다. 네트워크 정책 테스트에 대한 자세한 내용은 네트워크 정책 개요를 참조하세요.
- API의 허용된 IP 주소. 이 문제를 해결하는 방법에 대한 자세한 내용은 클러스터의 API 서버가 권한을 부여한 IP 범위 업데이트를 참조하세요.
- 프라이빗 방화벽. 프라이빗 방화벽을 통해 AKS 트래픽을 라우팅하는 경우 AKS 클러스터에 필요한 아웃바운드 네트워크 규칙 및 FQDN에 설명된 대로 아웃바운드 규칙이 있는지 확인합니다.
- 프라이빗 DNS. 프라이빗 클러스터를 호스팅하고 API 서버에 연결할 수 없는 경우 DNS 전달자가 제대로 구성되지 않은 것일 수 있습니다. 적절한 통신을 보장하려면 사용자 지정 DNS를 사용하는 허브 및 스포크의 단계를 완료합니다.
컨테이너 인사이트를 사용하여 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
에 리소스에 액세스할 수 있는 권한이 없는 것일 수 있습니다. 이 경우 적절한 RoleBinding
및 ClusterRoleBinding
개체를 만들어야 합니다. 역할 및 역할 바인딩에 대한 자세한 내용은 액세스 및 ID를 참조하세요. 클러스터에서 RBAC를 구성하는 방법에 대한 예제는 RBAC 권한 부여 사용을 참조하세요.
참가자
Microsoft에서 이 문서를 유지 관리합니다. 원래 다음 기여자가 작성했습니다.
보안 주체 작성자:
- Michael Walters | 선임 컨설턴트
기타 기여자:
- Mick Alberts | 테크니컬 라이터
- Ayobami Ayodeji | 선임 프로그램 관리자
- Bahram Rushenas | 설계자