IaC/Service Mesh

Istio 설치 및 실습

Somaz 2024. 2. 13. 21:21
728x90
반응형

Overview

이번 글에서는 Istio를 Kubernetes 클러스터에 설치하고, Bookinfo 샘플 애플리케이션을 통해 실습하는 과정을 정리했다.
Istio는 서비스 메쉬 프레임워크로, 트래픽 제어, 보안, 관측(Observability) 기능을 제공하여 마이크로서비스 아키텍처를 효과적으로 운영할 수 있도록 도와준다.

 

설치 과정에서는 istioctl을 사용하여 Istio를 demo 프로파일로 설치하였고, 이후 Envoy 사이드카 자동 주입을 위한 네임스페이스 라벨 설정, Bookinfo 애플리케이션 배포, Istio Gateway 및 VirtualService 구성 등을 단계별로 실습했다.

 

또한, GCP 환경에서 Istio Ingress Gateway를 NodePort 방식으로 노출하고, Kiali, Grafana, Prometheus, Jaeger 등의 애드온을 설치하여 서비스 메쉬의 상태와 트래픽 흐름을 시각화하였다.

 

 

출처 : https://istio.io/latest/about/service-mesh/

 

 

 

 

📅 관련 글

2023.04.15 - [IaC/Service Mesh] - Istio란?

2023.03.08 - [IaC/Service Mesh] - Service Mesh vs Api Gateway

 

 

 

 


 

 

 

Istio 설치 및 다운로드

 

 

Istio 다운로드

# 최신버전 다운로드
curl -L <https://istio.io/downloadIstio> | sh -

# 특정버전 다운로드
curl -L <https://istio.io/downloadIstio> | ISTIO_VERSION=1.20.2 TARGET_ARCH=x86_64 sh -

# 디렉토리 접속
cd istio-1.20.2

# path추가
export PATH=$PWD/bin:$PATH

 

 

 

Istio 설치

demo로 설치하여 공부해본다.

istioctl install --set profile=demo -y

kubectl label namespace default istio-injection=enabled

# label 확인
kubectl get ns --show-labels
NAME                  STATUS   AGE    LABELS
default               Active   140m   istio-injection=enabled,kubernetes.io/metadata.name=default
istio-system          Active   52s    kubernetes.io/metadata.name=istio-system
kube-node-lease       Active   140m   kubernetes.io/metadata.name=kube-node-lease
kube-public           Active   140m   kubernetes.io/metadata.name=kube-public
kube-system           Active   140m   kubernetes.io/metadata.name=kube-system
network-policy-test   Active   132m   kubernetes.io/metadata.name=network-policy-test
  • 나중에 애플리케이션을 배포할 때 Envoy 사이드카 프록시를 자동으로 삽입하도록 Istio에 지시하려면 네임스페이스 라벨을 추가해야 한다.

 

 

 

 

Istio 설치 시 고려사항

항목 설명
버전 관리 Istio는 자주 업데이트되며, 버전마다 설정 방법이 다소 달라질 수 있음. 특히 1.5 이후 istiod 단일 컨트롤러로 변경된 점을 유의. 최신 버전 기준으로 학습하는 것을 추천.
프로파일 선택 demo, default, minimal, external 등 다양한 프로파일 제공됨. 성능 테스트나 실제 운영 환경에서는 default 또는 external 프로파일 권장.
리소스 사용량 Istio는 강력하지만, Sidecar 프록시가 추가되면서 서비스당 약 50~100MB 정도 메모리 사용 증가. 클러스터 리소스 계획에 반영 필요.

 

 

 

 

설치 후 체크리스트

체크 포인트 명령어  예시설명
컨트롤 플레인 상태 확인 `k get po -n istio-system` `Istiod, ingress, egress, addon` 정상 기동 확인
네임스페이스 라벨 확인 `k get ns --show-labels` `istio-injection=enabled` 라벨 확인
Sidecar 주입 확인 `k describe po <pod명>` pod 설명에서 Envoy sidecar 포함 여부 확인

 

 

 

 

Helm으로 설치하는 방법도 추천

현재 설명은 istioctl을 활용한 설치지만, Helm을 선호하는 환경에서는 아래처럼 Helm Chart를 활용할 수도 있다.

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
helm install istiod istio/istiod -n istio-system --set profile=demo

 

 

 

 

 


 

 

 

 

 

