새소식

인기 검색어

Service_Mesh/Istio

[Istio-2주차] Ingress Gateway, Virtual Service (실습)

  • -

Istio gateways 와 Virtual Service 실습

  • Gateway(L4/L5) , VirtualService(L7)
  • Gateway를 통한 액세스: 클러스터 진입 지점 정의 - 외부 트래픽 수용
  • VirtualService 를 통한 내부 라우팅: 인입 트래픽을 클러스터 내 서비스(배포)라우팅
  • 보안: 인입 트래픽 보호 (HTTPS, x.509)

 

 

1. Istio Ingress Gateway 구조 이해와 기동 확인

Istio에서는 Ingress Gateway를 통해 외부에서 클러스터로 유입되는 트래픽을 수용한다. (Envoy를 통해 구성됨)

 

 

  • 실습 환경 재구성
# 제공 예제 파일 clone
git clone https://github.com/AcornPublishing/istio-in-action
cd istio-in-action/book-source-code-master
pwd # 각자 자신의 pwd 경로
code .

# 아래 extramounts 생략 시, myk8s-control-plane 컨테이너 sh/bash 진입 후 직접 git clone 가능
kind create cluster --name myk8s --image kindest/node:v1.23.17 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30000 # Sample Application (istio-ingrssgateway) HTTP
    hostPort: 30000
  - containerPort: 30001 # Prometheus
    hostPort: 30001
  - containerPort: 30002 # Grafana
    hostPort: 30002
  - containerPort: 30003 # Kiali
    hostPort: 30003
  - containerPort: 30004 # Tracing
    hostPort: 30004
  - containerPort: 30005 # Sample Application (istio-ingrssgateway) HTTPS
    hostPort: 30005
  - containerPort: 30006 # TCP Route
    hostPort: 30006
  - containerPort: 30007 # New Gateway 
    hostPort: 30007
  extraMounts: # 해당 부분 생략 가능
  - hostPath: /root/istio_gasida/istio-in-action/book-source-code-master # 각자 자신의 pwd 경로로 설정
    containerPath: /istiobook
networking:
  podSubnet: 10.10.0.0/16
  serviceSubnet: 10.200.1.0/24
EOF

# 설치 확인
docker ps

# 노드에 기본 툴 설치
docker exec -it myk8s-control-plane sh -c 'apt update && apt install tree psmisc lsof wget bridge-utils net-tools dnsutils tcpdump ngrep iputils-ping git vim -y'

# (옵션) metrics-server
helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
helm install metrics-server metrics-server/metrics-server --set 'args[0]=--kubelet-insecure-tls' -n kube-system
kubectl get all -n kube-system -l app.kubernetes.io/instance=metrics-server
# myk8s-control-plane 진입 후 설치 진행
docker exec -it myk8s-control-plane bash
-----------------------------------
# (옵션) 코드 파일들 마운트 확인
tree /istiobook/ -L 1
혹은
git clone ... /istiobook # 마운트 안한 경우

# istioctl 설치
export ISTIOV=1.17.8
echo 'export ISTIOV=1.17.8' >> /root/.bashrc

curl -s -L https://istio.io/downloadIstio | ISTIO_VERSION=$ISTIOV sh -
cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl
istioctl version --remote=false

# default 프로파일 컨트롤 플레인 배포
istioctl install --set profile=default -y

# 설치 확인 : istiod, istio-ingressgateway, crd 등
kubectl get istiooperators -n istio-system -o yaml
kubectl get all,svc,ep,sa,cm,secret,pdb -n istio-system
kubectl get cm -n istio-system istio -o yaml
kubectl get crd | grep istio.io | sort

# 보조 도구 설치
kubectl apply -f istio-$ISTIOV/samples/addons
kubectl get pod -n istio-system

# 빠져나오기
exit
-----------------------------------

# 실습을 위한 네임스페이스 설정
kubectl create ns istioinaction
kubectl label namespace istioinaction istio-injection=enabled
kubectl get ns --show-labels

