[DevOps] Istio virtualhost 사용법

안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 Istio virtualhost를 통한 트래픽 관리에 대해서 정리를 해보려고 합니다. 필자가 속한 프로젝트에서는 Istio를 grpc 분산용으로 사용하고 있습니다. 그러나 따로 트래픽 관리라던지, 인증가 인가에 대한 내용을 적용하고 있지는 않습니다.

Istio의 L7 Envoy proxy를 사용은 하고있으나, 적절하게 기능들을 활용하고 있지는 않기에 이번 포스팅을 통해서 어떠한 내용들을 다룰 수 있는지를 기록하고자 합니다.

istio관련된 시리즈는 아래에서 확인이 가능합니다.

1. Bookinfo Sample app

istio는 친절하게도 설치를 하게 되면 샘플 앱을 제공하고 있습니다. 이부분이 서비스 메시를 이해하는데 많은 도움이 되었습니다.

먼저 설치는 다음의 포스팅을 확인해주시기 바랍니다.

설치를 하고 다음의 경로를 이동을 하게 되면, example이 존재합니다.

# bookinfo sample 예제
/istio-1.10.0/samples/bookinfo

# bookinfo application 설치
$kubectl apply -f /platform/kube/book/bookinfo.yaml

해당 파일을 설치하게 되면, 다음과 같이 여러개의 어플리케이션이 설치가 됩니다.

service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created

service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created

service/reviews created
serviceaccount/bookinfo-reviews created
deployment.apps/reviews-v1 created
deployment.apps/reviews-v2 created
deployment.apps/reviews-v3 created

service/productpage created
serviceaccount/bookinfo-productpage created
deployment.apps/productpage-v1 created

productpage, details, reviews, ratings로 구성이 되어있고, 전체적인 아키텍처는 다음과 같습니다 .

bookinfo_1

사전에 클러스터에 Istio-1.10.0 버전을 설치하였고, default namespace에 injection 까지 마친상태였습니다. 이후에 각 서비스와 함께 Envoy 사이트카를 주입하여 Istio 환경에서 서비스를 구성하고 실행하기만 하면됩니다.

예제에서는 Ingress를 사용하게끔 되어있지만, 별도의 Ingress Layer를 사용하지 않고, Product Page자체를 Node port로 외부로 노출시켰습니다.

# product page 외부로 노출 시키기

kubectl patch svc productpage -p '{"spec": {"type": "NodePort"}}'
service/productpage patched

# service port 
$ kubectl get svc
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
details       ClusterIP   192.168.59.179           9080/TCP         94s
kubernetes    ClusterIP   192.168.0.1              443/TCP          22h
productpage   NodePort    192.168.32.89            9080:32383/TCP   94s
ratings       ClusterIP   192.168.50.87            9080/TCP         94s
reviews       ClusterIP   192.168.56.81            9080/TCP         94s

최종적으로 {host ip} : 32383/productpage 로 접속을 하면 다음과 같은 화면이 노출됩니다.

bookinfo_2

2. Destination rule과 Virtual host

1) Destinatino Rule

DestinationRule라우팅이 발생한 후 서비스를 위한 트래픽에 적용되는 정책을 정의합니다. 이러한 규칙은 로드 밸런싱에 대한 구성, 사이드카의 연결 풀 크기, 로드 밸런싱 풀에서 비정상 호스트를 감지하고 제거하기 위한 이상값 감지 설정을 지정합니다.

자세한 설정은 다음의 공식 Document에서 볼 수 있습니다.

Destination Rule

bookinfo 예제에서 다음의 경로 파일을 열어봅니다.

# destionation rule all 
$ vi bookinfo/networking/destination-rule-all.yaml

내용이 길지만, 하나의 부분에 대해서 말씀을 드리겠습니다.

#  destination-rule-all.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3

host: reviews 는 서비스의 이름을 말합니다.

subsets 는 서비스의 개별 버전을 나타내는 하나 이상의 명명된 집합입니다. 트래픽 정책은 하위 집합 수준에서 재정의할 수 있습니다.

위에서는 각 labeling의 version기준으로 v1, v2, v3로 나누었습니다. 처음 아키텍처 그림에서 reviews가 3개의 버전을 서비스가 되는 것을 볼 수 있었습니다.

# destination-rule-reviews.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3

