내 마음대로 네트워크 시리즈 - 8

김경준·2026년 1월 1일

네트워크

목록 보기
8/8
post-thumbnail

개요

원래라면 AWS EKS에 istio를 설치하고 테스트를 바로 진행하려고 했는데, 로컬에서 테스트하며 정리를 해야할 것 같아서
kind로 생성한 로컬 클러스터에 istio를 설치하고 간단히 동작을 테스트 해보자

참고자료

  • 소스코드는 13디렉토리를 참고

kind로 테스트 진행

kind로 클러스터 생성

먼저 아래 yaml 파일을 작성한다. 로컬에서 접근할 것이기 때문에 control plane 노드에 30800 포트를 명시해준다. 이 포트를 이용해 server로 접근할 수 있다.

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  image: kindest/node:v1.33.4
  extraPortMappings:
  # containerPort는 Kind 노드(컨테이너)의 포트
  # 이 포트는 Service의 nodePort와 일치
  - containerPort: 30800
    # hostPort는 로컬 머신(PC)의 포트
    hostPort: 30800
    protocol: TCP
- role: worker
  image: kindest/node:v1.33.4
  labels:
    role: server
- role: worker
  image: kindest/node:v1.33.4
  labels:
    role: istiod
- role: worker
  image: kindest/node:v1.33.4
  labels:
    role: istio-gateway
- role: worker
  image: kindest/node:v1.33.4
  labels:
    role: istio-gateway

클러스터를 생성한다

kind create cluster --name 1-33 --config cluster.yaml

istio 설치

13/helm 디렉토리에서 helmfile을 이용해 설치한다.
먼저 base를 설치한다.

helmfile sync --selector name=istio-base

다음으로 istiod를 설치한다. nodeSelector에 role=istiod를 명시했다.

helmfile sync --selector name=istio-istiod

다음으로 ingress gateway를 설치한다. 서비스 타입은 NodePort이고 nodeSelector와 affinity를 이용해, 서로 다른 노드에 스케줄링 되도록 했다. (각 노드에 1개씩)

helmfile sync --selector name=istio-gateway

server 파드 배포

server namespace에 배포한다.

kubectl create ns server
kubectl -n server apply -f server.yaml

kube sniff로 트래픽 확인

먼저 server, ingress gateway 이름을 변수로 저장한다.

export SERVER=$(kubectl get pod -n server | grep server | awk '{print $1}')

read GATEWAY1 GATEWAY2 <<< $(kubectl get pods -n istio-system -l istio=gateway -o jsonpath='{.items[*].metadata.name}')
export GATEWAY1 GATEWAY2

sniff로 8000포트 트래픽 기록을 시작한다. 각 파드마다 별도의 터미널에서 실행

kubectl sniff $SERVER -n server -f 'port 8000' --image ghcr.io/nefelim4ag/ksniff-helper:v4 --tcpdump-image ghcr.io/nefelim4ag/tcpdump:latest
kubectl sniff $GATEWAY1 -n istio-system -p -f 'port 8000' --image ghcr.io/nefelim4ag/ksniff-helper:v4 --tcpdump-image ghcr.io/nefelim4ag/tcpdump:latest
kubectl sniff $GATEWAY2 -n istio-system -p -f 'port 8000' --image ghcr.io/nefelim4ag/ksniff-helper:v4 --tcpdump-image ghcr.io/nefelim4ag/tcpdump:latest

로컬에서 python을 이용해 트래픽을 보낸다.

PORT=30800 ENDPOINT="/index" python ./client.py 10

istio ingress gateway 2개 중 1개에만 8000번 포트 트래픽을 확인할 수 있다.

아래는 server 파드의 트래픽이다

istio-system 네임스페이스의 파드 ip 확인 - 10.244.1.5

kubectl get pod -owide -n istio-system          
NAME                             READY   STATUS    RESTARTS   AGE     IP            NODE           NOMINATED NODE   READINESS GATES
istio-gateway-778cbb66c7-l65jd   1/1     Running   0          4h24m   10.244.4.7    1-33-worker3   <none>           <none>
istio-gateway-778cbb66c7-vwr4m   1/1     Running   0          4h24m   10.244.1.5    1-33-worker4   <none>           <none>
istiod-5764bfc-t25wc             1/1     Running   0          4h24m   10.244.3.3    1-33-worker2   <none>           <none>

server 파드의 ip 확인 - 10.244.2.2

kubectl get pod -owide -n server      
NAME                     READY   STATUS    RESTARTS   AGE     IP           NODE          NOMINATED NODE   READINESS GATES
ksniff-9kfzh             1/1     Running   0          40m     10.244.2.3   1-33-worker   <none>           <none>
server-66c6967c6-kjjz5   1/1     Running   0          4h20m   10.244.2.2   1-33-worker   <none>           <none>

