EKS 클러스터에서 보안 그룹 아웃바운드를 Whitelist 방식으로 엄격하게 제어하는 사이트가 있었습니다. NLB 도메인을 호출하는 구조였는데, 보안 그룹에 NLB 규칙을 추가했음에도 연결이 되지 않았습니다.
curl로 NLB 도메인을 직접 테스트하면 타임아웃이 났습니다. 그런데 IP를 직접 지정하면 멀쩡히 응답했습니다. 방화벽·라우팅·네트워크 설정은 모두 정상이었고, Security Group 규칙도 다시 훑어봐도 이상한 부분이 없었습니다.
문제는 도메인 이름 자체에 있었습니다. DNS 쿼리가 막혀 NLB 도메인을 IP로 풀지 못하고 있었던 것입니다.
해결책은 169.254.169.253/32 포트 53(UDP/TCP)을 아웃바운드 허용 목록에 추가하는 것 한 줄이었습니다.
DNS가 막혔는지 먼저 확인하는 방법
증상이 "도메인 안 됨, IP 됨"이라면 DNS부터 의심해야 합니다. 다음 명령으로 빠르게 확인할 수 있습니다.
# NLB 도메인 DNS 조회 — 응답이 없거나 timeout이면 DNS 차단
dig my-nlb.ap-northeast-2.elb.amazonaws.com
# 또는
nslookup my-nlb.ap-northeast-2.elb.amazonaws.com
# 169.254.169.253 직접 질의 — 정상이면 IP 반환, 차단이면 응답 없음
dig @169.254.169.253 my-nlb.ap-northeast-2.elb.amazonaws.com
dig 응답이 없거나 ;; connection timed out 이 나온다면 DNS 쿼리가 차단된 것입니다.
EKS Pod 안에서 확인한다면:
kubectl run -it --rm debug --image=nicolaka/netshoot --restart=Never -- \
dig @169.254.169.253 my-nlb.ap-northeast-2.elb.amazonaws.com
전체 호출 흐름
NLB 도메인을 호출할 때 실제로 일어나는 일입니다.
[EC2]
│
│ ① NLB 도메인 DNS 쿼리 (UDP/TCP 53)
▼
[169.254.169.253] ← AWS VPC DNS Resolver
│
│ ② NLB IP 응답
▼
[EC2]
│
│ ③ NLB IP로 직접 연결
▼
[NLB]
①번 DNS 쿼리가 막혀 있으면 NLB IP를 알 수 없으니 ③번도 불가능합니다. IP를 직접 지정하면 ①~②를 건너뛰기 때문에 연결되는 것입니다.
169.254.169.253은 무엇인가
169.254.x.x는 RFC 3927에서 정의된 링크-로컬(Link-Local) 주소 대역입니다. 라우터를 통해 전달되지 않고 같은 네트워크 링크 내에서만 유효합니다.
AWS는 이 대역에서 두 가지 주요 주소를 예약합니다.
| 주소 | 용도 |
|---|---|
169.254.169.254 | EC2 Instance Metadata Service (IMDS) |
169.254.169.253 | VPC DNS Resolver (Route 53 Resolver) |
AWS VPC에는 원래 VPC CIDR 첫 번째 주소 + 2(예: CIDR이 10.0.0.0/16이면 10.0.0.2)에 DNS Resolver가 있습니다. 169.254.169.253은 이 주소의 고정 별칭으로, VPC CIDR이 무엇이든 동일하게 사용할 수 있습니다. 모든 AWS 리전, 모든 VPC에서 항상 이 주소입니다.
왜 아웃바운드 Whitelist 환경에서 차단되는가
보안 그룹 아웃바운드를 Whitelist로 운영하면, 명시적으로 허용된 목적지·포트 조합 외에는 모두 차단됩니다. "VPC 내부 통신이니 DNS는 당연히 되겠지"라고 생각하기 쉬운데, 여기서 함정이 있습니다.
169.254.169.253은 링크-로컬 주소입니다. VPC의 서브넷 CIDR 대역(예: 10.0.0.0/16)에 속하지 않습니다. 따라서 10.0.0.0/16 전체 허용 같은 규칙을 추가해도 이 주소는 포함되지 않습니다. 포트 53을 별도로 명시하지 않으면 DNS 쿼리가 조용히 차단됩니다.
에러 로그에도 잘 나타나지 않습니다. 앱 입장에서는 "DNS 응답 없음 → 연결 타임아웃"으로 보일 뿐이고, 차단 자체는 로그 없이 일어납니다. 이 때문에 원인을 찾기가 어렵습니다.
EKS 환경의 특수성
EKS에서는 DNS 경로가 한 단계 더 있습니다. 앱 Pod는 직접 169.254.169.253을 쿼리하지 않고, 먼저 CoreDNS를 거칩니다.
[앱 Pod]
│ ① NLB 도메인 DNS 쿼리
▼
[CoreDNS Pod] ← kube-dns Service (ClusterIP)
│ ② upstream DNS 쿼리 (UDP/TCP 53)
▼
[169.254.169.253] ← AWS VPC DNS Resolver
│ ③ NLB IP 응답
▼
[앱 Pod]
│ ④ NLB IP로 직접 연결
▼
[NLB]
CoreDNS Pod는 Worker Node 위에서 실행됩니다. 따라서 허용이 필요한 곳은 CoreDNS가 실행되는 Worker Node의 보안 그룹입니다. 앱 Pod의 보안 그룹이 아닙니다.
EKS에서 자주 발생하는 두 가지 상황이 있습니다.
① 노드 그룹 보안 그룹 아웃바운드 제한
Worker Node 보안 그룹에서 아웃바운드를 제한할 때 DNS 포트를 빠뜨리는 경우입니다. 169.254.169.253/32 포트 53이 없으면 CoreDNS가 upstream 쿼리를 보내지 못합니다. 클러스터 전체 DNS 조회가 실패하게 됩니다.
② Kubernetes NetworkPolicy 적용
네임스페이스에 default-deny NetworkPolicy를 걸었을 때, kube-system 네임스페이스의 CoreDNS까지 영향을 받는 경우가 있습니다. CoreDNS Pod의 egress에 169.254.169.253/32 포트 53을 명시적으로 허용해야 합니다.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-coredns-egress-dns
namespace: kube-system
spec:
podSelector:
matchLabels:
k8s-app: kube-dns
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 169.254.169.253/32
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
해결 방법 — 보안 그룹 규칙 추가
UDP 53과 TCP 53을 함께 허용합니다. DNS 응답 크기가 512바이트를 넘으면 UDP에서 TCP로 자동으로 재시도하기 때문에 TCP도 빠뜨리면 안 됩니다.
AWS CLI:
# UDP 53
aws ec2 authorize-security-group-egress \
--group-id sg-xxxxxxxxxx \
--protocol udp \
--port 53 \
--cidr 169.254.169.253/32
# TCP 53
aws ec2 authorize-security-group-egress \
--group-id sg-xxxxxxxxxx \
--protocol tcp \
--port 53 \
--cidr 169.254.169.253/32
Terraform:
resource "aws_security_group_rule" "dns_udp_egress" {
type = "egress"
security_group_id = aws_security_group.node.id
protocol = "udp"
from_port = 53
to_port = 53
cidr_blocks = ["169.254.169.253/32"]
description = "AWS VPC DNS Resolver"
}
resource "aws_security_group_rule" "dns_tcp_egress" {
type = "egress"
security_group_id = aws_security_group.node.id
protocol = "tcp"
from_port = 53
to_port = 53
cidr_blocks = ["169.254.169.253/32"]
description = "AWS VPC DNS Resolver (TCP fallback)"
}
169.254.169.253은 VPC CIDR에 관계없이 고정 주소이므로, 이 규칙 하나면 모든 리전·모든 VPC에서 동일하게 동작합니다.
마치며
"IP로는 되는데 도메인으로는 안 된다"는 증상은 DNS 차단의 전형적인 패턴입니다. 보안 그룹 규칙을 아무리 들여다봐도 이상이 없어 보이는 이유는, 169.254.169.253이 VPC 서브넷 대역 밖의 링크-로컬 주소라 기존 허용 규칙에 포함되지 않기 때문입니다.
아웃바운드 제어가 강한 환경(금융·의료 등 컴플라이언스 요건이 있는 시스템)에서 보안 그룹 베이스라인을 정의할 때, 169.254.169.253/32 UDP/TCP 53을 기본 항목에 넣어두면 이런 류의 디버깅에 시간을 낭비하지 않습니다.