- Published on
EKS에서 Pod DNS는 되는데 외부 HTTPS만 실패할 때
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서버리스가 아닌 EKS에서 DNS 조회는 되는데 외부 HTTPS만 실패하는 상황은 생각보다 흔합니다. nslookup google.com은 잘 되는데 curl https://google.com이 타임아웃/핸드셰이크 실패/리셋으로 끝나면, 문제는 DNS가 아니라 TCP/443 egress 경로 혹은 TLS 계층에 있습니다.
이 글은 “무엇부터 확인하면 가장 빨리 좁혀지나”에 초점을 둔 실전 트러블슈팅 가이드입니다.
증상 패턴 정리: DNS 성공 ≠ HTTPS 성공
먼저 증상을 로그/에러 문자열로 분류하면 원인 후보가 크게 줄어듭니다.
Could not resolve host→ DNS 문제(이번 주제와 다름)connect timeout,Operation timed out→ 라우팅/NAT/SG/NACL/프록시/네트워크 정책TLS handshake timeout→ MTU/패킷 드롭, 프록시, SNI, 중간 장비, 방화벽 DPI, 오버로드SSL: certificate verify failed→ CA 번들/신뢰체인/프록시 MITMconnection reset by peer,EOF,server disconnected→ 프록시/중간장비/서버측 정책/ALPN/HTTP2 등
TLS 타임아웃 계열은 원인이 다양하므로, 별도 체크리스트도 함께 참고하면 좋습니다: EKS TLS handshake timeout 원인·해결 9가지
1) 재현을 표준화: 디버그용 Pod에서 계층별 확인
애플리케이션 컨테이너 안에서만 재현하면 원인(라이브러리/CA/프록시/네트워크)을 분리하기 어렵습니다. 먼저 네트워크 도구가 있는 Pod를 띄워 DNS → TCP → TLS → HTTP 순으로 확인합니다.
디버그 Pod 실행
kubectl run netshoot -it --rm \
--image=nicolaka/netshoot \
--restart=Never -- bash
(1) DNS 확인
nslookup example.com
# 또는
DIG=dig; $DIG +short example.com
(2) TCP 443 연결 확인(핵심)
# TCP 레벨에서 443 포트가 열리는지
nc -vz example.com 443
# 더 확실히: IP로 직접 테스트(네임 해석 영향 제거)
IP=$(dig +short example.com | head -n1)
nc -vz $IP 443
nc: timed out이면 NAT/라우팅/보안그룹/NACL/네트워크 정책 쪽으로 거의 확정입니다.
(3) TLS 핸드셰이크 확인(SNI 포함)
# SNI를 포함한 핸드셰이크
openssl s_client -connect example.com:443 -servername example.com -brief
# IP로 접속하되 SNI는 도메인으로
openssl s_client -connect ${IP}:443 -servername example.com -brief
-servername(SNI)가 없으면 일부 CDN/가상호스팅은 정상 인증서를 주지 않습니다.
(4) HTTP 요청 확인
curl -Iv https://example.com --connect-timeout 5 --max-time 15
여기까지 결과를 가지고 아래 원인별 섹션으로 내려가면 됩니다.
2) 가장 흔한 원인: Private Subnet인데 NAT Gateway/라우팅이 없음
EKS 노드(또는 Pod가 붙는 ENI)가 Private Subnet에 있고, 외부 인터넷으로 나가려면 보통 NAT Gateway가 필요합니다.
- DNS는 CoreDNS가 VPC 내부 Resolver(169.254.169.253 등)로 질의하므로 되지만
- HTTPS는 인터넷으로 나가야 하므로 NAT/IGW 경로가 없으면 실패합니다.
확인 포인트
- 노드가 속한 서브넷의 라우트 테이블에서
0.0.0.0/0 -> nat-xxxx(Private Subnet)- 또는
0.0.0.0/0 -> igw-xxxx(Public Subnet)
- NAT Gateway가 있는 Public Subnet은
0.0.0.0/0 -> igw-xxxx- NAT에 Elastic IP가 연결되어 있음
빠른 판별 방법
- 디버그 Pod에서
nc -vz example.com 443가 타임아웃 - 같은 클러스터에서 Public Subnet 노드로 스케줄링했을 때는 성공
해결
- 워커 노드가 Private Subnet이면 NAT Gateway(가용영역별 권장)를 구성하고
- 해당 Private Subnet 라우트 테이블의 기본 경로를 NAT로 지정합니다.
3) 보안그룹(Security Group) Egress 또는 NACL이 443을 막음
EKS 노드 보안그룹은 기본적으로 egress가 열려있지만, 조직 정책으로 egress를 제한하는 경우가 많습니다.
확인 포인트
- Node SG egress에
TCP 443또는All traffic이 허용되어 있는가 - NACL에서 ephemeral port(대략 1024-65535) 반환 트래픽이 허용되는가
- NAT/인터넷 통신은 “나가는 포트/들어오는 응답 포트”가 함께 열려야 합니다.
증상 힌트
nc -vz가 즉시refused또는 특정 네트워크 에러- 같은 VPC 내 다른 목적지(예: VPC 엔드포인트)만 되고 인터넷만 안 됨
해결
- SG egress에
0.0.0.0/0:443허용(또는 사내 egress CIDR/프록시로 제한) - NACL inbound/outbound에 ephemeral port 범위를 포함
4) HTTP(S) 프록시 환경: NO_PROXY 누락으로 내부/외부가 꼬임
기업망/보안망에서는 Pod가 직접 인터넷으로 나가지 못하고 프록시를 통해서만 나가야 하는 구성이 있습니다.
이때 DNS는 되지만 HTTPS가 실패하는 전형적인 원인이:
HTTPS_PROXY는 설정됐는데 프록시가 443 CONNECT를 허용하지 않음NO_PROXY가 누락되어 Kubernetes 내부 도메인까지 프록시로 보내며 오작동- 프록시가 TLS MITM을 하면서 사내 CA를 신뢰하지 않아 인증서 검증 실패
확인
env | egrep -i 'http_proxy|https_proxy|no_proxy'
curl -Iv https://example.com --proxy $HTTPS_PROXY
curl -Iv https://example.com --noproxy '*'
권장 NO_PROXY 예시
NO_PROXY=localhost,127.0.0.1,.svc,.cluster.local,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
해결
- 프록시 정책에 맞춰
HTTP(S)_PROXY/NO_PROXY를 정확히 설정 - 사내 MITM 프록시라면 컨테이너에 사내 Root CA를 배포
5) MTU/PMTUD 이슈: DNS는 되는데 TLS에서 멈춘다
DNS 패킷은 작아서 통과하지만, TLS 핸드셰이크/인증서 체인/ALPN 협상은 패킷이 커질 수 있습니다. VPC CNI, 터널링, 방화벽 장비 조합에서 MTU 불일치가 있으면 “TLS handshake timeout”이 발생하기 쉽습니다.
빠른 진단
nc -vz host 443는 성공openssl s_client에서 멈추거나handshake timeout
패킷 크기 테스트(대략적)
# DF(단편화 금지)로 MTU 추정 (ICMP 허용 환경에서만 유효)
ping -M do -s 1472 1.1.1.1
ping -M do -s 1372 1.1.1.1
해결 방향
- 노드/ENI/네트워크 경로에서 MTU를 일관되게 맞추기
- CNI 설정, 터널/오버레이 사용 여부 점검
세부 원인과 조치 항목은 위에서 링크한 TLS 타임아웃 글이 도움이 됩니다: EKS TLS handshake timeout 원인·해결 9가지
6) 컨테이너 CA 번들 문제: curl은 되는데 앱 SDK만 실패하는 경우도
운영 중 가장 낚이기 쉬운 케이스가 “Pod에서 curl은 되는데 애플리케이션(파이썬/노드/자바)만 HTTPS 실패”입니다. 이때는 네트워크가 아니라 런타임의 CA store가 오래됐거나 비어있는 경우가 많습니다(특히 distroless/minimal 이미지).
증상
curl https://api...성공- 파이썬
httpx,requests, 자바PKIX path building failed등 인증서 검증 실패
파이썬 예시(재현 코드)
import httpx
url = "https://example.com"
try:
r = httpx.get(url, timeout=10)
print(r.status_code)
except Exception as e:
print("FAILED:", repr(e))
RemoteProtocolError나 연결 종료가 섞여 보이면, 네트워크/프록시 문제 가능성도 있으니 아래 글의 분류가 유용합니다: Python httpx RemoteProtocolError 서버 끊김 원인과 해결
해결
- Debian/Ubuntu 계열:
ca-certificates패키지 설치 및 갱신 - Alpine:
apk add ca-certificates && update-ca-certificates - 사내 프록시 MITM이면 사내 Root CA를
/usr/local/share/ca-certificates에 추가 후 업데이트
7) NetworkPolicy로 egress 443이 차단됨(Calico/Cilium 등)
EKS 기본 VPC CNI만으로는 NetworkPolicy가 동작하지 않지만, Calico/Cilium 등을 설치한 경우 Pod egress가 정책으로 막힐 수 있습니다.
확인
kubectl get networkpolicy -A
kubectl describe networkpolicy -n <ns> <name>
해결
- 대상 네임스페이스의 egress 정책에
to: 0.0.0.0/0+ports: 443허용 - 또는 프록시/egress gateway로만 나가도록 설계했다면 해당 경로만 허용
8) VPC 엔드포인트(PrivateLink)와 DNS 옵션 충돌
S3/ECR/STS 같은 AWS API를 VPC 엔드포인트로 붙였는데, 외부 HTTPS(공용 인터넷)도 동시에 써야 하는 환경에서 DNS 옵션이 꼬이면 “어떤 도메인은 내부로 가고 어떤 도메인은 외부로 가는” 혼합 상태가 됩니다.
enableDnsHostnames,enableDnsSupport가 꺼져 있거나- 엔드포인트의 Private DNS 설정이 의도와 다르게 켜져 있어 특정 도메인이 내부로만 해석
이 케이스는 “외부 전체”가 아니라 “특정 도메인만” 실패하는 형태로 나타나는 경우가 많습니다.
9) 실전 체크리스트: 10분 안에 원인 좁히기
아래 순서로 하면 불필요한 추측을 줄일 수 있습니다.
- 디버그 Pod에서
nslookup성공 확인 nc -vz host 443- 타임아웃이면: NAT/라우팅/SG/NACL/NetworkPolicy부터
openssl s_client -connect host:443 -servername host- 여기서 멈추면: MTU/중간장비/프록시/DPI 의심
curl -Iv https://hostcertificate verify failed면: CA 번들/사내 CA
- 애플리케이션만 실패하면
- 런타임 CA store, HTTP/2 설정, 프록시 환경변수, 타임아웃 값을 확인
10) 마무리: “DNS는 된다”는 단서의 의미
DNS가 된다는 건 CoreDNS와 VPC Resolver까지의 경로가 정상이라는 뜻일 뿐, 인터넷으로 나가는 egress 경로가 정상이라는 뜻은 아닙니다. EKS에서 외부 HTTPS만 실패하면 대부분은 다음 셋 중 하나로 수렴합니다.
- NAT/라우팅 누락(Private Subnet 기본 경로 없음)
- 보안그룹/NACL/NetworkPolicy egress 차단
- TLS 계층 이슈(MTU/프록시/CA 번들/SNI)
위의 계층별 테스트(nc→openssl→curl)를 표준 루틴으로 만들어두면, 비슷한 장애를 만났을 때 재현과 원인 분리가 훨씬 빨라집니다.