trafficPolicy : loadBalancer, connectionPool, outlierDetection, tls을 통해 특정 목적지와 특정 포트에 적용할 수 있는 트래픽 정책입니다.

위의 예에서는 random traffic으로 로드밸런싱을 하도록 구성을 했습니다.

2) Virtual Service

위의 정해진 Destination Rule을 기준으로 가상 서비스를 만들 수 있습니다. 트래픽을 어떤식으로 라우팅을 할지 설정이 가능합니다.

# virtual-service-all-v1.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: productpage
spec:
  hosts:
  - productpage
  http:
  - route:
    - destination:
        host: productpage
        subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - route:
    - destination:
        host: ratings
        subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: details
spec:
  hosts:
  - details
  http:
  - route:
    - destination:
        host: details
        subset: v1

위의 예제에서는 모든 서비스를 v1으로 보내겠다는 설정을 적용하였습니다.

host 트래픽이 보내질 목적지 host(Service name) 입니다.

http > route > destination Destination Rule에서 정의한 곳으로 트래픽을 보내기 위해 설정을 합니다.

아래 2개의 파일을 배포하게 되면, ratings 서비스가 v1으로만 트래픽이 전달이 되므로, 별점 정보는 노출이 되지 않는(v1) 으로 서비스를 하게 됩니다.

destination-rule-all.yaml
virtual-service-all-v1.yaml

3. Intellegent Routing

위의 예제와 더불어 Routing에 대해서 bookinfo 예제 파일로 설명을 드리겠습니다.

특정 User에게 특정 버전만 서비스 하기

# virtual-service-reviews-test-v2.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: reviews
        subset: v2
  - route:
    - destination:
        host: reviews
        subset: v1

headers에 jason이라고 있으면, reviews를 v2로 서비스 하고 그외에는 v1으로 서비스를 합니다.

점진적 마이그레이션

다음 구성에서 보시듯이, reviews의 8:2 비율로 v1과 v2로 라우팅을 시키는 내용입니다.

# virtual-service-reviews-80-20.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 80
    - destination:
        host: reviews
        subset: v2
      weight: 20

4. Fault Injection

어플리케이션의 복원력에 대해서 확인하기 위해서 오류를 강제로 삽입할 수 있는 기능입니다.

다음 예제는 jason으로 로그인시 rating 서비스가 100%의 확률로 7초의 딜레이를 강제적으로 발생시키는 내용입니다.

# virtual-service-ratings-test-delay.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    fault:
      delay:
        percentage:
          value: 100.0
        fixedDelay: 7s
    route:
    - destination:
        host: ratings
        subset: v1
  - route:
    - destination:
        host: ratings
        subset: v1

다음은 jason으로 로그인시 100%의 확률로 500에러를 발생하는 내용입니다.

# virtual-service-ratings-test-abort.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    fault:
      abort:
        percentage:
          value: 100.0
        httpStatus: 500
    route:
    - destination:
        host: ratings
        subset: v1
  - route:
    - destination:
        host: ratings
        subset: v1  

5. Circuit Breaker

Circuit Breaker는 탄력적인 마이크로 서비스 애플리케이션을 만드는 데 중요한 패턴입니다. Circuit breaking을 사용하면 장애의 영향, 지연 시간 급증 및 기타 네트워크 특성의 바람직하지 않은 영향을 제한하는 애플리케이션을 작성 할 수 있습니다.

  • 서비스 A -> B -> C의 구조에서 C가 장애가 발생을 하게 되면, B는 대기를 하게 되고 덩달아 A도 대기상태에 빠져 서비스 불능상태에 빠지게 됩니다. 하나의 장애가 다른 서비스들도 적체를 유발하여 장애가 전파됩니다.
  • Circuit Breaker는 기능 자체가 동작하지 않는 경우에 Breaking을 통해 해당 서비스로 트래픽이 가지 않도록 차단을 하여 장애가 전파되지 않도록 하는데 목적이 있습니다.

6. 마치며..

이번시간에는 istio의 virtual host를 통해서 트래픽제어를 정리해봤습니다. istio를 잘만 활용하면, 수많은 MSA구조의 어플리케이션들 사이에서 적절하게 트래픽을 분배하고 라우팅을 할 수 있습니다. 이를 통해서 장애도 제어를 할 수 있을것 같다는 생각이 들었습니다.
다음시간에는 istio의 실제 적용 사례를 정리해보도록 하겠습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다