Keda 공식 홈페이지
Keda 구성 시 참고 주소
과연 kubernetes에서 제공해주는 기본 hpa 말고 개발환경에 맞는 pod 오토스케일링은 안되는 걸까? 라는 호기심으로 시작하여 알아보니 prometheus와 연동하여 prometheus의 지표를 사용하여 오토스케일링 하는 방법이 있어 적용하는 과정입니다 !
KEDA 기반으로 확장 할 수 있는 이벤트 소스 중 Prometheus랑 연동하여 스케일
ex) Facade API, node.js 등 CPU와 Memory 지표를 가지고 스케일이 어려운 상황이므로 Prometheus랑 연동하여 스케일
helm 설치 가이드
~~helm 설치 (mac-os)
$ brew install helm~~
스크립트로 helm 설치
$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
$ chmod 700 get_helm.sh
$ ./get_helm.sh
$ helm repo add kedacore https://kedacore.github.io/charts
$ helm repo update
~~# keda를 설치할 namespace 생성
$ kubectl create namespace keda
$ helm install keda kedacore/keda --namespace keda~~
keda 삭제 시 주의사항
scaleobject를 제외하고 패키지만 삭제 시 불필요한 scaleobject들이 남아있어 리소스를 먼저 삭제 후
keda 삭제
for i in $(kubectl get scaledobjects -oname);
do kubectl patch $i -p '{"metadata":{"finalizers":null}}' --type=merge
done
for i in $(kubectl get scaledjobs -oname);
do kubectl patch $i -p '{"metadata":{"finalizers":null}}' --type=merge
done
Keda-helm-repo 받기
$ helm pull keda kedacore/keda
$ tar xvf ~
$ cd keda
Prometheus의 매트릭을 이용하는 scale 예시 yaml
apiVersion: v1
kind: Secret
metadata:
name: keda-prom-secret
namespace: default
data:
username: "dXNlcm5hbWUK" # Must be base64
password: "cGFzc3dvcmQK" # Must be base64
---
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
name: keda-prom-creds
namespace: default
spec:
secretTargetRef:
- parameter: username
name: keda-prom-secret
key: username
- parameter: password
name: keda-prom-secret
key: password
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: facade-api
namespace: ns
spec:
pollingInterval: 60
minReplicaCount: 1
maxReplicaCount: 10
scaleTargetRef:
name: facade-api
triggers:
- type: prometheus
metadata:
serverAddress:
metricName: http_requests_total
threshold: '60'
query: max(nodejs_active_handles_total{app_kubernetes_io_name=~"facade-api"})
# sum(rate(http_requests_total{deployment="my-deployment"}[2m]))
# authModes: "basic"
# authenticationRef:
# name: keda-prom-creds
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: api
namespace: [오토스케일을 설정하고 싶은 리소스가 존재하는 ns에 설정]
spec:
pollingInterval: 60 # 초 단위
minReplicaCount: 1
maxReplicaCount: 10
scaleTargetRef:
name: facade-api
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus.[prometheus가 설치된 ns].svc.cluster.local:9090
metricName: nodejs_active_handles_total
threshold: '60'
query: max(nodejs_active_handles_total{app_kubernetes_io_name=~"facade-api"})
# sum(rate(http_requests_total{deployment="my-deployment"}[2m]))
# authModes: "basic"
# authenticationRef:
# name: keda-prom-creds
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: web
namespace: [오토스케일을 설정하고 싶은 리소스가 존재하는 ns에 설정]
spec:
pollingInterval: 60
minReplicaCount: 2
maxReplicaCount: 10
scaleTargetRef:
name: web
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus.[prometheus가 설치된 ns].svc.cluster.local:9090
metricName: nodejs_active_handles_total_web
threshold: '40'
query: max(nodejs_active_handles_total{app_kubernetes_io_name=~"web"})
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/namespaces/YOUR_NAMESPACE/YOUR_METRIC_NAME"
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/namespaces/[namespace]/nodejs_active_handles_total_web"
여러 ScaledObject가 동일한 메트릭 이름을 가질 때 메트릭을 얻는 방법
kubectl get scaledobject SCALEDOBJECT_NAME -n NAMESPACE -o jsonpath={.metadata.labels}
kubectl get scaledobject web -n NAMESPACE -o jsonpath={.metadata.labels}
kubectl get scaledobject facade-api -n NAMESPACE -o jsonpath={.metadata.labels}
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/namespaces/sample-ns/s1-rabbitmq-queueName2?labelSelector=scaledobject.keda.sh%2Fname%3D{ScaledObjectName}"
Facade
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/namespaces/[namespace]/s0-prometheus-nodejs_active_handles_total?labelSelector=scaledobject.keda.sh%2Fname%3Dfacade-api"
Web
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/namespaces/[namespace]/s0-prometheus-nodejs_active_handles_total_web?labelSelector=scaledobject.keda.sh%2Fname%3Dweb"
TEST - 방법
부하TEST를 하기에는 추가적인 비용이 발생하므로 threshold의 값을 임의로 낮추어서 test 진행
TEST part.1 - 순서
threshold: 40 → threshold: 3
interval이 걸려 있으므로 1분 대기
5/3 hpa가 동작 (1분 소요)
deployment 상태도 1
5/3 이므로 hpa 스케일링 시작
deploy에서 pod 개수가 순차적으로 증가하는 모습
web의 pod 수가 [1 → 2] , [2 → 3] 증가 후 hpa에서 자원들이 안정화 된 모습 - 1667m/3
threshold: 3 → threshold: 40으로 늘려 준 뒤
정상적으로 pod들도 내려간 모습
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: web
namespace: [오토스케일을 설정하고 싶은 리소스가 존재하는 ns에 설정]
spec:
pollingInterval: 60
minReplicaCount: 1
maxReplicaCount: 10
scaleTargetRef:
name: web
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus.[prometheus가 설치된 ns].svc.cluster.local:9090
metricName: nodejs_active_handles_total_web
threshold: '20' # 수치를 낮춰서 진행
query: max(nodejs_active_handles_total{app_kubernetes_io_name=~"web"})
#sum(rate(http_requests_total{deployment="my-deployment"}[2m]))
# authModes: "basic"
# authenticationRef:
# name: keda-prom-creds
TEST part.2 - 순서
threshold: 40 → threshold: 20
interval이 걸려 있으므로 1분 대기
ngrinder를 활용하여 부하진행
5/20 hpa가 동작 (1분 소요)
deployment 상태도 1
209/20 이므로 hpa 스케일링 시작
kubectl get hpa -n [namespace] -w 시 web의 TARGETS = 209
prometheus = 209
동일한 쿼리 사용 확인
kubectl get hpa -n [namespace] -w 시 TARGETS = 97
prometheus = 97
동일한 쿼리 사용 확인
deploy에서 pod 개수가 순차적으로 증가하는 모습
web의 pod 수가 [1 → 10] 증가 후 hpa에서 자원들이 안정화 된 모습 - 500m/20
test 마무리 부하 test 종료시 5/20 안정적이므로 rplicas가 내려간 모습
interval 1분으로 인하여 1분이 지난 뒤 감소한 모습
![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/4fad9608-72de-4edf-a6c7-afb2c27d7c1a/Untitled.png)
정상적으로 pod들도 내려간 모습