폴트 주입 — 장애 시나리오로 탄력성 테스트하기

폴트 주입 — 장애 시나리오로 탄력성 테스트하기

폴트 주입(fault injection)은 실제 장애를 만들지 않고도 애플리케이션의 탄력성을 시험하는 방법이에요. Istio는 트래픽에 인위적인 딜레이를 넣거나 HTTP 응답을 강제로 실패시키는 규칙을 VirtualService로 만들 수 있게 해줘요. 이 태스크에서는 Bookinfo 샘플로 딜레이 폴트와 어보트(abort) 폴트를 각각 주입해서 애플리케이션의 숨은 버그를 찾아보는 과정을 따라가요.

출처: Fault Injection — Istio 공식 문서

시작하기 전에

$ kubectl apply -f @samples/bookinfo/networking/virtual-service-all-v1.yaml@
$ kubectl apply -f @samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml@

위 설정 기준으로 요청은 이렇게 흐르게 돼요.

  • productpagereviews:v2ratings (사용자 jason만)
  • productpagereviews:v1 (나머지 모두)

HTTP 딜레이 폴트 주입

Bookinfo 마이크로서비스의 탄력성을 시험하기 위해, 사용자 jasonreviews:v2ratings 사이에 7초 딜레이를 주입할 거예요. 이 테스트는 Bookinfo에 의도적으로 심어 둔 버그를 드러내 줘요.

reviews:v2 서비스는 ratings 호출에 10초로 하드코딩된 커넥션 타임아웃을 갖고 있어요. 넣은 7초 딜레이에도 불구하고 엔드투엔드 흐름은 에러 없이 이어질 걸로 예상돼요.

테스트 사용자 jason에게 오는 트래픽을 지연시키는 폴트 주입 규칙을 만들어요.

$ kubectl apply -f @samples/bookinfo/networking/virtual-service-ratings-test-delay.yaml@

규칙이 만들어졌는지 확인해 볼게요.

$ kubectl get virtualservice ratings -o yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
...
spec:
  hosts:
  - ratings
  http:
  - fault:
      delay:
        fixedDelay: 7s
        percentage:
          value: 100
    match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: ratings
        subset: v1
  - route:
    - destination:
        host: ratings
        subset: v1

새 규칙이 모든 파드에 전파되도록 몇 초 기다려요.

딜레이 설정 테스트

브라우저에서 Bookinfo 앱을 열고 /productpage에서 사용자 jason으로 로그인해요. 약 7초 만에 에러 없이 홈페이지가 로드될 걸 기대하지만, 실제로는 Reviews 영역에 에러 메시지가 보여요.

Sorry, product reviews are currently unavailable for this book.

개발자 도구의 Network 탭을 열어 /productpage를 다시 로드하면 실제로 약 6초에 로드되는 걸 볼 수 있어요.

무슨 일이 벌어졌나

버그를 찾았어요. 마이크로서비스에 하드코딩된 타임아웃 때문에 reviews 서비스가 실패한 거예요.

예상대로 reviewsratings 사이 타임아웃이 10초로 하드코딩돼 있어서 7초 딜레이는 reviews에 영향을 주지 않아요. 하지만 productpagereviews 사이에도 3초 + 리트라이 1회로 총 6초인 하드코딩 타임아웃이 있어요. 결과적으로 productpagereviews 호출이 6초 뒤에 조기 타임아웃되어 에러를 던진 거예요.

이런 버그는 서로 다른 팀이 각각의 마이크로서비스를 독립적으로 개발하는 일반적인 엔터프라이즈 환경에서 흔히 생겨요. Istio의 폴트 주입 규칙은 실제 사용자에게 영향을 주지 않고도 이런 이상 징후를 찾아내게 도와줘요.

버그 고치기

보통은 productpagereviews 타임아웃을 늘리거나 reviewsratings 타임아웃을 줄이고, 고친 마이크로서비스를 재시작한 뒤 /productpage가 에러 없이 응답하는지 확인하는 식으로 고쳐요. 그런데 reviews v3에는 이미 수정본이 돌고 있어요. reviews:v3reviewsratings 타임아웃을 10초에서 2.5초로 줄여서 다운스트림 productpage 요청의 타임아웃(이보다 작음)과 맞췄어요.

traffic shifting 태스크대로 모든 트래픽을 reviews:v3로 옮기면, 딜레이 규칙을 2.5초 미만(예: 2초)으로 바꿔서도 에러 없이 이어지는지 확인해 볼 수 있어요.

HTTP 어보트 폴트 주입

마이크로서비스 탄력성의 또 다른 테스트 방법은 HTTP 어보트 폴트를 넣는 거예요. 여기서는 테스트 사용자 jason에게 ratings 마이크로서비스의 HTTP 어보트를 주입할 거예요.

이 경우 페이지가 즉시 로드되면서 "Ratings service is currently unavailable" 메시지가 보일 걸 기대해요.

사용자 jason에게 HTTP 어보트를 보내는 폴트 주입 규칙을 만들어요.

$ kubectl apply -f @samples/bookinfo/networking/virtual-service-ratings-test-abort.yaml@

규칙이 만들어졌는지 확인해 볼게요.

$ kubectl get virtualservice ratings -o yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
...
spec:
  hosts:
  - ratings
  http:
  - fault:
      abort:
        httpStatus: 500
        percentage:
          value: 100
    match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: ratings
        subset: v1
  - route:
    - destination:
        host: ratings
        subset: v1

어보트 설정 테스트

Bookinfo 앱에서 /productpage로 사용자 jason으로 로그인해요. 규칙이 모든 파드에 전파됐다면 페이지가 즉시 로드되면서 "Ratings service is currently unavailable" 메시지가 나타나요.

jason으로 로그아웃하거나 시크릿 창(또는 다른 브라우저)에서 Bookinfo를 열면, jason을 제외한 모두에게는 ratings를 전혀 호출하지 않는 reviews:v1로 가는 것을 확인할 수 있어요. 그래서 에러 메시지가 보이지 않죠.

정리

적용한 라우팅 규칙을 제거해요.

$ kubectl delete -f @samples/bookinfo/networking/virtual-service-all-v1.yaml@

뒤이어 배울 태스크가 없다면 Bookinfo 정리 지침대로 애플리케이션을 종료해요.

더 알아보기 (Learn more)