본문 바로가기
DevOps

EKS에서 Amazon DocumentDB 연결 테스트: 왜 telnet은 안되고 mongo는 될까?

by Rainbound-IT 2025. 8. 12.
반응형

 

 

AWS EKS에 documentDB를 연결하기 위해 일반적인 보안설정(SG,routing,NACL..) 을 마치고 telnet으로 해당 포트를 테스트 해보았는데 time out이 걸려서 뭐 잘못했는지 엄청 헤매는 경험이 있었습니다.

 

그러다가 해당 앱의 client 연결 하는것을 받아 해보았는데 접속이 되었습니다.
나의 무적의 telnet 테스트가 안되다니... 시간 오래 걸린것보다 충격이어서 정리 들어갑니다.

 

목차

     

     

    • telnet/nc는 L4(포트) 열림만 확인합니다. TLS/인증은 모릅니다.
    • DocumentDB는 TLS 필수 + Mongo 프로토콜을 요구하므로, telnet만으론 “무응답/타임아웃처럼” 보일 수 있어요.
    • 정확한 순서는 nc(L4) → openssl s_client(TLS) → mongo/mongosh(L7) 입니다.
    • 타임아웃이면 대개 SG/CIDR 불일치, NACL 왕복 포트, NetPol egress, SNAT 경로 문제입니다.

    구성 전제

    • DocumentDB: 프라이빗 서브넷 2개(예: 10.0.11.0/24, 10.0.12.0/24)에 배치, SG 인바운드 27017만 허용
    • EKS: 프라이빗 서브넷에 노드/파드 구동
    • 테스트 엔드포인트: 클러스터 엔드포인트(기본), 읽기 분산 확인은 리더 엔드포인트 사용
    • 중요: 로컬 PC(인터넷)에서 프라이빗 DocDB로 telnet은 당연히 실패합니다. 테스트는 VPC 내부(EKS 파드/EC2) 에서 하세요.

    무엇을 어떻게 검사할까? (정확한 기준 잡기)


     

    레벨 목적 도구/명령 기대결과
    L4 포트 열림 nc -vz <endpoint> 27017 또는 telnet open/succeeded/Connected면 경로 OK
    TLS TLS 핸드셰이크 openssl s_client -connect <endpoint>:27017 -tls1_2 핸드셰이크 로그가 보이면 TLS OK
    L7 Mongo 프로토콜 mongo/mongosh + TLS 옵션 { "ok" : 1 } 면 앱 레벨 OK
     

    telnet 결과는 TLS/인증과 무관합니다. 그래서 telnet이 “멈춘 것처럼” 보이거나 타임아웃이어도, mongo는 잘 되는 상황이 발생합니다.


    빠른 시작: EKS 파드에서 3단계 검사

    1) L4 (포트 오픈)

    kubectl run netcheck --image=nicolaka/netshoot --restart=Never --rm -it -- \
      sh -lc 'nc -vz <DOCDB_ENDPOINT> 27017 || true'

    2) TLS 핸드셰이크

    kubectl run sslcheck --image=nicolaka/netshoot --restart=Never --rm -it -- \
      sh -lc 'echo | openssl s_client -connect <DOCDB_ENDPOINT>:27017 -tls1_2 | head -n 20'

    3) L7 (Mongo ping)

    1회 점검용: CA 검증 생략

    kubectl run docdb-ping --image=mongo:5.0 --restart=Never --rm -it -- \
      bash -lc 'mongo "mongodb://USER:PASS@<DOCDB_ENDPOINT>:27017/admin?ssl=true&replicaSet=rs0&retryWrites=false" --sslAllowInvalidCertificates --eval "db.runCommand({ ping: 1 })"'

    권장(운영): RDS CA 번들로 검증

    kubectl run docdb-ping --image=mongo:5.0 --restart=Never --rm -it -- \
      bash -lc 'curl -fsSL https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem -o /tmp/rds-ca.pem && \
                mongo "mongodb://USER:PASS@<DOCDB_ENDPOINT>:27017/admin?ssl=true&replicaSet=rs0&retryWrites=false" \
                --ssl --sslCAFile /tmp/rds-ca.pem --eval "db.runCommand({ ping: 1 })"'

    PowerShell(이스케이프 주의) 버전이 필요하면 말해주세요. 따옴표를 백틱으로 감싼 예시를 드릴게요.


    클러스터 엔드포인트 vs 리더 엔드포인트

    • 클러스터 엔드포인트: 보통 Primary로 붙습니다(기본 연결/쓰기/기본 점검용).
    • 리더 엔드포인트: 읽기 부하 분산/세컨더리로 라우팅 확인 시 사용.
    • 단순 연결성/기본 동작은 클러스터 엔드포인트로 충분합니다.

    왜 telnet은 실패하고 mongo는 성공할까? (대표 원인 7)

    1. TLS 필수 서비스의 무응답/즉시 종료
      telnet은 빈 TCP 세션만 열고 대기 → 서버/중간 장비가 비-TLS 세션을 무응답 혹은 즉시 드롭.
    2. IPv6 우선 해석
      telnet/nc가 AAAA로 먼저 시도했다가 경로 미구성으로 타임아웃. 드라이버는 v4 재시도해 성공하는 케이스.
      → nc -4 / getent ahostsv4로 강제 확인.
    3. 중간 장비의 L7 시그니처 검사
      특정 포트(27017)에 TLS/Mongo 시그니처가 없으면 차단. 드라이버는 TLS로 식별 → 통과.
    4. SNAT/경로 차이
      egress 게이트웨이/NAT/프록시로 소스 IP가 달라지면, DocDB SG의 CIDR 허용과 불일치로 드롭.
    5. 연결 수 제한/스로틀링
      드라이버는 재시도/백오프가 있지만, telnet은 단발성이라 타임아웃처럼 보일 수 있음.
    6. MTU/PMTUD 블랙홀(희귀)
      큰 패킷 구간부터 드롭. openssl/mongo에서만 재현되거나 반대도 가능. tcpdump로 확인.
    7. 클라이언트/쉘 인용 문제
      PowerShell 따옴표/옵션 차이, BusyBox nc 동작 차이 등으로 의도한 명령이 안 날아감.

    타임아웃일 때 진단 플로우 (실무형)

    # Pod IP / DNS 해석
    kubectl run diag --image=nicolaka/netshoot --restart=Never --rm -it -- sh -lc '
      set -x
      ip -4 -o addr show eth0
      getent hosts <DOCDB_ENDPOINT> || true
      getent ahostsv4 <DOCDB_ENDPOINT> || true
    '
    
    # L4 (IPv4 강제) → 실패하면 경로/SG/NACL/NetPol 의심
    kubectl run l4 --image=nicolaka/netshoot --restart=Never --rm -it -- \
      sh -lc 'nc -4vz <DOCDB_ENDPOINT> 27017 || true'
    
    # TLS → 여기서도 실패면 TLS/중간장비/MTU 의심
    kubectl run tls --image=nicolaka/netshoot --restart=Never --rm -it -- \
      sh -lc "echo | openssl s_client -connect <DOCDB_ENDPOINT>:27017 -tls1_2 | head -n 20"
    
    # (선택) 패킷 스니핑
    kubectl run sniff --image=nicolaka/netshoot --restart=Never --rm -it -- \
      sh -lc 'tcpdump -ni eth0 port 27017 -vv'

    체크리스트 (실패 시 순서대로)

    1. Pod IP CIDRDocDB SG 인바운드 CIDR 일치 여부
      • 생각한 대역(예: 10.0.11/12)과 실제 파드/노드 대역이 다를 수 있음
      • 가장 견고한 방법: CIDR 대신 SG→SG 허용(EKS 노드 SG or Pod SG)
    2. NetworkPolicy egress
      • kubectl get netpol -A
      • 테스트 네임스페이스에 egress allow 임시 정책 적용해 차단 요인 배제
    3. NACL(Stateless!) 왕복 포트
      • DocDB 서브넷: Inbound 27017, Outbound 1024–65535
      • EKS 서브넷: Outbound 27017, Inbound 1024–65535
    4. IPv6 시도 차단/경로
      • nc -4로 v4 강제, DNS 해석 결과 확인
    5. SNAT/프록시 경로 확인
      • 소스 IP가 노드 IP/NAT GW라면 DocDB SG의 CIDR/SG 허용과 맞춰야 함

    “원클릭” 네트워크 진단 Job (로그로 한 번에 확인)

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: docdb-netdiag
    spec:
      template:
        spec:
          restartPolicy: Never
          containers:
          - name: diag
            image: nicolaka/netshoot
            command: ["sh","-lc"]
            args:
            - |
              set -x
              echo "== Pod IP / Node =="
              ip -4 -o addr show eth0
              echo "Node:"; cat /etc/hostname
              echo "== DNS resolve =="
              nslookup <DOCDB_ENDPOINT> || true
              getent hosts <DOCDB_ENDPOINT> || true
              echo "== L4 port test (nc) =="
              nc -4vz <DOCDB_ENDPOINT> 27017 || true
              echo "== TLS handshake (openssl) =="
              (echo | openssl s_client -connect <DOCDB_ENDPOINT>:27017 -tls1_2) | head -n 30 || true
    kubectl apply -f docdb-netdiag.yaml
    kubectl wait --for=condition=complete job/docdb-netdiag --timeout=120s
    kubectl logs job/docdb-netdiag

    SG/NACL/NetPol 모범 사례

    • SG는 CIDR보다 SG→SG 허용이 안전
      • EKS 노드 SG(또는 “SG for Pods” 사용 시 파드 SG)를 DocDB SG 인바운드 소스로 지정
    • NACL은 왕복 모두 허용
      • DB 서브넷 Inbound 27017, Outbound 1024–65535
      • EKS 서브넷 Outbound 27017, Inbound 1024–65535
    • NetPol
      • 기본 차단을 쓰는 경우, DocDB로 나가는 egress 허용을 명시

    Terraform 예시 (SG→SG 허용권장)

     
    # DocDB SG에 EKS 노드 SG를 소스로 허용
    resource "aws_security_group_rule" "docdb_from_nodes" {
      type                     = "ingress"
      security_group_id        = aws_security_group.docdb.id
      from_port                = 27017
      to_port                  = 27017
      protocol                 = "tcp"
      source_security_group_id = var.eks_node_sg_id
      description              = "Allow DocDB from EKS node SG"
    }
     

    (테스트 중에는 임시로 VPC CIDR을 열어 경로를 확인하고, 이후 반드시 최소 권한으로 좁히세요.)


    FAQ

    • Q. ServiceAccount/IAM 권한이 없어도 연결 되나요?
      A. 네. L4 연결은 권한과 무관합니다. 권한은 API 호출/클라우드 리소스 접근과 관련.
    • Q. telnet이 TLS에 영향 있나요?
      A. 아니요. telnet은 L4만. TLS는 openssl s_client로 확인하세요.
    • Q. 로컬 PC에서 왜 telnet이 안 되나요?
      A. DocDB는 프라이빗 엔드포인트라 외부에서 바로 접근 불가. VPC 내부(EKS/EC2)에서만 의미가 있습니다. (또는 SSM 포트포워딩)

    마무리

    • 정확한 테스트 순서: nc(L4) → openssl s_client(TLS) → mongo ping(L7)
      • L4(경로/SG/NACL): nc -vz <endpoint> <port>
      • TLS: openssl s_client -connect <endpoint>:<port> -tls1_2
      • L7(엔진): RDS→ mysql/psql , DocumentDB→ mongo/mongosh(+ RDS CA 번들)
    • 실패 시: Pod IP ↔ DocDB SG CIDR 일치, SG→SG 허용, NACL 왕복 포트, NetPol egress, SNAT/IPv6 이슈를 차례로 점검
    • 운영: RDS CA 번들로 TLS 검증, 읽기 분산은 리더 엔드포인트
    반응형

    댓글