81~84일차) 2025-04-24 ~ 2025-04-29 [3. k8s 팀 프로젝트] - 이스티오 실습(bookinfo, MSA, 장애복구)
🔁 마이크로서비스 확장 예시
✅ bookinfo-gateway.yaml
apiVersion: networking.istio.io/v1
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/v1
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
✅ bookinfo.yaml
# Copyright Istio Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# <http://www.apache.org/licenses/LICENSE-2.0>
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##################################################################################################
# This file defines the services, service accounts, and deployments for the Bookinfo sample.
#
# To apply all 4 Bookinfo services, their corresponding service accounts, and deployments:
#
# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
#
# Alternatively, you can deploy any resource separately:
#
# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -l service=reviews # reviews Service
# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -l account=reviews # reviews ServiceAccount
# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -l app=reviews,version=v3 # reviews-v3 Deployment
##################################################################################################
##################################################################################################
# Details service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
name: details
labels:
app: details
service: details
spec:
ports:
- port: 9080
name: http
selector:
app: details
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-details
labels:
account: details
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: details-v1
labels:
app: details
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: details
version: v1
template:
metadata:
labels:
app: details
version: v1
spec:
serviceAccountName: bookinfo-details
containers:
- name: details
image: docker.io/istio/examples-bookinfo-details-v1:1.20.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
##################################################################################################
# Ratings service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
name: ratings
labels:
app: ratings
service: ratings
spec:
ports:
- port: 9080
name: http
selector:
app: ratings
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-ratings
labels:
account: ratings
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ratings-v1
labels:
app: ratings
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: ratings
version: v1
template:
metadata:
labels:
app: ratings
version: v1
spec:
serviceAccountName: bookinfo-ratings
containers:
- name: ratings
image: docker.io/istio/examples-bookinfo-ratings-v1:1.20.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
##################################################################################################
# Reviews service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
name: reviews
labels:
app: reviews
service: reviews
spec:
ports:
- port: 9080
name: http
selector:
app: reviews
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-reviews
labels:
account: reviews
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v1
labels:
app: reviews
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: reviews
version: v1
template:
metadata:
labels:
app: reviews
version: v1
spec:
serviceAccountName: bookinfo-reviews
containers:
- name: reviews
image: docker.io/istio/examples-bookinfo-reviews-v1:1.20.2
imagePullPolicy: IfNotPresent
env:
- name: LOG_DIR
value: "/tmp/logs"
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
- name: wlp-output
mountPath: /opt/ibm/wlp/output
volumes:
- name: wlp-output
emptyDir: {}
- name: tmp
emptyDir: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v2
labels:
app: reviews
version: v2
spec:
replicas: 1
selector:
matchLabels:
app: reviews
version: v2
template:
metadata:
labels:
app: reviews
version: v2
spec:
serviceAccountName: bookinfo-reviews
containers:
- name: reviews
image: docker.io/istio/examples-bookinfo-reviews-v2:1.20.2
imagePullPolicy: IfNotPresent
env:
- name: LOG_DIR
value: "/tmp/logs"
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
- name: wlp-output
mountPath: /opt/ibm/wlp/output
volumes:
- name: wlp-output
emptyDir: {}
- name: tmp
emptyDir: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v3
labels:
app: reviews
version: v3
spec:
replicas: 1
selector:
matchLabels:
app: reviews
version: v3
template:
metadata:
labels:
app: reviews
version: v3
spec:
serviceAccountName: bookinfo-reviews
containers:
- name: reviews
image: docker.io/istio/examples-bookinfo-reviews-v3:1.20.2
imagePullPolicy: IfNotPresent
env:
- name: LOG_DIR
value: "/tmp/logs"
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
- name: wlp-output
mountPath: /opt/ibm/wlp/output
volumes:
- name: wlp-output
emptyDir: {}
- name: tmp
emptyDir: {}
---
##################################################################################################
# Productpage services
##################################################################################################
apiVersion: v1
kind: Service
metadata:
name: productpage
labels:
app: productpage
service: productpage
spec:
ports:
- port: 9080
name: http
selector:
app: productpage
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-productpage
labels:
account: productpage
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: productpage-v1
labels:
app: productpage
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: productpage
version: v1
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9080"
prometheus.io/path: "/metrics"
labels:
app: productpage
version: v1
spec:
serviceAccountName: bookinfo-productpage
containers:
- name: productpage
image: docker.io/istio/examples-bookinfo-productpage-v1:1.20.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
✅ destination-rule-all.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: productpage
spec:
host: productpage
subsets:
- name: v1
labels:
version: v1
---
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
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: ratings
spec:
host: ratings
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v2-mysql
labels:
version: v2-mysql
- name: v2-mysql-vm
labels:
version: v2-mysql-vm
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: details
spec:
host: details
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
---
Reviews 마이크로서비스의 v1 : 리뷰에 별 없음 Reviews 마이크로서비스의 v2 : 리뷰에 검정 별 Reviews 마이크로서비스의 v3 : 리뷰에 빨강 별
✅ virtual-service-all-v1.yaml
v1 서비스만 보이도록(별없음)
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
---
🔹 카나리 배포
✅ virtual-service-reviews-80-20.yaml
v1(별없음): 80%, v2(검정별): 20% 트래픽 → 5개의 요청마다 4개를 이전 버전으로, 1개를 새로운 버전으로
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
✅ virtual-service-reviews-v3.yaml
v3 서비스만 보이도록(빨간별)
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v3
🔹 결합 주입
✅ virtual-service-reviews-test-delay.yaml
v3에 대해 50%의 확률로 4초간의 HTTP 지연
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v3
fault:
delay:
percentage:
value: 50
fixedDelay: 4s
✅ virtual-service-reviews-test-delay.yaml 50%의 확률로 HTTP 500 에러를 발생
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v3
fault:
abort:
percentage:
value: 50
httpStatus: 500
- fault-tolerance-retry-timeout.yaml 50% 확률로 500에러 실패하면 3번 재시도, 2초 대기 총 요청 타임아웃은 5초
kubectl logs reviews-v3-77947c4c78-kcsw7 -c istio-proxy
kubectl exec -it productpage-v1-57ffb6658c-zcbwf -c istio-proxy -- curl -v http://reviews:9080/reviews/
100%도 50%로해도 500 로그 확인 또 안되네 브라우저에서 리뷰 안뜨는거 + 안떴다가 retry하니까 뜨는건 확인O
# 1. Fault Injection + Retry + Timeout 예시
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: reviews
namespace: msa-demo
spec:
hosts:
- reviews
http:
- fault:
abort:
percentage:
value: 50
httpStatus: 500
retries:
attempts: 3
perTryTimeout: 2s
retryOn: gateway-error,connect-failure,refused-stream,5xx
timeout: 5s
route:
- destination:
host: reviews
subset: v3
- fault-tolerance-circuit-breaker.yaml 5초 안에 5xx 오류가 2번 발생하면 해당 서버를 30초 동안 트래픽 대상에서 제외시켜버림 전체 서버의 최대 100%까지 제외 가능
# 2. Circuit Breaker 예시 (DestinationRule에 추가)
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: reviews
namespace: msa-demo
spec:
host: reviews
subsets:
- name: v3
labels:
version: v3
trafficPolicy:
outlierDetection:
consecutive5xxErrors: 2
interval: 5s
baseEjectionTime: 30s
maxEjectionPercent: 100
- fault-tolerance-mirroring.yaml 진짜 트래픽은 v1으로 보내고 ****v3로도 몰래 똑같은 트래픽을 복제해서 테스트함 (응답은 안 기다림)
# 3. Mirroring (복제 테스트) 예시
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: reviews
namespace: msa-demo
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
mirror:
host: reviews
subset: v3
mirrorPercentage:
value: 100.0
book-info fault-inject 실습
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: v2
- destination:
host: reviews
subset: v2
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
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
- route:
- destination:
host: ratings
subset: v2
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: details
spec:
hosts:
- details
http:
- route:
- destination:
host: details
subset: v1
---
쿠버네티스 환경에서 MSA구성
각각 불러온 이미지
choiseungyoung/book:3
choiseungyoung/frontend:8
choiseungyoung/review:2
book-service.yml
book-service.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: book-service
namespace: msa-demo
spec:
replicas: 1
selector:
matchLabels:
app: book
template:
metadata:
labels:
app: book
spec:
containers:
- name: book
image: choiseungyoung/book:3
ports:
- containerPort: 5001
---
apiVersion: v1
kind: Service
metadata:
name: book-service
namespace: msa-demo
spec:
selector:
app: book
ports:
- port: 5001
targetPort: 5001
type: ClusterIP
frontend-service.yml
frontend-service.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-service
namespace: msa-demo
spec:
replicas: 1
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: choiseungyoung/frontend:8
ports:
- containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
name: frontend-service
namespace: msa-demo
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 5000
type: LoadBalancer
review-service.yml
review-service.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: review-service
namespace: msa-demo
spec:
replicas: 1
selector:
matchLabels:
app: review
template:
metadata:
labels:
app: review
spec:
containers:
- name: review
image: choiseungyoung/review:2
ports:
- containerPort: 5002
---
apiVersion: v1
kind: Service
metadata:
name: review-service
namespace: msa-demo
spec:
selector:
app: review
ports:
- port: 5002
targetPort: 5002
type: ClusterIP
MSA환경에서 서비스매쉬를 이용한 장애복구
용어 | 설명 |
Fault Injection | 일부러 지연(delay)이나 오류(abort)를 발생시켜 서비스 장애를 흉내냄 |
Retry | 요청 실패 시 정해진 횟수만큼 자동 재시도 |
Timeout | 응답을 일정 시간 안에 못 받으면 중단 |
Circuit Breaker | 일정 횟수 이상 실패하면 더 이상 요청 안 보내고 끊어버림 (서비스 보호용) |
사용한 장애복구
기능 | 설정 위치 | 설명 |
🔁 Retry / Timeout | VirtualService | 트래픽 라우팅 시 재시도/시간초과 제어 |
⚡ Circuit Breaker | DestinationRule | 서비스 인스턴스가 지속적으로 에러나면 차단 |
- Fault Injection, Retry, Timeout은 VirtualService에서 설정하고
- Circuit Breaker는 DestinationRule에서 설정한다.
✅장애와 자동복구를 위한 virtualservice.yml → 이거 쓰지 말고 아래꺼 사용
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: review-vs
namespace: msa-demo
spec:
hosts:
- review-service
http:
- fault:
delay:
fixedDelay: 5s
percentage:
value: 100.0
retries:
attempts: 3
perTryTimeout: 2s
retryOn: gateway-error,connect-failure,refused-stream
route:
- destination:
host: review-service
port:
number: 5002
✅아예 첨부터 오류코드 반환 → 이거 사용!
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: review-vs
namespace: msa-demo
spec:
hosts:
- review-service
http:
- fault:
abort:
percentage:
value: 100.0
httpStatus: 500
route:
- destination:
host: review-service
port:
number: 5002
✅Circuitbreak를 위한 destinationrule.yml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: review-destination
namespace: msa-demo
spec:
host: review-service
trafficPolicy:
outlierDetection:
consecutixve5xxErrors: 3 # 5xx 오류 3번 연속 발생 시
interval: 10s # 검사 간격
baseEjectionTime: 30s # 차단 시간 (30초 동안 해당 인스턴스 제외)
maxEjectionPercent: 100 # 최대 몇 %까지 제외할 수 있는지
로그보기
kubectl logs -l app=frontend -c istio-proxy -n msa-demo | grep review-service
결과
리뷰 작성이 불가능!
Frontend v1,v2구성 후 카나리 배포 확인 , 이후 v2에 fault injection 후 circuit break
✅ 1. msa-demo 네임스페이스 먼저 생성
kubectl create namespace msa-demo
✅ 2. Istio 사이드카 자동 주입 활성화 (이거 중요해!)
kubectl label namespace msa-demo istio-injection=enabled
frontend v1
frontend-service.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-v1
namespace: msa-demo
spec:
replicas: 1
selector:
matchLabels:
app: frontend
version: v1
template:
metadata:
labels:
app: frontend
version: v1
spec:
containers:
- name: frontend
image: choiseungyoung/frontend:21
ports:
- containerPort: 5000
frontend v2
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-v2
namespace: msa-demo
spec:
replicas: 1
selector:
matchLabels:
app: frontend
version: v2
template:
metadata:
labels:
app: frontend
version: v2
spec:
containers:
- name: frontend
image: choiseungyoung/frontend:8
ports:
- containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
name: frontend-service
namespace: msa-demo
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 5000
type: LoadBalancer
gateway.yml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: msa-gateway
namespace: msa-demo
spec:
selector:
istio: ingressgateway # Istio의 기본 Ingress Gateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
frontend-virtualservice.yml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: frontend-vs
namespace: msa-demo
spec:
hosts:
- "*"
gateways:
- msa-gateway
http:
- match:
- uri:
prefix: /
route:
- destination:
host: frontend-service
subset: v1
port:
number: 80
weight: 90
- destination:
host: frontend-service
subset: v2
port:
number: 80
weight: 10
frontend-destinationrule.yml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: frontend-destination
namespace: msa-demo
spec:
host: frontend-service
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
book-service.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: book-service
namespace: msa-demo
spec:
replicas: 1
selector:
matchLabels:
app: book
template:
metadata:
labels:
app: book
spec:
containers:
- name: book
image: choiseungyoung/book:3
ports:
- containerPort: 5001
---
apiVersion: v1
kind: Service
metadata:
name: book-service
namespace: msa-demo
spec:
selector:
app: book
ports:
- port: 5001
targetPort: 5001
type: ClusterIP
review-service.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: review-service
namespace: msa-demo
spec:
replicas: 1
selector:
matchLabels:
app: review
template:
metadata:
labels:
app: review
spec:
containers:
- name: review
image: choiseungyoung/review:2
ports:
- containerPort: 5002
---
apiVersion: v1
kind: Service
metadata:
name: review-service
namespace: msa-demo
spec:
selector:
app: review
ports:
- port: 5002
targetPort: 5002
type: ClusterIP
kubectl apply -f gateway.yml -n msa-demo
kubectl apply -f frontend-service.yml -n msa-demo
kubectl apply -f frontend-service2.yml -n msa-demo
kubectl apply -f frontend-destinationrule.yml -n msa-demo
kubectl apply -f frontend-virtualservice.yml -n msa-demo
kubectl apply -f book-service.yml -n msa-demo
kubectl apply -f review-service.yml -n msa-demo
결과 가중치 80 , 20
Fault injection
"헤더 기반 fault injection은 실제 서비스에 영향 안 주고, 선택적으로 테스트하거나 A/B 실험하는 데 유용하다."
그치만 브라우저처럼 사용자 입력 기반에선 안 먹힘.
frontend-virtualservice.yml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: frontend-vs
namespace: msa-demo
spec:
hosts:
- "*"
gateways:
- msa-gateway
http:
- match:
- headers:
x-version:
exact: v2
fault:
abort:
percentage:
value: 100.0
httpStatus: 500
route:
- destination:
host: frontend-service
subset: v2
port:
number: 80
- route:
- destination:
host: frontend-service
subset: v1
port:
number: 80
weight: 80
- destination:
host: frontend-service
subset: v2
port:
number: 80
weight: 20
frontend-dest.yml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: frontend-dr
namespace: msa-demo
spec:
host: frontend-service
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
trafficPolicy:
outlierDetection:
consecutive5xxErrors: 1
interval: 1s
baseEjectionTime: 30s
maxEjectionPercent: 100
version v1으로 curl →200반환
version v2로 curl → 500반환
curl 211.183.3.202 로 하면 v1,v2 둘 다 뜬다. 가중치에 따라!