| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- maven
- IntelliJ
- JavaScript
- BPMN
- Linux
- dbeaver
- log4j2
- SAP
- gradle
- docker
- Windows
- kubectl
- LOG4J
- useEffect
- nginx
- database
- gson
- Spring
- NCP
- react
- Kubernetes
- nodejs
- mybatis
- Git
- tibero
- JPA
- MySQL
- springboot
- VSCode
- Java
- Today
- Total
두 손끝의 창조자
Kubernetes 클러스터 접속 불가 트러블슈팅: connection refused에서 인증서 만료까지 본문
문제 발생
작년까지 잘 사용하던 Kubernetes 클러스터에 kubectl get pod 명령을 실행했더니 갑자기 아래와 같은 오류가 발생했다.
E0113 11:36:45.788189 43303 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: Get \"https://10.90.3.131:6443/api?timeout=32s\": dial tcp 10.90.3.131:6443: connect: connection refused"
The connection to the server 10.90.3.131:6443 was refused - did you specify the right host or port?트러블슈팅 과정
1단계: 문제 범위 좁히기
connection refused 에러는 API Server 자체에 TCP 연결조차 되지 않는다는 의미다. 인증이나 권한 문제 이전에 네트워크나 서버 상태에 문제가 있다는 것이다.
일단 클러스터 서버에 SSH로 직접 접속을 시도했고, 접속은 정상적으로 되었다. 서버는 살아있다는 뜻이다.
2단계: 클러스터 서버에서 직접 테스트
클러스터 서버 내부에서도 kubectl get pod 명령을 실행해봤다. 역시나 동일한 오류가 발생했다. 이제 원인을 두 가지로 좁힐 수 있었다:
- 6443 포트가 막혔거나
- API Server 인증서가 만료되었거나
작년까지 잘 사용했다는 점, 그리고 정확히 1년이 지난 시점이라는 점을 고려하면 인증서 만료 가능성이 높았다.
3단계: 클러스터 인증서 갱신
클러스터의 인증서를 갱신하기로 결정했다. kubeadm 기반 클러스터라면 다음 명령으로 인증서를 갱신할 수 있다:
sudo kubeadm certs renew all
sudo systemctl restart kubelet
인증서 갱신 후 다시 로컬에서 접속을 시도했다.
4단계: 새로운 에러 발생
이번에는 다른 에러가 나타났다:
E0113 13:29:47.493890 59567 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: the server has asked for the client to provide credentials"
error: You must be logged in to the server (the server has asked for the client to provide credentials)connection refused에서 provide credentials로 에러가 바뀌었다. 이는 문제가 한 단계 진전되었다는 의미다:
- 이전: API Server 자체에 접속 불가
- 현재: API Server 접속은 되지만 인증 실패
직감적으로 알 수 있었다. 클러스터의 인증서는 갱신했지만, 로컬의 ~/.kube/config 파일은 여전히 만료된 인증서를 사용하고 있었던 것이다.
5단계: 로컬 kubeconfig 갱신
클러스터 서버에서 새로 생성된 admin.conf를 로컬로 복사했다:
# 클러스터 서버에서
sudo cat /etc/kubernetes/admin.conf
# 로컬에서
# 위 내용을 ~/.kube/config에 덮어쓰기
그리고 다시 kubectl get pod를 실행했다. 접속 성공!
문제의 근본 원인
이번 장애의 핵심은 인증서 만료였다. kubeadm으로 구성한 Kubernetes 클러스터는 기본적으로 인증서 유효기간이 1년이다.
트러블슈팅 과정을 정리하면:
- 클러스터 서버의 API Server 인증서 만료 →
connection refused발생 - 클러스터 인증서 갱신 → API Server 정상화
- 로컬 kubeconfig의 클라이언트 인증서 만료 →
provide credentials발생 - 로컬 kubeconfig 갱신 → 정상 접속
재발 방지 방법
1. 인증서 만료일 확인
정기적으로 인증서 만료일을 확인하자:
kubeadm certs check-expiration
2. 인증서 갱신 루틴 설정
운영 캘린더에 연 1회 인증서 갱신 작업을 등록해두자. 만료 전에 미리 갱신하면 장애를 예방할 수 있다:
sudo kubeadm certs renew all
sudo systemctl restart kubelet
# 로컬 kubeconfig도 업데이트
sudo cp /etc/kubernetes/admin.conf ~/.kube/config
3. kubeconfig 백업
중요한 설정은 항상 백업해두자:
cp ~/.kube/config ~/.kube/config.bak.$(date +%F)
교훈
이번 트러블슈팅을 통해 얻은 교훈:
- 에러 메시지를 정확히 읽자:
connection refused와provide credentials는 완전히 다른 문제다 - 문제를 단계별로 좁혀가자: 네트워크 → 서버 → 인증 순으로 체계적으로 접근
- 정기 점검이 중요하다: 인증서 만료는 장애가 아니라 "정기 점검 누락"에 가깝다
kubeadm 기반 클러스터를 운영한다면, 인증서 관리는 필수다. 1년에 한 번, 꼭 인증서를 갱신하자!