샘플 어플리케이션 배포

# 배포
k apply -f samples/bookinfo/platform/kube/bookinfo.yaml

# 서비스 확인
k get svc
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
details       ClusterIP   10.233.25.129   <none>        9080/TCP   13s
kubernetes    ClusterIP   10.233.0.1      <none>        443/TCP    143m
productpage   ClusterIP   10.233.13.24    <none>        9080/TCP   12s
ratings       ClusterIP   10.233.18.41    <none>        9080/TCP   13s
reviews       ClusterIP   10.233.3.236    <none>        9080/TCP   13s

# pod 확인
k get po
NAME                             READY   STATUS    RESTARTS   AGE
details-v1-698d88b-sfrpw         2/2     Running   0          2m16s
productpage-v1-675fc69cf-hsnlf   2/2     Running   0          2m15s
ratings-v1-6484c4d9bb-9jdhx      2/2     Running   0          2m16s
reviews-v1-5b5d6494f4-gqfnl      2/2     Running   0          2m15s
reviews-v2-5b667bcbf8-zjgm7      2/2     Running   0          2m15s
reviews-v3-5b9bd44f4-rr6s9       2/2     Running   0          2m15s

# 앱 확인
kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>

 

 

`bookinfo-gateway.yaml` 확인

cat samples/bookinfo/networking/bookinfo-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  # The selector matches the ingress gateway pod labels.
  # If you installed Istio using Helm following the standard documentation, this would be "istio=ingress"
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 8080
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
  - "*"
  gateways:
  - bookinfo-gateway
  http:
  - match:
    - uri:
        exact: /productpage
    - uri:
        prefix: /static
    - uri:
        exact: /login
    - uri:
        exact: /logout
    - uri:
        prefix: /api/v1/products
    route:
    - destination:
        host: productpage
        port:
          number: 9080

 

 

해당 어플리케이션을 lstio Ingress Gateway와 연결한다.

k apply -f samples/bookinfo/networking/bookinfo-gateway.yaml

# 구성 확인
istioctl analyze

✔ No validation issues found when analyzing namespace: default.

 

 

현재 LB가 없기 때문에 NodePort를 확인해준다.

# 현재 구성 확인 한다.
k get svc istio-ingressgateway -n istio-system
NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                                                                      AGE
istio-ingressgateway   LoadBalancer   10.233.19.220   <pending>     15021:30820/TCP,80:32233/TCP,443:30564/TCP,31400:30670/TCP,15443:32168/TCP   10m

kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}'
32233

 

 

GCE를 사용중이기 때문에 terraform으로 방화벽을 열어준다.

