Istio Performance & Stability


docker engine 18.06.2-ce, kubernetes 1.13.4, Istio 1.1.1 , minikube v0.35.0, macOS Mojave 10.14.4(18E226)

Istio의 성능 결과 문서를 정리하고 github 에 공개되어 있는 벤치마크 프로젝트를 minikube 환경에서 직접 실행해 봅니다.

개요


1000 services and 2000 sidecars with 70,000 mesh-wide requests per second

Performance Summary

Offical Load Test 결과는 아래와 같음

  • Envoy 프록시 초당 100건 - 0.6 vCPU and 50 MB memory 사용
  • istio-telemery 서비스 - 0.6 vCPU 사용
  • Pilot - 1 vCPU, 1.5G memory 사용
  • Envoy 프록시 latency - 8ms가 90%

Control Plane 성능

  • 설정과 가능한 시스템 상태 에 따라서 CPU, Memory 필요량 결정
  • CPU 사이즈는 다음 사항에 따라 결정
    • The rate of deployment changes.
    • The rate of configuration changes.
    • The number of proxies connecting to Pilot.
  • a single Pilot instance can support 1000 services, 2000 sidecars with 1 vCPU and 1.5 GB of memory.

Data Plane 성능

아래 사항이외에도 많은 요소에 따라 결정됨

  • Number of client connections
  • Target request rate
  • Request size and Response size
  • Number of proxy worker threads*
  • Protocol
  • CPU cores
  • Number and types of proxy filters, specifically Mixer filter.

CPU & Memory

// TODO

Latency

// TODO

fortio.org

  • Latency 측정 툴
  • Istio 로드 테스팅툴로 시작
  • 실행시간을 퍼센트로 계산해서 기록해줌

  • 실치 (mac)
    • brew install fortio
    • Docker 설치도 가능
  • 사용예제
    $ fortio load http://www.google.com
    

Offical Performance Test 프로젝트


/istio-install

  • https://github.com/istio/tools/tree/master/perf/istio-install
  • 성능테스트를 위해 Istio를 설정하는 스크립트 및 Helm 제공.
  • 이 클러스터는 Istio의 한계를 테스트하기 위한 아주 큰 클러스터로 설계
  • 대부분의 테스트는 Istio 표준 설치 상태에서 실행 가능
  • 성능체크를 위한 이스티오 성능 권장 설정되어 있으나 대용량 클러스터가 필요, 적어도 32 vCPU

/load

  • https://github.com/istio/tools/tree/master/perf/load
  • 이스티오 havey load 상에서 테스트하기 위한 대용량 서비스를 생성하는 툴을 제공
  • Fortio 인스턴스로 설치
  • 각 인스턴스는 적어도 6 vCPU에 6G 메모리 필요 (그림상으로는 인스턴스가 9인데. 그럼 54 vCPU에 54G 리소스가 필요한건가?)

/benchmark

  • https://github.com/istio/tools/tree/master/perf/benchmark
  • 파드와 다양한 셋업 간의 트래픽 메트릭스와 latency를 측정하는 테스트를 제공
  • 다양한 페이로드 크기와 커넥션 수를 변경하며 각 설정값에서 두개의 파드간의 성능 측정
  • 측정 변경값 : 커넥션수, qps
  • 측정 시나리오
    • default : sidecar -> sidecar
    • serversidecar : client -> sidecar
    • baseline : clinet -> server
  • 결과분석
    • Fortio & Prometheus 로 부터 qps, cpu/memory, latency 추출

