KANS3 - Service Mesh : Istio-Mode(Sidecar, Ambient) - 01/03

서비스 메시

마이크로 서비스 아키텍쳐의 환경에서 전체 시스템에 대한 모니터링의 어려움과 운영시 장애 또는 문제 발생시 원친 찾기가 어려움에서 출발했습니다. 주로 Istio, Linkerd와 같은 것들이 대표적이고 MSA로 배포된 어플리케이션들에 대해 통신이나 경로를 제어하는데 사용합니다.

# 기본 동작
App -> App

# Sidecar를 통한 Proxy사용
APP      APP
Proxy -> Proxy

# 관리가 필요하다
App           App
Proxy   ->   Proxy
 Control Plane ┘
  • Proxy 는 중앙에서 설정 관리가 잘되는 툴을 선택. 즉, 원격에서 동적인 설정 관리가 유연해야함 → 풍부한 API 지원이 필요 ⇒ Envoy
    • ‘구글 IBM 리프트(Lyft)‘가 중심이 되어 개발하고 있는 오픈 소스 소프트웨어이며, C++ 로 구현된 고성능 Proxy 인 엔보이(Envoy)
    • 네트워크의 투명성을 목표, 다양한 필터체인 지원(L3/L4, HTTP L7), 동적 configuration API 제공, api 기반 hot reload 제공
  • 중앙에서 어떤 동작/설정을 관리해야 될까? 라우팅, 보안 통신을 위한 mTLS 관련, 동기화 상태 정보 등

이를 통해 아래의 효과들을 얻을수 있습니다.

  • 트래픽 모니터링 : 요청의 ‘에러율, 레이턴시, 커넥션 개수, 요청 개수’ 등 메트릭 모니터링, 특정 서비스간 혹은 특정 요청 경로로 필터링 → 원인 파악 용이!
  • 트래픽 컨트롤 : 트래픽 시프팅(Traffic shifting), 서킷 브레이커(Circuit Breaker), 폴트 인젝션(Fault Injection), 속도 제한(Rate Limit)
    • 트래픽 시프팅(Traffic shifting) : 예시) 99% 기존앱 + 1% 신규앱 , 특정 단말/사용자는 신규앱에 전달하여 단계적으로 적용하는 카니리 배포 가능
    • 서킷 브레이커(Circuit Breaker) : 목적지 마이크로서비스에 문제가 있을 시 접속을 차단하고 출발지 마이크로서비스에 요청 에러를 반환 (연쇄 장애, 시스템 전제 장애 예방)
    • 폴트 인젝션(Fault Injection) : 의도적으로 요청을 지연 혹은 실패를 구현
    • 속도 제한(Rate Limit) : 요청 개수를 제한

Istio

  • 파일럿(Pilot): 모든 Envoy 사이드카에서 프록시 라우팅 규칙을 관리하며, 서비스 디스커버리와 로드 밸런싱 설정을 제공합니다.
  • 갤리(Galley): Istio와 쿠버네티스(TLS 연결 및 파일럿에 필요한 설정)를 연결해 주는 역할을 합니다. 서비스 메시 구성 데이터를 검증하고 변환합니다.
  • 시타델(Citadel): 보안 기능을 담당하며, TLS 인증서 발급 및 관리를 통해 서비스 간 통신의 암호화를 수행합니다.

Istio 구성요소와 envoy : 컨트롤 플레인(istiod) , 데이터 플레인(istio-proxy > envoy)

  • istiod : Pilot(데이터 플레인과 통신하면서 라우팅 규칙을 동기화, ADS), Gally(Istio 와 K8S 연동, Endpoint 갱신 등), Citadel(연결 암호화, 인증서 관리 등)

  • Istio proxy : Golang 으로 작성되었고 envoy 래핑한 Proxy, istiod와 통신하고 서비스 트래픽을 통제, 옵저버빌리티를 위한 메트릭 제공

  • 이스티오는 각 파드 안에 사이드카엔보이 프록시가 들어가 있는 형태

  • 모든 마이크로서비스간 통신은 엔보이를 통과하여, 메트릭을 수집하거나 트래픽 컨트롤을 할 수 있음

  • 트래픽 컨트롤을 하기위해 엔보이 프록시에 전송 룰을 설정 → 컨트롤 플레인이스티오가 정의된 정보를 기반으로 엔보이 설정을 하게 함

  • 마이크로서비스 간의 통신을 mutual TLS 인증(mTLS)으로 서로 TLS 인증으로 암호화 할 수 있음

  • 각 애플리케이션은 파드 내의 엔보이 프록시에 접속하기 위해 localhost 에 TCP 접속을 함