## Firewall ##
resource "google_compute_firewall" "test_server_ssh" {
  name    = "allow-ssh-test-server"
  network = var.shared_vpc

  allow {
    protocol = "tcp"
    ports    = ["22", "32233"]
  }

  source_ranges = ["${var.public_ip}/32""]
  target_tags   = [var.test_server]

  depends_on = [module.vpc]
}

 

 

접속이 잘된다.

 

 

아래와 같이 로그도 확인할 수 있다.

k logs -n istio-system -l app=istio-ingressgateway
[2024-01-23T05:37:24.511Z] "GET /static/bootstrap/css/bootstrap-theme.min.css HTTP/1.1" 200 - via_upstream - "-" 0 23409 12 11 "10.233.64.194" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "a7e9fa4e-6091-94c5-b8fd-7b3eda3874d7" "34.64.45.131:32233" "10.233.64.118:9080" outbound|9080||productpage.default.svc.cluster.local 10.233.64.203:39806 10.233.64.203:8080 10.233.64.194:51114 - -
[2024-01-23T05:37:24.513Z] "GET /static/jquery.min.js HTTP/1.1" 200 - via_upstream - "-" 0 89493 16 13 "10.233.64.194" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "bab1b698-cc35-9361-b326-f3080674d89e" "34.64.45.131:32233" "10.233.64.118:9080" outbound|9080||productpage.default.svc.cluster.local 10.233.64.203:39820 10.233.64.203:8080 10.233.64.194:26863 - -
[2024-01-23T05:37:24.514Z] "GET /static/bootstrap/js/bootstrap.min.js HTTP/1.1" 200 - via_upstream - "-" 0 37045 15 15 "10.233.64.194" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "8d0e8404-a8c9-9cf8-a904-37c61bc7f4d3" "34.64.45.131:32233" "10.233.64.118:9080" outbound|9080||productpage.default.svc.cluster.local 10.233.64.203:39832 10.233.64.203:8080 10.233.64.194:31483 - -
[2024-01-23T05:37:24.567Z] "GET /favicon.ico HTTP/1.1" 404 NR route_not_found - "-" 0 0 0 - "10.233.64.194" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "66f15798-f936-9c9d-b73e-677808a3b67f" "34.64.45.131:32233" "-" - - 10.233.64.203:8080 10.233.64.194:26863 - -
[2024-01-23T05:37:46.329Z] "GET /productpage HTTP/1.1" 200 - via_upstream - "-" 0 4294 27 27 "10.233.65.132" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "cec1d906-c3cc-9d25-a512-a6f1af5f77c0" "34.64.176.165:32233" "10.233.64.118:9080" outbound|9080||productpage.default.svc.cluster.local 10.233.64.203:39802 10.233.64.203:8080 10.233.65.132:49237 - -
[2024-01-23T05:37:46.386Z] "GET /static/bootstrap/css/bootstrap.min.css HTTP/1.1" 200 - via_upstream - "-" 0 121200 6 5 "10.233.65.132" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "1daf5183-97be-9df8-9186-5361e08b8ef8" "34.64.176.165:32233" "10.233.64.118:9080" outbound|9080||productpage.default.svc.cluster.local 10.233.64.203:39802 10.233.64.203:8080 10.233.65.132:49237 - -
[2024-01-23T05:37:46.387Z] "GET /static/bootstrap/css/bootstrap-theme.min.css HTTP/1.1" 200 - via_upstream - "-" 0 23409 7 7 "10.233.65.132" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "3ffd067f-747f-99e7-bfb6-19fe6df6b33f" "34.64.176.165:32233" "10.233.64.118:9080" outbound|9080||productpage.default.svc.cluster.local 10.233.64.203:39832 10.233.64.203:8080 10.233.65.132:49303 - -
[2024-01-23T05:37:46.392Z] "GET /static/bootstrap/js/bootstrap.min.js HTTP/1.1" 200 - via_upstream - "-" 0 37045 12 12 "10.233.65.132" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "6a4e3113-0026-905c-be66-1fdcd4314bbd" "34.64.176.165:32233" "10.233.64.118:9080" outbound|9080||productpage.default.svc.cluster.local 10.233.64.203:40894 10.233.64.203:8080 10.233.65.132:49305 - -
[2024-01-23T05:37:46.389Z] "GET /static/jquery.min.js HTTP/1.1" 200 - via_upstream - "-" 0 89493 14 10 "10.233.65.132" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "cb9acf87-411d-960d-b65b-0432c9879910" "34.64.176.165:32233" "10.233.64.118:9080" outbound|9080||productpage.default.svc.cluster.local 10.233.64.203:39802 10.233.64.203:8080 10.233.65.132:49304 - -
[2024-01-23T05:37:46.446Z] "GET /favicon.ico HTTP/1.1" 404 NR route_not_found - "-" 0 0 0 - "10.233.65.132" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "8d960b9a-ed38-9600-b00c-83e7719c2aad" "34.64.176.165:32233" "-" - - 10.233.64.203:8080 10.233.65.132:49304 - -

 

 

 


 

 

 

 

 

대시보드 확인

Istio는 여러 가지 원격 측정 애플리케이션과 통합된다. 이는 서비스 Mesh의 구조를 이해하고, Mesh의 토폴로지를 표시하고, Mesh의 상태를 분석하는 데 도움이 될 수 있다.

 

 

Kiali 및 기타 애드온을 설치 하고 배포될 때까지 기다린다.

kubectl apply -f samples/addons

kubectl rollout status deployment/kiali -n istio-system
Waiting for deployment "kiali" rollout to finish: 0 of 1 updated replicas are available...
deployment "kiali" successfully rolled out

 

 

Kiali를 NodePort로 열어준다.

kubectl patch -n istio-system svc kiali -p '{"spec": {"type": "NodePort"}}'
service/kiali patched

k get svc -n istio-system |grep kiali
kiali                  NodePort       10.233.15.141   <none>        20001:32634/TCP,9090:30542/TCP                                               3m12s

 

 

동일하게 방화벽을 열어준다.

## Firewall ##
resource "google_compute_firewall" "test_server_ssh" {
  name    = "allow-ssh-test-server"
  network = var.shared_vpc

  allow {
    protocol = "tcp"
    ports    = ["22", "32233", "32767"]
  }

  source_ranges = ["${var.public_ip}/32""]
  target_tags   = [var.test_server]

  depends_on = [module.vpc]
}

 

 

접속이 잘된다.

 

 

추적 데이터를 보려면 서비스에 요청을 보내야 한다. 본 샘플링 비율이 1%인 경우 첫 번째 추적이 표시되기 전에 최소 100개의 요청을 보내야 한다. 서비스에 100개의 요청을 보낸다.

export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')

for i in $(seq 1 100); do curl -s -o /dev/null "http://$GATEWAY_URL/productpage"; done

 

 

 

Kiali 대시보드 활용 예시

  • 서비스 메쉬 내 트래픽 흐름 시각화
  • 각 서비스 간 요청 수, 에러율, 응답시간 확인
  • VirtualService, DestinationRule 등 설정된 리소스 UI로 확인 가능
  • 버전별 트래픽 비율 확인 가능 (Canary 배포 모니터링)

 

 

 

 


 

 

 

Istio의 주요 리소스 (CRD)

리소스 설명 주요 필드
Gateway Ingress 트래픽 수신 설정 hosts, servers, selector
VirtualService 서비스 간 트래픽 라우팅 정책 hosts, gateways, http (match/route)
DestinationRule 백엔드 서비스 연결 정책 host, trafficPolicy, subsets
ServiceEntry 외부 서비스 연결 등록 hosts, addresses, ports

 

 

Bookinfo 구성도 이해

bookinfo는 Istio 학습용 대표 샘플로, 서비스 간 호출 관계는 아래와 같다.

  • 각 서비스에 Envoy 사이드카가 붙어서 트래픽을 관리하는 구조

 

 

 

실전 운영 팁

상황
Canary 배포 VirtualService에서 weight 비율 조정
A/B 테스트 쿠키나 헤더 기반 라우팅 설정
장애 테스트 Fault Injection 기능 활용 (지연, 에러 응답 주입)
인증 및 보안 PeerAuthentication, AuthorizationPolicy 설정으로 mTLS 강제 및 RBAC 구성
외부 서비스 호출 ServiceEntry로 DNS 등록 (ex: 외부 DB, 외부 API 호출)
관측 Kiali, Prometheus, Grafana 연동은 필수 구성

 

 

 

Istio Canary 배포 예시 (VirtualService)

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: productpage
spec:
  hosts:
    - productpage.default.svc.cluster.local
  http:
    - route:
        - destination:
            host: productpage
            subset: v1
          weight: 80
        - destination:
            host: productpage
            subset: v2
          weight: 20

 

 

 

 


 

 

 

 

마무리

 

  • 이번 포스팅에서는 Istio 설치 및 Bookinfo 예제까지 따라해보면서 Istio의 기본 개념과 구성 방법을 학습해봤다.
  • Istio는 강력한 기능을 제공하는 만큼, 설치 및 운영 난이도도 높은 편이지만, 서비스 메쉬 표준 솔루션으로 자리 잡은 만큼 실제 운영 환경에서도 점차 도입이 늘어나고 있다.
  • 다음 시간에는 Canary 배포, Fault Injection, mTLS 구성 같은 고급 활용법과, Istio + Prometheus + Grafana + Loki를 통한 모니터링/로깅 통합 환경 구성법도 이어서 다뤄보겠다!

 

 

 

 

 


Reference

https://istio.io/latest/docs/setup/getting-started/

https://musclebear.tistory.com/157

https://github.com/istio/istio/tree/master/samples/bookinfo

https://istio.io/latest/about/service-mesh/

 

 

 

728x90
반응형

'IaC > Service Mesh' 카테고리의 다른 글

Istio란?  (0) 2023.04.15
Service Mesh vs Api Gateway  (0) 2023.03.08