KnativeCon 2022 - How Fast is FaaS? Reducing Cold Start Times in Knative
Knative Serving 간단한 설명
- k8s Deployment 생성 과정을 단순화
- Traffic Split for Rollout / Rollback
- AutoTLS for https
- Scale to Zero 기능... 문제는 getting back to One 하려할 때.
Knative Serving의 Scale to Zero / Scale to One 동작방식 정리
현재 service는 scale to zero 상태. 즉 Knative Revision은 있지만, Deployment에 pod 개수는 0인 상황
- k8s Ingress로 request가 들어온다. (contour, courier, istio 등)
- Activator가 트래픽을 받고, Autoscaler에게 요청을 보낸다. Autoscaler는 replicaset을 1로 변경한다.
- k8s가 pod를 생성한다. pod에는 두 개의 컨테이너 - Queue Proxy, App - 가 올라간다.
- istio까지 있으면 envoy proxy가 포함되지만 일단 여기서는 설명하지 않음
- queue-proxy는 simple, fast container - App Container에 ping 보내서 앱이 준비됐는지 체크
- queue-proxy가 App Container의 Health check에 성공하면, Activator가 Queue-proxy로 트래픽 전달
- Autoscaler는 Queue proxy에서 traffic concurrency 정보를 측정한다.
- 기준치 이상의 concurrent traffic이 들어올 경우 replica를 늘려준다.
- Stable 상태로 접어들면, 트래픽이 Activator를 거치지 않고 전달된다.
- stable 상태? - Enough Capacity to sustain the load.
프로세스 중 가장 시간이 오래걸리는 영역은 'Application Pod is created and Running' 부분.
- 이미지 캐시 안되어 있으면 pull 받아오기
- container 생성 + 실행
- readiness, liveness probes
Cold Start 분류
pod가 뜰 때, 해당 pod가 동작할 노드의 상태에 따라 대략 네 가지 상태로 분류할 수 있다.
분류 기준이 될 변수(조건)은 두 가지.
- Is Container Running on that node (Y/N)
- Is Image cached on that node (Y/N)
Cold Start : 이미지가 노드에 캐시되어 있지도 않고, 실행중인 상태도 아닌 경우. 시간이 가장 오래걸림
Warm Disk : 이미지가 노드에 캐시는 되어 있으나, 실행중인 상태가 아님.
Warm Memeory : Container Pause. 트래픽을 받을 준비는 되지 않은 상태.
Warm CPU : Actively Running
Suggestion for User
CNI Space, OCI Space, Cloud Native Space 각 영역에서 고민하고 있는 부분.
Image Pull 최적화하기
- Small Images: 이미지 자체의 크기를 최대한 줄여라
- Base image 작은 거 쓰고, Multi-stage나 docker-slim 등의 방법으로 이미지 자체의 크기를 작게
- Always pull 또는 latest tag 사용하지 않기. 노드에 캐시해두고 쓰는 걸 권장함
- multi-tenant 환경이라서 pod에 떠있는 이미지가 서로 다르면 안되는 상황이라면 어쩔 수 없다.
- Deploy the service but never make it run the first pod? (flag / annotation 있다고 함)
- Knative CRD 중 하나인 Image... 이게 정확히 무슨 기능을 해주는지는 설명하지 않았음. 더 알아보면 좋을 듯
그럼에도 특정 언어의 응답속도가 더 오래 걸리는 건 어쩔 수 없다.
- graalvm + quarkus 조합으로 Java 응답시간을 줄일 수는 있음.
- scale-down-delay: queue proxy에서 보내는 request값이 0이 되었을 때, 어느 정도 시간이 지나야 scale to zero가 될 것인지. (Wait time before shut down and terminate the pod)
- scale-to-zero-pod-retention-period: traffic burst 이후 요청이 줄어들어서 pod를 감소시킬 때, scale to zero로 돌입하기 직전 마지막 pod는 wait time을 좀더 길게 주는 것. (burst traffic이 들어오고 나서, 다시 burst traffic이 들어올 때 응답시간을 단축시키기 위한 옵션으로 보임)
- measure traffic bursty.
Hidden cost : Istio, CNI
- istio를 사용하는 건, boot up container가 하나 더 필요한 셈. istio를 추가했을 때 발생할 성능 이슈는 https://github.com/knative-sandbox/kperf 에서 테스트할 수 있다.
- 특정 cloud provider가 사용하는 CNI... ip pool 정보 가져오는 데 걸리는 시간. 보안 등 서비스 성능과는 무관한 이슈로 bare metal / on-prem에서 knative 사용할 때 발생할 수 있다.
개선 진행중인 작업
각 진영에서 pod up and running 속도 향상을 위해 진행하고 있는 것들은 위와 같다.
knative 진영
- Performance enhancements 진행 중
- Container Freezer
- Kperf
Knative Suggestion : Container Freezer
Container Freezer는, knative의 scale to one 프로세스에 Freeze Daemon을 추가한 것.
- 요청이 들어오면, queue proxy가 app에 readiness probe를 체크하는 대신 Freeze Daemon에 요청을 보낸다.
- Freeze Daemon은 Frozen되어 있던 사용자 App에 Resume 요청을 보낸다.
- 만약 요청이 더 이상 들어오지 않을 경우, Queue proxy는 Freeze Daemon에 App Freeze 요청을 보낸다.
발표 시점에서는 alpha 단계. 퍼포먼스 테스트 결과는 아래와 같다.
Kperf
kperf에서 생성해주는 그래프.
- yellow line (가로축 바닥) : pod scheduled
- orange line (그래프 최상단 줄) : container ready
즉 orange - yellow 사이 구간은 container가 동작할 때까지 걸리는 시간을 의미함. 시각화할 수 있다.
k8s / container runtime / CNI 진영
- Secret pulled images: 보안상의 이유로 cached된 image를 쓸 수 없는 경우가 있을 수 있음. 보안이 강화된 image pull 정책.
- kubelet performance
- CNI 진영에서 PR
- performance : CNI plug-in loading을 병렬로 실행
- improvement
QnA
Q. Container Freezer를 쓰면, 내부적으로 정확히 어떻게 되나? saving resource가 가능해지는 이유?
- 현재 cpu 리소스만 절약됨. 메모리는 그대로. Container 상태 중 Paused와 유사하다고 보면 된다. docker pause 기능을 containerd에서 실행한 셈.
Q. What barriers do you see to turning this on by default?
- probing interface 방식. 지금은 readiness probe를 활용해서 container 상태를 체크중. container pause 기능을 쓰면, readiness probe 방식을 적용할 수 없음.
- 그래서 startup probe 기능을 도입하려는 시도 중임. 좀더 면밀히 테스트해야 하기에 알파 테스트부터 하고 있다.