노드는 프라이빗이고 VPN은 거기에 닿지만, kubectl은 여전히 클러스터와 대화하지 못한다. 이 두 사실은 무관하다. kubectl이 쓰는 주소는 자격 증명을 가져올 때 kubeconfig에 저장된 서버 URL에서 오며, 추가하는 어떤 경로도 그것을 바꾸지 않는다. 한편 kubectl이 애초에 도달하려는 대상은 노드가 아니다.

다섯 가지 점검, 중요한 유일한 값부터 시작한다.

점검 1: kubeconfig의 서버 URL을 읽어라

자격 증명을 쏟아내지 않고 엔드포인트를 출력하라: kubectl config view --minify -o jsonpath="{.clusters[0].cluster.server}". 그 한 문자열이 클라이언트가 IP 주소, DNS 이름, 의도하지 않은 외부 주소 중 어디를 가리키는지 알려 준다. 이 조사의 나머지는 모두 그것에서 나온다.

URL이 설정했다고 생각한 엔드포인트가 아니라면, 나머지 진단은 주의를 분산시킬 뿐이다.

점검 2: URL을 엔드포인트 유형과 맞춰라

현재 GKE는 IP 기반과 DNS 기반 컨트롤 플레인 액세스를 모두 지원하며, 가져온 자격 증명이 둘 중 하나를 고른다. gcloud container clusters get-credentials NAME --location REGION --internal-ip은 내부 IP 엔드포인트를 기록하고, --dns-endpoint는 DNS 기반 액세스를 선택한다. 어느 플래그도 네트워크 경로를 제공하지 않으므로, 자격 증명을 가져오면 연결이 고쳐질 것이라 기대하는 사람은 놀란다. 의도적으로 다시 가져온 뒤 URL을 다시 읽어라.

URL을 다시 읽지 않고 플래그를 바꾸는 것이 노트북이 두 클러스터의 자격 증명과 하나의 혼란스러운 오류를 안고 끝나는 방식이다.

승인된 네트워크 항목은 누가 외부 엔드포인트에 도달할 수 있는지를 정하며 내부 엔드포인트에는 적용되지 않는다. 프라이빗 경로를 시험하려고 그것을 넓히는 것은 진단이 아니라 노출을 바꾸는 일이다.

점검 3: 그 엔드포인트로 가는 경로를 증명하라

URL이 내부 IP라면 클라이언트가 실제로 있는 네트워크에서의 경로, 허용된 소스 범위, 클러스터의 리전 또는 글로벌 액세스 설정을 확인하라. 컨트롤 플레인 범위와 노드 서브넷은 같은 목적지가 아니므로, 노드로 통하는 경로는 엔드포인트에 대해 아무것도 증명하지 못한다. DNS 기반 액세스의 경로는 문서화된 Private Google Access 구성이 있는 Google API 연결이며, 워커 서브넷으로 가는 경로가 아니다. kubectl을 탓하기 전에 평범한 TCP 연결로 엔드포인트를 시험하라.

타임아웃은 경로 문제다. 403은 정책 문제다. 둘은 같은 해결책을 공유하지 않는다.

점검 4: 로그와 exec를 API 호출과 분리하라

일반 API 요청이 성공하는데 kubectl logs 또는 kubectl exec가 실패한다면, 이미 엔드포인트 선택을 지난 것이다. 그 작업들은 해당 Kubernetes 권한이 필요하고 컨트롤 플레인에서 노드로의 통신에 의존하며, 실패는 타임아웃이 아니라 Forbidden 응답일 수 있다. 노드로의 SSH 액세스는 전혀 다른 서비스를 시험하는 것이며 그것들을 확립하지 않는다.

두 분류는 서로 다른 곳에 살기 때문에 VPN 티켓을 다시 열기 전에 오류 분류를 읽어라.

점검 5: 다음 사람을 위해 세 가지 관찰을 남겨라

선택된 API URL, 승인된 API 요청 하나가 작동하는지, 그리고 정확히 어떤 후속 작업이 실패하는지를 오류 텍스트와 함께 기록하라. 그 세 줄이 엔드포인트 선택과 노드 액세스를 분리하며, 완벽히 좋은 VPN 경로가 결코 실어 나르지 않은 요청의 탓으로 돌려지는 것을 막는다.

다음 엔지니어는 터널이 고장 났는지 물을 것이다. 당신의 메모가 이미 그 답을 하고 있어야 한다.

관련 글