E-앰비언트 모드 헬름 세팅
개요
이전 글에서 딥하게 앰비언트 모드의 이론과 동작 원리에 대해 파고들었다.
이번 노트에서는, 이 동작들을 실제로 검증한다.
다음 노트에서 앰비언트 모드이기에 고려해야 하는 각종 트래픽 제어 및 보안 설정을 하는 방법들을 살펴볼 예정인데, 이건 시간 나면 추가하겠다.
기본 클러스터 세팅
kind create cluster --name myk8s --image kindest/node:v1.32.2 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30000 # Sample Application
hostPort: 30000
- containerPort: 30001 # Prometheus
hostPort: 30001
- containerPort: 30002 # Grafana
hostPort: 30002
- containerPort: 30003 # Kiali
hostPort: 30003
- containerPort: 30004 # Tracing
hostPort: 30004
- containerPort: 30005 # kube-ops-view
hostPort: 30005
extraMounts:
- hostPath: ./pcap
containerPath: /pcap
- role: worker
extraMounts:
- hostPath: ./pcap
containerPath: /pcap
- role: worker
extraMounts:
- hostPath: ./pcap
containerPath: /pcap
networking:
podSubnet: 10.10.0.0/16
serviceSubnet: 10.200.1.0/24
EOF
# MetalLB
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.9/config/manifests/metallb-native.yaml
# The status of Deployment doesn't ensure the readiness of its Pods.
#kubectl -n metallb-system wait --for condition=available deployment controller --timeout=60s
kubectl -n metallb-system wait --for condition=Ready po --timeout=60s --all=true
sleep 1
cat << EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default
namespace: metallb-system
spec:
addresses:
- 172.18.255.101-172.18.255.120
EOF
cat << EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default
namespace: metallb-system
spec:
ipAddressPools:
- default
EOF
# external client
docker run -d --rm --name mypc --network kind nicolaka/netshoot sleep infinity
alias de='docker exec -ti mypc '
기본 세팅은 KIND로, 멀티 노드 세팅을 한다.
MetalLB를 통해 로드 밸런서 서비스가 정상 세팅되도록 만들었다.
헬름 기반 앰비언트 모드 구축
앰비언트 모드는 버전 관리를 명확하게 하기 위해 헬름 기반 설치가 권장된다.
헬름 설치는 istioctl의 방식과 조금 다르게 몇 가지 순서를 두고 설치를 진행해야 한다.
- istio-base - 이스티오 커스텀 리소스 설치
- istiod - 컨트롤 플레인 설치
- 앰비언트 모드라면 추가로
- Gateway API CRD
- istio-cni
- ztunnel
단계가 늘어나서 좀 복잡해 보이지만, 결국 컴포넌트들을 하나 하나 세팅하는 것일 뿐이다.
################################################################################
# Install Istio Ambient
################################################################################
helm repo add istio https://istio-release.storage.googleapis.com/charts
#helm repo update
helm install istio-base istio/base -n istio-system --create-namespace --wait --set meshConfig.accessLogFile=/dev/stdout --set variant=debug
kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml
helm install istiod istio/istiod --namespace istio-system --set profile=ambient --wait --set variant=debug
# If there's too much resource used during installing istio-cni, the pod for the master node fails.
# Error says there's too many open files, and once it starts to fail, it never recovered.
sleep 5
helm install istio-cni istio/cni -n istio-system --set profile=ambient --wait --set variant=debug
helm install ztunnel istio/ztunnel -n istio-system --wait --set variant=debug
중간에 일부러 sleep을 부여했다.
이렇게 한 이유는 헬름 설치가 컴포넌트 배치의 모든 준비 상태, 내부 프로세스의 초기화 상태까지 고려하지는 않기 때문이다.
해당 지연을 부여하지 않고 진행할 때 지속적으로 컨트롤 플레인 istio-cni에서 too many open files
에러가 나왔다.
istio-cni에 ulimit
해보면 제한이 안 걸려있던데 왜 이렇게 되는 건지 잘은 모르겠다.
구체적으로 해당 에러는 watch 핸들의 최대 허용 수가 넘어갈 때 발생한다고 한다.[1]
이상한 건, 해당 에러가 한 번 뜨면 클러스터를 날려먹기 전까지 문제가 해결되지 않기도 했다는 것.
구체적으로 해당 에러는 istio-cni가 cri의 플러그인 설정 파일에 있는 다른 cni(kindnet)의 설정 파일에 쓰기 작업을 할 때 발생했다.
혹시 개별 파일에 접근 가능한 프로세스 갯수도 노드 별 전역 제한을 걸 수 있는 건가 했는데 이 부분은 확실치 않다.
당장은 컨트롤 플레인에서만 발생했다는 점에서 노드 내 자원의 리소스 경합이 일어났다고 판단을 내렸다.
몇 초만 지연을 부여해도 해당 문제는 해결됐다.
추가적으로 variant에 debug를 세팅하면 배치되는 컨테이너 이미지들이 전부 debug용으로 세팅된다.
앰비언트의 기본 이미지는 distroless로 설정돼있어 테스트에 있어서는 매우 귀찮음을 유발하기에 이렇게 바꿔줬다.
(참고로 가능한 값이 distroless, debug 두 개 뿐이다.)
다음은 기타 세팅이다.
################################################################################
# Install Observability tools
################################################################################
kubectl apply -f samples/addons
kubectl patch svc -n istio-system prometheus -p '{"spec": {"type": "NodePort", "ports": [{"port": 9090, "targetPort": 9090, "nodePort": 30001}]}}'
kubectl patch svc -n istio-system grafana -p '{"spec": {"type": "NodePort", "ports": [{"port": 3000, "targetPort": 3000, "nodePort": 30002}]}}'
kubectl patch svc -n istio-system kiali -p '{"spec": {"type": "NodePort", "ports": [{"port": 20001, "targetPort": 20001, "nodePort": 30003}]}}'
kubectl patch svc -n istio-system tracing -p '{"spec": {"type": "NodePort", "ports": [{"port": 80, "targetPort": 16686, "nodePort": 30004}]}}'
kubectl apply -f bookinfo.yaml
#kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
kubectl apply -f samples/bookinfo/gateway-api/bookinfo-gateway.yaml
kubectl apply -f debug.yaml
GWLB=$(kubectl get svc bookinfo-gateway-istio -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
istioctl을 설치할 때 기본으로 제공되는 관측가능성 도구와 북인포 예제를 사용했다.
여기에 디버깅용 넷슛 파드를 추가적으로 배치했는데, 조금의 커스텀을 넣었다.
apiVersion: v1
kind: Pod
metadata:
name: debug
spec:
volumes:
- name: local
hostPath:
path: "/pcap"
containers:
- name: debug
image: nicolaka/netshoot
command: [sh, -c, "sleep 60d"]
volumeMounts:
- mountPath: /pcap
name: local
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app: productpage
terminationGracePeriodSeconds: 0
바로 이렇게 안티 어피니티를 넣어서 넷슛 파드로 트래픽을 쏠 서비스와 의도적으로 다른 노드에 배치되게 했다.
추가적으로 트래픽 캡쳐를 위해 볼륨 마운팅해서 내 로컬에서 pcap 파일을 쉽게 열어볼 수 있도록 세팅했다.
해당 마운팅은 북인포 예제의 productpage 서비스에도 세팅했다.
설치 확인
기본적인 설치가 완료되면 이렇게 istio-system에 여러 컴포넌트들이 배치된다.
키알리로 확인해보면 details에 아직 메시의 관리를 받지 않는다는 정보도 출력해준다.
게이트웨이의 경우 이스티오의 게이트웨이 클래스를 통해 배포가 됐기 때문에 메시의 일원으로 취급은 되고 있다.
참고로 현재 이스티오에서는 gateway api에 대한 기본적인 지원을 해주기 때문에 설치 시 위의 클래스들도 알아서 배치해버린다.
컴포넌트 정보 확인
본격적으로 컴포넌트들의 상세 상태를 확인해본다.
먼저 istio-cni를 보면 다음과 같이 cni 파일을 읽어서 해당 파일에 자신의 플러그인 정보를 주입힌다.
(참고로 지연을 주지 않고 세팅했을 때 이 cni 파일에 쓰기 작업이 들어가는 부분에서 에러가 발생했다.)
추가적으로 ztunnel과 연결이 수립됐을 때 해당 정보도 출력하는 것을 볼 수 있다.
k -n istio-system get daemonsets.apps istio-cni-node -ojson | yq '.spec.template.spec.volumes[].hostPath'
istio-cni는 노드의 여러 경로를 마운팅하고 있다.
네임스페이스 관리를 해야 하다보니 netns나 프로세스 디렉토리까지, 다양하게 마운팅을 해두는 것을 볼 수 있다.
여기에 양식을 확인해보면 NET_ADMIN, SYS_ADMIN과 같은 막강한 권한을 가지고 있다.
위험한 역할을 istio-cni가 거의 다 수행해주는 덕에 ztunnel은 상대적으로는 적은 권한을 가진다.
라곤 하지만 SYS_ADMIN을 가지고 있는 것은 똑같다.
네임스페이스에 진입하는 setns 함수는 CAP_SYS_ADMIN을 가져야 하다보니 어쩔 수 없는 부분으로 보인다.[2]
그래도 호스트패스 볼륨으로 가지는 것은 istio-cni와 통신할 때 사용하는 통로밖에 없다.
ztunnel이 열고 있는 소켓들은 무엇이 있는가?
keti -n istio-system ztunnel-fn7n4 -- ss -ntlp
설정을 받는 포트로는 위의 것들을 열어뒀다.
여기에 istio-cni와 통신하는 창구로 ztunnel 소켓 파일도 있는 것을 확인할 수 있다.
해당 파일은 istio-cni와 ztunnel이 노드 호스트패스에 배치해두고 사용한다.
ztunnel은 엔보이와 동일하게 디버깅을 위해 15000포트를 열어두고 있다.
keti -n istio-system ztunnel-qlw9h -- curl localhost:15000/config_dump
엔보이랑 비교하면 정말 선녀 같은 설정 덤프..
재밌는 점은 워크로드 설정 부분을 보면 ztunnel, istio-cni, istiod 등 그냥 클러스터에 존재하는 모든 파드들을 워크로드 리스트에 저장시켜둔다는 것.
이 중에서 프로토콜 정보만 딸깍 바꾸면 그때부터 메시 내부 트래픽이 되도록 세팅된다.
메시 정보 확인
앰비언트 모드에서도 마찬가지로 istioctl을 이용해 메시 정보를 확인할 수 있다.
다만 조금 새로운 명령어들을 써줘야만 한다.
istioctl proxy-status
istioctl ztunnel-config workload
istioctl ztunnel-config service
istioctl waypoint list
이런 식으로 말이다.
먼저 proxy status를 보면 예제로서 세운 게이트웨이 워크로드의 프록시가 잡히고, ztunnel 들이 추적된다.
여기에 대고 이전 처럼 proxy-config를 할 수 있을까?
일반적인 대상들에 대해서는 불가능하다.
애초에 proxy-config 명령어는 대상 파드에 exec 명령으로 15000포트에 config_dump를 떠오는 방식으로 동작한다.
그러니 사이드카 모드에서만 통용되던 명령어인 것이다.
그렇지만 gateway 워크로드는 여전히 엔보이로 만들어지기에 문제 없이 추적할 수 있다.
게이트웨이 추적
이 게이트웨이 리소스는 게이트웨이 API로 설정된 게이트웨이라는 점에서 차이가 있어서, 비단 앰비언트 모드이기에 발생하는 설정 간 차이가 있지는 않을 것이다.
차이라고 한다면 ztunnel이 워크로드 상태를 가지고 있기 때문에 발생하는 차이가 있을 것으로 보인다.
먼저 리스너 설정 정보를 보자.
게이트웨이 리소스로 설정된 80 포트가 열려 있고, 이외에는 그냥 connect_originate라는 클러스터로 연결된다.
게이트웨이 리소스로 열린 라우트 설정은 라우트로 확인할 수 있다.
값들이 거의 존재하지 않는다..
엔보이에 적용된 설정들은 전부 HTTPRoute 리소스의 정보만 반영돼있다.
클러스터 설정을 보면 본격적으로 재밌는 클러스터가 눈에 띈다.
HBONE 터널을 사용하는 클러스터..
해당 클러스터에 매칭되면 게이트웨이 엔드포인트로 트래픽을 넘긴다.
클러스터 내부 트래픽과 더불어 외부 트래픽을 전부 처리하기 위한 설정으로 보인다.
다음으로는 기본으로 트래픽이 흘러들어갈 클러스터였던 connect_originate를 본다.
해당 클러스터의 설정에 대해 게이트웨이는 일반적인 프록시 역할을 수행하는 것으로 보인다.
커넥트 연결을 받고 이로부터 웨이포인트의 15008 포트로, 즉 hbone으로 연결해서 트래픽을 전달하는 것으로 보인다.
앰비언트 모드 세팅
본격적으로 앰비언트 모드를 세팅하면 발생하는 일을 살펴보자.
먼저 앰비언트 ztunnel을 보면 모든 워크로드와 서비스의 정보를 이미 알고 있다.
현재는 프로토콜이 TCP로, ztunnel이 일절 트래픽에 관여하지 않고 있는 상태이다.
기본 앰비언트 적용
여기에서 메시에 들어가게 하는 것은 매우 간단하다!
kubectl label namespace default istio.io/dataplane-mode=ambient
일단 앰비언트 모드를 세팅하는 것은 너무나도 간단하다.
사이드카 모드였다면 파드를 재기동했어야 했겠지만, 앰비언트는 워크로드에 일절 영향을 주지 않는다.
설정하자마자 default 네임스페이스에 있는 파드들의 protocol이 HBONE으로 표시되는 것을 확인할 수 있다.
해당 파드들이 배치된 노드의 istio-cni 로그를 확인해보면 허겁지겁 iptables를 세팅하는 것을 확인할 수 있다.
여기에 ztunnel에게 해당 파드 받아라 하는 내용까지 로그로 담긴다.
그럼 ztunnel 로그도 한번 확인해보자.
여기에서도 어떤 파드에 설정하라 받았다, 프록시 시작한다 간결하게 출력해준다.
그리고 어떤 리스너들이 설정됐는지 로그로 남겨준다.
설정이 적용된 파드에 들어가서 iptables를 확인해보면 조작이 일어난 것을 확인할 수 있다.
참고로 pexec은 강한 권한을 가진 파드를 실행시켜서 원하는 파드의 네임스페이스에 접근해 원하는 조작을 수행하는 kubectl 플러그인이다.
나는 조금 더 정확하게 해당 컨테이너의 네임스페이스의 모든 것을 확인하고 싶어서 직접 들어가서 확인을 진행했다.
# 노드 진입 후
DEBUG_PID=$(ps -ef | grep sleep | head -n 1 | awk '{print $2}')
# pid 확인
nsenter -t $DEBUG_PID -a
디버깅용 파드에 명령어를 sleep으로 주었기 때문에 sleep을 실행하는 프로세스를 찾아 들어갔다.
리스닝 소켓 정보를 뜯어보니 ztunnel이 열어둔 포트 경로가 확인된다.
그러나 프로세스의 정보는 확인할 수 없었다.
/proc
에 들어가서 찾아보려고 해도 해당 소켓 파일의 경로를 찾기가 어려웠다.
내부 트래픽 경로는 분명하게 수정되는 동시에 워크로드는 알기 힘든 상황에 놓이게 되는 것 같다.
대충 시도해 본 것들은..
find /run /var/run /tmp /proc -type s
직접 들어가서 전부 뒤져보기 등..
생각해보면 이렇게 소켓의 정보를 확인하기 어려운 게 당연한 것 같기도 한 것이, 한 파드 내의 두 컨테이너 간 연결을 추적할 때도 결국 마찬가지의 상황에 놓인다.
두 컨테이너가 공유하는 것은 네트워크 네임스페이스 뿐이기 때문에 소켓 정보를 볼 수는 있어도 실제 파일은 찾을 수가 없는 것과 같은 것이다.
기본 gateway api 리소스 확인
2주차에도 한번 본 적 있는 리소스이지만, 앰비언트에서는 이제 필수적인 방식인 게이트웨이 api 리소스 양식을 살펴본다.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
gatewayClassName: istio
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Same
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: bookinfo
spec:
parentRefs:
- name: bookinfo-gateway
rules:
- matches:
- path:
type: Exact
value: /productpage
- path:
type: PathPrefix
value: /static
- path:
type: Exact
value: /login
- path:
type: Exact
value: /logout
- path:
type: PathPrefix
value: /api/v1/products
backendRefs:
- name: productpage
port: 9080
게이트웨이 리소스에서는 어떤 포트를 수신할 것인지 세팅하고 자신에게 걸 수 있는 라우트 리소스를 제한한다.
listeners[].hostname
필드를 설정하면 수신할 호스트 이름도 지정하는 게 가능하나, 이 예시에서는 그냥 모든 호스트를 받을 수 있도록 설정됐다.
즉 해당 게이트웨이의 ip로 들어오는 모든 80번 포트로의 요청을 받아낸다.
라우트 리소스에서는 해당 게이트웨이를 먼저 부모로 지정한다.
이후 세부 룰을 지정하고, 해당 라우트 룰을 통해 트래픽이 흐를 서비스를 지정한다.
적용된 리소스를 확인해본다.
k get gtw
k get httproute
이스티오 게이트웨이의 alias가 gw라, gtw가 약자다..(불-편)
심지어 라우트는 별칭도 없다..
아무튼 적당히 기다리다보면 해당 리소스들이 제대로 생성된다.
게이트웨이는 해당 워크로드가 제대로 준비되기 전까지 programmed가 False로 잡혀있는데 이거 생각보다 시간이 좀 걸린다.
이 다음에 E-앰비언트 ztunnel 트래픽 경로 분석을 진행했다.
웨이포인트 적용
웨이포인트는 전적으로 게이트웨이 api를 이용해 만들도록 제한되어 있다.
먼저 게이트웨이 역할을 할 워크로드를 만들고 버츄얼 서비스로 설정하는 식은 불가능하다.
게이트웨이 리소스를 만드는 방법을 매우 간단하게 지원을 해주고 있기에 안 써봤다고 해도 어려울 것은 없다.
istioctl waypoint generate --for service
istioctl waypoint apply --for service
보다시피 적용되는 설정은 이게 끝이다!
웨이포인트는 ztunnel로부터만 트래픽을 받는데 항상 HBONE 통신을 하므로 해당 부분에 대한 리스너만 설정이 되면 끝인 것이다..
그래서 사실 위와 같이 명령어의 도움을 빌리지 않고 직접 다른 이름을 가진 웨이포인트를 마음껏 만들 수 있다.
gatewayClass 이름을 istio-waypoint로 지정해주기만 하면 해당 게이트웨이로 인해 생성될 엔보이를 웨이포인트로 사용할 수 있다.
라벨 부분은 워크로드로 향하는 트래픽에 대해서도 적용할지, 서비스를 거쳐서 가는 트래픽만 적용할지 등을 나타내는 설정이다.
참고로 실제 배치되는 웨이포인트 워크로드 양식은 이렇게 된다.
그러나 웨이포인트가 배치된다고 해당 네임스페이스의 트래픽이 전부 웨이포인트를 경유하게 되는 것은 아니다.
보다시피 istioctl zc service/workload
를 찍어보면 웨이포인트 컬럼에 None이라고 적힌 것을 보면 알 수 있다.
이제 경유를 받게 하고 싶은 서비스나 워크로드를 지정하는 작업을 해야 한다.
이 작업도 어려울 것 없이, 네임스페이스나 해당 서비스에 라벨을 지정하기만 하면 된다.
kubectl label ns default istio.io/use-waypoint=waypoint
라벨로 istio.io/use-waypoint
에 만들어진 웨이포인트의 이름을 적어주기만 하면 된다!
istioctl waypoint apply
를 할 시 기본 만들어지는 게이트웨이 리소스의 이름이 waypoint라 라벨 값에 waypoint라고 적는다는 것에 유의하자.
이제 ztunnel에서는 위 서비스로 트래픽이 가야 하는 경우에 웨이포인트를 경유시킬 것이다.
json으로 뜯어보면 기본적인 서비스에 대한 정보에 더불어 웨이포인트의 경로가 명시된다.
웨이포인트 엔보이 설정 파일
이제 본격적으로 웨이포인트로 동작하는 엔보이의 설정이 어떻게 돼있는지 뜯어본다.
먼저 리스너로, 위의 게이트웨이와 마찬가지로 대상이 되는 서비스만 리스너로 받는다.
여기에 만약 각종 L7 기능을 넣게 된다면 비로소 라우트 설정이 들어가게 될 것이다.
엔보이 설정 상으로는 15008, 즉 HBONE 포트로 들어오는 트래픽에 대해 인터널 리스너를 설정한다.
이때 인터널 리스너가 INBOUND, 즉 들어오는 방향으로만 그대로 내보낸다는 것이 바로 목적지 기반 정책 제어를 하는 웨이포인트의 큰 특징이다.
참고로 설정을 더 뜯어보면 15008을 수신하는 리스너를 보면 막상 클러스터가 설정돼있다.
해당 클러스터 이름은 main_internal인데 이게 리스너 설정에 보이는 내부 리스너이다.
다시 리스너 설정으로 돌아와 main_internal 리스너를 보면 아래와 같이 여러 서비스에 대한 매칭을 걸고 있다.
기존 엔보이 설정은 내부 리스너를 설정할 때 리스너에 useOriginDst를 설정하여 내부 리스너가 사용되도록 설정했다.
그런데 여기에서는 클러스터로 내부 리스너를 등록하는 식으로 설정되는 것 같은데, 이런 식으로 설정이 가능한지는 처음 알았다.
HBONE 통신을 하며 내부 패킷을 뜯어낸 이후에야 대상이 될 리스너를 설정할 수 있기 때문에 아무래도 패킷을 복호화하는 과정이 먼저 필요할 것이다.
그래서 관련된 필터체인을 거치는 과정이 먼저 들어간 이후 트래픽을 보낼 리스너를 설정할 수 있게 되는 건데, 엔보이의 기존 내부 리스너 설정 방식에서는 지원하지 않는 방법이기 때문에 가상의 클러스터로 내부 리스너를 가리키도록 설정한 것으로 보인다.
아울러 웨이포인트 엔보이는 ztunnel에서 오는 트래픽은 15008 포트로 받지만, 다른 방식으로 들어오는 트래픽에 대해서는 connect_originate 리스너로 수신해야 한다.
이러한 트래픽도 처리하기 위해서 로직 변경이 일어난 게 아닐까 한다.
애초에 엔보이 잘알이라고 자신할 수 없기에, 최대한 드러난 현상을 이해하는데 초점을 맞췄으니 상당한 뇌피셜이란 것을 참고하자.
엔드포인트 설정을 보면 아예 scheme이 envoy로 박힌 main_internal을 확인할 수 있다.
그럼 트래픽을 실제로 보내면 어떻게 동작하는가?
keti debug -- curl productpage:9080
이렇게 보내고 나서 또다시 각 ztunnel의 로그를 확인해보자.
먼저 debug 쪽의 ztunnel 로그를 보면 waypoint로 보낸 요청이 outbound로 잡히는 것을 확인할 수 있다.
반대로 받은 측의 ztunnel에서는 waypoint로부터 inbound 요청을 받았다.
일일히 패킷을 뜨지 않았지만 웨이포인트 엔보이의 설정 정보와 ztunnel의 기본 동작 방식을 생각하면 실제 경로가 어떻게 이뤄졌는지 쉼게 짐작할 수 있다.
- 출발지 컨테이너:46684 to 출발지 ztunnel:15001
- 출발지 ztunnel:?? to 중간 웨이포인트:15008
- 중간 웨이포인트:56462 to 목적지 ztunnel:15008
- 목적지 ztunnel:?? to 목적지 컨테이너:9080
ztunnel들이 요청을 보낼 때 사용된 포트는 패킷을 뜯지 않으면 모른다.
다만 위의 로그 정보만 보더라도 이런 식으로 트래픽이 경유했을 것은 쉽게 파악할 수 있다.
키알리 확인
트래픽 경로에 대한 추적은 키알리로 마지막으로 간단하게 시각화하고 끝내고자 한다.
watch -d curl http://172.18.255.101/productpage -o /dev/null -v
기본적으로 키알리를 보게 되면 서비스 간, 그리고 내부 워크로드의 트래픽이 어떻게 흘러가는지 파악할 수 있다.
그런데 여기에서 Display 버튼에서 waypoint 프록시를 보도록 세팅하게 되면..
굉장히 어지럽게 나오기 시작한다!
서비스 기능에 맞춰 흘러가는 트래픽만 보고 싶다면 상단에서 아예 http 트래픽만 켜거나, 아니면 서비스 그래프로 보면 된다.
실제 트래픽의 흐름은 tcp로 파란색 줄로 출력되고 있는 것을 확인할 수 있다.
productpage에서 웨이포인트로 가는 tcp 트래픽 라인을 잡아보면 details와 reivews가 호스트로 추적된다.
한 가지 키알리를 보며 아쉬웠던 것은 웨이포인트의 신원을 이용해 통신을 한다는 정보를 확인할 방법이 없다는 것.
아무튼 현재 트래픽의 흐름에만 초점을 맞춰서 도식화를 해보면 다음과 같은 모양이 된다.
네임스페이스 단위로 웨이포인트를 사용하도록 설정했기 때문에 모든 트래픽이 웨이포인트를 경유하고 있는 것을 볼 수 있다.
그러나 딱 한 가지, 게이트웨이에서 productpage로 가는 요청은 웨이포인트를 거치지 않는다.
이전에 봤던 사항으로, ztunnel에서 출발하는 트래픽이 아닌 이상 웨이포인트를 거치지 않는다는 것을 여기에서 확인할 수 있는 것이다.
게이트웨이는 일반 엔보이기 때문에 ztunnel이 트래픽을 캡쳐하지 않는다.
그 결과 웨이포인트를 거치지 않고 트래픽이 productpage로 전달돼버렸다.
이후에 이스티오의 각종 설정을 넣는 실습을 E-앰비언트 모드에서 메시 기능 활용으로 넣었다.
결론
앰비언트 모드는 분명 사용법이 간단해서 가볍다는 인상을 받았다.
그러나 동시에 앰비언트 모드는 기존 모드와의 호환성을 위해서 많은 부분에서 엄격함을 포기한 것 같은 생각도 계속 든다.
당장 정책 관련 리소스에 targetRef
를 설정해야 한다던가 하는 부분도 그렇다.
그리고 웨이포인트의 설정은 웨이포인트를 경유해야만 적용되는데 사실 이를 경유하기 위한 조건이 은근히 까다롭다.
사이드카 프록시, 게이트웨이에서 출발하는 트래픽을
앰비언트는 적응하기 전까지 굉장한 휴먼 에러를 발생시킬 것이라고 생각한다.
이러한 부분들은 차차 개선되어갈지 모르겠다.
관련 문서
지식 문서, EXPLAIN
이름3 | is-folder | 생성 일자 |
---|---|---|
E-앰비언트 모드에서 메시 기능 활용 | false | 2025-06-07 20:56 |
E-앰비언트 ztunnel 트래픽 경로 분석 | false | 2025-06-07 20:36 |
앰비언트 모드 | false | 2025-06-02 14:51 |
기타 문서
Z0-연관 knowledge, Z1-트러블슈팅 Z2-디자인,설계, Z3-임시, Z5-프로젝트,아카이브, Z8,9-미분류,미완이름4 | 코드 | 타입 | 생성 일자 |
---|---|---|---|
I-ztunnel이 다른 네임스페이스에서 요청 보내는 코드 분석 | Z1 | topic/idea | 2025-06-07 20:44 |
I-다른 네임스페이스 같은 포트 리스닝 서버 구현 | Z1 | topic/idea | 2025-06-07 19:39 |
9W - 앰비언트 모드 구조, 원리 | Z8 | published | 2025-06-07 19:17 |
9W - 앰비언트 헬름 설치, 각종 리소스 실습 | Z8 | published | 2025-06-07 19:27 |