공부하고 기록하는, 경제학과 출신 개발자의 노트

학습일지/Service Mesh

Istio Memory 사용량 체크 - Knative Service 개수와 Sidecar Memory 관계 확인

inspirit941 2023. 10. 9. 14:25
반응형

Knative + Istio 조합한 Serverless Service에서 어느 날부터 Sidecar OOMKilled가 발생

 

배포한 knative service 개수는 큰 변화가 없고 k8s 클러스터 리소스도 충분히 여유가 있는데,
istio sidecar가 Memory Limit을 초과해서 OOMkilled가 발생한다.

 

 

찾아보니 mesh에 포함된 workload 개수가 증가할수록 istio-proxy의 메모리 사용량이 증가하는 문제는 이미 잘 알려져 있었고,
Sidecar CR을 사용해서 mesh가 관리할 workload를 namespace 또는 label selector 등을 사용해 제한하는 방식을 안내하고 있었다.

https://medium.com/geekculture/watch-out-for-this-istio-proxy-sidecar-memory-pitfall-8dbd99ea7e9d

 

Watch Out for This Istio Proxy Sidecar Memory Pitfall

We encountered many perplexing issues throughout our ongoing service mesh journey with Istio at my company, many of which left us wishing…

medium.com

https://www.youtube.com/watch?v=JcfLUHdntN4 

 

하나의 Knative Service가 배포될 때 istio-proxy의 메모리 사용량은 얼마나 증가하는지는 확인해봐야 할 것 같아서
테스트해보고 정리한 내용.


 

istio Sidecar는 Knative Revision으로 만들어진 k8s Service의 EDS를 전부 관리하고 있다. scale 0 상태라 해도.

테스트로, knative service를 5번 업데이트해서 revision을 5개, Deployment를 5개 생성한 다음
istioctl proxy-config cluster 명령어로 deployment pod의 envoy configuration을 찾아봤다.

Knative Service Workload는 1개, kubernetes에 pod가 배포된 Deployment는 1개이지만
istio Sidecar는 00001부터 00005까지의 모든 Deployment Workload의 통신에 필요한 정보를 관리하고 있었다.

  • revision이 클러스터에서 관리 중일 경우
    ingressgateway의 traffic splitting 기능을 활용하기 위해서인 것으로 보인다.
  • traffic split을 바로 적용하려면
    Envoy에서도 각 deployment workload별 configuration을 메모리에 들고 있어야 할 테니까.
  • knative는 revision 배포 시 k8s service / k8s private service 두 개를 생성하며
    private의 경우 port 8012, 8022, 9090, 9091, 80, 443 / service의 경우 port 80, 443을 지원한다.

그렇다는 건, Knative Workload를 신규 생성하는 것뿐만 아니라

기존 Workload를 수정하는 작업만으로도
관리해야 할 Envoy Endpoint 개수가 선형적으로 증가하는 셈이다.

-> Knative Revision 개수가 증가할 때 istio Sidecar의 리소스 사용량이 얼마나 늘어나는지 확인해볼 필요가 있었다.


테스트 방법

istio sidecar 메모리 변화를 측정할 knative service를 생성한다.

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: measure-pod
  namespace: istio-system
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/min-scale: "1"
      labels:
        sidecar.istio.io/inject: "true" ## 특정 workload에만 sidecar injection
    spec:
      containers:
      - image: docker.io/kennethreitz/httpbin
        resources:
          requests:
            cpu: 25m
            memory: 25Mi

Knative는 1.11.0, istio는 1.18.2, default 옵션 그대로 설치했다.
그러면 sidecar의 memory request는 128Mi, memory Limit은 1Gi로 설정된다.

knative revision 개수를 늘려가며 Sidecar Limit을 초과하는 시점이 언제인지를 체크해보았다.

default_service_name="test-service"

kn service create $default_service_name --image docker.io/kennethreitz/httpbin --no-wait --scale-init 0 --request memory=25Mi,cpu=25m
for i in $(seq 1 200); do
    kn service update $default_service_name --image docker.io/kennethreitz/httpbin --no-wait --scale-init 0 --env key=$i --request memory=25Mi,cpu=25m
done

revision 개수를 200개씩 늘려가며 sidecar의 메모리 사용량 변화를 확인해본다.

  • scale init을 0으로 설정해서 pod가 실제로 스케줄링되지는 않게 하고, --no-wait 옵션을 줘서 revision이 최대한 빠르게 생성되도록 한다.
  • knative에서 하나의 service에 매핑할 수 있는 revision 개수는 최대 1000개. 따라서 test-service로 revision을 1000개 생성한 뒤, test-service-2 라는 이름으로 새 knative service를 배포했다.

sidecar의 메모리 사용량은 prometheus로 수집되는 값을 확인했다.

  • Memory usage가 대략 800Mi 에서 1.6Gi로 급상승하는 지점이 있는데, istio-proxy에서 OOMkilled가 발생한 순간이다.
  • revision 개수를 1200개 -> 1400개로 증가시키는 시점에서 발생했다.
  • measure-pod의 annotation에 sidecar.istio.io/proxyMemoryLimit=2Gi 를 추가해서 메모리 limit을 2Gi로 올렸다.

 

revision을 200개씩 증가시키면서 확인한 istio proxy의 메모리 사용량 결과는 대략 다음과 같다.

다운로드 (27)

대략 revision이 200개 증가할 때마다 istio proxy의 메모리 사용량이 150Mi 정도 증가하는 양상을 보여주었다.

 


아래 방법을 참고해서 개별 sidecar의 메모리 사용량을 pprof로도 수집해봤는데,
문서와 설정이 다른 건지 제대로 pprof 수치가 수집이 안 되어서 참고하지는 못했다.

https://github.com/istio/istio/wiki/Analyzing-Istio-Performance

 

Analyzing Istio Performance

Connect, secure, control, and observe services. Contribute to istio/istio development by creating an account on GitHub.

github.com

 

 

반응형