circuit break에 대해 다양한 관점이 있습니다. 이 글에서 말하는 circuit break는 쿠버네티스 pod 안정성 관점에서 circuit break입니다. pod 안전성 관점에서 circuit break는 pod가 죽지 않도록, 강제로 pod에 들어오는 요청을 거절합니다. 요청을 거절하는 이유는 쿠버네티스 관점에서 pod가 죽지 않게 보호하기 위해서입니다. pod가 처리할 수 있는 요청수보다 많은 요청을 받으면, pod는 재실행 될 수 있습니다. pod의 cpu, memory가 100%를 넘게 사용하는 상황이 발생하고 OOM 또는 probe검사 실패로 pod가 재실행됩니다.
만약 모든 pod가 재실행되는 경우 서비스 장애로 이루어집니다. 그래서 운영자는 pod 재실행되지 않도록 안전하게 보호해야 하는데, 구현 방법 중 한개가 circuit break입니다.
비지니스 관점에서는 장애범위를 최소화합니다. pod가 다른 pod가 호출하고 그 pod가 다른 pod를 호출하는 것처럼 비지니스 호출이 꼬리를 물 때, 어느 한 곳에 장애가 일어나면 장애가 전파됩니다. 장애가 전파되면 디버깅이 어렵고 복구하기가 매우 힘듭니다. 그래서 미리 circuit break를 설정하여 장애범위를 축소시켜 향후 대처를 빠르게 합니다.
istio circuit break는 envoy trafficPolicy필드로 설정합니다. trafficPolicy는 트래픽흐름을 제어합니다.
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: example
spec:
host: "example.com"
trafficPolicy:
connectionPool:
생략
outlierDetection:
생략
YAML
복사
•
connectionPool은 커넥션 풀 기반으로 요청을 거절합니다. 만약 설정한 커넥션을 넘으면 host로 오는 요청을 거절합니다.
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: circuit-break-example
spec:
host: "circuit-break-example"
trafficPolicy:
connectionPool:
tcp:
maxConnections: 50
http:
http1MaxPendingRequests: 50
maxRequestsPerConnection: 50
YAML
복사
•
outlier detection(이상탐지)는 요청을 일정시간동안 거절할 때 사용합니다. 아래 예제에서는 host요청 응답이 5xx에러가 연속 7번 발생하면 3분동안, host로 오는 요청을 거절합니다. 요청 거절 시간은 baseEjectionTime으로 설정합니다.
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: example
spec:
host: "example.com"
trafficPolicy:
outlierDetection:
consecutive5xxErrors: 7 # 연속 7개의 5xx 에러 발생 시 차단
baseEjectionTime: 3m # 차단된 Pod 복귀 시간 (기본 30초)
maxEjectionPercent: 100 # 최대 100%의 Pod를 차단 가능
consecutiveErrors: 1 # error 1회 발생시 -> unhealthy
...이하생략
YAML
복사
connection Pool Example
•
connection Pool로 circuit break를 구현합니다. connection pool 최대 갯수를 초과하면 host에 대한 요청을 거절합니다.
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: circuit-break-example
spec:
host: "circuit-break-example"
trafficPolicy:
connectionPool:
tcp:
maxConnections: 50
http:
http1MaxPendingRequests: 50
maxRequestsPerConnection: 50
YAML
복사
outlier detetion Example
•
5xx http응답이 7번 발생하면 host에 대한 요청을 3분간 거절합니다.
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: example
spec:
host: "example.com"
trafficPolicy:
outlierDetection:
consecutive5xxErrors: 7
baseEjectionTime: 3m
YAML
복사
모니터링 방법
istio는 요청에 대한 메트릭을 남깁니다. 어떤 출발지가 어떤 도착지로 요청을 했는지 그리고 요청에 대한 결과를 메트릭으로 남깁니다. 메트릭이름은 istio_requests_total입니다.
sum(istio_requests_total{response_code=~"5[0-9]{2}"}) by (source_app, destination_service_name) != 0
SQL
복사
utlierDetection(이상탐지)설정으로 생긴 circuit break는 실시간으로만 istioctl명령어로 디버깅 가능합니다.
istioctl proxy-status
Shell
복사
istioctl proxy-config endpoints {pod이름}.{namespace}
Shell
복사
connectionPool설정으로 circuit break가 적용되었다면 envoy_cluster_upstream_rq_pending_overflow메트릭을 보면 됩니다.
envoy_cluster_upstream_rq_pending_overflow != 0
SQL
복사
실습
•
deployment.yaml
# 200 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-v200
namespace: demo
spec:
replicas: 1
selector:
matchLabels:
app: demo
version: v200
template:
metadata:
labels:
app: demo
version: v200
spec:
containers:
- name: demo-v200
image: IMAGE # 200 응답 이미지
ports:
- containerPort: 8081
---
# 5xx Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-v5xx
namespace: demo
spec:
replicas: 1
selector:
matchLabels:
app: demo
version: v5xx
template:
metadata:
labels:
app: demo
version: v5xx
spec:
containers:
- name: app-v5xx
image: IMAGE # 5xx 응답 이미지
imagePullPolicy: Always
ports:
- containerPort: 8081
YAML
복사
•
gateway.yaml
# Gateway 설정
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: demo-gateway
namespace: demo
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
YAML
복사
•
svc.yaml
apiVersion: v1
kind: Service
metadata:
name: demo-service
namespace: demo
spec:
selector:
app: demo
ports:
- protocol: TCP
port: 8081
targetPort: 8081
YAML
복사
•
vs.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: demo-virtualservice
namespace: demo
spec:
hosts:
- "*"
gateways:
- demo-gateway
http:
- route:
- destination:
host: demo-service
port:
number: 8081
YAML
복사
•
dr.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: demo-dr
namespace: demo
spec:
host: demo-service
trafficPolicy:
outlierDetection:
maxEjectionPercent: 100 # 서비스 전체를 차단
consecutive5xxErrors: 3 # 5xx 오류가 3회 연속 발생하면 Circuit Breaker 발동
interval: 5s # 오류를 체크하는 주기
baseEjectionTime: 30s # Circuit Breaker 발동 시 30초간 해당 서비스로의 트래픽을 차단
YAML
복사
kubectl label namespace default istio-injection=enabled
Shell
복사
# 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.
##################################################################################################
# httpbin service
##################################################################################################
apiVersion: v1
kind: ServiceAccount
metadata:
name: httpbin
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
service: httpbin
spec:
ports:
- name: http
port: 8000
targetPort: 80
selector:
app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
version: v1
template:
metadata:
labels:
app: httpbin
version: v1
spec:
serviceAccountName: httpbin
containers:
- image: docker.io/kong/httpbin
imagePullPolicy: IfNotPresent
name: httpbin
ports:
- containerPort: 80
YAML
복사
kubectl apply -f httpbin.yaml
Shell
복사
•
마이크로서비스 로드 테스트 툴인 fortio를 설치
apiVersion: v1
kind: Service
metadata:
name: fortio
labels:
app: fortio
service: fortio
spec:
ports:
- port: 8080
name: http
selector:
app: fortio
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: fortio-deploy
spec:
replicas: 1
selector:
matchLabels:
app: fortio
template:
metadata:
annotations:
# This annotation causes Envoy to serve cluster.outbound statistics via 15000/stats
# in addition to the stats normally served by Istio. The Circuit Breaking example task
# gives an example of inspecting Envoy stats via proxy config.
proxy.istio.io/config: |-
proxyStatsMatcher:
inclusionPrefixes:
- "cluster.outbound"
- "cluster_manager"
- "listener_manager"
- "server"
- "cluster.xds-grpc"
labels:
app: fortio
spec:
containers:
- name: fortio
image: fortio/fortio:latest_release
imagePullPolicy: Always
ports:
- containerPort: 8080
name: http-fortio
- containerPort: 8079
name: grpc-ping
YAML
복사
kubectl apply -f fortio-deploy.yaml
Shell
복사
export FORTIO_POD=$(kubectl get pods -lapp=fortio -o 'jsonpath={.items[0].metadata.name}')
kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio curl -quiet http://httpbin:8000/get
Shell
복사
•
Prometheus Install
kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/addons/prometheus.yam
Shell
복사
•
Kiali Install
kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/addons/kiali.yaml
Shell
복사
kubectl patch svc kiali -n istio-system -p '{"spec": {"type": "LoadBalancer"}}'
Shell
복사
kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio load -c 2 -qps 0 -n 20 -loglevel Warning http://httpbin:8000/get
Shell
복사
•
최소한의 커넥션만 허용하도록 설정
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
outlierDetection:
consecutiveErrors: 1
interval: 1s
baseEjectionTime: 3m
maxEjectionPercent: 100
YAML
복사
kubectl apply -f dr.yaml
Shell
복사
kubectl exec "$FORTIO_POD" -c fortio -- /usr/bin/fortio load -c 3 -qps 0 -n 30 -loglevel Warning http://httpbin:8000/get
Shell
복사
•
Grafana Install
kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/addons/grafana.yaml
Shell
복사
kubectl patch svc grafana -n istio-system -p '{"spec": {"type": "LoadBalancer"}}'
Shell
복사
•
Jaeger Install
kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/addons/jaeger.yaml
Shell
복사
kubectl patch svc tracing -n istio-system -p '{"spec": {"type": "LoadBalancer"}}'
Shell
복사