# istio-ingressgateway 서비스 : NodePort 변경 및 nodeport 지정 변경 , externalTrafficPolicy 설정 (ClientIP 수집)
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec": {"type": "NodePort", "ports": [{"port": 80, "targetPort": 8080, "nodePort": 30000}]}}'
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec": {"type": "NodePort", "ports": [{"port": 443, "targetPort": 8443, "nodePort": 30005}]}}'
kubectl patch svc -n istio-system istio-ingressgateway -p '{"spec":{"externalTrafficPolicy": "Local"}}'
kubectl describe svc -n istio-system istio-ingressgateway

# NodePort 변경 및 nodeport 30001~30003으로 변경 : prometheus(30001), grafana(30002), kiali(30003), tracing(30004)
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}]}}'

# Prometheus 접속 : envoy, istio 메트릭 확인
open http://127.0.0.1:30001

# Grafana 접속
open http://127.0.0.1:30002

# Kiali 접속 1 : NodePort
open http://127.0.0.1:30003

# (옵션) Kiali 접속 2 : Port forward
kubectl port-forward deployment/kiali -n istio-system 20001:20001 &
open http://127.0.0.1:20001

# tracing 접속 : 예거 트레이싱 대시보드
open http://127.0.0.1:30004


# 접속 테스트용 netshoot 파드 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: netshoot
spec:
  containers:
  - name: netshoot
    image: nicolaka/netshoot
    command: ["tail"]
    args: ["-f", "/dev/null"]
  terminationGracePeriodSeconds: 0
EOF

 

  • istio 에서 ingressgateway 동작 확인
kubectl get pod -n istio-system -l app=istio-ingressgateway

Running 상태로 1/1 컨테이너 기동을 확인

 

proxy 상태 확인

docker exec -it myk8s-control-plane istioctl proxy-status

 

 

proxy 설정 확인

# proxy 설정 확인
docker exec -it myk8s-control-plane istioctl proxy-config all deploy/istio-ingressgateway.istio-system
docker exec -it myk8s-control-plane istioctl proxy-config listener deploy/istio-ingressgateway.istio-system
ADDRESS PORT  MATCH DESTINATION
0.0.0.0 15021 ALL   Inline Route: /healthz/ready*
0.0.0.0 15090 ALL   Inline Route: /stats/prometheus*

docker exec -it myk8s-control-plane istioctl proxy-config routes deploy/istio-ingressgateway.istio-system
NAME     DOMAINS     MATCH                  VIRTUAL SERVICE
         *           /stats/prometheus*
         *           /healthz/ready*
         
docker exec -it myk8s-control-plane istioctl proxy-config cluster deploy/istio-ingressgateway.istio-system
docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy/istio-ingressgateway.istio-system
docker exec -it myk8s-control-plane istioctl proxy-config log deploy/istio-ingressgateway.istio-system
docker exec -it myk8s-control-plane istioctl proxy-config secret deploy/istio-ingressgateway.istio-system

# 설정 참고
kubectl get istiooperators -n istio-system -o yaml

 

 

kubectl exec -n istio-system deploy/istio-ingressgateway -- ps aux

 

 

kubectl exec -n istio-system deploy/istio-ingressgateway -- whoami
kubectl exec -n istio-system deploy/istio-ingressgateway -- id


이때 pilot-agent, envoy 프로세스가 정상 기동되고 있었고, 사용자 ID는 istio-proxy로 확인

2. Gateway 리소스 생성 및 적용

Ingress Gateway가 트래픽을 수용하도록 하기 위해서는 Gateway 리소스를 정의해야 한다.

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: coolstore-gateway  # (1) 게이트웨이 이름
spec:
  selector:
    istio: ingressgateway  # (2) 어느 게이트웨이 구현체인가?
  servers:
  - port:
      number: 80          # (3) 노출할 포트
      name: http
      protocol: HTTP
    hosts:
    - "webapp.istioinaction.io" # (4) 이 포트의 호스트