docker로 구동중인 kind 클러스터의 노드 ip 확인 172.18.0.6

docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -q)
/1-33-worker - 172.18.0.5
/1-33-worker4 - 172.18.0.4
/1-33-worker2 - 172.18.0.3
/1-33-worker3 - 172.18.0.2
/1-33-control-plane - 172.18.0.6

client.py를 다시 실행하고 각 파드별로 소켓 연결 상태를 확인하면

// server
root@server-66c6967c6-kjjz5:/app# netstat -antp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      1/python3.13        
tcp        0      0 10.244.2.2:8000         10.244.1.5:56740        ESTABLISHED 11/python3.13

// istio gateway
istio-proxy@istio-gateway-778cbb66c7-vwr4m:/$ netstat -antp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:15090           0.0.0.0:*               LISTEN      17/envoy            
tcp        0      0 0.0.0.0:15090           0.0.0.0:*               LISTEN      17/envoy            
tcp        0      0 0.0.0.0:15021           0.0.0.0:*               LISTEN      17/envoy            
tcp        0      0 0.0.0.0:15021           0.0.0.0:*               LISTEN      17/envoy            
tcp        0      0 127.0.0.1:15000         0.0.0.0:*               LISTEN      17/envoy            
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      17/envoy            
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      17/envoy            
tcp        0      0 10.244.1.5:15021        10.244.1.1:54452        TIME_WAIT   -                   
tcp        0      0 10.244.1.5:15021        10.244.1.1:46966        TIME_WAIT   -                   
tcp        0      0 10.244.1.5:52162        10.96.225.207:15012     ESTABLISHED 1/pilot-agent       
tcp        0      0 10.244.1.5:15021        10.244.1.1:50410        TIME_WAIT   -                   
tcp        0      0 10.244.1.5:15021        10.244.1.1:59786        TIME_WAIT   -                   
tcp        0      0 127.0.0.1:48208         127.0.0.1:15020         ESTABLISHED 17/envoy            
tcp        0      0 10.244.1.5:15021        10.244.1.1:33434        TIME_WAIT   -                   
tcp        0      0 10.244.1.5:80           172.18.0.6:3609         ESTABLISHED 17/envoy            
tcp        0      0 127.0.0.1:53688         127.0.0.1:15020         ESTABLISHED 17/envoy            
tcp        0      0 10.244.1.5:56740        10.244.2.2:8000         ESTABLISHED 17/envoy            
tcp6       0      0 :::15020                :::*                    LISTEN      1/pilot-agent       
tcp6       0      0 127.0.0.1:15020         127.0.0.1:48208         ESTABLISHED 1/pilot-agent       
tcp6       0      0 127.0.0.1:15020         127.0.0.1:53688         ESTABLISHED 1/pilot-agent 

연결상태를 정리하면 아래와 같다.
localhost:30800 -> control-plane node(172.18.0.6:3609)
control-plane node(172.18.0.6:3609) -> istio gateway(10.244.1.5:80)
istio gateway(10.244.1.5:56740) -> server(10.244.2.2:8000)

이렇게 연결되어 있는 상태에서, istio gateway를 삭제해보자

kubectl delete pod istio-gateway-778cbb66c7-vwr4m

client 로그는 아래와 같이 삭제 직후 요청이 실패하는 걸 확인할 수 있다.

--- Waiting for 10 seconds... ---
--- Sending keep-alive request #149 (GET /index) ---
--- Received response #149 ---
HTTP/1.1 200 OK

--- Waiting for 10 seconds... ---
--- Sending keep-alive request #150 (GET /index) ---
--- Received response #150 ---
HTTP/1.1 200 OK

--- Waiting for 10 seconds... ---
--- Sending keep-alive request #151 (GET /index) ---

*** TEST FAILED: Server closed connection (recv() returned 0 bytes) ***

*** TEST FAILED: Connection was reset by peer! ***
Error (Code: 54): Connection closed by peer

Socket closed.

패킷을 확인해보면 아래와 같다

  • istio gateway
  • server

client에서는 현재 graceful하게 종료를 하지 않아서 에러가 발생하지만 istio ingress gateway와 server에서는 FIN 패킷으로 정상 종료된 것을 확인할 수 있다.

요약 및 정리

로컬에서 테스트했을 때, client와 연결된 istio gateway 파드가 client <-> server 사이의 요청을 중개해주는 걸 확인할 수 있다.

istio gateway가 여러 개가 존재해도, 이미 연결되어 있는 client의 경우 연결 에러가 발생할 수 있다. 그래서 keep-alive 연결을 사용하는 client의 경우 retry 로직이 필요하다.

istio에서는 preStop, terminationDrainDuration를 활용할 수 있지만 이 또한 이미 연결된 client에서 retry를 해주는 게 바람직할 것 같다.

profile
DevOps로 일하고 있습니다

0개의 댓글