https://youtu.be/hsJ2qtwoWZw?si=K1sRyOkeJotnkdh5
k8s는 run application at scale이 가능함. built-in으로 제공되는 autoscaler / 추가로 설치하는 것까지 종류가 다양하다.
- 낮에 트래픽 많고 밤에는 적은 이커머스 사이트라거나
- ETL 수행이 끝나면, 작업에 사용한 리소스를 반납해서 비용을 줄인다거나
일반적으로는 scale을 위해 pod를 증가시키는데, k8s 클러스터 리소스에 여유가 없을 경우 node를 증가시켜야 한다.
- 따라서 autoscale할 대상이 pod인지 node인지 구분해서 설명한다.
HPA
- k8s CRD 방식으로 구현. k8s Controller plane을 사용함.
- CPU / Memory 사용량에 따라 Deployment 또는 StatefulSet의 pod 개수를 변경한다.
- 일반적으로, Metric 수집을 위해 Metrics Server를 클러스터에 배포한다.
cf. GCP GKE, Azure AKS는 metrics server가 설치된 클러스터를 제공하지만, AWS EKS는 설치되지 않은 채 제공된다.
metric server는 각 노드의 kubelet를 사용해서 정보를 수집하고, 수집된 데이터를 다른 컴포넌트에 전달한다.
HPA를 배포하면, 대상이 될 Resource (i.e. Deployment)의 metric 정보를 토대로 scaling을 진행한다.
- Deployment나 Statulset는 resource Request 필드는 필수, Limit은 optional (highly recommended) 필드.
- gitOps 등으로 배포한다면, replicas 필드는 명시하지 않는 것을 권장. HPA가 세팅하기 때문.
- HPA에서 cpu 또는 memory의 사용량이 기준치를 넘을 경우 scale하도록 설정할 수 있다.
다만, 꼭 CPU / Memory만을 scale의 기준치로 쓸 수는 없다. 아래와 같은 4 Golden Signals 정보가 대표적인 예시인데
- Latency
- Traffic
- Errors
- Saturation
예컨대 사용자 앱이 100 RPS를 넘을 수 없는 구조라면, scale 기준은 CPU / Memory가 아니라 RPS여야 한다.
- Metrics Server는 이런 정보를 수집하지 않는다.
- Prometheus와 같은 별도의 컴포넌트가 필요.
Prometheus Operator 설치하고, instance를 세팅한다.
확인해야 할 애플리케이션을 배포하고, Prometheus가 체크할 수 있도록 ServiceMonitor 또는 PodMonitor를 배포한다.
Prometheus에서 수집한 metric을 Convert해서 custom.metrics.k8s.io로 매핑하는 Adapter를 생성한다.
- adapter를 사용해서 custom metrics로 등록한 데이터는 HPA에서 활용할 수 있다.
추가로, 이렇게 되면 기존의 CPU / Memory 정보도 metrics server 컴포넌트를 쓰지 않아도 된다.
- pod의 cAdvisor 정보 활용하면 pod의 cpu / memory 정보를 얻을 수 있다.
- cpu / memory 정보도 adapter 활용해서 metrics.k8s.io 에 등록하면 된다.
단, node 단위로 metric 수집하려면 node-exporter가 각 노드마다 필요하다.
- 그래야 metric server에서 kubelet 사용해서 수집하던 노드 단위의 metric정보를 완전히 대체할 수 있다.
이 조건이 전부 충족되면, RPS (number of request per second) 또는 다른 종류의 metric으로도 Scaling이 가능하다.
VPA
DB와 같은 Stateful 애플리케이션의 경우, stateless app 대비 Scale out이 쉽지 않다. Scale Up이 필요한 경우가 있음.
- k8s에서는 scale up을 위한 Autoscaler로 VPA가 있다.
VPA는 2개의 모드가 있다.
- Recreate: 기존 pod를 삭제하고, resource request를 변경한 신규 pod를 생성하는 방식. 인스턴스가 날아가기 때문에 매우 유의해서 써야 한다.
- initial: 인스턴스 최초 생성할 때만 resource 할당하고, 이후에는 변동 없음
- off: 가장 많이 쓰는 모드. Recommendation만 제공해준다.
- maintenance window 동안의 데이터를 토대로 next recommendation 정보를 전달.
클러스터에 별도로 CR과 Controller를 설치하면, k describe vpa <app name>
형태로 recommendation 정보를 볼 수 있다.
- HPA와 동시에 사용할 수 없다.
stateless 서비스와는 궁합이 좋지 않다. 쓰지 않는 것을 권장.
- nginx 5개 pod가 있으면, 5개의 workload가 작업을 처리할 수 있는 최적 cpu / memory를 추천해준다.
- 같은 작업을 하는 pod가 20개 있으면, 20개의 workload가 작업을 처리할 수 있는 최적 cpu / memory를 추천해준다.
즉 stateless app에 유의미한 동작방식을 제공하지 않음.
따라서 horizontal scale이 어려운 stateful application일 때만 사용하는 게 좋다.
KEDA
서비스가 Kafka / NAS / RabbitMQ 같은 message queue를 두고, Producer / Consumer 방식으로 구성된 경우가 있을 수 있다.
- message Queue의 정보를 보고, 메시지가 많이 들어올 경우 consumer pod를 scale out하는 방식.
- 장점: message Queue에 데이터가 없으면 Scale 0으로 떨어뜨릴 수 있다.
다양한 종류의 scaler를 지원하고 있다.
- 퍼블릭 클라우드 서비스인 dynamoDB나 오픈소스 프로덕트인 etcd, mysql, kafka 등
- 클러스터에 KEDA controller 배포한다.
- scale out 기준이 될 queue 개수를 설정한다. 예시의 경우 5
- 메시지 발행이 많아지면, 그만큼 많이 pod를 실행한다.
- 메시지 consume이 끝나고 queue에 데이터가 없으면, scale 0까지 내려갈 수 있다.
- idle pod 띄워두는 형태로 커스텀할 수 있다.
Cluster Autoscaler
클러스터의 노드를 autoscaling하는 방식.
- AWS는 사용자가 직접 세팅해야 하지만, Azure나 GCP는 Managed 형태로 쉽게 설치하고 사용할 수 있다.
일반적으로 k8s는 autoscaling group을 구성한다. 노드 타입 (cpu / memory)은 같을 수도, 다를 수도 있다.
- pending pod 개수를 확인해서, 여유가 없을 경우 autoscaling group에 정의된 노드 타입을 새로 할당한다.
- 문제는, pending pod에서 필요한 리소스 양이 매우 적은데 (cpu 100m), 이거 하나 때문에 신규 노드를 할당해야만 하는 경우.
- 신규 노드는 곧 비용인데, 이러면 낭비가 너무 크다.
Karpenter
AWS에서 개발한 cluster autoscaling tool.
- instead of scaling out node group with same instance types, analyze the pending pod resource / create EC2 instance fit with pending workloads.
단, logging / monitoring / other Agents를 Daemonset으로 노드마다 설치해야 하는 경우
- daemonset까지 충족하기 위해 large instance가 할당되는 edge case 고려해야 한다.
Serverless Kubernetes : Fargate (AWS) / Autopilot (GCP)
Dedicated Cluster에 노드 할당 / 애플리케이션을 배포해준다.
- 리소스 낭비 걱정은 없으나, 단가가 일반 EC2 인스턴스보다 비싸다.