이 페이지에서는 Google Kubernetes Engine(GKE) 사용 문제를 해결하는 단계를 보여줍니다.
추가 지원이 필요하면 Cloud Customer Care에 문의하세요.Kubernetes 리소스 디버그
Kubernetes 리소스에 다음 문제에 문제가 발생한 경우
클러스터의 경우 Kubernetes 문서의 클러스터 문제해결을 참조하세요.
애플리케이션, 포드 또는 컨트롤러 객체는 애플리케이션 문제 해결을 참조하세요.
동일한 Virtual Private Cloud(VPC) 네트워크에 있는 Compute Engine VM 사이의 연결 또는 VPC 네트워크 피어링에 연결된 2개의 VPC 네트워크 사이의 연결에 관해서는 내부 IP 주소를 사용하는 가상 머신(VM) 인스턴스 사이의 연결 문제 해결을 참조하세요.
Cloud NAT, VPC 기반 클러스터, 또는 IP 마스커레이드 에이전트를 사용하여 클러스터에서 외부 IP 주소로 트래픽을 전송할 때 패킷 손실이 발생하는 경우 GKE 클러스터에서 Cloud NAT 패킷 손실 문제 해결을 참조하세요.
kubectl
명령어 문제 해결
이 섹션에는 kubectl
명령어의 여러 문제 유형에 대한 문제 해결 단계가 포함되어 있습니다.
문제: kubectl
명령어를 찾을 수 없음
kubectl
명령어를 찾을 수 없다는 메시지가 표시되면 kubectl
바이너리를 다시 설치하고 $PATH
환경 변수를 설정합니다.
다음 명령어를 실행하여
kubectl
바이너리를 설치합니다.gcloud components update kubectl
설치 프로그램에서
$PATH
환경 변수를 수정하라는 메시지가 표시되면 '예'라고 답합니다. 이 변수를 수정하면 전체 파일 경로를 입력하지 않고kubectl
명령어를 사용할 수 있습니다.또는 셸이
~/.bashrc
(macOS에서는~/.bash_profile
)과 같은 환경 변수를 저장하는 위치에 다음 줄을 추가합니다.export PATH=$PATH:/usr/local/share/google/google-cloud-sdk/bin/
다음 명령어를 실행하여 업데이트된 파일을 로드합니다. 다음 예시는
.bashrc
를 사용합니다.source ~/.bashrc
MacOS를 사용하는 경우
.bashrc
대신~/.bash_profile
을 사용하세요.
문제: kubectl
명령어가 'connection refused' 오류 반환
kubectl
명령어가 'connection refused' 오류가 반환하면 다음 명령어를 사용하여 클러스터 컨텍스트를 설정해야 합니다.
gcloud container clusters get-credentials CLUSTER_NAME
CLUSTER_NAME
에 입력할 내용을 모르겠으면 다음 명령어를 사용하여 클러스터를 나열합니다.
gcloud container clusters list
오류: kubectl
명령어의 시간 초과됨
클러스터를 만들고 클러스터에 kubectl
명령어를 실행하려고 했지만 kubectl
명령어가 타임아웃되면 다음과 같은 오류가 표시됩니다.
Unable to connect to the server: dial tcp IP_ADDRESS: connect: connection timed out
Unable to connect to the server: dial tcp IP_ADDRESS: i/o timeout
.
이러한 오류는 kubectl
이 클러스터 컨트롤 플레인과 통신할 수 없음을 나타냅니다.
이 문제를 해결하려면 클러스터가 설정된 컨텍스트를 확인하고 설정한 후 클러스터에 대한 연결을 확인하세요.
$HOME/.kube/config
로 이동하거나kubectl config view
명령어를 실행하여 구성 파일에 클러스터 컨텍스트 및 컨트롤 플레인의 외부 IP 주소가 포함되는지 확인합니다.클러스터 사용자 인증 정보를 설정합니다.
gcloud container clusters get-credentials CLUSTER_NAME \ --location=COMPUTE_LOCATION \ --project=PROJECT_ID
다음을 바꿉니다.
CLUSTER_NAME
: 클러스터의 이름입니다.COMPUTE_LOCATION
: Compute Engine 위치입니다.PROJECT_ID
: GKE 클러스터가 생성된 프로젝트의 ID입니다.
클러스터가 비공개 GKE 클러스터인 경우 기존 승인된 네트워크 목록에 연결을 시도하는 머신의 발신 IP가 포함되어 있는지 확인합니다. 콘솔에서 또는 다음 명령어를 실행하여 기존 승인된 네트워크를 찾을 수 있습니다.
gcloud container clusters describe CLUSTER_NAME \ --location=COMPUTE_LOCATION \ --project=PROJECT_ID \ --format "flattened(masterAuthorizedNetworksConfig.cidrBlocks[])"
머신의 발신 IP가 위 명령어의 결과에서 승인된 네트워크 목록에 포함되지 않았으면,
- 콘솔을 사용하는 경우 비공개 클러스터의 컨트롤 플레인에 연결할 수 없음의 안내를 따릅니다.
- Cloud Shell에서 연결하는 경우 Cloud Shell을 사용하여 비공개 클러스터 액세스의 안내를 따릅니다.
오류: kubectl
명령어가 'failed to negotiate an api version' 오류 반환
kubectl
명령어에서 'failed to negotiate an api version' 오류를 반환하면 kubectl
에 인증 사용자 인증 정보가 있는지 확인해야 합니다.
gcloud auth application-default login
문제: kubectl
logs
, attach
, exec
, port-forward
명령어에서 응답을 중지함
kubectl
logs
, attach
, exec
또는 port-forward
명령어에서 응답을 중지하면 일반적으로 API 서버가 노드와 통신할 수 없습니다.
먼저 클러스터에 노드가 있는지 확인합니다. 클러스터의 노드 수를 0으로 줄이면 명령어가 작동하지 않습니다. 이 문제를 해결하려면 노드가 최소한 한 개 이상 되도록 클러스터 크기를 조절합니다.
클러스터에 노드가 하나 이상 있으면 보안 통신을 사용 설정하기 위해 SSH 또는 Konnectivity 프록시 터널을 사용하고 있는지 확인합니다. 다음 섹션에서는 각 방법과 관련된 문제 해결 단계를 설명합니다.
SSH 문제 해결
SSH를 사용하는 경우 GKE는 Compute Engine 프로젝트 메타데이터에 SSH 공개 키 파일을 저장합니다. Google 제공 이미지를 사용하는 모든 Compute Engine VM은 VM의 승인된 사용자 목록에 추가할 SSH 키를 위해 프로젝트의 공통 메타데이터와 인스턴스의 메타데이터를 정기적으로 확인합니다. 또한 GKE는 컨트롤 플레인의 IP 주소에서 클러스터의 각 노드로 SSH 액세스를 허용하는 방화벽 규칙을 Compute Engine 네트워크에 추가합니다.
SSH 문제는 다음과 같은 이유로 발생할 수 있습니다.
네트워크의 방화벽 규칙은 컨트롤 플레인에서 SSH 액세스를 허용하지 않습니다.
모든 Compute Engine 네트워크는 모든 IP 주소에서 SSH 액세스를 허용하는(유효한 비공개 키 필요)
default-allow-ssh
라는 방화벽 규칙으로 생성됩니다. 또한 GKE는 특별히 클러스터의 컨트롤 플레인에서 클러스터의 노드로 SSH 액세스를 허용하는gke-CLUSTER_NAME-RANDOM_CHARACTERS-ssh
형식의 SSH 규칙을 각 공개 클러스터에 삽입합니다.이러한 규칙 중 어느 규칙이라도 존재하지 않으면 컨트롤 플레인에서 SSH 터널을 열 수 없습니다.
이것이 문제 원인인지 확인하려면 구성에 이러한 규칙이 있는지 확인합니다.
이 문제를 해결하려면 모든 클러스터 노드에 있는 태그를 식별한 다음 컨트롤 플레인의 IP 주소에서 해당 태그가 있는 VM에 대한 액세스를 허용하는 방화벽 규칙을 다시 추가하세요.
프로젝트의
ssh-keys
공통 메타데이터 항목이 가득 찼습니다.'ssh-keys'라는 프로젝트의 메타데이터 항목이 최대 크기 제한에 가까워지면 GKE는 SSH 터널을 열기 위해 자체 SSH 키를 추가할 수 없습니다.
이 문제인지 확인하려면 ssh-key 목록의 길이를 확인하세요. 선택적으로
--project
플래그를 포함하여 다음 명령어를 실행하여 프로젝트의 메타데이터를 볼 수 있습니다.gcloud compute project-info describe [--project=PROJECT_ID]
이 문제를 해결하려면 더 이상 필요 없는 일부 SSH 키를 삭제합니다.
클러스터의 VM에서 'ssh-keys' 키로 메타데이터 필드를 설정했습니다.
VM의 노드 에이전트는 프로젝트 전체 SSH 키보다 인스턴스별 ssh-keys를 선호합니다. 따라서 특별히 클러스터 노드에 SSH 키를 설정한 경우, 프로젝트 메타데이터에 있는 컨트롤 플레인의 SSH 키가 노드에 사용되지 않습니다.
문제인지 확인하려면
gcloud compute instances describe VM_NAME
를 실행하고 메타데이터에서ssh-keys
필드를 찾습니다.이 문제를 해결하려면 인스턴스 메타데이터에서 인스턴스별 SSH 키를 삭제합니다.
Konnectivity 프록시 문제 해결
다음 시스템 배포를 확인하여 클러스터에 Konnectivity 프록시가 사용되는지 확인할 수 있습니다.
kubectl get deployments konnectivity-agent --namespace kube-system
Konnectivity 프록시 문제는 다음과 같은 이유로 발생할 수 있습니다.
네트워크의 방화벽 규칙은 컨트롤 플레인에 대해 Konnectivity 에이전트 액세스를 허용하지 않습니다.
클러스터를 만들면 Konnectivity 에이전트 포드가 컨트롤 플레인에 대해 연결을 설정하고 포트
8132
에서 유지보수합니다.kubectl
명령어 중 하나를 실행하면 API 서버가 이 연결을 사용해서 클러스터와 통신합니다.네트워크의 방화벽 규칙에 이그레스 거부 규칙이 포함된 경우 에이전트 연결을 방해할 수 있습니다.
이것이 문제의 원인인지 확인하려면 네트워크의 방화벽 규칙을 점검하여 이그레스 거부 규칙이 포함되어 있는지 확인합니다.
이 문제를 해결하려면 포트 8132에서 클러스터 컨트롤 플레인에 대한 이그레스 트래픽을 허용하세요. (비교를 위해 API 서버에는 443이 사용됩니다.)
클러스터의 네트워크 정책은
kube-system
네임스페이스에서workload
네임스페이스로의 인그레스를 차단합니다.클러스터의 정상 작동에는 이러한 기능이 필요하지 않습니다. 클러스터의 네트워크를 모든 외부 액세스로부터 잠그려고 하면 이러한 기능이 작동하지 않습니다.
이것이 문제 원인인지 확인하려면 다음 명령어를 실행하여 영향을 받는 네임스페이스에서 네트워크 정책을 찾습니다.
kubectl get networkpolicy --namespace AFFECTED_NAMESPACE
이 문제를 해결하려면 네트워크 정책의
spec.ingress
필드에 다음을 추가합니다.- from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system podSelector: matchLabels: k8s-app: konnectivity-agent
오류 4xx 문제 해결
다음 섹션에서는 오류 400, 401, 403, 404, 관련 인증 및 승인 오류 문제를 해결하는 데 도움이 됩니다.
문제: GKE 클러스터에 연결할 때 인증 및 승인 오류
GKE 클러스터에 연결할 때 HTTP 상태 코드 401(승인되지 않음)과 함께 인증 및 승인 오류가 발생할 수 있습니다. 이 문제는 로컬 환경의 GKE 클러스터에서 kubectl
명령어를 실행할 때 발생할 수 있습니다.
이 문제의 원인은 다음 중 하나일 수 있습니다.
gke-gcloud-auth-plugin
인증 플러그인이 올바르게 설치 또는 구성되지 않았습니다.- 클러스터 API 서버에 연결하고
kubectl
명령어를 실행하기 위한 권한이 부족합니다.
원인을 진단하려면 다음 섹션의 단계를 따르세요.
curl
을 사용하여 클러스터에 연결
인증 및 승인 오류의 원인을 진단하려면 curl
을 사용하여 클러스터에 연결합니다.
curl
을 사용하면 kubectl
CLI 및 gke-gcloud-auth-plugin
플러그인을 우회하게 됩니다.
환경 변수를 설정합니다.
APISERVER=https://$(gcloud container clusters describe CLUSTER_NAME --location=COMPUTE_LOCATION --format "value(endpoint)") TOKEN=$(gcloud auth print-access-token)
액세스 토큰이 유효한지 확인합니다.
curl https://oauth2.googleapis.com/tokeninfo?access_token=$TOKEN
API 서버에서 핵심 API 엔드포인트에 연결을 시도합니다.
gcloud container clusters describe CLUSTER_NAME --location=COMPUTE_LOCATION --format "value(masterAuth.clusterCaCertificate)" | base64 -d > /tmp/ca.crt curl -s -X GET "${APISERVER}/api/v1/namespaces" --header "Authorization: Bearer $TOKEN" --cacert /tmp/ca.crt
curl
명령어가 성공하면 kubeconfig에서 플러그인 구성 섹션의 단계에 따라 플러그인이 원인인지 확인합니다.curl
명령어가 다음과 비슷한 출력과 함께 실패하면 클러스터에 액세스할 수 있는 올바른 권한이 없는 것입니다.{ "kind": "Status", "apiVersion": "v1", "metadata": {}, "status": "Failure", "message": "Unauthorized", "reason": "Unauthorized", "code": 401 }
이 문제를 해결하려면 클러스터에 액세스할 수 있는 올바른 권한을 얻으세요.
kubeconfig에서 플러그인 사용 구성
클러스터에 연결할 때 인증 및 승인 오류가 발생하지만 curl
을 사용하여 클러스터에 연결할 수 있다면, gke-gcloud-auth-plugin
플러그인이 없어도 클러스터에 액세스할 수 있게 해야 합니다.
이 문제를 해결하려면 클러스터에 인증할 때 gke-gcloud-auth-plugin
바이너리를 무시하도록 로컬 환경을 구성합니다. 버전 1.25 이상을 실행하는 Kubernetes 클라이언트에서는 gke-gcloud-auth-plugin
바이너리가 필수이므로 kubectl
CLI 버전 1.24 이하를 사용해야 합니다.
플러그인 없이 클러스터에 액세스하려면 다음 단계를 수행합니다.
curl
을 사용하여kubectl
CLI 버전 1.24를 설치합니다.curl -LO https://dl.k8s.io/release/v1.24.0/bin/linux/amd64/kubectl
kubectl
CLI 버전 1.24 이하를 사용할 수 있습니다.텍스트 편집기에서 Bash 셸에 대한
.bashrc
와 같은 셸 시작 스크립트 파일을 엽니다.vi ~/.bashrc
MacOS를 사용하는 경우 이 안내에서
.bashrc
대신~/.bash_profile
을 사용하세요.다음 줄을 파일에 추가하고 저장합니다.
export USE_GKE_GCLOUD_AUTH_PLUGIN=False
시작 스크립트를 실행합니다.
source ~/.bashrc
.kube/config
파일을 설정하는 클러스터의 사용자 인증 정보를 가져옵니다.gcloud container clusters get-credentials CLUSTER_NAME \ --location=COMPUTE_LOCATION
다음을 바꿉니다.
CLUSTER_NAME
: 클러스터의 이름입니다.COMPUTE_LOCATION
: Compute Engine 위치입니다.
kubectl
명령어를 실행합니다.kubectl cluster-info
이러한 명령어를 실행할 때 401 오류 또는 비슷한 승인 오류가 발생하면 올바른 권한이 있는지 확인한 다음 오류를 반환한 단계를 다시 실행합니다.
오류 400: 노드 풀에 다시 만들기 필요
'오류 400, 노드 풀에 다시 만들기 필요'는 다음과 비슷한 양상입니다.
ERROR: (gcloud.container.clusters.update) ResponseError: code=400, message=Node pool "test-pool-1" requires recreation.
이 오류는 컨트롤 플레인과 노드를 다시 만드는 작업을 수행하려고 시도할 때 발생합니다. 예를 들어 이 오류는 진행 중인 사용자 인증 정보 순환을 완료할 때 발생할 수 있습니다.
백엔드에서 노드 풀이 다시 만들도록 표시되었지만 실제 다시 만들기 작업이 시작되려면 일부 시간이 걸릴 수 있습니다. 따라서 GKE가 아직 클러스터에 하나 이상의 노드 풀을 다시 만들지 않았으므로 작업이 실패합니다.
이 문제를 해결하려면 다음 중 한 가지를 따르세요.
- 다시 만들기가 수행될 때까지 기다립니다. 기존 유지보수 기간 및 제외 항목과 같은 요소에 따라 몇 시간, 며칠, 몇 주가 걸릴 수 있습니다.
컨트롤 플레인과 동일한 버전으로 버전 업그레이드를 시작하여 영향을 받는 노드 풀 다시 만들기를 수동으로 시작합니다.
다시 만들기를 시작하려면 다음 명령어를 실행합니다.
gcloud container clusters upgrade CLUSTER_NAME \ --node-pool=POOL_NAME
업그레이드가 완료된 후 작업을 다시 시도합니다.
오류 403: 권한 부족
오류 403, 권한 부족은 다음과 유사합니다.
ERROR: (gcloud.container.clusters.get-credentials) ResponseError: code=403, message=Required "container.clusters.get" permission(s) for "projects/<your-project>/locations/<region>/clusters/<your-cluster>".
gcloud container clusters get-credentials
을 사용하여 GKE 클러스터에 연결을 시도하지만 계정에 Kubernetes API 서버에 액세스할 수 있는 권한이 없을 때 이 오류가 발생합니다.
이 문제를 해결하려면 다음 단계를 따르세요.
액세스 문제가 있는 계정을 식별합니다.
gcloud auth list
Kubernetes API 서버에 인증의 안내에 따라 계정에 필요한 액세스 권한을 부여합니다.
오류 404: gcloud container
명령어를 호출할 때 리소스를 '찾을 수 없음'
오류 403, 리소스를 찾을 수 없음이 발생하면 gcloud container
명령어를 호출할 때 Google Cloud CLI에 다시 인증하여 문제를 해결하세요.
gcloud auth login
오류 400/403: 계정에 수정 권한 없음
계정 오류(오류 400 또는 403)로 인해 수정 권한이 누락되면 다음 중 하나가 수동으로 삭제되었거나 수정되었음을 나타냅니다.
Compute Engine 또는 Kubernetes Engine API를 사용 설정하면 Google Cloud가 다음 서비스 계정 및 에이전트를 만듭니다.
- 프로젝트에 대해 수정 권한이 있는 Compute Engine 기본 서비스 계정
- 프로젝트에 대해 수정 권한이 있는 Google API 서비스 에이전트
- 프로젝트에 대해 Kubernetes Engine 서비스 에이전트 역할이 있는 Google Kubernetes Engine 서비스 계정
언제든지 누군가가 이러한 권한을 수정하거나 프로젝트에서 역할 결합을 제거하거나 서비스 계정을 완전히 삭제하거나 API를 사용 중지하면 클러스터 생성 및 모든 관리 기능이 실패합니다.
Google Kubernetes Engine 서비스 계정에 프로젝트에 할당된 Kubernetes Engine 서비스 에이전트 역할이 있는지 확인하려면 다음 단계를 따르세요.
다음 패턴을 사용하여 Google Kubernetes Engine 서비스 계정의 이름을 계산합니다.
service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com
여기에서
PROJECT_NUMBER
를 프로젝트 번호로 바꿉니다.Google Kubernetes Engine 서비스 계정에 아직 프로젝트에 Kubernetes Engine 서비스 에이전트 역할이 할당되지 않은 것을 확인합니다. 이 명령어에서
PROJECT_ID
를 프로젝트 ID로 바꿉니다.gcloud projects get-iam-policy PROJECT_ID
문제를 해결하려면 다음을 시도해 보세요.
- 다른 사용자가 Google Kubernetes Engine 서비스 계정에서 Kubernetes Engine 서비스 에이전트 역할을 삭제한 경우 다시 추가합니다.
그렇지 않은 경우 다음 안내에 따라 Kubernetes Engine API를 다시 사용 설정합니다. 그러면 서비스 계정과 권한이 올바르게 복원됩니다.
콘솔
Google Cloud 콘솔의 API 및 서비스 페이지로 이동합니다.
프로젝트를 선택합니다.
API 및 서비스 사용 설정을 클릭합니다.
Kubernetes를 검색한 후 검색 결과에서 API를 선택합니다.
사용 설정을 클릭합니다. 이전에 API를 사용 설정했으면 먼저 API를 중지했다가 다시 사용 설정해야 합니다. API와 관련 서비스가 사용 설정되는 데 몇 분 정도 걸릴 수 있습니다.
gcloud
gcloud CLI에서 다음 명령어를 실행합니다.
PROJECT_NUMBER=$(gcloud projects describe "PROJECT_ID"
--format 'get(projectNumber)')
gcloud projects add-iam-policy-binding PROJECT_ID \
--member "serviceAccount:service-${PROJECT_NUMBER?}@container-engine-robot.iam.gserviceaccount.com" \
--role roles/container.serviceAgent
GKE 클러스터 연결 문제 해결
CONDITION_NOT_MET 오류: constraints/compute.vmExternalIpAccess 제약 조건 위반
조직 정책 제약 조건 constraints/compute.vmExternalIpAccess가 Deny All
로 구성되었거나 공개 GKE 클러스터를 만들려고 시도 중인 조직, 폴더, 프로젝트 수준에서 특정 VM 인스턴스로 외부 IP를 제한하도록 구성되었습니다.
공개 GKE 클러스터를 만들면 이 클러스터의 워커 노드를 구성하는 기본 Compute Engine VM에 외부 IP 주소가 할당됩니다. 조직 정책 제약조건 constraints/compute.vmExternalIpAccess를 Deny All
로 구성하거나 특정 VM 인스턴스로 외부 IP를 제한하도록 구성하면 정책에 따라 GKE 워커 노드가 외부 IP 주소를 가져오지 못하도록 방지되어 클러스터 만들기 오류가 발생합니다.
클러스터 만들기 작업 로그를 찾으려면 로그 탐색기를 사용해서 다음과 비슷한 검색어로 GKE 클러스터 작업 감사 로그를 검토할 수 있습니다.
resource.type="gke_cluster"
logName="projects/test-last-gke-sa/logs/cloudaudit.googleapis.com%2Factivity"
protoPayload.methodName="google.container.v1beta1.ClusterManager.CreateCluster"
resource.labels.cluster_name="CLUSTER_NAME"
resource.labels.project_id="PROJECT_ID"
이 문제를 해결하기 위해서는 GKE 공개 클러스터를 만들려고 시도 중인 프로젝트에서 constraints/compute.vmExternalIpAccess
제약조건에 적용되는 정책이 Allow All
인지 확인합니다. 이 제약조건 사용에 대한 자세한 내용은 특정 VM 인스턴스로 외부 IP 주소 제한을 참조하세요. 제약조건을 Allow All
로 설정한 후 실패한 클러스터를 삭제하고 새 클러스터를 만듭니다. 이 작업은 실패한 클러스터 복구가 가능하지 않기 때문에 필요합니다.
배포된 워크로드 문제 해결
워크로드 Pod에 문제가 있으면 GKE가 오류를 반환합니다.
kubectl
명령줄 도구 또는 Google Cloud 콘솔을 사용하여 포드 상태를 확인할 수 있습니다.
kubectl
클러스터에서 실행 중인 모든 Pod를 확인하려면 다음 명령어를 실행합니다.
kubectl get pods
다음과 같이 출력됩니다.
NAME READY STATUS RESTARTS AGE
POD_NAME 0/1 CrashLoopBackOff 23 8d
특정 Pod에 대한 자세한 내용을 보려면 다음 명령어를 실행합니다.
kubectl describe pod POD_NAME
POD_NAME
을 원하는 Pod의 이름으로 바꿉니다.
콘솔
다음 단계를 수행합니다.
Google Cloud 콘솔에서 워크로드 페이지로 이동합니다.
원하는 워크로드를 선택합니다. 개요 탭에 워크로드 상태가 표시됩니다.
관리형 Pod 섹션에서 오류 상태 메시지를 클릭합니다.
다음 섹션에서는 워크로드가 반환하는 몇 가지 일반적인 오류와 그 해결 방법을 설명합니다.
오류: CrashLoopBackOff
CrashLoopBackOff
는 컨테이너가 다시 시작 후 반복적으로 비정상 종료됨을 나타냅니다. 컨테이너는 다양한 원인으로 인해 비정상 종료될 수 있습니다. Pod의 로그를 확인하면 근본 원인을 해결할 수 있습니다.
기본적으로 비정상 종료된 컨테이너는 5분으로 제한된 지수 지연으로 다시 시작됩니다. spec: restartPolicy
에서 restartPolicy
필드 배포의 포드 사양을 설정하여 이 동작을 변경할 수 있습니다. 이 필드의 기본값은 Always
입니다.
Google Cloud 콘솔을 사용하여 CrashLoopBackOff
오류를 문제 해결할 수 있습니다.
비정상 종료 루프 포드 대화형 플레이북으로 이동합니다.
클러스터에 대해 문제 해결하려는 클러스터 이름을 입력합니다.
네임스페이스에 대해 문제 해결하려는 네임스페이스를 입력합니다.
(선택사항) 이후의
CrashLoopBackOff
오류를 알리도록 알림을 만듭니다.- 향후 문제 완화 팁 섹션에서 알림 만들기를 선택합니다.
로그 검사
kubectl
명령줄 도구 또는 Google Cloud 콘솔을 사용하여 포드의 컨테이너가 비정상 종료되는 원인을 확인할 수 있습니다.
kubectl
클러스터에서 실행 중인 모든 Pod를 확인하려면 다음 명령어를 실행합니다.
kubectl get pods
CrashLoopBackOff
오류가 있는 Pod를 찾습니다.
pod의 로그를 가져오려면 다음 명령어를 실행합니다.
kubectl logs POD_NAME
POD_NAME
을 문제가 있는 pod의 이름으로 바꿉니다.
-p
플래그를 전달하여 pod 컨테이너의 이전 인스턴스 로그(있는 경우)를 가져올 수도 있습니다.
콘솔
다음 단계를 수행합니다.
Google Cloud 콘솔에서 워크로드 페이지로 이동합니다.
원하는 워크로드를 선택합니다. 개요 탭에 워크로드 상태가 표시됩니다.
관리형 포드 섹션에서 문제가 있는 포드를 클릭합니다.
포드의 메뉴에서 로그 탭을 클릭합니다.
비정상 종료된 컨테이너의 '종료 코드' 확인
다음 태스크를 수행하여 종료 코드를 확인할 수 있습니다.
다음 명령어를 실행합니다.
kubectl describe pod POD_NAME
POD_NAME
을 Pod의 이름으로 바꿉니다.containers: CONTAINER_NAME: last state: exit code
필드 값을 검토합니다.- 종료 코드가 1이면 애플리케이션 비정상 종료로 인해 컨테이너가 비정상 종료된 것입니다.
- 종료 코드가 0이면 앱이 실행된 시간을 확인합니다.
애플리케이션의 기본 프로세스가 종료되면 컨테이너가 종료됩니다. 앱 실행이 아주 빨리 끝나면 컨테이너가 계속 다시 시작될 수 있습니다.
실행 중인 컨테이너에 연결
Pod에 대한 셸을 엽니다.
kubectl exec -it POD_NAME -- /bin/bash
pod에 컨테이너가 두 개 이상 있으면 -c CONTAINER_NAME
을 추가합니다.
이제 컨테이너에서 bash 명령어를 실행할 수 있습니다. 네트워크를 테스트하거나 애플리케이션에서 사용하는 파일 또는 데이터베이스에 액세스할 수 있는지 확인할 수 있습니다.
ImagePullBackOff 및 ErrImagePull 오류
ImagePullBackOff
와 ErrImagePull
은 컨테이너가 사용하는 이미지를 이미지 레지스트리에서 로드할 수 없음을 나타냅니다.
Google Cloud 콘솔 또는 kubectl
명령줄 도구를 사용하여 이 문제를 확인할 수 있습니다.
kubectl
포드의 컨테이너 이미지에 대한 자세한 정보를 보려면 다음 명령어를 실행합니다.
kubectl describe pod POD_NAME
콘솔
다음 단계를 수행합니다.
Google Cloud 콘솔에서 워크로드 페이지로 이동합니다.
원하는 워크로드를 선택합니다. 개요 탭에 워크로드 상태가 표시됩니다.
관리형 포드 섹션에서 문제가 있는 포드를 클릭합니다.
포드의 메뉴에서 이벤트 탭을 클릭합니다.
문제: 이미지를 찾을 수 없는 경우
이미지를 찾을 수 없는 경우, 다음을 수행합니다.
- 이미지의 이름이 올바른지 확인합니다.
- 이미지의 태그가 올바른지 확인합니다. (
:latest
를 사용하거나 태그를 사용하지 않으면 최신 이미지를 가져올 수 있습니다.) - 이미지에 전체 레지스트리 경로가 있으면 사용 중인 Docker 레지스트리에 있는지 확인합니다. 이미지 이름만 제공하는 경우, Docker Hub 레지스트리를 확인합니다.
Docker 이미지를 수동으로 가져옵니다.
SSH를 통해 노드에 연결합니다.
예를 들어 VM에 SSH로 연결하려면 다음을 실행합니다.
gcloud compute ssh VM_NAME --zone=ZONE_NAME
다음을 바꿉니다.
VM_NAME
: VM의 이름입니다.ZONE_NAME
: Compute Engine 영역입니다.
docker-credential-gcr configure-docker
를 실행합니다. 이 명령어는/home/[USER]/.docker/config.json
에서 구성 파일을 생성합니다. 이 파일에credHelpers
필드의 이미지 레지스트리가 포함되는지 확인합니다. 예를 들어 다음 파일에는 asia.gcr.io, eu.gcr.io, gcr.io, marketplace.gcr.io, us.gcr.io에 호스팅된 이미지의 인증 정보가 포함됩니다.{ "auths": {}, "credHelpers": { "asia.gcr.io": "gcr", "eu.gcr.io": "gcr", "gcr.io": "gcr", "marketplace.gcr.io": "gcr", "us.gcr.io": "gcr" } }
docker pull IMAGE_NAME
를 실행합니다.
이 방법이 효과적이면 pod에서 ImagePullSecrets을 지정해야 할 수도 있습니다. 포드는 자체 네임스페이스에 있는 이미지 가져오기 보안 비밀만을 참조할 수 있으므로 이 프로세스는 네임스페이스당 한 번 수행해야 합니다.
오류: 권한 거부됨
"permission denied" 또는 "no pull access" 오류가 발생하면 로그인되어 있고 이미지에 대한 액세스 권한이 있는지 확인합니다. 이미지를 호스팅하는 레지스트리에 따라 다음 방법 중 하나를 시도합니다.
Artifact Registry
이미지가 Artifact Registry에 있으면 노드 풀의 서비스 계정에 이미지가 포함된 저장소에 대한 읽기 액세스 권한이 필요합니다.
서비스 계정에 artifactregistry.reader
역할을 부여합니다.
gcloud artifacts repositories add-iam-policy-binding REPOSITORY_NAME \
--location=REPOSITORY_LOCATION \
--member=serviceAccount:SERVICE_ACCOUNT_EMAIL \
--role="roles/artifactregistry.reader"
다음을 바꿉니다.
REPOSITORY_NAME
: Artifact Registry 저장소의 이름입니다.REPOSITORY_LOCATION
: Artifact Registry 저장소의 리전입니다.SERVICE_ACCOUNT_EMAIL
: 노드 풀과 연결된 IAM 서비스 계정의 이메일 주소입니다.
Container Registry
이미지가 Container Registry에 있으면 노드 풀의 서비스 계정에 이미지가 포함된 Cloud Storage 버킷에 대한 읽기 액세스 권한이 필요합니다.
버킷에서 읽을 수 있도록 서비스 계정에 roles/storage.objectViewer
역할을 부여합니다.
gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
--member=serviceAccount:SERVICE_ACCOUNT_EMAIL \
--role=roles/storage.objectViewer
다음을 바꿉니다.
SERVICE_ACCOUNT_EMAIL
: 노드 풀과 연결된 서비스 계정의 이메일입니다.gcloud iam service-accounts list
를 사용하여 프로젝트의 모든 서비스 계정을 나열할 수 있습니다.BUCKET_NAME
: 이미지가 포함된 Cloud Storage 버킷의 이름입니다.gcloud storage ls
를 사용하여 프로젝트의 모든 버킷을 나열할 수 있습니다.
레지스트리 관리자가 Container Registry 대신 gcr.io
도메인에 대해 이미지를 저장하도록 Artifact Registry에서 gcr.io 저장소를 설정한 경우 Container Registry 대신 Artifact Registry에 대해 읽기 액세스 권한을 부여해야 합니다.
비공개 레지스트리
이미지가 비공개 레지스트리에 있으면 이미지에 액세스하기 위해 키가 필요할 수 있습니다. 자세한 내용은 비공개 레지스트리 사용을 참조하세요.
오류 401 승인되지 않음: 비공개 Container Registry 저장소에서 이미지를 가져올 수 없음
비공개 Container Registry 저장소에서 이미지를 가져올 때 다음과 비슷한 오류가 발생할 수 있습니다.
gcr.io/PROJECT_ID/IMAGE:TAG: rpc error: code = Unknown desc = failed to pull and
unpack image gcr.io/PROJECT_ID/IMAGE:TAG: failed to resolve reference
gcr.io/PROJECT_ID/IMAGE]:TAG: unexpected status code [manifests 1.0]: 401 Unauthorized
Warning Failed 3m39s (x4 over 5m12s) kubelet Error: ErrImagePull
Warning Failed 3m9s (x6 over 5m12s) kubelet Error: ImagePullBackOff
Normal BackOff 2s (x18 over 5m12s) kubelet Back-off pulling image
포드를 실행 중인 노드를 식별합니다.
kubectl describe pod POD_NAME | grep "Node:"
노드에 스토리지 범위가 포함되었는지 확인합니다.
gcloud compute instances describe NODE_NAME \ --zone=COMPUTE_ZONE --format="flattened(serviceAccounts[].scopes)"
노드의 액세스 범위에는 최소한 다음 중 하나 이상이 포함되어야 합니다.
serviceAccounts[0].scopes[0]: https://www.googleapis.com/auth/devstorage.read_only serviceAccounts[0].scopes[0]: https://www.googleapis.com/auth/cloud-platform
충분한 범위를 사용해서 노드가 포함된 노드 풀을 다시 만듭니다. 기존 노드는 수정할 수 없고, 올바른 범위를 사용해서 노드를 다시 만들어야 합니다.
권장사항:
gke-default
범위를 사용해서 새 노드 풀을 만듭니다.gcloud container node-pools create NODE_POOL_NAME \ --cluster=CLUSTER_NAME \ --zone=COMPUTE_ZONE \ --scopes="gke-default"
스토리지 범위만 사용해서 새 노드 풀을 만듭니다.
gcloud container node-pools create NODE_POOL_NAME \ --cluster=CLUSTER_NAME \ --zone=COMPUTE_ZONE \ --scopes="https://www.googleapis.com/auth/devstorage.read_only"
오류: 예약할 수 없는 포드
PodUnschedulable
은 리소스 부족 또는 일부 구성 오류로 인해 Pod를 예약할 수 없음을 나타냅니다.
Kubernetes API 서버 및 Kubernetes 스케줄러 측정항목을 Cloud Monitoring으로 전송하도록 GKE 클러스터를 구성한 경우 스케줄러 측정항목 및 API 서버 측정항목에서 이러한 오류에 대한 자세한 정보를 찾을 수 있습니다.
Google Cloud 콘솔을 사용하여 PodUnschedulable
오류를 문제 해결할 수 있습니다.
예약할 수 없는 포드 대화형 플레이북으로 이동합니다.
클러스터에 대해 문제 해결하려는 클러스터 이름을 입력합니다.
네임스페이스에 대해 문제 해결하려는 네임스페이스를 입력합니다.
(선택사항) 이후의
PodUnschedulable
오류를 알리도록 알림을 만듭니다.- 향후 문제 완화 팁 섹션에서 알림 만들기를 선택합니다.
오류: 리소스 부족
CPU, 메모리 또는 다른 리소스 부족을 나타내는 오류가 발생할 수 있습니다. 예: '모든 조건자와 일치하는 노드를 사용할 수 없음: cpu 부족 (2)'은 2개의 노드에 포드의 요청 충족에 사용할 수 있는 CPU가 충분하지 않음을 나타냅니다.
포드 리소스 요청이 적격한 노드 풀에서 단일 노드의 요청을 초과할 경우 GKE가 포드를 예약하지 않고 새 노드를 추가하기 위한 수직 확장을 트리거하지 않습니다. GKE가 포드를 예약할 수 있도록 하려면 포드에 대해 더 적은 수의 리소스를 요청하거나 리소스가 충분한 새 노드 풀을 만들어야 합니다.
또한 예약되지 않은 포드가 실행될 수 있는 노드를 사용해서 GKE가 노드 풀을 자동으로 만들 수 있도록 노드 자동 프로비저닝을 사용 설정할 수 있습니다.
기본 CPU 요청은 100m 또는 CPU의 10%(또는 코어 한 개)입니다.
더 많은 리소스 또는 더 적은 리소스를 요청하려면 spec: containers: resources: requests
의 포드 사양에 값을 지정합니다.
오류: MatchNodeSelector
MatchNodeSelector
는 Pod의 라벨 선택기와 일치하는 노드가 없음을 나타냅니다.
spec: nodeSelector
에서 Pod 사양의 nodeSelector
필드에 지정된 라벨을 통해 이를 확인할 수 있습니다.
클러스터의 노드에 라벨이 어떻게 지정되어 있는지 확인하려면 다음 명령어를 실행합니다.
kubectl get nodes --show-labels
노드에 라벨을 연결하려면 다음 명령어를 실행합니다.
kubectl label nodes NODE_NAME LABEL_KEY=LABEL_VALUE
다음을 바꿉니다.
NODE_NAME
: 원하는 노드LABEL_KEY
: 라벨의 키LABEL_VALUE
: 라벨의 값
자세한 내용은 포드를 노드에 할당을 참조하세요.
오류: PodToleratesNodeTaints
PodToleratesNodeTaints
는 현재 노드 taint를 허용하는 노드가 없으므로 포드를 어떠한 노드에도 예약할 수 없음을 나타냅니다.
이 경우인지 확인하려면 다음 명령어를 실행합니다.
kubectl describe nodes NODE_NAME
출력에서 키-값 쌍과 예약 효과가 나열되는 Taints
필드를 확인합니다.
나열된 효과가 NoSchedule
이면 일치하는 톨러레이션이 없는 한 노드에서 pod를 예약할 수 없습니다.
이 문제를 해결하는 한 가지 방법은 taint를 제거하는 것입니다. 예를 들어 NoSchedule taint를 삭제하려면 다음 명령어를 실행합니다.
kubectl taint nodes NODE_NAME key:NoSchedule-
오류: PodFitsHostPorts
PodFitsHostPorts
는 노드가 사용하려 하는 포트가 이미 사용 중임을 나타냅니다.
이 문제를 해결하려면 spec: containers: ports: hostPort
에서 Pod 사양의 hostPort
값을 확인합니다. 이 값을 다른 포트로 변경해야 할 수도 있습니다.
오류: 최소 가용성 없음
노드에 적절한 리소스가 있지만 여전히 Does not have minimum availability
메시지가 표시되면 Pod 상태를 확인합니다. 상태가 SchedulingDisabled
또는 Cordoned
이면 노드가 새 포드를 예약할 수 없습니다. Google Cloud 콘솔 또는 kubectl
명령줄 도구를 사용해서 노드 상태를 확인할 수 있습니다.
kubectl
노드 상태를 가져오려면 다음 명령어를 실행합니다.
kubectl get nodes
노드에서 예약을 사용 설정하려면 다음을 실행합니다.
kubectl uncordon NODE_NAME
콘솔
다음 단계를 수행합니다.
Google Cloud 콘솔에서 Google Kubernetes Engine 페이지로 이동합니다.
원하는 클러스터를 선택합니다. 노드 탭에 노드와 노드 상태가 표시됩니다.
노드에서 예약을 사용 설정하려면 다음 단계를 수행합니다.
목록에서 원하는 노드를 클릭합니다.
노드 세부정보에서 차단 해제 버튼을 클릭합니다.
오류: 노드당 최대 노드 수 한도 도달
클러스터의 모든 노드에서 노드당 최대 노드 수 한도에 도달하면 포드가 예약 불가능한 상태로 멈춥니다. 포드 이벤트 탭에서 Too many pods
문구가 포함된 메시지가 표시됩니다.
Google Cloud 콘솔의 GKE 클러스터 세부정보에 있는 노드 탭에서
Maximum pods per node
구성을 확인합니다.노드 목록을 가져옵니다.
kubectl get nodes
각 노드에 대해 노드에서 실행 중인 포드 수를 확인합니다.
kubectl get pods -o wide | grep NODE_NAME | wc -l
한도에 도달하면 새 노드 풀을 추가하거나 기존 노드 풀에 노드를 더 추가합니다.
문제: 클러스터 자동 확장 처리가 사용 설정된 상태로 최대 노드 풀 크기에 도달
클러스터 자동 확장 처리 구성에 따라 노드 풀이 최대 크기에 도달했으면 GKE에서 이 노드 풀로 예약되었을 포드에 대해 수직 확장이 트리거되지 않습니다. 이 노드 풀로 포드를 예약하려면 클러스터 자동 확장 처리 구성을 변경합니다.
문제: 클러스터 자동 확장 처리가 사용 중지된 상태로 최대 노드 풀 크기에 도달
노드 풀이 최대 노드 수에 도달했고 클러스터 자동 확장 처리가 사용 중지되어 있으면 GKE가 노드 풀로 포드를 예약할 수 없습니다. GKE가 클러스터 크기를 자동으로 조정할 수 있도록 노드 풀의 크기를 늘리거나 또는 클러스터 자동 확장 처리를 사용 설정합니다.
오류: 결합 해제된 PersistentVolumeClaim
Unbound PersistentVolumeClaims
는 Pod가 결합되지 않은 PersistentVolumeClaim을 참조함을 나타냅니다. 이 오류는 PersistentVolume이 프로비저닝을 실패한 경우에 발생할 수 있습니다. PersistentVolumeClaim의 이벤트를 가져오고 실패를 검사하여 프로비저닝 실패를 확인할 수 있습니다.
이벤트를 가져오려면 다음 명령어를 실행합니다.
kubectl describe pvc STATEFULSET_NAME-PVC_NAME-0
다음을 바꿉니다.
STATEFULSET_NAME
: StatefulSet 객체의 이름입니다.PVC_NAME
: PersistentVolumeClaim 객체의 이름입니다.
이는 PersistentVolume을 수동으로 사전 프로비저닝하고 PersistentVolumeClaim에 결합하는 중에 구성 오류가 있어도 발생할 수 있습니다. 볼륨을 다시 사전 프로비저닝할 수 있습니다.
오류: 할당량 부족
GKE가 클러스터를 수직 확장할 수 있도록 프로젝트에 Compute Engine 할당량이 충분한지 확인합니다. GKE가 포드를 예약할 수 있도록 클러스터에 노드를 추가하려고 시도할 때 수직 확장으로 인해 프로젝트의 가용 할당량이 초과될 경우 scale.up.error.quota.exceeded
오류 메시지가 표시됩니다.
자세한 내용은 ScaleUp 오류를 참조하세요.
문제: 지원 중단된 API
클러스터의 부 버전에서 삭제된 지원 중단된 API를 사용 중이 아닌지 확인합니다. 자세한 내용은 GKE 지원 중단을 참조하세요.
오류: "범위 0에 대한 할당 실패: 설정된 범위에 IP 주소 없음"
GKE 버전 1.18.17 이상에서는 컨테이너가 시작되기 전 포드가 삭제되었을 때 메모리 부족(OOM) 이벤트로 인해 잘못된 포드 제거가 수행되는 문제가 수정되었습니다. 이러한 잘못된 제거로 인해 포드가 고립되고 할당된 노드 범위로부터 예약된 IP 주소를 계속 사용할 수 있습니다.
시간이 지나면 고립된 포드가 쌓여 GKE에서 새 포드에 할당할 수 있는 IP 주소가 부족하게 됩니다. 그 결과 할당된 노드 범위에 새 포드에 할당할 수 있는 가용 IP가 없어서 failed
to allocate for range 0: no IP addresses in range set
오류 메시지가 표시됩니다.
이 문제를 해결하려면 GKE 버전 1.18.17 이상으로 클러스터 및 노드 풀을 업그레이드합니다.
GKE 버전 1.18.17 이전의 클러스터에서 이 문제를 방지하고 해결하려면 이후에 OOM 이벤트가 발생하지 않도록 리소스 한도를 늘리고, 고립된 포드를 삭제하여 IP 주소를 회수합니다.
또한 GKE IP 주소 사용률 통계도 확인할 수 있습니다.
영향을 받는 노드에서 고립된 포드 삭제
노드를 드레이닝하거나, 노드 풀을 업그레이드하거나, 영향을 받는 디렉터리를 이동하여 고립된 포드를 삭제할 수 있습니다.
노드 드레이닝(권장)
새 포드가 예약되지 않도록 노드를 차단합니다.
kubectl cordon NODE
NODE
를 드레이닝하려는 노드 이름으로 바꿉니다.노드를 드레이닝합니다. GKE가 배포로 관리되는 포드를 다른 노드에 자동으로 다시 예약합니다.
--force
플래그를 사용해서 관리 리소스가 없는 고립된 포드를 드레이닝합니다.kubectl drain NODE --force
GKE가 새 포드를 예약할 수 있도록 노드를 차단 해제합니다.
kubectl uncordon NODE
영향을 받는 디렉터리 이동
/var/lib/kubelet/pods
에서 고립된 포드 디렉터리를 식별하고 GKE가 포드를 해지하도록 기본 디렉터리 외부로 이동합니다.
리소스 종료 문제 해결
문제: 네임스페이스가 Terminating
상태로 멈춰 있음
네임스페이스는 네임스페이스 내에 하나 이상의 리소스가 존재할 때 Kubernetes 파이널라이저를 사용하여 삭제를 방지합니다.
kubectl delete
명령어를 사용하여 네임스페이스를 삭제할 때는 Kubernetes가 종속 리소스를 삭제하고 모든 파이널라이저를 지울 때까지 네임스페이스가 Terminating
상태로 전환됩니다. 네임스페이스 수명 주기 컨트롤러는 먼저 GKE가 삭제해야 하는 네임스페이스의 모든 리소스를 나열합니다. GKE가 종속 리소스를 삭제할 수 없거나 네임스페이스 수명 주기 컨트롤러가 네임스페이스가 비어 있는지 확인할 수 없으면 사용자가 문제를 해결할 때까지 네임스페이스가 Terminating
상태로 유지됩니다.
Terminating
상태로 멈춘 네임스페이스를 해결하려면 삭제를 차단하는 비정상 구성요소를 식별하고 이를 삭제해야 합니다. 다음 솔루션 중 하나를 시도해 보세요.
사용할 수 없는 API 서비스 찾기 및 삭제
사용할 수 없는 API 서비스를 나열합니다.
kubectl get apiservice | grep False
응답하지 않는 서비스를 문제 해결합니다.
kubectl describe apiservice API_SERVICE
API_SERVICE
를 응답하지 않는 서비스 이름으로 바꿉니다.네임스페이스가 여전히 종료 중인지 확인합니다.
kubectl get ns | grep Terminating
나머지 리소스 찾기 및 삭제
종료 네임스페이스에 남은 모든 리소스를 나열합니다.
kubectl api-resources --verbs=list --namespaced -o name | xargs -n 1 kubectl get -n NAMESPACE
NAMESPACE
를 삭제하려는 네임스페이스의 이름으로 바꿉니다.출력에 표시된 모든 리소스를 삭제합니다.
네임스페이스가 여전히 종료 중인지 확인합니다.
kubectl get ns | grep Terminating
네임스페이스 강제 삭제
네임스페이스 삭제를 차단하는 파이널라이저를 삭제하여 네임스페이스를 강제 종료할 수 있습니다.
네임스페이스 매니페스트를 YAML 파일로 저장합니다.
kubectl get ns NAMESPACE -o yaml > ns-terminating.yml
텍스트 편집기에서 매니페스트를 열고
spec.finalizers
필드에서 모든 값을 삭제합니다.vi ns-terminating.yml
파이널라이저 필드가 비어 있는지 확인합니다.
cat ns-terminating.yml
다음과 유사하게 출력됩니다.
apiVersion: v1 kind: Namespace metadata: annotations: name: NAMESPACE spec: finalizers: status: phase: Terminating
HTTP 프록시를 시작하여 Kubernetes API에 액세스합니다.
kubectl proxy
curl
을 사용하여 네임스페이스 매니페스트를 바꿉니다.curl -H "Content-Type: application/yaml" -X PUT --data-binary @ns-terminating.yml http://127.0.0.1:8001/api/v1/namespaces/NAMESPACE/finalize
네임스페이스가 여전히 종료 중인지 확인합니다.
kubectl get ns | grep Terminating
문제: GKE 클러스터에서 Cloud NAT 패킷 손실 문제 해결
VPC 기반 GKE 비공개 클러스터의 노드 VM은 외부 IP 주소가 없으며 그 자체로 인터넷에 연결할 수 없습니다. 비공개 클러스터가 공개 연결을 수행하도록 Cloud NAT를 사용해서 외부 IP 주소 및 포트를 할당할 수 있습니다.
노드 VM에 Cloud NAT의 외부 포트 및 IP 주소 할당이 부족해지면 패킷이 삭제됩니다. 이를 방지하기 위해서는 아웃바운드 패킷 비율을 줄이거나 사용 가능한 Cloud NAT 소스 IP 주소 및 포트의 할당을 늘릴 수 있습니다. 다음 섹션에서는 GKE 비공개 클러스터의 컨텍스트에서 Cloud NAT로부터 패킷 손실을 진단하고 문제 해결하는 방법을 설명합니다.
패킷 손실 진단
이 섹션에서는 Cloud Logging을 사용하여 손실된 패킷을 로깅하고 Cloud Monitoring을 사용해서 손실된 패킷의 원인을 진단하는 방법을 설명합니다.
손실된 패킷 로깅
Cloud Logging에서 다음 쿼리를 사용하여 손실된 패킷을 로깅할 수 있습니다.
resource.type="nat_gateway" resource.labels.region=REGION resource.labels.gateway_name=GATEWAY_NAME jsonPayload.allocation_status="DROPPED"
REGION
: 클러스터가 있는 리전의 이름입니다.GATEWAY_NAME
: Cloud NAT 게이트웨이의 이름입니다.
이 명령어는 Cloud NAT 게이트웨이에서 삭제된 모든 패킷의 목록을 반환하지만 원인을 식별하지 않습니다.
패킷 손실의 원인 모니터링
손실된 패킷의 원인을 식별하려면 Cloud Monitoring에서 측정항목 관찰자를 쿼리합니다. 패킷은 세 가지 이유 중 하나로 삭제됩니다.
OUT_OF_RESOURCES
또는 ENDPOINT_ALLOCATION_FAILED
오류 코드로 인해 삭제된 패킷을 식별하려면 다음 쿼리를 사용합니다.
fetch nat_gateway metric 'router.googleapis.com/nat/dropped_sent_packets_count' filter (resource.gateway_name == NAT_NAME) align rate(1m) every 1m group_by [metric.reason], [value_dropped_sent_packets_count_aggregate: aggregate(value.dropped_sent_packets_count)]
NAT_ALLOCATION_FAILED
오류 코드로 인해 삭제된 패킷을 식별하려면 다음 쿼리를 사용합니다.
fetch nat_gateway metric 'router.googleapis.com/nat/nat_allocation_failed' group_by 1m, [value_nat_allocation_failed_count_true: count_true(value.nat_allocation_failed)] every 1m
문제: GKE IP 마스커레이딩이 있는 Cloud NAT
이전 쿼리가 빈 결과를 반환하고 GKE 포드가 외부 IP 주소와 통신할 수 없으면 구성 문제를 해결하세요.
구성 | 문제 해결 |
서브넷의 기본 IP 주소 범위에만 적용되도록 구성된 Cloud NAT |
Cloud NAT가 서브넷의 기본 IP 주소 범위에 대해서만 구성된 경우 클러스터에서 외부 IP 주소로 전송된 패킷에 소스 노드 IP 주소가 있어야 합니다. 이 Cloud NAT 구성에 대한 설명은 다음과 같습니다.
|
포드 IP에 사용된 서브넷의 보조 IP 주소 범위에만 적용되도록 구성된 Cloud NAT |
Cloud NAT가 클러스터의 포드 IP에 사용되는 서브넷의 보조 IP 주소 범위에 대해서만 구성된 경우 클러스터에서 외부 IP 주소로 전송된 패킷에 소스 포드 IP 주소가 있어야 합니다. 이 Cloud NAT 구성에 대한 설명은 다음과 같습니다.
|
패킷 손실을 방지하도록 최적화
다음 방법으로 패킷 손실을 중단할 수 있습니다.
동적 포트 할당을 사용하고 VM당 최대 포트 수를 늘리도록 Cloud NAT 게이트웨이를 구성합니다.
정적 포트 할당을 사용하는 경우 VM당 최소 포트 수를 늘립니다.
애플리케이션 최적화
애플리케이션이 동일한 대상 IP 주소 및 포트에 대해 아웃바운드 연결을 여러 번 수행하면 Cloud NAT가 할당된 NAT 소스 주소 및 소스 포트 튜플 수를 사용해서 대상에 수행할 수 있는 모든 연결을 빠르게 소비할 수 있습니다. 이 시나리오에서 애플리케이션의 아웃바운드 패킷 비율을 줄이면 패킷 손실을 줄이는 데 도움이 됩니다.
대상에 대한 동시 연결 수 제한을 포함하여 Cloud NAT가 NAT 소스 주소 및 소스 포트를 사용하여 연결을 수행하는 방법은 포트 및 연결을 참조하세요.
애플리케이션에서 아웃바운드 연결 비율을 줄이면 패킷 손실을 완화하는 데 도움이 될 수 있습니다. 이렇게 하려면 열린 연결을 재사용하면 됩니다. 연결을 재사용하는 일반적인 방법에는 연결 풀링, HTTP/2와 같은 프로토콜을 사용한 연결 다중화, 여러 요청에 재사용되는 영구 연결 설정이 있습니다. 자세한 내용은 포트 및 연결을 참조하세요.
gcpdiag로 GKE 클러스터 Austoscaler 문제 디버그
gcpdiag
는 오픈소스 도구입니다. 공식적으로 지원되는 Google Cloud 제품이 아닙니다.
gcpdiag
도구를 사용하면 Google Cloud 프로젝트 문제를 식별하고 수정할 수 있습니다. 자세한 내용은 GitHub의 gcpdiag 프로젝트를 참조하세요.
- scale.up.error.out.of.resources
- scale.up.error.quota.exceeded
- scale.up.error.waiting.for.instances.timeout
- scale.up.error.ip.space.exhausted
- scale.up.error.service.account.deleted
- scale.down.error.failed.to.evict.pods
- no.scale.down.node.node.group.min.size.reached
Google Cloud 콘솔
- 다음 명령어를 작성하고 복사합니다.
- Google Cloud 콘솔을 열고 Cloud Shell을 활성화합니다. Cloud 콘솔 열기
- 복사한 명령어를 붙여넣습니다.
gcpdiag
명령어를 실행하면gcpdiag
Docker 이미지를 다운로드한 후 진단 검사를 수행합니다. 해당되는 경우 출력 안내를 따라 실패한 검사를 수정합니다.
gcpdiag runbook gke/cluster-autoscaler --project=PROJECT_ID \
--parameter name=CLUSTER_NAME \
--parameter location=LOCATION
Docker
Docker 컨테이너에서 gcpdiag
를 시작하는 래퍼를 사용하여 gcpdiag
를 실행할 수 있습니다. Docker 또는 Podman이 설치되어 있어야 합니다.
- 로컬 워크스테이션에서 다음 명령어를 복사하고 실행합니다.
curl https://gcpdiag.dev/gcpdiag.sh >gcpdiag && chmod +x gcpdiag
-
gcpdiag
명령어를 실행합니다../gcpdiag runbook gke/cluster-autoscaler --project=PROJECT_ID \ --parameter name=CLUSTER_NAME \ --parameter location=LOCATION
이 런북에 사용 가능한 매개변수를 봅니다.
다음을 바꿉니다.
- PROJECT_ID: 리소스가 포함된 프로젝트의 ID입니다.
- CLUSTER_NAME: 프로젝트 내 대상 GKE 클러스터의 이름입니다.
- LOCATION: 대상 GKE 클러스터가 있는 위치입니다(영역 클러스터는 영역, 리전 클러스터는 리전).
유용한 플래그:
--project
: PROJECT_ID--universe-domain
: 해당되는 경우 리소스를 호스팅하는 신뢰할 수 있는 파트너 주권 클라우드 도메인--parameter
또는-p
: 런북 파라미터
모든 gcpdiag
도구 플래그의 목록과 설명은 gcpdiag
사용 안내를 참조하세요.
문제: 노드 버전이 컨트롤 플레인 버전과 호환되지 않음
클러스터의 컨트롤 플레인이 실행 중인 Kubernetes 버전을 확인한 다음 클러스터의 노드 풀이 실행 중인 Kubernetes 버전을 확인하세요. 클러스터의 노드 풀 중 컨트롤 플레인보다 오래된 부 버전이 2개 초과이면 클러스터에 문제가 발생할 수 있습니다.
GKE팀은 사용자를 대신하여 클러스터 컨트롤 플레인의 업그레이드를 주기적으로 수행합니다. 컨트롤 플레인은 안정적인 새 Kubernetes 버전으로 업그레이드됩니다. 기본적으로 클러스터 노드는 자동 업그레이드가 사용 설정되어 있으며, 사용 중지하지 않는 것이 좋습니다.
클러스터 노드에 자동 업그레이드가 사용 중지되어 있고 노드 풀 버전을 컨트롤 플레인과 호환되는 버전으로 수동으로 업그레이드하지 않으면 자동으로 업그레이드되는 컨트롤 플레인과 노드는 결국 호환되지 않게 됩니다. 클러스터의 컨트롤 플레인과 노드 간의 비호환성으로 인해 예기치 않은 문제가 발생할 수 있습니다.
GKE 컨트롤 플레인은 컨트롤 플레인보다 최대 2개 부 버전이 낮은 노드와 호환됩니다. 예를 들어 Kubernetes 1.31 컨트롤 플레인은 Kubernetes 1.31, 1.30, 1.29 노드와 호환됩니다. 자세한 내용은 GKE 버전 편향 정책을 참조하세요.
이 문제를 해결하려면 노드 풀 버전을 컨트롤 플레인과 호환되는 버전으로 수동으로 업그레이드하세요.
영향을 받는 노드에서 실행되는 워크로드가 워크로드 프로세스로 인해 중단되는 것이 우려되는 경우 다음 단계를 수행하여 워크로드를 새 노드 풀로 마이그레이션합니다.
- 호환되는 버전으로 새 노드 풀을 만듭니다.
- 기존 노드 풀의 노드를 Cordon합니다.
- 선택적으로 기존 노드 풀에서 실행되는 워크로드를 업데이트하여
cloud.google.com/gke-nodepool:NEW_NODE_POOL_NAME
라벨의 nodeSelector를 추가합니다. 여기서NEW_NODE_POOL_NAME
은 새 노드 풀의 이름입니다. 이렇게 하면 GKE가 새 노드 풀의 노드에 이러한 워크로드를 배치합니다. - 기존 노드 풀을 드레이닝합니다.
- 새 노드 풀에서 워크로드가 성공적으로 실행되는지 확인합니다. 성공적으로 실행될 경우 이전 노드 풀을 삭제할 수 있습니다. 워크로드 중단이 발견되면 기존 노드 풀에서 노드 차단을 취소하고 새 노드를 드레이닝하여 기존 노드에서 워크로드를 다시 예약합니다. 문제 해결을 수행하고 다시 시도합니다.
클러스터의 측정항목이 Cloud Monitoring에 표시되지 않는 문제 해결
프로젝트에서 Monitoring API와 Logging API를 사용 설정했는지 확인합니다. Google Cloud 콘솔의 Cloud Monitoring 개요에서 프로젝트를 볼 수 있는지도 확인해야 합니다.
문제가 계속되면 다음과 같은 가능한 원인을 확인하세요.
클러스터에서 모니터링을 사용 설정했는지 확인합니다.
기본적으로 Google Cloud 콘솔과 Google Cloud CLI에서 생성된 클러스터에는 Monitoring이 사용 설정되지만 다음 명령어를 실행하거나 Google Cloud 콘솔에서 클러스터 세부정보를 클릭하여 사용 설정 여부를 확인할 수 있습니다.
gcloud container clusters describe CLUSTER_NAME
이 명령어의 출력에는 다음과 비슷하게
monitoringConfig
섹션의enableComponents
목록에 있는SYSTEM_COMPONENTS
가 포함됩니다.monitoringConfig: componentConfig: enableComponents: - SYSTEM_COMPONENTS
모니터링이 사용 설정되어 있지 않으면 다음 명령어를 실행하여 사용 설정합니다.
gcloud container clusters update CLUSTER_NAME --monitoring=SYSTEM
클러스터가 만들어진 지 또는 모니터링이 사용 설정된 지 얼마나 되었나요?
새 클러스터의 측정항목이 Cloud Monitoring에 표시되는 데 최대 1시간이 걸릴 수 있습니다.
클러스터에서 실행되는
heapster
또는gke-metrics-agent
(OpenTelemetry Collector)가 "kube-system" 네임스페이스에 있나요?클러스터에 리소스가 부족하므로 이 Pod가 워크로드를 예약하지 못할 수 있습니다.
kubectl get pods --namespace=kube-system
을 호출하고 이름에heapster
또는gke-metrics-agent
가 있는 Pod를 찾아 Heapster 또는 OpenTelemetry가 실행 중인지 확인합니다.클러스터의 컨트롤 플레인이 노드와 통신할 수 있나요?
Cloud Monitoring이 작동하려면 마스터가 노드와 통신해야 합니다. 다음 명령어를 실행하면 마스터가 노드와 통신하는지 확인할 수 있습니다.
kubectl logs POD_NAME
이 명령어가 오류를 반환하면 SSH 터널이 문제의 원인일 수 있습니다. 자세한 내용은 이 섹션을 참조하세요.
Cloud Logging 에이전트와 관련된 문제가 있으면 문제해결 문서를 참조하세요.
자세한 내용은 로깅 문서를 참조하세요.
문제: 공유 VPC 클러스터의 계정 권한 누락
공유 VPC 클러스터의 경우 서비스 프로젝트의 GKE 서비스 계정에 호스트 프로젝트의 호스트 서비스 에이전트 사용자 역할에 대한 바인딩이 있는지 확인합니다. gcloud CLI를 사용하여 이 작업을 수행할 수도 있습니다.
역할 바인딩이 있는지 확인하려면 호스트 프로젝트에서 다음 명령어를 실행합니다.
gcloud projects get-iam-policy PROJECT_ID \
--flatten="bindings[].members" \
--format='table(bindings.role)' \
--filter="bindings.members:SERVICE_ACCOUNT_NAME
다음을 바꿉니다.
PROJECT_ID
: 호스트 프로젝트 ID입니다.SERVICE_ACCOUNT_NAME
: GKE 서비스 계정 이름입니다.
출력에서 roles/container.hostServiceAgentUser
역할을 찾습니다.
ROLE
...
roles/container.hostServiceAgentUser
...
목록에 hostServiceAgentUser
역할이 없으면 호스트 서비스 에이전트 사용자 역할 부여의 안내를 따라 서비스 계정에 바인딩을 추가합니다.
기본 서비스 계정 복원 대상
Google Cloud 프로젝트
GKE의 기본 서비스 계정인 container-engine-robot
이 실수로 프로젝트에서 결합 해제될 수 있습니다. GKE Service Agent는 서비스 계정에 클러스터 리소스를 관리할 권한을 부여하는 Identity and Access Management(IAM) 역할입니다. 서비스 계정에서 이 역할 바인딩을 제거하면 기본 서비스 계정이 프로젝트에서 바인딩 해제되어 애플리케이션 배포와 기타 클러스터 작업 수행이 불가능해질 수 있습니다.
gcloud CLI 또는 Google Cloud 콘솔을 사용하여 프로젝트에서 서비스 계정이 삭제되었는지 확인할 수 있습니다.
gcloud
다음 명령어를 실행합니다.
gcloud projects get-iam-policy PROJECT_ID
PROJECT_ID
를 프로젝트 ID로 바꿉니다.
콘솔
Google Cloud 콘솔에서 IAM 및 관리자 페이지로 이동합니다.
명령어나 대시보드에 서비스 계정 중 container-engine-robot
이 표시되지 않으면 서비스 계정이 결합 해제된 것입니다.
GKE Service Agent 역할 결합을 삭제했으면 다음 명령어를 실행하여 역할 결합을 복원합니다.
PROJECT_NUMBER=$(gcloud projects describe "PROJECT_ID" --format 'get(projectNumber)')
gcloud projects add-iam-policy-binding PROJECT_ID \
--member "serviceAccount:service-${PROJECT_NUMBER?}@container-engine-robot.iam.gserviceaccount.com" \
--role roles/container.serviceAgent
역할 결합이 부여되었는지 확인하려면 다음 명령어를 실행합니다.
gcloud projects get-iam-policy $PROJECT_ID
container.serviceAgent
역할과 함께 서비스 계정 이름이 표시되면 역할 결합이 부여된 것입니다. 예를 들면 다음과 같습니다.
- members:
- serviceAccount:service-1234567890@container-engine-robot.iam.gserviceaccount.com
role: roles/container.serviceAgent
Compute Engine 기본 서비스 계정 사용 설정
일반적으로 Compute Engine 기본 서비스 계정인 노드 풀에 사용된 서비스 계정이 사용 중지된 경우 노드가 클러스터에 등록되지 않을 수 있습니다.
gcloud CLI 또는 Google Cloud 콘솔을 사용하여 프로젝트에서 서비스 계정이 사용 중지되었는지 확인할 수 있습니다.
gcloud
다음 명령어를 실행합니다.
gcloud iam service-accounts list --filter="NAME~'compute' AND disabled=true"
콘솔
Google Cloud 콘솔에서 IAM 및 관리자 페이지로 이동합니다.
명령어 또는 대시보드에 서비스 계정이 사용 중지된 것으로 표시되면 다음 명령어를 실행하여 서비스 계정을 사용 설정합니다.
gcloud iam service-accounts enable PROJECT_ID-compute@developer.gserviceaccount.com
PROJECT_ID
를 프로젝트 ID로 바꿉니다.
이렇게 해도 노드 등록 문제가 해결되지 않으면 노드 등록 문제 해결에서 추가 문제 해결 안내를 참조하세요.
문제: 노드 할당 가능을 사용 설정한 후 포드가 대기 중 상태에서 멈춤
노드 할당 가능을 사용 설정한 후 Pod가 대기 중 상태에서 멈추는 문제가 발생하면 다음 사항에 유의하세요.
1.7.6 버전부터는 GKE에서 Docker 및 운영체제를 포함하여 Kubernetes 오버헤드에 사용할 CPU와 메모리를 예약합니다. Pod에서 각 머신 유형별로 예약 가능한 양에 대한 자세한 내용은 클러스터 아키텍처를 참조하세요.
업그레이드 후 pod가 대기 중이면 다음을 수행하는 것이 좋습니다.
pod의 CPU 및 메모리 요청이 최대 사용량을 초과하지 않는지 확인합니다. GKE에서 오버헤드에 사용할 CPU와 메모리를 예약하는 반면 Pod는 이러한 리소스를 요청할 수 없습니다. Pod가 사용량 보다 많은 CPU 또는 메모리를 요청하면 다른 Pod가 이러한 리소스를 요청하지 못하게 되어 클러스터 사용률이 떨어질 수 있습니다. 자세한 내용은 리소스 요청이 있는 pod 예약 방법을 참조하세요.
클러스터 크기를 조정해 봅니다. 자세한 내용은 클러스터 크기 조절을 참조하세요.
클러스터를 다운그레이드하여 이 변경사항을 되돌립니다. 자세한 내용은 클러스터 또는 노드 풀 수동 업그레이드를 참조하세요.
- Kubernetes 스케줄러 측정항목을 Cloud Monitoring에 전송하고 스케줄러 측정항목을 확인하도록 클러스터를 구성합니다.
문제: 클러스터의 루트 인증 기관이 곧 만료됨
클러스터의 루트 인증 기관이 곧 만료됩니다. 일반적인 클러스터 작업이 중단되지 않도록 하려면 사용자 인증 정보 순환을 수행해야 합니다.
오류: "'Foo' 인스턴스에 'instance-template' 메타데이터가 포함되지 않음"
업그레이드, 확장, 자동 노드 복구 수행이 실패하는 노드 풀의 상태로 "'Foo' 인스턴스에 'instance-template' 메타데이터가 포함되지 않음" 오류가 표시될 수 있습니다.
이 메시지는 GKE에서 할당된 VM 인스턴스의 메타데이터가 손상되었음을 나타냅니다. 이는 일반적으로 커스텀 방식으로 작성된 자동화 또는 스크립트가 새 인스턴스 메타데이터를 추가하려고 시도할 때(예: block-project-ssh-keys
) 그리고 값을 추가하거나 업데이트하는 대신 기존 메타데이터를 삭제할 때 발생합니다.
커스텀 메타데이터 설정에서 VM 인스턴스 메타데이터에 대해 알아볼 수 있습니다.
중요한 메타데이터 값(특히 instance-template
, kube-labels
, kubelet-config
, kubeconfig
, cluster-name
, configure-sh
, cluster-uid
)이 삭제된 경우 이러한 값이 GKE 운영에 중요하기 때문에 노드 또는 전체 노드 풀이 불안정한 상태로 전환될 수 있습니다.
인스턴스 메타데이터가 손상된 경우 메타데이터를 복구하는 가장 좋은 방법은 손상된 VM 인스턴스가 포함된 노드 풀을 다시 만드는 것입니다. 클러스터에 노드 풀을 추가하고 새 노드 풀에서 노드 수를 늘려야 하며, 다른 노드 풀에서는 노드를 차단하고 삭제해야 합니다. 노드 풀 간의 워크로드 마이그레이션 안내를 참조하세요.
인스턴스 메타데이터를 수정한 사람과 시간을 찾으려면 Compute Engine 감사 로깅 정보를 검토하거나 다음과 비슷한 검색어로 로그 탐색기를 사용해서 로그를 찾을 수 있습니다.
resource.type="gce_instance_group_manager"
protoPayload.methodName="v1.compute.instanceGroupManagers.setInstanceTemplate"
로그에서 요청 시작자 IP 주소 및 사용자 에이전트를 찾을 수 있습니다.
requestMetadata: {
callerIp: "REDACTED"
callerSuppliedUserAgent: "google-api-go-client/0.5 GoogleContainerEngine/v1"
}
문제: Cloud KMS 키에 대한 액세스 권한이 손실되었습니다.
GKE의 기본 서비스 계정이 Cloud KMS 키에 액세스할 수 없으면 다음 오류 메시지가 표시됩니다.
Cluster problem detected (Kubernetes Engine Service Agent account unable to use CloudKMS key configured for Application Level encryption).
이 문제를 해결하려면 사용 중지된 키 다시 사용 설정을 수행합니다.
GKE의 보안 비밀에 대한 자세한 내용은 애플리케이션 계층에서 보안 비밀 암호화를 참조하세요.
문제: 보안 비밀 암호화 업데이트 실패
Cloud KMS 키 사용 설정, 중지, 업데이트 작업에 실패한 경우 애플리케이션 계층 보안 비밀 암호화 문제 해결 가이드를 참조하세요.