はじめに
この記事ではAzure Kubernetes Service(以下、AKS)とKEDAを利用したサーバレスなイベント駆動型アプリケーションの構築方法について解説します。
想定読者
- Kubernetesを利用したことがある方
- Azureが好きな方
Kubernetesにおけるスケーリング
Kubernetesにおけるアプリケーション(ポッド)のスケールの方法の1つとしてHPA(Horizontal Pod Autoscaler)があります。これはPodで利用しているリソース消費量(CPUやメモリ)を監視して、高負荷時にポッドを自動でスケールアウトするものです。
この記事で紹介するKEDAは同じく水平スケールを実現するKubernetesのコンポーネントで、イベント駆動型のアプリケーションに対応しています。KEDAではHPAに比べて以下の特徴があります。
-
イベントの急激な増加を素早く検知して、処理前にスケールアウトをする
HPAではイベントがPodに到達した後、リソースの消費量等をもとにスケールアウトの判断することが多いです(External Metricsなど、必ずしもそうではありません)。一方でKEDAではイベントソース(キューやストリームなど)の状態を監視して、イベントがPodに到達する前にあらかじめスケールアウトの判断をすることができます。
-
イベントが発生していない時に無駄なリソースを消費しない
HPAではスケール範囲が1~nであり、イベントが発生していない場合にもリソースの消費が発生します。一方でKEDAではスケール範囲が0~nであり、イベントが発生していない場合のリソース消費量を抑えることができます。
KEDAとは
MicrosoftとRed Hatが中心となって開発されたオープンソースプロジェクトで、Kubernetes Event-driven Autoscalingの頭文字をとってKEDAとされています。Kubernetes上で動作するサーバレスなイベント駆動型のオートスケールを実現します。KEDAを利用することで、0~nのスケーリングを実現できます。サーバレスと呼ばれるのはこの特徴があるからです。
アーキテクチャ
KEDAは大きく3つのコンポーネントにより構成されています。ControllerとScaler、Metrics adapterです。
Controllerは、KubernetesのDeploymentに対してアクティブ・非アクティブを制御し、0からのスケールを実現しています。
Scalerはトリガとして指定された外部リソースからメトリクス(キューの長さなど)を取得します。
Metrics adapterはScalerで取得したメトリクスをHPAに提供します。従来のHPAが対応しているメトリクスに加えて、豊富な情報を利用してオートスケールを実現できます。
詳細な情報は公式サイトのこちらを参照してください。
サポートするイベントソース
KEDAで処理できるイベントソースとして、以下Azureリソースを利用したものに対応しています。ここで挙げたトリガ以外にも様々なトリガに対応しているので、KEDAのサイトをご覧ください。
- Azure Storage Queue
- Azure Service Bus Queue
- Azure Event/IoT Hubs
- Azure Log Analytics
- Azure Monitor
Azure Functionsとの統合
さらにAKSでKEDAを利用するうえで便利なことの1つに、Azure Functionsと統合できることが挙げられます。
Azure Functionsのコードをそのままにコンテナ化することで、AKS上にホストすることができるのです。
ここからは実際にその流れを解説していきます。
AKSとKEDAを利用してサーバレスアプリケーションを構築する
Azure Storage QueueをトリガとしたAzure FunctionsをAKSにデプロイするシナリオを想定します。
事前準備(ローカルPC)
ローカルPCに以下ツールをインストールします。
-
Azure Funtionsを開発するためのコマンドラインツールです。AKSにKEDAをインストールしたりAKSにデプロイしたりする機能が含まれています。
-
Azureリソースを操作するのに利用します。
-
kubernetesを制御するためのコマンドラインツールです。本記事では動作確認などに利用します。
-
Azure Functionsのコードをコンテナ化し、レジストリにPushするために利用します。
Azureリソースの構築
Azureの以下リソースを利用します。それぞれのリンクを参考に構築します。
-
構築後、AKSからACRを参照できるようにするため、以下コマンドを実行してください。
az aks update -n <AKS名> -g <リソースグループ名> --attach-acr <ACR名>
手順
AKSへの接続情報取得
以下コマンドを実行し、AKSへの接続情報を取得します。
az aks get-credentials --resource-group <リソースグループ名> --name <AKSクラスタ名>
kubectl config get-contexts
を実行したときに作成したAKSクラスターが選択されていればOKです。
KEDAのインストール
Azure Functions Core Toolsを利用してKEDAをAKSにインストールします。
以下コマンドを実行してKEDAをインストールします。
kubectl create namespace keda
func kubernetes install --namespace keda
コンソールにKEDA v2 is installed in namespace keda
と表示されればインストール完了です。
試しにkubectl get pods --namespace keda
を実行すると、kedaのPodが確認できます。
NAME READY STATUS RESTARTS AGE
keda-metrics-apiserver-8458c8f96d-mcblr 1/1 Running 0 1m
keda-operator-69c986985-sdp46 1/1 Running 0 1m
ACRへのログイン
ACRへコンテナをpushするため、Azure CLIを利用してACRにログインします。
az acr login -n <ACR名>
コンソールにLogin Succeed
と表示されればログイン完了です。
Azure Functionsのプロジェクトと関数の作成
Azure Functionsのプロジェクトを作成します。AKSではコンテナを利用するため、--docker-only
オプションをつけてプロジェクトを作成します。また言語はJavaScriptを利用します。
func init --docker-only --javascript
続けて関数を作成します。
func new --javascript --template "Azure Queue Storage trigger" --name queuefunc
作成されたファイルのうち、以下をそれぞれ書き換えます。
-
index.js
:メイン処理スケーリングを確認するため待機処理を追加
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
module.exports = async function (context, myQueueItem) {
sleep(10000); // ←この行を追加
context.log('JavaScript queue trigger function processed work item', myQueueItem);
};
-
local.setting.json
:環境変数の定義AzureWebJobsStorage
に作成したストレージアカウントの接続文字列を追加
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "node",
"AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=...."
}
}
-
function.json
:関数の定義トリガとなるQueueの名前、ストレージアカウントの接続文字列が書かれている環境変数名を追加
{
"bindings": [
{
"name": "myQueueItem",
"type": "queueTrigger",
"direction": "in",
"queueName": "Storage Queueの名前",
"connection": "AzureWebJobsStorage"
}
]
}
AKSへのデプロイ
準備が整ったのでAKSへのデプロイを実施します。
Azure Functionsのプロジェクトのディレクトリで、以下コマンドを実行します。
func kubernetes deploy --name <関数の名前> --registry <ACR名.azurecr.io> --namespace keda
このコマンドを実行すると、内部的に以下の処理が行われています。
- Dockerイメージのビルド
- DockerイメージのレジストリへのPush
- AKSへのマニフェストのデプロイ
実際にACRを確認すると指定した関数名のリポジトリが作成され、イメージがPushされていることが確認できます。(タグはlatest)
またAKSにデプロイされるオブジェクトは、先ほどのコマンドに--dry-run
のオプションをつけることでマニフェストを確認できます。
func kubernetes deploy --name <関数の名前> --registry <ACR名.azurecr.io> --namespace keda --dry-run
3つのKubernetesオブジェクトがデプロイされていることを確認できます。
-
Deployment
アプリケーション本体
-
Secret
local.setting.json
内で定義した環境変数 -
KEDAのカスタムリソースで、トリガやスケール対象のDeploymentを指定する
動作確認
指定したAzure Queue Storageに対して(数100件ほど)メッセージを追加したときのPodの状態になります。作成したqueuefuncがスケールアウトしていることを確認できます。
またメッセージをすべて処理した後の状態でアイドル状態が続けば、対象のPodは1つも存在しない状態になることも確認できます。冒頭で解説した0~nのスケールを確認することができました。
おわりに
この記事ではKEDAを利用してAzure FunctionsをAKSで実行する流れについて解説しました。
本文中で解説しきれませんでしたが、プロダクション環境での利用する場合は、環境変数の扱いやコンテナのタグの運用方法など様々な検討事項が残ります。KEDAのサイトやAzure Functionsのリファレンスにヒントがありますのでぜひ参照してみてください。