Envoy(Use Istio Sidecar)

Envoy는 그 자체로 L4/L7용 Proxy이지만, Istio에서는 이를 POD의 통신을 위한 Sidecar Proxy로 사용됩니다. 그리고 가장 좋은 부분은 구성(설정)을 동적으로 관리할수 있도록 API가 제공이 된다는 점입니다.

  • Istio 구성요소와 envoy : 컨트롤 플레인(istiod) - ADS 를 이용한 Configuration 동기화 - 데이터 플레인(istio-proxy → envoy)

  • Cluster : envoy 가 트래픽을 포워드할 수 있는 논리적인 서비스 (엔드포인트 세트), 실제 요청이 처리되는 IP 또는 엔드포인트의 묶음을 의미.

  • Endpoint : IP 주소, 네트워크 노드로 클러스터로 그룹핑됨, 실제 접근이 가능한 엔드포인트를 의미. 엔드포인트가 모여서 하나의 Cluster 가 된다.

  • Listener : 무엇을 받을지 그리고 어떻게 처리할지 IP/Port 를 바인딩하고, 요청 처리 측면에서 다운스트림을 조정하는 역할.

  • Route : Listener 로 들어온 요청을 어디로 라우팅할 것인지를 정의. 라우팅 대상은 일반적으로 Cluster 라는 것에 대해 이뤄지게 된다.

  • Filter : Listener 로부터 서비스에 트래픽을 전달하기까지 요청 처리 파이프라인

  • UpStream : envoy 요청을 포워딩해서 연결하는 백엔드 네트워크 노드 - 사이드카일때 application app, 아닐때 원격 백엔드

  • DownStream : An entity connecting to envoy, In non-sidecar models this is a remote client

Envoy API 사용 사례

  • Service Mesh 솔루션이나, Gateway API 구현체들을 Enovy를 내부적으로 사용하고 있으며, Envoy가 제공하는 동적 구성을 위한 API (xDS Sync API)를 이용하여 다양한 네트워크 정책을 구성하게 됩니다.
  • Envoy의 xDS Sync API는 아래와 같은 레이어에서 동작하게 됩니다.
    • LDS - Listener Discovery Service
    • RDS - Route Discovery Service
    • CDS - Cluseter Discovery Service
    • EDS - Endpoint Discovery Service

실습

Istio 설치(K3s)

# istioctl 설치
export ISTIOV=1.23.2
echo "export ISTIOV=1.23.2" >> /etc/profile
curl -s -L https://istio.io/downloadIstio | ISTIO_VERSION=$ISTIOV TARGET_ARCH=x86_64 sh -
tree istio-$ISTIOV -L 2 # sample yaml 포함
cp istio-$ISTIOV/bin/istioctl /usr/local/bin/istioctl
istioctl version --remote=false

# 실습을 위한 커스터마이징 배포
istioctl profile list
istioctl profile dump default
istioctl profile dump --config-path components.ingressGateways
istioctl profile dump --config-path values.gateways.istio-ingressgateway
istioctl profile dump demo

istioctl profile dump demo > demo-profile.yaml
vi demo-profile.yaml # 복잡성을 줄이게 실습 시나리오 환경 맞춤
--------------------
    egressGateways:
    - enabled: false
--------------------    

istioctl install -f demo-profile.yaml -y

        |\
        | \
        |  \
        |   \
      /||    \
     / ||     \
    /  ||      \
   /   ||       \
  /    ||        \
 /     ||         \
/______||__________\
____________________
  \__       _____/
     \_____/

✔ Istio core installed ⛵️
✔ Istiod installed 🧠
✔ Ingress gateways installed 🛬
✔ Installation complete                                                                                                                                                      Made this installation the default for cluster-wide operations.

