Search

Circuit break

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
복사