Kubernetes を基盤としたプロジェクトで実際に利用している、KEDA というコンポーネントのメジャーバージョンが上がったので追加機能についてまとめる.
KEDAとは
KEDA (Kubernetes Event-driven Autoscaling)は, kubernetes clusterに追加できる単一目的の軽量コンポーネントで,CNCFのSandboxプロジェクトにホストされているkubernetes ベースのイベント駆動オートスケーラーである. 宣言的に定義されたイベントに応じて, Kubernetes の任意のコンテナーのスケーリングを促進できる. Horizontal Pod Autoscaler などの kubernetesコンポーネントと連携して動作し,上書きや重複なしに機能拡張できる.
keda.sh
KEDA を使うと嬉しいこと
Kubernetes Horizontal Pod Autoscaler では CPU , Memory , Metrics API をトリガーに自動スケーリングが可能である. しかし, 多くの点で, それは症状の治療に似ており, 実際の原因ではないことがある. 例えばメッセージングの仕組みを利用していた場合に, 大量のメッセージによって最終的にCPU使用率が上昇するが, この場合本当にスケーリングしたい条件は, キューに滞留しているメッセージの数であったりする.
これらの場合, KEDA を用いればシンプルに スケーリング環境を構築できる.
v2の追加機能
追加されたスケール対象
- StatefulSet
- Custom Resource
- ScaledJobs
DeploymentやJobが主な対象だったが、サブリソースとしての Custom Resource
や Jobスケール専用の ScaledJobs
が追加されたり
対象毎の特性に応じたプロパティ設定が可能となった.
追加されたスケーラー
- CPU
- Memory
- External Push
- Metrics API
- Azure Log Analytics
- IBM MQ
Kubernetes Horizontal Pod Autoscaler でも取得が可能だった CPU , Memory も追加されているのが印象的である.
Kubernetesの複雑さの一部を取り除くために, Kubernetes API を使用しなくても対処できるようにするためだと推測している.
事前準備
localに kubernetes 環境を構築する。 今回は minikube を使って cluster の構築を行う.
kubernetes.io
インストール
- KEDAをインストールする. (今回はマニフェストを用いる)
$ kubectl apply -f https://github.com/kedacore/keda/releases/download/v2.0.0/keda-2.0.0.yaml
namespace/keda created
customresourcedefinition.apiextensions.k8s.io/scaledjobs.keda.sh created
customresourcedefinition.apiextensions.k8s.io/scaledobjects.keda.sh created
customresourcedefinition.apiextensions.k8s.io/triggerauthentications.keda.sh created
serviceaccount/keda-operator created
clusterrole.rbac.authorization.k8s.io/keda-external-metrics-reader created
clusterrole.rbac.authorization.k8s.io/keda-operator created
rolebinding.rbac.authorization.k8s.io/keda-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/keda-hpa-controller-external-metrics created
clusterrolebinding.rbac.authorization.k8s.io/keda-operator created
clusterrolebinding.rbac.authorization.k8s.io/keda:system:auth-delegator created
service/keda-metrics-apiserver created
deployment.apps/keda-metrics-apiserver created
deployment.apps/keda-operator created
apiservice.apiregistration.k8s.io/v1beta1.external.metrics.k8s.io created
Namespace
や Deployment
など KEDA のリソースが作成されている.
$ kubectl get all -n keda
NAME READY STATUS RESTARTS AGE
pod/keda-metrics-apiserver-5bffbfbd68-ftg6q 1/1 Running 0 3m12s
pod/keda-operator-7b98595dc7-b4rnb 1/1 Running 0 3m12s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/keda-metrics-apiserver ClusterIP 10.97.130.94 <none> 443/TCP,80/TCP 3m12s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/keda-metrics-apiserver 1/1 1 1 3m12s
deployment.apps/keda-operator 1/1 1 1 3m12s
NAME DESIRED CURRENT READY AGE
replicaset.apps/keda-metrics-apiserver-5bffbfbd68 1 1 1 3m12s
replicaset.apps/keda-operator-7b98595dc7 1 1 1 3m12s
イベント駆動スケールを試す
せっかくなので KEDA v2から追加された Metrics API
を試してみる
今回は自分で定義したAPIから Metrics を取得する.
サンプルはこちら
github.com
- KEDA の トリガー対象とmetrics用のアプリケーションをデプロイする.
$ make deploy-app
or
$ kubectl apply -f ./deploy/demo/app/
namespace/demo created
service/components-mock created
deployment.apps/components-mock created
deployment.apps/nginx created
demo Namespace
にmetrics用のアプリケーションcomponents-mockとスケール対象のnginxがデプロイされる.
$ kubectl get all -n demo
NAME READY STATUS RESTARTS AGE
pod/components-mock-6b58c499dd-x6bf7 1/1 Running 0 95s
pod/nginx-6799fc88d8-p9jp5 1/1 Running 0 95s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/components-mock ClusterIP 10.99.64.141 <none> 3003/TCP 95s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/components-mock 1/1 1 1 95s
deployment.apps/nginx 1/1 1 1 95s
NAME DESIRED CURRENT READY AGE
replicaset.apps/components-mock-6b58c499dd 1 1 1 95s
replicaset.apps/nginx-6799fc88d8 1 1 1 95s
- KEDA の
ScaledObject
をデプロイする
今回デプロイする ScaledObject
の閾値は 2
に設定している.
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: http-scaledobject
namespace: demo
labels:
deploymentName: nginx
spec:
maxReplicaCount: 5
scaleTargetRef:
name: nginx
triggers:
- type: metrics-api
metadata:
targetValue: '2'
url: "http://components-mock.demo.svc.cluster.local:3003/components"
valueLocation: "components.worker.tasks"
なお, サンプルではレスポンスのデフォルトが 0
のため ScaledObject
がトリガーされnginxが0
に Scale Inする.
$ make deploy-scaledobject
or
$ kubectl apply -f ./deploy/demo/scaledobject/metrics-api.yaml
scaledobject.keda.sh/http-scaledobject created
demo Namespace を確認すると 0
に Scale In したことが分かる.
$ kubectl get po -n demo
NAME READY STATUS RESTARTS AGE
components-mock-6b58c499dd-x6bf7 1/1 Running 0 7m16s
- 値を変更して, Scale Outさせる
/deploy/demo/app/component.yaml
を変更する
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: components-mock
name: components-mock
namespace: demo
spec:
replicas: 1
selector:
matchLabels:
app: components-mock
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
labels:
app: components-mock
spec:
containers:
- name: components-mock
image: cabi99/components-mock:0.0.1
env:
- name: WORKER_TASKS
value: "0"
imagePullPolicy: Always
ports:
- containerPort: 3003
変更後に再デプロイする.
$ make deploy-app
or
$ kubectl apply -f ./deploy/demo/app/
namespace/demo unchanged
service/components-mock unchanged
deployment.apps/components-mock configured
deployment.apps/nginx unchanged
nginx が Scale Outしていることが確認できる.
$ kubectl get po -n demo -w
NAME READY STATUS RESTARTS AGE
components-mock-6c494cd68b-4tkmv 1/1 Running 0 32s
nginx-6799fc88d8-22q9l 0/1 ContainerCreating 0 4s
nginx-6799fc88d8-22q9l 1/1 Running 0 5s
なお、今回は閾値を2にしているので、WORKER_TASKS を 10
に変更してデプロイすれば, maxReplicaCount
で定義した値までScale Outする.
$ kubectl get po -n demo -w
NAME READY STATUS RESTARTS AGE
components-mock-6d66575d55-r8vxh 1/1 Running 0 2m17s
nginx-6799fc88d8-22q9l 1/1 Running 0 4m11s
nginx-6799fc88d8-95r6v 1/1 Running 0 2m4s
nginx-6799fc88d8-jkdqw 1/1 Running 0 2m4s
nginx-6799fc88d8-wkmq4 1/1 Running 0 2m4s
nginx-6799fc88d8-xvctr 1/1 Running 0 109s
まとめ
KEDA v2を触ってみたが, v1との使い勝手に大きな差はなかった.
しかし, 今回のバージョンアップで CPU と メモリ が追加により, Kubernetes Horizontal Pod Autoscaler と共存する形でなく, 自動スケーリング のリソースは全て KEDA に統一することで シンプル性を担保できる.
また, Metrics API を利用すれば, APIが提供されているサービスをトリガーにすることが容易であったり, SQLクエリに基づいてワークフローを自動スケーリングも可能になるので拡張性の高い環境構築に活かせると感じた.