Ssoon

1주차 : Istio 첫걸음 (7) - Traffic Routing 본문

Istio Hands-on Study [1기]

1주차 : Istio 첫걸음 (7) - Traffic Routing

구구달스 2025. 4. 12. 20:21
CloudNet@ 가시다님이 진행하는 Istio Hands-on Study [1기]

 Istio Traffic Routing

Istio를 사용하면 서비스 간 요청을 세밀하게 제어할 수 있어요.
즉, "어떤 요청이 어떤 서비스 버전으로 갈지"를 정밀하게 조절할 수 있는 기능입니다.

💡 Istio로 가능한 것

  • 배포(Deploy)와 릴리스(Release)를 분리해서 안정적으로 운영 가능
  • 트래픽을 사용자 그룹별로 분리해서 라우팅 가능
  • 예: 내부 직원만 v2 사용, 일반 사용자는 계속 v1 사용
  • 트래픽 점진 릴리스, 카나리 배포 등 다양한 전략 지원

🧰 사용하는 Istio 리소스

  • DestinationRule: 서비스의 버전을 구분 (v1, v2 등)
  • VirtualService: 요청 조건에 따라 어떤 버전으로 라우팅할지 설정
Istio는 서비스 버전별로 트래픽을 정밀하게 나누어 안정적으로 새로운 기능을 배포할 수 있게 도와줍니다.

✅ 실습

💠 catalog 애플리케이션의 새 버전(v2)을 배포

  • catalog-v2라는 이름으로, catalog 앱의 버전 2를 1개의 파드로 실행합니다.
  • 파드는 istioinaction/catalog:latest 이미지를 사용하고, 3000번 포트에서 HTTP 요청을 받습니다.
  • 환경 변수로 네임스페이스(KUBERNETES_NAMESPACE)와 이미지 표시 설정(SHOW_IMAGE=true)을 전달합니다.
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-UQRJB87:~/istio-in-action/book-source-code-master$ cat <<EOF | kubectl -n istioinaction apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: catalog
    version: v2
  name: catalog-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: catalog
      version: v2
  template:
    metadata:
      labels:
        app: catalog
        version: v2
    spec:
      containers:
      - env:
        - name: KUBERNETES_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: SHOW_IMAGE
          value: "true"
        image: istioinaction/catalog:latest
        imagePullPolicy: IfNotPresent
        name: catalog
        ports:
        - containerPort: 3000
          name: http
          protocol: TCP
        securityContext:
          privileged: false
EOF

💠 istioinaction 네임스페이스의 쿠버네티스 리소스(Deployment, Pod, Service, Endpoints)

  • Deployment: catalog(v1), catalog-v2, webapp이 각각 1개 파드로 실행 중.
  • Pod: catalog, catalog-v2, webapp 파드가 정상 실행 중(각각 2개 컨테이너).
  • Service: catalog와 webapp이 내부 IP로 요청을 받음(80번 포트).
  • Endpoints: catalog은 두 개의 IP:포트, webapp은 한 개의 IP:포트로 연결됨.
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-UQRJB87:~/istio-in-action/book-source-code-master$ kubectl get deploy,pod,svc,ep -n istioinaction
NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/catalog      1/1     1            1           3h13m
deployment.apps/catalog-v2   1/1     1            1           8s
deployment.apps/webapp       1/1     1            1           3h13m

NAME                              READY   STATUS    RESTARTS   AGE
pod/catalog-6cf4b97d-5p442        2/2     Running   0          3h13m
pod/catalog-v2-6df885b555-tpkq2   2/2     Running   0          8s
pod/webapp-7685bcb84-mcmxv        2/2     Running   0          3h13m

NAME              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/catalog   ClusterIP   10.200.1.172   <none>        80/TCP    3h13m
service/webapp    ClusterIP   10.200.1.145   <none>        80/TCP    3h13m

NAME                ENDPOINTS                         AGE
endpoints/catalog   10.10.0.11:3000,10.10.0.14:3000   3h13m
endpoints/webapp    10.10.0.12:8080                   3h13m

💠 istioinaction 네임스페이스의 Istio Gateway와 VirtualService 리소스

  • Gateway: outfitters-gateway가 외부 트래픽을 처리
  • VirtualService:
    • catalog: catalog 서비스 트래픽 관리
    • webapp-virtualservice: 모든 호스트(*)를 outfitters-gateway로 처리
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-UQRJB87:~/istio-in-action/book-source-code-master$ kubectl get gw,vs -n istioinaction
NAME                                             AGE
gateway.networking.istio.io/outfitters-gateway   160m

NAME                                                       GATEWAYS                 HOSTS         AGE
virtualservice.networking.istio.io/catalog                                          ["catalog"]   52m
virtualservice.networking.istio.io/webapp-virtualservice   ["outfitters-gateway"]   ["*"]         160m

 

💠 DestinationRule을 istioinaction 네임스페이스에 적용해 catalog 서비스의 트래픽을 버전별로 관리하도록 설정

  • catalog 서비스를 대상으로, 두 개의 서브셋을 정의:
    • version-v1: version: v1 레이블이 붙은 파드.
    • version-v2: version: v2 레이블이 붙은 파드.
  • 이 설정은 Istio가 catalog 서비스의 v1v2 버전을 구분해 트래픽을 분배
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-UQRJB87:~/istio-in-action/book-source-code-master$ cat <<EOF | kubectl -n istioinaction apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: catalog
spec:
  host: catalog
  subsets:
  - name: version-v1
    labels:
      version: v1
  - name: version-v2
    labels:
      version: v2