# 설치 확인
k get all,svc,ep,sa,cm,secret,pdb -n istio-system
NAME                                        READY   STATUS    RESTARTS   AGE
pod/istio-ingressgateway-64f9774bdc-x54sg   1/1     Running   0          2m49s
pod/istiod-868cc8b7d7-qchx7                 1/1     Running   0          2m59s

NAME                           TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                                      AGE
service/istio-ingressgateway   LoadBalancer   10.200.1.162   <pending>     15021:31242/TCP,80:31662/TCP,443:30634/TCP   2m49s
service/istiod                 ClusterIP      10.200.1.187   <none>        15010/TCP,15012/TCP,443/TCP,15014/TCP        2m59s

NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/istio-ingressgateway   1/1     1            1           2m49s
deployment.apps/istiod                 1/1     1            1           2m59s

NAME                                              DESIRED   CURRENT   READY   AGE
replicaset.apps/istio-ingressgateway-64f9774bdc   1         1         1       2m49s
replicaset.apps/istiod-868cc8b7d7                 1         1         1       2m59s

NAME                                                       REFERENCE                         TARGETS              MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/istio-ingressgateway   Deployment/istio-ingressgateway   cpu: <unknown>/80%   1         5         1          2m49s
horizontalpodautoscaler.autoscaling/istiod                 Deployment/istiod                 cpu: <unknown>/80%   1         5         1          2m59s

NAME                             ENDPOINTS                                                     AGE
endpoints/istio-ingressgateway   10.10.0.6:15021,10.10.0.6:8080,10.10.0.6:8443                 2m49s
endpoints/istiod                 10.10.0.5:15012,10.10.0.5:15010,10.10.0.5:15017 + 1 more...   2m59s

NAME                                                  SECRETS   AGE
serviceaccount/default                                0         3m1s
serviceaccount/istio-ingressgateway-service-account   0         2m49s
serviceaccount/istio-reader-service-account           0         3m
serviceaccount/istiod                                 0         2m59s

NAME                                            DATA   AGE
configmap/istio                                 2      2m59s
configmap/istio-ca-root-cert                    1      2m51s
configmap/istio-gateway-status-leader           0      2m51s
configmap/istio-leader                          0      2m51s
configmap/istio-namespace-controller-election   0      2m51s
configmap/istio-sidecar-injector                2      2m59s
configmap/kube-root-ca.crt                      1      3m1s

NAME                     TYPE               DATA   AGE
secret/istio-ca-secret   istio.io/ca-root   5      2m51s

NAME                                              MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
poddisruptionbudget.policy/istio-ingressgateway   1               N/A               0                     2m49s
poddisruptionbudget.policy/istiod                 1               N/A               0                     2m59s

# Ingress Gateway 설정 변경
k patch svc -n istio-system istio-ingressgateway -p '{"spec": {"type": "NodePort", "ports": [{"port": 80, "targetPort": 8080, "nodePort": 30000}]}}'

# Egress Gateway 설정 변경
k patch svc -n istio-system istio-ingressgateway -p '{"spec":{"externalTrafficPolicy": "Local"}}'

# default namespace에 sidecar 설정
# mutating Webhook admisstion controller 사용
k label namespace default istio-injection=enabled
k get ns -L istio-injection
NAME                 STATUS   AGE     ISTIO-INJECTION
default              Active   7m33s   enabled

Nginx 설정 배포 및 Istio 설정

# Nginx 배포
cat <<EOF | k apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kans-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-websrv
spec:
  replicas: 1
  selector:
    matchLabels:
      app: deploy-websrv
  template:
    metadata:
      labels:
        app: deploy-websrv
    spec:
      serviceAccountName: kans-nginx
      terminationGracePeriodSeconds: 0
      containers:
      - name: deploy-websrv
        image: nginx:alpine
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: svc-clusterip
spec:
  ports:
    - name: svc-webport
      port: 80
      targetPort: 80
  selector:
    app: deploy-websrv
  type: ClusterIP
EOF

# Istio 설정
cat <<EOF | k apply -f -
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: test-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: nginx-service
spec:
  hosts:
  - "*"  # 도메인 접속이 잘 되지 않을 경우 "*" 로 변경하고 IP로 접속 할 것
  gateways:
  - test-gateway
  http:
  - route:
    - destination:
        host: svc-clusterip
        port:
          number: 80