/stability

  • https://github.com/istio/tools/tree/master/perf/stability
  • Istio의 안정성을 보장하기 위해서 다양한 Istio의 기능을 발휘하는 테스트를 제공
  • 테스트의 목적은 통합테스트와 차별화된 장기적고 연속적으로 실행

  • 테스트 종류
    • http10 : http 1.0 지원 테스트
    • graceful-shutdown
      • 프록시의 자연스러운 종료를 보장하는지를 테스트임
      • 서버가 재배포될때 연결이 끊어지지 않게 트래픽들이 새로운 배포로 자연스럽게 옮겨지는지 확인
    • gateway-bouncer : 게이트웨이 준바상태 테스트
    • istio-upgrader : 기본값이 아님. 이스티오 컴포넌들을 재배치 이스티오 전체에 영향을 미치는지
    • allconfig : 현재버그 있음
    • sds-certmanager : g클라우드 GCP DNS 설정과 gcp DNS 존 DNS_ZONE 환경변수 값 지정 필요
  • 성능 분석
    • Grafana 대시보드 : 테스트 성능분석 및 상태 측정에 유용할 툴
    • https://github.com/istio/tools/blob/master/metrics/check_metrics.py : 프로메테우스로부터 metrics 를 가져고 각각의 시나리오의 상태를 확인하기 위한 분석 할 수 있음. Grafana 만으로는 괜찮은 실행상태인지 판단하기 애매한 몇몇 테스트에 유용함

준비작업 (Performance, Stability 테스트 공통)


minikube

  • minikube 인스턴스 삭제 설치 (minikube 설치 되어있다는 전제)
  • minikube 기본값으로 kubernetes + istio 설치 + 성능측정이 불가능하므로 리소스를 늘려서(6cpu, 8g) 인스턴스를 생성
$ minikube delete
$ minikube start --cpus 6 --memory 8192
$ minikube ssh

Helm 초기화

  • helm 클라이언트가 설치되었다는 전제
$ helm init

