E-앰비언트 ztunnel 트래픽 경로 분석

개요

앰비언트 모드를 세팅한 이후, 전체적인 흐름을 알아보기 위해 iptables를 분석하고 패킷을 까보았다.
E-앰비언트 모드 헬름 세팅에서 먼저 세팅을 진행한다.

keti debug -- curl productpage:9080

ztunnel 레벨의 경로만 분석하면, 웨이포인트는 그저 한 홉이 증가하는 것에 불과하다.
그래서 그다지 어려운 레벨은 아니라 ztunnel 쪽에서 일어나는 위주로 정리한다.

간단한 트래픽에 대한 ztunnel 로그는 다음과 같이 나타난다.
image.png
출발지(debug)의 ztunnel의 로그는 다음과 같다.
목적지가 15008, 즉 hbone 포트였고 그 안 속 패킷은 9080 포트를 가리키고 있다.
또한 출발지 측에서 "나가는" 트래픽에 대한 로그이기 때문에 direction=outbound로 찍히는 것이 확인된다.
image.png
반대로 목적지(productpage)의 ztunnel 로그는 이렇게 남는다.
표시되는 src, dst 자체의 정보는 비슷한데, 눈 여겨 볼 지점 중 하나는 출발지의 임시 포트가 다르다는 것이다.
출발지에서 찍힌 임시 포트는 앱 컨테이너가 날린 트래픽에 대한 포트 정보이나, 목적지에서 찍히는 임시 포트는 출발지의 ztunnel이 날린 트래픽에 대한 포트 정보가 남기 때문에 이러한 결과가 나온다.
추가로 트래픽이 들어온 측의 로그라 direction=inbound가 나오고 있다.

iptables 분석

세팅은 이런 식으로 해서 패킷 카운트를 확인했다.

TABLE="mangle nat"
CHAIN="PREROUTING ISTIO_PRERT OUTPUT ISTIO_OUTPUT"
watch -d "for i in $TABLE ; do for j in $CHAIN ; do iptables -t \$i -n -v -L \$j; echo; done; echo; done"

먼저 mangle 테이블은 이렇게 생겼다.

Chain PREROUTING (policy ACCEPT 675 packets, 158K bytes)
 pkts bytes target     prot opt in     out     source               destination         
  675  158K ISTIO_PRERT  0    --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain ISTIO_PRERT (1 references)
 pkts bytes target     prot opt in     out     source               destination         
   48  3749 CONNMARK   0    --  *      *       0.0.0.0/0            0.0.0.0/0            mark match 0x539/0xfff CONNMARK xset 0x111/0xfff

Chain OUTPUT (policy ACCEPT 688 packets, 107K bytes)
 pkts bytes target     prot opt in     out     source               destination         
  688  107K ISTIO_OUTPUT  0    --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain ISTIO_OUTPUT (1 references)
 pkts bytes target     prot opt in     out     source               destination         
  346 75875 CONNMARK   0    --  *      *       0.0.0.0/0            0.0.0.0/0            connmark match  0x111/0xfff CONNMARK restore

이 테이블 정보를 이해하기 위한 몇 가지 지식이 있다.

iptables에서 match a / b 의 의미는 패킷 c에 대해 c & b == a를 묻는 것이다.
즉 AND연산을 하는 것인데, 0xfff(1로 채워진 12비트)에 AND 연산을 한다는 건 그냥 하위 12 비트가 a와 같냐고 묻는 것과 같다.

connmark와 mark가 구제적으로 다르다는 사실에 유의해야 한다.
connmark는 컨트랙 모듈이 관리하는 커넥션 엔트리에 마킹되는 값으로, 커널 내부에서 패킷 구조체에 마킹되는 값과 다르다.

룰 해석 자체는 그렇게 어렵지는 않다.
들어오는 트래픽에 대해서는 마크가 0x539일 경우 커넥션 마크를 0x111로 세팅한다.
그리고 나가는 트래픽의 커넥션 마크에 0x111이 세팅되어 있다면 해당 값을 일반 마크에도 세팅한다.
이 마킹 정보들은 이후 nat 테이블에서 사용된다.
여기에서 0x539는 ztunnel측에서 세팅해주는 값으로 십진수로는 1337이다.

