kubectl "You must be logged in to the server (Unauthorized)" 해결 6가지
어제까지 멀쩡히 돌아가던 kubectl get pods가 오늘 갑자기 이렇게 뱉어냅니다.
error: You must be logged in to the server (Unauthorized)손에 땀이 나죠. 하지만 결론부터 말하면 이건 "권한이 없다(403)"가 아니라 "당신이 누구인지 클러스터가 증명하지 못했다(401)" 라는 인증(authentication) 영역의 문제입니다. 즉 RBAC 설정을 뒤지기 전에 내 신분증(토큰·인증서)이 유효한지부터 봐야 합니다.
이 시리즈(K8s_Troubleshooting_Guide)의 앞 편들이 스케줄링·이미지·네트워크 같은 워크로드 영역을 다뤘다면, 12편인 이번 글은 authn/authz 영역으로 넘어옵니다. 에러 문구를 그대로 검색해서 들어오셨다면, 5분 안에 원인을 특정하고 복붙 명령으로 복구하는 것을 목표로 갑니다.
401 vs 403: 가장 먼저 잡고 가야 할 개념
트러블슈팅의 절반은 "어느 동네 문제인지" 구분하는 데서 끝납니다.
| 에러 메시지 | HTTP 코드 | 의미 | 원인 영역 | 1차 점검 대상 |
|---|---|---|---|---|
You must be logged in to the server (Unauthorized) | 401 | 내가 누구인지 증명 실패 (인증) | authn | 토큰/인증서 만료, context, 클라우드 자격증명 |
Forbidden ... cannot list resource ... | 403 | 누군지는 알지만 권한 없음 (인가) | authz | RBAC Role/RoleBinding |
핵심 비유: 401은 출입증 자체가 만료·분실된 상태, 403은 출입증은 있는데 그 방에 들어갈 권한이 없는 상태입니다. 이 글은 401에 집중하고, 403(RBAC)은 아래 5번 원인에서 경계선만 짚어줍니다.
원인별 진단·해결 6가지 (복붙 명령 위주)
(1) kubeconfig 토큰/인증서 만료
가장 흔한 범인입니다. 단기 만료(STS) 토큰이 보편화되면서 "몇 시간 뒤 갑자기" 패턴이 잦아졌습니다.
# 진단: 현재 사용자에 박힌 token / 인증서 정보 확인
kubectl config view --raw --minify출력에서 user: 아래 token:이 있거나 exec: 블록이 있는지 봅니다. 정적 토큰이 박혀 있다면 만료됐을 가능성이 큽니다. 해결은 발급처에서 토큰을 재발급받아 갱신하는 것입니다(클라우드면 3번으로).
(2) 잘못된 context/cluster 지정
멀티 클러스터 환경에서 dev 자격증명으로 prod를 찌르는 사고가 의외로 많습니다.
# 진단
kubectl config current-context # 지금 어디를 보고 있나
kubectl config get-contexts # * 표시가 현재 context
# 해결
kubectl config use-context <원하는-context-이름>get-contexts 출력의 CLUSTER/AUTHINFO 컬럼이 의도한 값인지 확인하세요. 엉뚱한 context였다면 이것만으로 끝납니다.
(3) 클라우드 IAM 토큰 만료 (EKS / GKE)
EKS는 aws-iam-authenticator 또는 aws eks get-token(exec credential plugin)으로 STS 단기 토큰을 발급합니다. AWS 세션이 만료되면 aws-iam-authenticator token expired 또는 곧바로 401이 뜹니다.
# EKS: kubeconfig 자격증명 갱신
aws eks update-kubeconfig --region <리전> --name <클러스터명>
# 프로파일을 따로 쓴다면
aws eks update-kubeconfig --region <리전> --name <클러스터명> --profile <프로파일>
# GKE
gcloud container clusters get-credentials <클러스터명> --region <리전>EKS에서 가장 흔한 함정: aws sts get-caller-identity로 AWS 자격증명 자체가 유효한지 먼저 확인하세요. AWS 세션이 죽어 있으면 update-kubeconfig를 해도 토큰 발급 단계에서 똑같이 401이 납니다.
aws sts get-caller-identity # 여기서 에러나면 AWS 자격증명부터 갱신(4) client-certificate 권한·만료 확인
온프레미스 kubeadm 클러스터는 보통 client certificate 인증을 씁니다. 인증서는 기본 1년 만료라 까먹기 딱 좋습니다.
# 인증서 만료일 디코딩
openssl x509 -in ~/.kube/client.crt -noout -enddate
# 출력 예) notAfter=Jun 16 09:00:00 2026 GMT
# kubeconfig에 base64로 박혀 있다면
kubectl config view --raw -o jsonpath='{.users[0].user.client-certificate-data}' | base64 -d | openssl x509 -noout -enddatenotAfter가 지났다면 만료입니다. 인증서 파일 경로/권한(ls -l로 600 권장)도 함께 점검하고, kubeadm이라면 kubeadm certs renew 계열로 갱신합니다.
(5) RBAC 미부여 — 여기서 401이 아니라 403이 뜬다
여기가 401과 403의 경계선입니다. 인증은 됐는데 권한이 없으면 401이 아니라 403이 떠야 정상입니다. 즉 401이라면 RBAC는 보통 범인이 아닙니다.
# 내가 특정 동작을 할 수 있는지 확인
kubectl auth can-i list pods
kubectl auth can-i get pods --namespace prod출력이 no면 403(인가) 문제, 그런데도 메시지가 401이라면 인증 단계에서 이미 막힌 것이니 1~4번으로 돌아가세요.
(6) 시스템 시계 오차
JWT/STS 토큰에는 NotBefore/Expiry가 박혀 있어, 클라이언트 시계가 어긋나면 멀쩡한 토큰도 "아직 유효하지 않음" 또는 "만료됨"으로 검증 실패합니다. VM·컨테이너 환경에서 의외로 자주 발생합니다.
# 진단
timedatectl # System clock synchronized: yes 인지 확인
# 해결 (NTP 동기화)
sudo timedatectl set-ntp true
sudo systemctl restart systemd-timesyncdSystem clock synchronized: no거나 실제 시각과 수 분 이상 차이 나면 동기화 후 재시도하세요.
5분 빠른 진단 플로우
막혔을 때 위에서 아래로 순서대로 내려가면 됩니다.
- context 확인 →
kubectl config current-context로 엉뚱한 곳을 보고 있는지 (원인 2) - 토큰/인증서 만료 확인 →
kubectl config view --raw --minify+openssl x509 -enddate(원인 1·4) - 클라우드면 자격증명 갱신 →
aws sts get-caller-identity→aws eks update-kubeconfig ...또는gcloud ... get-credentials(원인 3) - 시계 확인 →
timedatectl동기화 여부 (원인 6) - 여기까지 통과하면 권한 영역 →
kubectl auth can-i ...로 403 여부 확인 (원인 5)
실무 경험 한마디: 멀티 클라우드 팀에서 401 신고의 70% 이상은 1번(context 오인)과 3번(AWS 세션 만료)이었습니다.
aws sts get-caller-identity한 줄을 진단 1순위로 습관화한 뒤로 평균 복구 시간이 눈에 띄게 줄었습니다.
예방이 곧 트러블슈팅 — 토큰 자동 갱신과 context 분리
복구도 중요하지만, 재발을 막는 게 진짜 실력입니다.
- exec credential plugin으로 자동 갱신: 정적 토큰을 박지 말고, kubeconfig의
user.exec로 매 요청 시 토큰을 새로 받게 하세요. EKS 권장 방식입니다.
users:
- name: my-eks
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
command: aws
args:
- eks
- get-token
- --cluster-name
- my-cluster
- --region
- ap-northeast-2- 클러스터별 context·kubeconfig 분리: prod와 dev를 한 파일에 섞지 말고
KUBECONFIG=~/.kube/prod:~/.kube/dev식으로 분리하거나, 셸 프롬프트에 현재 context를 노출(kube-ps1)해 오발사고를 줄이세요.
핵심 명령 요약: current-context로 위치 확인 → config view --raw/openssl x509로 만료 확인 → aws eks update-kubeconfig로 갱신 → timedatectl로 시계 점검 → auth can-i로 권한 구분.
다음 편 예고: K8s_Troubleshooting_Guide 13편 — 403 Forbidden과 RBAC 권한 설계 트러블슈팅에서 이번에 살짝 짚은 인가(authz) 영역을 본격적으로 파고듭니다.
자주 묻는 질문 (FAQ)
Q. aws eks update-kubeconfig를 했는데도 그대로 401이에요.
A. AWS 세션 자체가 만료된 경우입니다. aws sts get-caller-identity로 자격증명이 살아 있는지 먼저 확인하고, 만료됐으면 SSO 로그인(aws sso login)이나 키 갱신 후 다시 update-kubeconfig 하세요.
Q. 프로파일·리전이 여러 개라 헷갈립니다.
A. --profile과 --region을 명시하고, exec plugin args에도 동일한 값을 넣으세요. AWS_PROFILE 환경변수와 kubeconfig의 exec 설정이 다르면 엉뚱한 자격증명으로 토큰을 받아 401이 납니다.
Q. 401인데 RBAC 문제일 수도 있나요? A. 거의 아닙니다. RBAC 미부여는 인증을 통과한 뒤 발생하므로 보통 403으로 표시됩니다. 401이면 토큰·인증서·context·시계 문제일 확률이 높으니 5분 플로우의 1~4번부터 점검하세요.
이 글은 AI 에이전트가 1차 초안을 작성한 뒤, 사람 편집자가 사실관계·출처·톤과 맥락을 검토하여 발행했습니다. 오류나 부정확한 내용이 확인되면 24시간 이내에 정정합니다.
댓글
불러오는 중...