EOF
destinationrule.networking.istio.io/catalog created

💠 Istio의 Gateway, VirtualService, DestinationRule 리소스를 확인

  • Gateway: outfitters-gateway가 외부 트래픽을 처리
  • VirtualService:
    • catalog: catalog 서비스 트래픽 관리
    • webapp-virtualservice: 모든 호스트(*)를 outfitters-gateway로 처리 
  • DestinationRule: catalog 서비스의 트래픽을 버전별로 구분
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-UQRJB87:~/istio-in-action/book-source-code-master$ kubectl get gw,vs,dr -n istioinaction
NAME                                             AGE
gateway.networking.istio.io/outfitters-gateway   166m

NAME                                                       GATEWAYS                 HOSTS         AGE
virtualservice.networking.istio.io/catalog                                          ["catalog"]   58m
virtualservice.networking.istio.io/webapp-virtualservice   ["outfitters-gateway"]   ["*"]         166m

NAME                                          HOST      AGE
destinationrule.networking.istio.io/catalog   catalog   13s

💠 VirtualService를 istioinaction 네임스페이스에 적용해 catalog 서비스의 HTTP 트래픽을 version-v1 서브셋으로만 라우팅하도록 설정

  • catalog 서비스로 오는 모든 요청을 version: v1 레이블이 붙은 파드(v1 버전)로 보냅니다.
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-UQRJB87:~/istio-in-action/book-source-code-master$ cat <<EOF | kubectl -n istioinaction apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: catalog
spec:
  hosts:
  - catalog
  http:
  - route:
    - destination:
        host: catalog
        subset: version-v1
EOF
virtualservice.networking.istio.io/catalog configured
  • 1초마다 http://127.0.0.1:30000/api/catalog에 요청을 보내 상품 목록을 JSON으로 출력하고, 현재 시간을 표시
while true; do curl -s http://127.0.0.1:30000/api/catalog | jq; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; echo; done
  • v1 접속 확인

💠 VirtualService를 istioinaction 네임스페이스에 적용해 catalog 서비스의 HTTP 트래픽을 조건에 따라 라우팅

  • 요청에 x-dark-launch: v2 헤더가 있으면 version-v2 서브셋(v2 파드)으로 보냅니다.
  • 그 외의 경우는 version-v1 서브셋(v1 파드)으로 보냅니다.
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-UQRJB87:~/istio-in-action/book-source-code-master$ cat <<EOF | kubectl -n istioinaction apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: catalog
spec:
  hosts:
  - catalog
  http:
  - match:
    - headers:
        x-dark-launch:
          exact: "v2"
    route:
    - destination:
        host: catalog
        subset: version-v2
  - route:
    - destination:
        host: catalog
        subset: version-v1
EOF
virtualservice.networking.istio.io/catalog configured

💠 Istio의 Gateway, VirtualService, DestinationRule 리소스를 확인

  • Gateway: outfitters-gateway가 외부 트래픽을 받음
  • VirtualService:
    • catalog: catalog 서비스로 트래픽을 관리
    • webapp-virtualservice: 모든 호스트(*)를 outfitters-gateway로 처리 
  • DestinationRule: catalog 서비스의 트래픽을 버전별로 구분
(⎈|kind-myk8s:N/A) ssoon@DESKTOP-UQRJB87:~/istio-in-action/book-source-code-master$ kubectl get gw,vs,dr -n istioinaction
NAME                                             AGE
gateway.networking.istio.io/outfitters-gateway   172m

NAME                                                       GATEWAYS                 HOSTS         AGE
virtualservice.networking.istio.io/catalog                                          ["catalog"]   64m
virtualservice.networking.istio.io/webapp-virtualservice   ["outfitters-gateway"]   ["*"]         172m

NAME                                          HOST      AGE
destinationrule.networking.istio.io/catalog   catalog   6m42s
  • v1 접속 확인
while true; do curl -s http://127.0.0.1:30000/api/catalog | jq; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; echo; done

  • v2 접속 확인
while true; do curl -s http://127.0.0.1:30000/api/catalog -H "x-dark-launch: v2" | jq; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; echo; done

💠 실습 완료 후 삭제

(⎈|kind-myk8s:N/A) ssoon@DESKTOP-UQRJB87:~/istio-in-action/book-source-code-master$ kubectl delete deploy,svc,gw,vs,dr --all -n istioinaction && kind delete cluster --name myk8s
deployment.apps "catalog" deleted
deployment.apps "catalog-v2" deleted
deployment.apps "webapp" deleted
service "catalog" deleted
service "webapp" deleted
gateway.networking.istio.io "outfitters-gateway" deleted
virtualservice.networking.istio.io "catalog" deleted
virtualservice.networking.istio.io "webapp-virtualservice" deleted
destinationrule.networking.istio.io "catalog" deleted
Deleting cluster "myk8s" ...
Deleted nodes: ["myk8s-control-plane"]
Comments