이 게이트웨이 리소스 설정은 webapp.istioinaction.io 호스트에 대해 80번 포트를 리스닝하도록 envoy를 설정한다.

 

리소스 생성 후 확인

# 신규터미널 : istiod 로그
kubectl stern -n istio-system -l app=istiod
istiod-7df6ffc78d-w9szx discovery 2025-04-13T04:50:04.531700Z	info	ads	Push debounce stable[20] 1 for config Gateway/istioinaction/coolstore-gateway: 100.4665ms since last change, 100.466166ms since last push, full=true
istiod-7df6ffc78d-w9szx discovery 2025-04-13T04:50:04.532520Z	info	ads	XDS: Pushing:2025-04-13T04:50:04Z/14 Services:12 ConnectedEndpoints:1 Version:2025-04-13T04:50:04Z/14
istiod-7df6ffc78d-w9szx discovery 2025-04-13T04:50:04.537272Z	info	ads	LDS: PUSH for node:istio-ingressgateway-996bc6bb6-p6k79.istio-system resources:1 size:2.2kB
istiod-7df6ffc78d-w9szx discovery 2025-04-13T04:50:04.545298Z	warn	constructed http route config for route http.8080 on port 80 with no vhosts; Setting up a default 404 vhost
istiod-7df6ffc78d-w9szx discovery 2025-04-13T04:50:04.545584Z	info	ads	RDS: PUSH request for node:istio-ingressgateway-996bc6bb6-p6k79.istio-system resources:1 size:34B cached:0/0

# 터미널2
cat ch4/coolstore-gw.yaml
kubectl -n istioinaction apply -f ch4/coolstore-gw.yaml

# 확인
kubectl get gw,vs -n istioinaction
NAME                                            AGE
gateway.networking.istio.io/coolstore-gateway   26m

#
docker exec -it myk8s-control-plane istioctl proxy-status
NAME                                                  CLUSTER        CDS        LDS        EDS        RDS        ECDS         ISTIOD                      VERSION
istio-ingressgateway-996bc6bb6-p6k79.istio-system     Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-w9szx     1.17.8

docker exec -it myk8s-control-plane istioctl proxy-config listener deploy/istio-ingressgateway.istio-system
ADDRESS PORT  MATCH DESTINATION
0.0.0.0 8080  ALL   Route: http.8080
...