다음으로 nat 테이블은 이런 식으로 구성된다.

Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ISTIO_PRERT  0    --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain ISTIO_PRERT (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     6    --  *      *       169.254.7.127        0.0.0.0/0            tcp
    0     0 REDIRECT   6    --  *      *       0.0.0.0/0           !127.0.0.1            tcp dpt:!15008 mark match ! 0x539/0xfff redir ports 15006

Chain OUTPUT (policy ACCEPT 1 packets, 60 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   49  3756 ISTIO_OUTPUT  0    --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain ISTIO_OUTPUT (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     6    --  *      *       0.0.0.0/0            169.254.7.127        tcp
   24  2256 REDIRECT   17   --  *      !lo     0.0.0.0/0            0.0.0.0/0            mark match ! 0x539/0xfff udp dpt:53 redir ports 15053
    0     0 REDIRECT   6    --  *      *       0.0.0.0/0           !127.0.0.1            tcp dpt:53 mark match ! 0x539/0xfff redir ports 15053
    0     0 ACCEPT     6    --  *      *       0.0.0.0/0            0.0.0.0/0            mark match 0x111/0xfff
    0     0 ACCEPT     0    --  *      lo      0.0.0.0/0           !127.0.0.1           
   24  1440 REDIRECT   6    --  *      *       0.0.0.0/0           !127.0.0.1            mark match ! 0x539/0xfff redir ports 15001

이전 사이드카 모드 때의 iptables와 비교하면 꽤나 간결한 편이다.

테이블이 두 개 뿐이라 해석 자체는 상대적으로 쉽다.
먼저 들어오는 패킷에 대해 169.254.7.127에서 왔다면 무조건 통과시킨다.
해당 주소는 kubelet에서 오는 헬스체크 프로브에 대해 ztunnel이 SNAT 시키는 주소로, 이를 통해 헬스체크 패킷은 정상적으로 동작하게 만든다.
그리고 다음은 15006으로 리다이렉트를 시키는 조건이 적혀있는데, 간단하게 말하자면 그냥 앱 컨테이너에서 나가는 요청을 낚아채는 것이다.
사이드카 모드와 달리, 이제는 룰에 명시되지 않은 나머지 패킷들이 그냥 통과한다는 것을 유의할 필요가 있다.

패킷 확인

다음으로는 실제로 패킷을 캡쳐해서 어떻게 동작이 일어나는지 확인한다.
패킷을 실제로 뜯어보면 어떻게 트래픽이 이동했는지 감을 잡는데 도움된다.

아래 명령어는 전부 각 파드의 네임스페이스에 들어간 뒤에 캡쳐를 떴다.
참고로 productpage 파드에 들어가면 tcpdump 패키지를 설치해야 한다.

# curl to same node
tcpdump -i any -c 100 -w /pcap/same-node.pcap
# dump from debug pod
tcpdump -i any -c 100 -w /pcap/outbound-to-pod.pcap
# dump from productpage pod
tcpdump -i any -c 100 -w /pcap/inbound-from-pod.pcap

아웃바운드 트래픽

먼저 debug 파드 쪽에서 아웃바운드 트래픽을 캡쳐한 결과이다.
image.png
해당 트래픽을 포트를 기준으로 단계적으로 보자.

결국 앱 컨테이너의 요청은 ztunnel로 들어가고, ztunnel이 실제 요청을 날리는데 이 요청은 목적지 파드가 있는 곳의 ztunnel인 것이다.
그리고 그 요청은 15008 포트, HBONE을 통해 이뤄진다.
재밌는 것은 46048포트로 나가는 트래픽은 ztunnel이 날리는 트래픽인데, 파드의 네임스페이스에서 찍힌다는 것이다.
image.png
HBONE으로 한창 트래픽이 오가고, 이후에 ztunnel은 앱 컨테이너에 응답을 돌려준다.
물론 응답은 원래 목적지인 productpage 9080포트에서 온 것처럼 표시된다.

인바운드 트래픽

다음은 요청을 받았던 productpage에서 뜬 덤프이다.
image.png
이쪽은 플로우 그래프가 훨씬 단순하다.

image.png

최종적으로 정리하자면 현재 트래픽의 흐름은 이런 식으로 진행됐다.

ztunnel이 어떻게 워크로드 간 트래픽을 전달하는지 이제 명확하게 알 수 있다!

마지막으로 HBONE이 왜 터널인지 살짝 알 수 있는 대목으로, 반복적으로 요청을 보낸 패킷의 모습을 담아본다.
단순하게 위의 패킷을 뜨기 위해 debug 에서 productpage로 요청을 날린 것을 두어 번 반복했다.
image.png
앱 컨테이너에서의 요청 자체는 56436 임시 포트로 아무거나 부여받은 것이 확인된다.
그러나 15008로 향하는 출발지 ztunnel은 이전에 사용했던 46048포트를 그대로 사용하고 있다.
이는 HBONE 연결이 지속적으로 연결돼있으며, 추가적인 통신에 그대로 재사용된다는 것을 의미한다.
(conntrack -L을 찍어보면 만료 기한이 어마무시하게 길게 잡혀 있다..)
이후 트래픽은 원래도 0x539 마킹이 돼 있어 iptables에 영항을 받지 않겠지만 아예 컨트랙을 통해 추적되는 트래픽이기 때문에 iptables의 nat 테이블은 아예 거치지 않는 결과가 나오게 될 것이다.

하위 문서

이름 is-folder index noteType created
E-서버리스 실습 - - topic/explain 2024-06-27
E-도커 파일 구조 탐색 - - topic/explain 2024-08-05
E-로컬 ssh 서버 세팅 - - topic/explain 2024-07-13
E-쿠버네티스 클러스터 구축 - - topic/explain 2024-07-29
E-레디네스 프로브와 레디네스 게이트 - - topic/explain 2024-08-15
E-initialDelaySeconds가 아니라 스타트업 프로브가 필요한 이유 - - topic/explain 2024-08-25
E-초기화 컨테이너보다 앞서는 사이드카 컨테이너 - - topic/explain 2024-08-30
E-디플로이먼트 조작 - - topic/explain 2024-09-14
E-NFS 볼륨, 스토리지 클래스 설정 - - topic/explain 2024-10-17
E-AWS KRUG 핸즈온 실습 - ECS false - topic 2024-11-03
E-컨테이너 오라클 dbms 설치 false - topic/explain 2024-11-26
E-리눅스 dbeaver 설치 false - topic/explain 2024-11-26
E-오라클 사용자 및 테이블 스페이스 생성 false - topic/explain 2024-11-26
E-파드의 readinessProbe와 디플로이먼트의 minReadySeconds의 차이 false - topic/explain 2024-12-26
E-잡 패턴 실습 false - topic 2024-12-28
E-iptables와 nftables의 차이 false - topic/explain 2024-12-30
E-바인딩과 하드 링크의 차이 false - topic/explain 2025-01-16
E-emptyDir 제한 false - topic/explain 2025-01-16
E-쿠버네티스 인증 실습 false - topic/explain 2025-01-21
E-api 서버 감사 false - topic/explain 2025-01-21
E-파드 마운팅 recursiveReadOnly false - topic/explain 2025-02-27
E-projected 볼륨 - 동적 업데이트, 중복 활용 false - topic/explain 2025-03-10
E-쿠버 RBAC 권한 상승 방지 실습 false - topic/explain 2025-03-16
E-Kyverno 기본 실습 false - topic/explain 2025-03-17
E-검증 승인 정책 실습 false - topic/explain 2025-03-17
E-nodeName으로 스케줄링 실습 false - topic/explain 2025-03-19
E-openssl을 이용한 인증서 생성 실습 false - topic/explain 2025-03-22
E-buildKit을 활용한 멀티 플랫폼, 캐싱 빌드 실습 false - topic/explain 2025-03-30
E-이스티오의 데이터 플레인 트래픽 세팅 원리 false 1 topic/explain 2025-05-27
E-이스티오 가상머신 통합 false 1 topic/explain 2025-06-01
E-이스티오 설정 트러블슈팅하기 false 2 topic/explain 2025-05-18
E-deb 파일 뜯어보기 false 2 topic/explain 2025-06-01
E-앰비언트 모드 헬름 세팅 false 2 topic/explain 2025-06-03
E-이스티오 컨트롤 플레인 성능 최적화 false 3 topic/explain 2025-05-18
E-이스티오 DNS 프록시 동작 false 3 topic/explain 2025-06-01
E-앰비언트 ztunnel 트래픽 경로 분석 false 3 topic/explain 2025-06-07
E-이스티오 컨트롤 플레인 메트릭 false 4 topic/explain 2025-05-18
E-앰비언트 모드에서 메시 기능 활용 false 5 topic/explain 2025-06-07

관련 문서

지식 문서, EXPLAIN

이름3is-folder생성 일자
E-앰비언트 모드에서 메시 기능 활용false2025-06-07 20:56
E-앰비언트 모드 헬름 세팅false2025-06-03 19:27
앰비언트 모드false2025-06-02 14:51

기타 문서

Z0-연관 knowledge, Z1-트러블슈팅 Z2-디자인,설계, Z3-임시, Z5-프로젝트,아카이브, Z8,9-미분류,미완
이름4코드타입생성 일자
I-ztunnel이 다른 네임스페이스에서 요청 보내는 코드 분석Z1topic/idea2025-06-07 20:44
I-다른 네임스페이스 같은 포트 리스닝 서버 구현Z1topic/idea2025-06-07 19:39
9W - 앰비언트 모드 구조, 원리Z8published2025-06-07 19:17
9W - 앰비언트 헬름 설치, 각종 리소스 실습Z8published2025-06-07 19:27

참고