istio 설치

  • 몇가지 설치 방법 중 helm 으로 설치 (https://istio.io/docs/setup/kubernetes/install/helm/)
$ wget https://github.com/istio/istio/releases/download/1.1.1/istio-1.1.1-osx.tar.gz
$ tar -vxzf istio-1.1.1-osx.tar.gz
$ cd istio-1.1.1
$ kubectl create namespace istio-system
$ helm template install/kubernetes/helm/istio-init --name istio-init --namespace istio-system | kubectl apply -f -
$ helm template install/kubernetes/helm/istio --name istio --namespace istio-system | kubectl apply -f -

테스트 프로젝트 다운로드

$ git clone https://github.com/istio/tools.git
$ cd tools

Benchmark 테스트 진행


준비작업

  • 테스트로 사용할 twopods namespace를 생성하고 사이드카(envoy)가 설치될 수 있도록 istio-injection 레이블링
  • setup_test.sh 실행
$ cd perf/benchmark
$ DNS_DOMAIN=local ./setup_test.sh
  • twopods 라는 namespace로 “fortioclient”, “fortioserver” 2개 파드가 생성

테스트 진행

$ export NAMESPACE=twopods
$ python runner/runner.py 2,4 10,40 90 --serversidecar --clientsidecar --baseline
  • runner.py의 1,2번째 파라메터 2,4 는 connection
  • runner.py의 3,4번째 파라메터 10,40은 qps
  • runner.py의 5번째 파라메터 90은 수행시간을 의미
  • runner.py의 6번째 이후 파라메터는 테스트 종류를 의미 (3종)
    • serversidecar : server sidecar injection
    • clientsidecar : server & client sidecar injection
    • baseline : no sidecar
  • 위 예에서 90초 동안 (2 x 2 x 3) 12종류 테스트가 진행된다.
  • 결과 확인(forio.py실행)시 지정된 값 이전 데이터는 SKIP 처리(METRICS_START_SKIP_DURATION) default 값이 62로 지정되어 있으므로 측정시간을 최소 62초 이상으로 지정해야 합니다.
  • 환경변수 “NAMESPACE” 는 필수 (default 값은 ‘service-graph’)

결과확인

  • Prometheus, Fortio 포트 포워딩
$ kubectl -n twopods port-forward $(kubectl -n twopods get po -l app=fortioclient -o jsonpath={.items[0].metadata.name}) 8080 &
$ kubectl -n istio-system port-forward $(kubectl -n istio-system get po -l app=prometheus -o jsonpath={.items[0].metadata.name}) 9090 &
  • fortio.py를 실행하면 2개의 아래와 같은 내용을 가진 임시 파일이 생성
$ python ./runner/fortio.py http://localhost:8080 http://localhost:9090 --csv StartTime,ActualDuration,Labels,NumThreads,ActualQPS,p50,p90,p99,cpu_mili_avg_telemetry_mixer,cpu_mili_max_telemetry_mixer,mem_MB_max_telemetry_mixer,cpu_mili_avg_fortioserver_deployment_proxy,cpu_mili_max_fortioserver_deployment_proxy,mem_MB_max_fortioserver_deployment_proxy,cpu_mili_avg_ingressgateway_proxy,cpu_mili_max_ingressgateway_proxy,mem_MB_max_ingressgateway_proxy
{"mem_MB_max_ingressgateway_proxy": 24, "cpu_mili_max_telemetry_mixer": 5, "mem_MB_max_fortioserver_deployment_proxy": 29, "cpu_mili_min_ingressgateway_proxy": 13, "cpu_mili_min_fortio_deployment_captured": 22, "cpu_mili_avg_pilot_proxy": 11, "mem_MB_max_fortioserver_deployment_captured": 6, "proxyaccesslog": true, ......

분석 지표

  • fortio.py 실행하여 얻은 분석결과는 3개의 시나리오에 대한 latency 측정 결과(fortio)와 리소스 측정결과(prometheus)로 나누어집니다.

  • Fortio를 활용한 Latency 측정 (ms)
    • p50
    • p75
    • p90
    • p99
    • min
    • max
    • avg
  • prometheus를 활용한 구성요소 cpu(milisecond), memory(mb) 사용량 측정 - 각 요소들에 대한 min,max,avg 값
    • ingressgateway_proxy
    • telemetry_proxy
    • telemetry_mixer
    • pilot_proxy
    • pilot_discovery
    • policy_proxy
    • policy_mixer
    • fortio_deployment_proxy
    • fortio_deployment_captured
    • fortio_deployment_uncaptured
    • fortioserver_deployment_proxy
    • fortioserver_deployment_captured
    • fortioserver_deployment_uncaptured

Web UI에서 결과확인

  • FORTIO_URL PROMETHEUS_URL 을 웹브라우저에서 열면 확인가능
  • Prometheus 예제 쿼리를 실제 데이터 확인
irate(container_cpu_usage_seconds_total{container_name=~"mixer|policy|discovery|istio-proxy|captured|uncaptured"}[1m])
  • 참고 : Prometheus API 호출은 다음과 같음
$PROMETHEUS_URL/api/v1/query_range?start=2019-04-03T01:00:00.000Z&end=2019-04-03T02:00:00.000Z&step=15&query=irate(container_cpu_usage_seconds_total{container_name=~"mixer|policy|discovery|istio-proxy|captured|uncaptured"}[1m])

Stability 테스트 진행


준비작업

$ cd perf/stability/
  • minikube 환경이므로 LoadBalancer의 ExternalIP가 바인딩 되지 않는다. (Pending 상태) 그러므로 setup_tests.sh 파일을 열고 istio-ingressgateway의 gateway 주소를 변경 (39라인)
$ vi setup_tests.sh
$ local gateway=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingres/s[0].ip}')
$ local gateway="http://$(kubectl get service/istio-ingressgateway -n istio-system -o jsonpath={.spec.clusterIP})"

http10 테스트 실행

$ TESTS="http10" ./setup_tests.sh setup

네임스페이스 gateway-bouncer 조정 작업

  • ingree를 아래와 같이 NodePort로 변경해 주었으므로 아래와 같이 clusterIP를 사용하도록 수정
$ vi gateway-bouncer/setup.sh
$ INGRESS_IP=$(kubectl -n ${NAMESPACE} get service istio-ingress-${NAMESPACE} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ INGRESS_IP=$(kubectl -n ${NAMESPACE} get service istio-ingress-${NAMESPACE} -o jsonpath='{.spec.clusterIP}')
$ kubectl get pod -n http10
$ kubectl get pod -n gateway-bouncer
$ kubectl get pod -n graceful-shutdown

http10 테스트 결과분석

  • 프로메테우스 서비스 URL
$ echo "http://$(kubectl get service/prometheus -n istio-system -o jsonpath={.spec.clusterIP})"
  • 프로메테우스 예제 쿼리
irate(container_cpu_usage_seconds_total{namespace="http10"}[1m])
irate(container_cpu_usage_seconds_total{container_name=~"http10.+"}[1m])

posted at 2019/04/08 10:30