EOF

# 로컬테스트
curl -v -s 127.0.0.1:30000
*   Trying 127.0.0.1:30000...
* Connected to 127.0.0.1 (127.0.0.1) port 30000
> GET / HTTP/1.1
> Host: 127.0.0.1:30000
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< server: istio-envoy
...

# 리소스 정리
k delete gw,vs,deploy,svc --all

Bookinfo(데모)를 통한 Istio 실습

# bookinfo 배포
echo $ISTIOV
cat ~/istio-$ISTIOV/samples/bookinfo/platform/kube/bookinfo.yaml
k apply -f ~/istio-$ISTIOV/samples/bookinfo/platform/kube/bookinfo.yaml

# 확인
k exec "$(k 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>

# 인입 설정
cat ~/istio-$ISTIOV/samples/bookinfo/networking/bookinfo-gateway.yaml
k apply -f ~/istio-$ISTIOV/samples/bookinfo/networking/bookinfo-gateway.yaml

# 확인
k get gw,vs
NAME                                           AGE
gateway.networking.istio.io/bookinfo-gateway   23s

NAME                                          GATEWAYS               HOSTS   AGE
virtualservice.networking.istio.io/bookinfo   ["bookinfo-gateway"]   ["*"]   23s

istioctl proxy-status
NAME                                                   CLUSTER        CDS                LDS                EDS                RDS                ECDS        ISTIOD                      VERSION
details-v1-65cfcf56f9-pl7xh.default                    Kubernetes     SYNCED (2m38s)     SYNCED (2m38s)     SYNCED (2m38s)     SYNCED (2m38s)     IGNORED     istiod-868cc8b7d7-qchx7     1.23.2
istio-ingressgateway-64f9774bdc-x54sg.istio-system     Kubernetes     SYNCED (60s)       SYNCED (60s)       SYNCED (15m)       SYNCED (60s)       IGNORED     istiod-868cc8b7d7-qchx7     1.23.2
productpage-v1-d5789fdfb-xmk69.default                 Kubernetes     SYNCED (5m50s)     SYNCED (5m50s)     SYNCED (5m50s)     SYNCED (5m50s)     IGNORED     istiod-868cc8b7d7-qchx7     1.23.2
ratings-v1-7c9bd4b87f-6pwzk.default                    Kubernetes     SYNCED (2m32s)     SYNCED (2m32s)     SYNCED (2m32s)     SYNCED (2m32s)     IGNORED     istiod-868cc8b7d7-qchx7     1.23.2
reviews-v1-6584ddcf65-mkd8f.default                    Kubernetes     SYNCED (6m10s)     SYNCED (6m10s)     SYNCED (6m10s)     SYNCED (6m10s)     IGNORED     istiod-868cc8b7d7-qchx7     1.23.2
reviews-v2-6f85cb9b7c-fgqct.default                    Kubernetes     SYNCED (5m53s)     SYNCED (5m53s)     SYNCED (5m53s)     SYNCED (5m53s)     IGNORED     istiod-868cc8b7d7-qchx7     1.23.2
reviews-v3-6f5b775685-bv47t.default                    Kubernetes     SYNCED (2m52s)     SYNCED (2m52s)     SYNCED (2m52s)     SYNCED (2m52s)     IGNORED     istiod-868cc8b7d7-qchx7     1.23.2

모니터링

# Add-on 설치
tree ~/istio-$ISTIOV/samples/addons/
k apply -f ~/istio-$ISTIOV/samples/addons # 디렉터리에 있는 모든 yaml 자원을 생성
k rollout status deployment/kiali -n istio-system

# Add-on 포트 변경
k patch svc -n istio-system prometheus -p '{"spec": {"type": "NodePort", "ports": [{"port": 9090, "targetPort": 9090, "nodePort": 30001}]}}'
k patch svc -n istio-system grafana -p '{"spec": {"type": "NodePort", "ports": [{"port": 3000, "targetPort": 3000, "nodePort": 30002}]}}'
k patch svc -n istio-system kiali -p '{"spec": {"type": "NodePort", "ports": [{"port": 20001, "targetPort": 20001, "nodePort": 30003}]}}'