docker exec -it myk8s-control-plane istioctl proxy-config routes deploy/istio-ingressgateway.istio-system
NAME          DOMAINS     MATCH                  VIRTUAL SERVICE
http.8080     *           /*                     404
...     

# http.8080 정보의 의미는? 그외 나머지 포트의 역할은?
kubectl get svc -n istio-system istio-ingressgateway -o jsonpath="{.spec.ports}" | jq
[
  {
    "name": "status-port",
    "nodePort": 31674,
    "port": 15021,
    "protocol": "TCP",
    "targetPort": 15021
  },
  {
    "name": "http2",
    "nodePort": 30000, # 순서1
    "port": 80,        
    "protocol": "TCP",
    "targetPort": 8080 # 순서2
  },
  {
    "name": "https",
    "nodePort": 30005,
    "port": 443,
    "protocol": "TCP",
    "targetPort": 8443
  }
]

# HTTP 포트(80)을 올바르게 노출했다. VirtualService 는 아직 아무것도 없다.
docker exec -it myk8s-control-plane istioctl proxy-config routes deploy/istio-ingressgateway.istio-system -o json
docker exec -it myk8s-control-plane istioctl proxy-config routes deploy/istio-ingressgateway.istio-system -o json --name http.8080
[
    {
        "name": "http.8080",
        "virtualHosts": [
            {
                "name": "blackhole:80",
                "domains": [
                    "*"
                ]
            }
        ],
        "validateClusters": false,
        "ignorePortInHostMatching": true
    }
]

Virtual Service가 미적용되어 404 확인됨
포트 라우트 확인

적용 직후, Envoy에 라우트 정보가 반영되며 블랙홀 라우트 상태가 확인되었다.

3. VirtualService 리소스를 통한 라우팅 설정

Gateway만으로는 외부 트래픽이 목적지까지 도달할 수 없다. 트래픽의 목적지를 명시하는 VirtualService 리소스를 추가해야 한다.

  • VirtualService 리소스는 클라이언트가 특정 서비스와 통신하는 방법을 정의
    • FQDN, 사용 가능한 서비스 버전, 기타 라우팅 속성(재시도, 요청 타임아웃 등)
  • 가상 호스트 webapp.istioinaction.io 로 향하는 트래픽을 서비스 메시 내에 배포된 서비스로 라우팅
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: webapp-vs-from-gw
spec:
  hosts:
  - "webapp.istioinaction.io"
  gateways:
  - coolstore-gateway
  http:
  - route:
    - destination:
        host: webapp
        port:
          number: 80

 

리소스 생성 및 확인

# 신규터미널 : istiod 로그
kubectl stern -n istio-system -l app=istiod
istiod-7df6ffc78d-w9szx discovery 2025-04-13T05:15:16.485143Z	info	ads	Push debounce stable[21] 1 for config VirtualService/istioinaction/webapp-vs-from-gw: 102.17225ms since last change, 102.172083ms since last push, full=true
istiod-7df6ffc78d-w9szx discovery 2025-04-13T05:15:16.485918Z	info	ads	XDS: Pushing:2025-04-13T05:15:16Z/15 Services:12 ConnectedEndpoints:1 Version:2025-04-13T05:15:16Z/15
istiod-7df6ffc78d-w9szx discovery 2025-04-13T05:15:16.487330Z	info	ads	CDS: PUSH for node:istio-ingressgateway-996bc6bb6-p6k79.istio-system resources:23 size:22.9kB cached:22/22
istiod-7df6ffc78d-w9szx discovery 2025-04-13T05:15:16.488346Z	info	ads	LDS: PUSH for node:istio-ingressgateway-996bc6bb6-p6k79.istio-system resources:1 size:2.2kB
istiod-7df6ffc78d-w9szx discovery 2025-04-13T05:15:16.489937Z	info	ads	RDS: PUSH for node:istio-ingressgateway-996bc6bb6-p6k79.istio-system resources:1 size:538B cached:0/0


#
cat ch4/coolstore-vs.yaml
kubectl apply -n istioinaction -f ch4/coolstore-vs.yaml

# 확인
kubectl get gw,vs -n istioinaction
NAME                                            AGE
gateway.networking.istio.io/coolstore-gateway   26m

NAME                                                   GATEWAYS                HOSTS                         AGE
virtualservice.networking.istio.io/webapp-vs-from-gw   ["coolstore-gateway"]   ["webapp.istioinaction.io"]   49s

#
docker exec -it myk8s-control-plane istioctl proxy-status
NAME                                                  CLUSTER        CDS        LDS        EDS        RDS        ECDS         ISTIOD                      VERSION
istio-ingressgateway-996bc6bb6-p6k79.istio-system     Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-w9szx     1.17.8

docker exec -it myk8s-control-plane istioctl proxy-config listener deploy/istio-ingressgateway.istio-system
docker exec -it myk8s-control-plane istioctl proxy-config routes deploy/istio-ingressgateway.istio-system
NAME          DOMAINS     MATCH                  VIRTUAL SERVICE
http.8080     webapp.istioinaction.io     /*                     webapp-vs-from-gw.istioinaction
...     

docker exec -it myk8s-control-plane istioctl proxy-config routes deploy/istio-ingressgateway.istio-system -o json --name http.8080
[
    {
        "name": "http.8080",
        "virtualHosts": [
            {
                "name": "webapp.istioinaction.io:80",
                "domains": [
                    "webapp.istioinaction.io" #1 비교할 도메인
                ],
                "routes": [
                    {
                        "match": {
                            "prefix": "/"
                        },
                        "route": { #2 라우팅 할 곳
                            "cluster": "outbound|80||webapp.istioinaction.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                "retryOn": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
                                "numRetries": 2,
                                "retryHostPredicate": [
                                    {
                                        "name": "envoy.retry_host_predicates.previous_hosts",
                                        "typedConfig": {
                                            "@type": "type.googleapis.com/envoy.extensions.retry.host.previous_hosts.v3.PreviousHostsPredicate"
                                        }
                                    }
                                ],
                                "hostSelectionRetryMaxAttempts": "5",
                                "retriableStatusCodes": [
                                    503
                                ]
                            },
                            "maxGrpcTimeout": "0s"
                        },
                        "metadata": {
                            "filterMetadata": {
                                "istio": {
                                    "config": "/apis/networking.istio.io/v1alpha3/namespaces/istioinaction/virtual-service/webapp-vs-from-gw"
                                }
                            }
                        },
                        "decorator": {
                            "operation": "webapp.istioinaction.svc.cluster.local:80/*"
                        }
                    }
                ],
                "includeRequestAttemptCount": true
            }
        ],
        "validateClusters": false,
        "ignorePortInHostMatching": true
    }
]

# 실제 애플리케이션(서비스)를 배포 전으로 cluster 에 webapp, catalog 정보가 없다.
docker exec -it myk8s-control-plane istioctl proxy-config cluster deploy/istio-ingressgateway.istio-system
...

 

 

VirtualService 적용 후에는 Envoy가 도메인을 기반으로 라우팅을 수행하도록 구성되며, 실제 라우트 엔트리가 확인되었다.

docker exec -it myk8s-control-plane istioctl proxy-config routes deploy/istio-ingressgateway.istio-system -o json --name http.8080

4. 서비스 배포: webapp과 catalog

실제 애플리케이션을 배포해보자.

# 로그
kubectl stern -n istioinaction -l app=webapp
kubectl stern -n istioinaction -l app=catalog
kubectl stern -n istio-system -l app=istiod
istiod-7df6ffc78d-w9szx discovery 2025-04-13T05:59:52.736261Z	info	ads	LDS: PUSH request for node:webapp-7685bcb84-mck2d.istioinaction resources:21 size:50.1kB
istiod-7df6ffc78d-w9szx discovery 2025-04-13T05:59:52.749641Z	info	ads	RDS: PUSH request for node:webapp-7685bcb84-mck2d.istioinaction resources:13 size:9.9kB cached:12/13
istiod-7df6ffc78d-w9szx discovery 2025-04-13T05:59:54.076322Z	info	ads	CDS: PUSH for node:webapp-7685bcb84-mck2d.istioinaction resources:28 size:26.4kB cached:22/24
istiod-7df6ffc78d-w9szx discovery 2025-04-13T05:59:54.076489Z	info	ads	EDS: PUSH for node:webapp-7685bcb84-mck2d.istioinaction resources:24 size:4.0kB empty:0 cached:24/24
istiod-7df6ffc78d-w9szx discovery 2025-04-13T05:59:54.078289Z	info	ads	LDS: PUSH for node:webapp-7685bcb84-mck2d.istioinaction resources:21 size:50.1kB
istiod-7df6ffc78d-w9szx discovery 2025-04-13T05:59:54.078587Z	info	ads	RDS: PUSH for node:webapp-7685bcb84-mck2d.istioinaction resources:13 size:9.9kB cached:12/13
istiod-7df6ffc78d-w9szx discovery 2025-04-13T05:59:54.185611Z	info	ads	Push debounce stable[37] 1 for config ServiceEntry/istioinaction/webapp.istioinaction.svc.cluster.local: 100.490667ms since last change, 100.490459ms since last push, full=false
...

# 배포
cat services/catalog/kubernetes/catalog.yaml
cat services/webapp/kubernetes/webapp.yaml 
kubectl apply -f services/catalog/kubernetes/catalog.yaml -n istioinaction
kubectl apply -f services/webapp/kubernetes/webapp.yaml -n istioinaction

# 확인
kubectl get pod -n istioinaction -owide
NAME                     READY   STATUS    RESTARTS   AGE
catalog-6cf4b97d-nwh9w   2/2     Running   0          10m
webapp-7685bcb84-mck2d   2/2     Running   0          10m

# krew plugin images 설치 후 사용
kubectl images -n istioinaction
[Summary]: 1 namespaces, 2 pods, 6 containers and 3 different images
+------------------------+-------------------+--------------------------------+
|          Pod           |     Container     |             Image              |
+------------------------+-------------------+--------------------------------+
| catalog-6cf4b97d-nwh9w | catalog           | istioinaction/catalog:latest   |
+                        +-------------------+--------------------------------+
|                        | istio-proxy       | docker.io/istio/proxyv2:1.17.8 |
+                        +-------------------+                                +
|                        | (init) istio-init |                                |
+------------------------+-------------------+--------------------------------+
| webapp-7685bcb84-mck2d | webapp            | istioinaction/webapp:latest    |
+                        +-------------------+--------------------------------+
|                        | istio-proxy       | docker.io/istio/proxyv2:1.17.8 |
+                        +-------------------+                                +
|                        | (init) istio-init |                                |
+------------------------+-------------------+--------------------------------+

# krew plugin resource-capacity 설치 후 사용 : istioinaction 네임스페이스에 파드에 컨테이너별 CPU/Mem Request/Limit 확인
kubectl resource-capacity -n istioinaction -c --pod-count
kubectl resource-capacity -n istioinaction -c --pod-count -u
NODE                  POD                      CONTAINER     CPU REQUESTS   CPU LIMITS    CPU UTIL   MEMORY REQUESTS   MEMORY LIMITS   MEMORY UTIL   POD COUNT

myk8s-control-plane   *                        *             200m (2%)      4000m (50%)   9m (0%)    256Mi (2%)        2048Mi (17%)    129Mi (1%)    2/110
myk8s-control-plane   catalog-6cf4b97d-m7jq9   *             100m (1%)      2000m (25%)   5m (0%)    128Mi (1%)        1024Mi (8%)     70Mi (0%)
myk8s-control-plane   catalog-6cf4b97d-m7jq9   catalog       0m (0%)        0m (0%)       0m (0%)    0Mi (0%)          0Mi (0%)        22Mi (0%)
myk8s-control-plane   catalog-6cf4b97d-m7jq9   istio-proxy   100m (1%)      2000m (25%)   5m (0%)    128Mi (1%)        1024Mi (8%)     48Mi (0%)
...

#
docker exec -it myk8s-control-plane istioctl proxy-status
NAME                                                  CLUSTER        CDS        LDS        EDS        RDS        ECDS         ISTIOD                      VERSION
istio-ingressgateway-996bc6bb6-p6k79.istio-system     Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-w9szx     1.17.8
catalog-6cf4b97d-nwh9w.istioinaction                  Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-w9szx     1.17.8
webapp-7685bcb84-mck2d.istioinaction                  Kubernetes     SYNCED     SYNCED     SYNCED     SYNCED     NOT SENT     istiod-7df6ffc78d-w9szx     1.17.8

docker exec -it myk8s-control-plane istioctl proxy-config listener deploy/istio-ingressgateway.istio-system
docker exec -it myk8s-control-plane istioctl proxy-config cluster deploy/istio-ingressgateway.istio-system | egrep 'TYPE|istioinaction'
SERVICE FQDN                                            PORT      SUBSET     DIRECTION     TYPE           DESTINATION RULE
catalog.istioinaction.svc.cluster.local                 80        -          outbound      EDS            
webapp.istioinaction.svc.cluster.local                  80        -          outbound      EDS  

# istio-ingressgateway 에서 catalog/webapp 의 Service(ClusterIP)로 전달하는게 아니라, 바로 파드 IP인 Endpoint 로 전달함.
## 즉, istio 를 사용하지 않았다면, Service(ClusterIP) 동작 처리를 위해서 Node에 iptable/conntrack 를 사용했었어야 하지만,
## istio 사용 시에는 Node에 iptable/conntrack 를 사용하지 않아서, 이 부분에 대한 통신 라우팅 효율이 있다.
docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy/istio-ingressgateway.istio-system | egrep 'ENDPOINT|istioinaction'
ENDPOINT                                                STATUS      OUTLIER CHECK     CLUSTER
10.10.0.18:3000                                         HEALTHY     OK                outbound|80||catalog.istioinaction.svc.cluster.local
10.10.0.19:8080                                         HEALTHY     OK                outbound|80||webapp.istioinaction.svc.cluster.local

#
docker exec -it myk8s-control-plane istioctl proxy-config listener deploy/webapp.istioinaction
docker exec -it myk8s-control-plane istioctl proxy-config routes deploy/webapp.istioinaction
docker exec -it myk8s-control-plane istioctl proxy-config cluster deploy/webapp.istioinaction
docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy/webapp.istioinaction
docker exec -it myk8s-control-plane istioctl proxy-config secret deploy/webapp.istioinaction
docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy/webapp.istioinaction | egrep 'ENDPOINT|istioinaction'
ENDPOINT                                                STATUS      OUTLIER CHECK     CLUSTER
10.10.0.18:3000                                         HEALTHY     OK                outbound|80||catalog.istioinaction.svc.cluster.local
10.10.0.19:8080                                         HEALTHY     OK                outbound|80||webapp.istioinaction.svc.cluster.local

# 현재 모든 istio-proxy 가 EDS로 K8S Service(Endpoint) 정보를 알 고 있다
docker exec -it myk8s-control-plane istioctl proxy-config listener deploy/catalog.istioinaction
docker exec -it myk8s-control-plane istioctl proxy-config routes deploy/catalog.istioinaction
docker exec -it myk8s-control-plane istioctl proxy-config cluster deploy/catalog.istioinaction
docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy/catalog.istioinaction
docker exec -it myk8s-control-plane istioctl proxy-config secret deploy/catalog.istioinaction
docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy/catalog.istioinaction | egrep 'ENDPOINT|istioinaction'
ENDPOINT                                                STATUS      OUTLIER CHECK     CLUSTER
10.10.0.18:3000                                         HEALTHY     OK                outbound|80||catalog.istioinaction.svc.cluster.local
10.10.0.19:8080                                         HEALTHY     OK                outbound|80||webapp.istioinaction.svc.cluster.local

# netshoot로 내부에서 catalog 접속 확인
kubectl exec -it netshoot -- curl -s http://catalog.istioinaction/items/1 | jq
{
  "id": 1,
  "color": "amber",
  "department": "Eyewear",
  "name": "Elinor Glasses",
  "price": "282.00"
}

# netshoot로 내부에서 webapp 접속 확인 : 즉 webapp은 다른 백엔드 서비스의 파사드 facade 역할을 한다.
kubectl exec -it netshoot -- curl -s http://webapp.istioinaction/api/catalog/items/1 | jq
{
  "id": 1,
  "color": "amber",
  "department": "Eyewear",
  "name": "Elinor Glasses",
  "price": "282.00"
}

 


webapp과 catalog 서비스는 다음과 같이 배포하였다.

kubectl apply -f services/catalog/kubernetes/catalog.yaml -n istioinaction
kubectl apply -f services/webapp/kubernetes/webapp.yaml -n istioinaction

두 서비스는 각각 2개의 컨테이너(서비스, istio-proxy)를 포함하고 있다.

 

리소스 요청과 사용률은 kubectl resource-capacity로 확인하였다.

kubectl resource-capacity -n istioinaction -c --pod-count

 

또한, Envoy는 EDS를 통해 해당 서비스의 Endpoint 정보를 실시간으로 수신하고 있었다.

docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy/istio-ingressgateway.istio-system

5. 실제 요청 테스트 및 디버깅

웹에서 직접 요청을 테스트하기 위해 curl 명령어를 사용하였다.

curl -s http://localhost:30000/api/catalog -H "Host: webapp.istioinaction.io" | jq

 

정상적으로 Elinor Glasses가 포함된 JSON 응답을 수신했다.

 

반대로 Host 헤더 없이 요청할 경우 404가 반환되었다. (Envoy가 도메인을 기준으로 라우팅하기 때문)

curl http://localhost:30000/api/catalog -v

 

 

이번에는 netshoot로 내부에서 catalog 및 webapp 접속을 확인하였다.

kubectl exec -it netshoot -- curl -s http://catalog.istioinaction/items/1 | jq
kubectl exec -it netshoot -- curl -s http://webapp.istioinaction/items/1 | jq

즉 webapp은 다른 백엔드 서비스의 파사드 facade 역할을 한다.

 

 

6. mTLS 인증서 확인

webapp과 catalog의 사이드카 프록시에서 인증서를 확인하였다.
Envoy 관리 포트(15000)을 통해 인증서를 확인하고, base64 디코딩을 통해 유효기간 및 SAN 정보를 확인할 수 있었다.

kubectl exec -it deploy/webapp -n istioinaction -c istio-proxy -- curl http://localhost:15000/certs | jq

만료일자는 1day 서비스 인증서와 10y 루트 인증서로 구분되었다.

7. Endpoint 확장 확인 및 최적화 고찰

catalog, webapp 에 replicas=1 → 2로 증가 후 istio EDS(Endpoint) 정보 확인

# 로그 모니터링
kubectl stern -n istio-system -l app=istiod

# catalog, webapp 에 replicas=1 → 2로 증가
kubectl scale deployment -n istioinaction webapp --replicas 2
kubectl scale deployment -n istioinaction catalog --replicas 2

# 모든 istio-proxy 가 EDS로 해당 K8S Service의 Endpoint 목록 정보 동기화되어 알고 있음을 확인
docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy/istio-ingressgateway.istio-system | egrep 'ENDPOINT|istioinaction'
docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy/webapp.istioinaction | egrep 'ENDPOINT|istioinaction'
docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy/catalog.istioinaction | egrep 'ENDPOINT|istioinaction'
ENDPOINT                                                STATUS      OUTLIER CHECK     CLUSTER
10.10.0.13:3000                                         HEALTHY     OK                outbound|80||catalog.istioinaction.svc.cluster.local
10.10.0.14:8080                                         HEALTHY     OK                outbound|80||webapp.istioinaction.svc.cluster.local
10.10.0.15:8080                                         HEALTHY     OK                outbound|80||webapp.istioinaction.svc.cluster.local
10.10.0.16:3000                                         HEALTHY     OK                outbound|80||catalog.istioinaction.svc.cluster.local

# 다음 실습을 위해서 catalog, webapp 에 replicas=2 → 1로 감소 해두기
kubectl scale deployment -n istioinaction webapp --replicas 1
kubectl scale deployment -n istioinaction catalog --replicas 1

 

replicas=2로 확장 후, 각 Envoy proxy가 새로운 Endpoint 정보를 정확히 인식하고 있는지도 확인하였다.

kubectl scale deployment -n istioinaction webapp --replicas 2
kubectl scale deployment -n istioinaction catalog --replicas 2

docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy/istio-ingressgateway.istio-system | egrep 'ENDPOINT|istioinaction'
docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy/webapp.istioinaction | egrep 'ENDPOINT|istioinaction'
docker exec -it myk8s-control-plane istioctl proxy-config endpoint deploy/catalog.istioinaction | egrep 'ENDPOINT|istioinaction'

 

istio EDS 정보를 확인하면 엔드포인트가 각각 두개 씩 설정되어 있는 것을 확인할 수 있었다. 

 

 

Contents

포스팅 주소를 복사했습니다.

이 글이 도움이 되었다면 공감 부탁드립니다.