ほりひログ

所属組織の製品 (Azure とか) に関連する内容が多めだけど、個人の見解であって、所属組織を代表する公式情報ではないです。

Azure Functions on KEDA on AKS

この記事は、Microsoft Azure Tech Advent Calendar 2020 の 17 日目の記事です。

qiita.com

KEDA を使って、Azure Functions を動かしてみました。

KEDA

KEDA (Kubernetes Event-Driven Autoscaling) は、Kubernetes をベースに、処理すべきイベント量に応じて自動でスケーリングしてくれる仕組みです (ほぼ名前を直訳) 。

keda.sh

名前の通り、Kubernetes が必要なようです。
Kubernetes によるコンテナー オーケストレーションを、イベント ベースにやってくれる、というのが雑な理解。
Kubernetes 自体、名前くらいしか知らないんですが。

Azure Functions

ご存じ、Azure が提供する FaaS (Functions as a Service)です。

docs.microsoft.com

作成した関数を、HTTP や Azure の各サービスからの通知をトリガーから実行でき、出力結果についてもほかのサービスと連携が可能なので、使い勝手の良いサービスです。

Azure Functions は、関数を実行するランタイム部分と、スケーリングを制御する部分で構成される Azure 上のサービスで、このうち後者のスケーリング制御は KEDA/Kubernetes に置き換えることができます。
KEDA/Kubernetes 上で動作させることができるので、オンプレミス環境のような Azure プラットフォームの外で Azure(?) Functions が利用できます。

ちなみにランタイム部分はオープンソースとして GitHub で公開 されており、issue や Pull Request を通して開発者と直接コンタクトを取ることが可能ですので、興味がある方はどうぞ。

やってみる

実際に動かしてみます。

前準備

以下 3 つのコマンド ツールをローカル環境にインストールしておきます。

構築本番

Kubernetes が動くオンプレ環境が準備できなかったので、今回は Azure の Kubernetes サービス、AKS を使って試してみます。
# 結局 Azure 上なのであまり KEDA を使うメリットはわからないですが、あくまで「試し」です。

1. AKS リソースをデプロイ

ポータルからポチポチしたらデプロイできるので、難しいことはないです。

2. kubectl の設定

AKS 上の Kubernetes の認証情報をローカルの kubectl の設定ファイル ($HOME/.kube/config) に保存します。

az aks get-credentials --resource-group $RG_NAME --name $AKS_NAME

このコマンドを実行すると、kubectl から AKS 上の Kubernetes の操作が可能になります。
※以降の手順では、一切 kubectl を実行していませんが、func が内部的に使用しています。

Azure ポータルからもコマンドの確認が可能です。 f:id:horihiro:20201129103328p:plain

3. KEDA コンポーネントのインストール

AKS 上の Kubernetes名前空間を作成しつつ、KEDA コンポーネントをインストールします。

func kubernetes install --namespace $CLUSTER_NAMESPACE

4. デプロイする関数の準備

ローカルの開発環境に Function App 用のプロジェクトを作り、次に Queue トリガー関数を作ります。 関数の実装言語はお好みのものを。

func init --docker --javascript
func new --javascript --template "Azure Queue Storage trigger" --name queuetrigger1

最終的に Docker コンテナーとしてデプロイするので、Dockerfile を生成する --docker をつけています。
既に実装中のプロジェクトがある場合は、下記コマンドで Dockerfile を生成するといいでしょう。

func init --docker-only

AKS 上で起動が確認できればいいだけなので、作成した関数はほぼテンプレのまま、メッセージを受信してから 5 秒スリープするだけです。

const sleep = (time) => {
    return new Promise((res) => {
        setTimeout(() => {
            res();
        }, time);
    })
}
module.exports = async function (context, myQueueItem) {
    await sleep(5000);
    context.log('JavaScript queue trigger function processed work item', myQueueItem);
};

その他、function.json や Dockerfile はこちら。

{
  "bindings": [
    {
      "name": "myQueueItem",
      "type": "queueTrigger",
      "direction": "in",
      "queueName": "<QUEUE_NAME>",
      "connection": "<APPSETTING_NAME_FOR_QUEUE_STORAGE>"
    }
  ]
}
# To enable ssh & remote debugging on app service change the base image to the one below
# FROM mcr.microsoft.com/azure-functions/node:3.0-appservice
FROM mcr.microsoft.com/azure-functions/node:3.0

ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true

COPY . /home/site/wwwroot

RUN cd /home/site/wwwroot && \
    npm install

5. 関数のデプロイ

AKS の KEDA 上に関数をデプロイします。

その前に、local.settings.json で定義している値をデプロイ環境用のものに変更しておきます。
デプロイの時点で Function App のアプリケーション設定に相当する情報は、local.settings.json からインポートされ、KEDA の Secret として保存されますので、例えば、ローカルでの開発に Storage Emulator を使って UseDevelopmentStorage=true などを設定している場合は、デプロイ前に正しいストレージ アカウントへの接続文字列へ変更しておきます。

デプロイ自体のコマンドはこれだけです。

func kubernetes deploy --name $NAME_IMAGE --registry $USERNAME_REGISTRY --namespace $CLUSTER_NAMESPACE

このコマンドを実行すると、

  1. docker build でコンテナー イメージを作成
  2. docker push で Registry に登録
  3. $HOME/.kube/config の認証情報に基づいて、Kubernetes に反映

が一気に実行され、デプロイ完了です。

動作確認

実際に関数を動かした時に、KEDA でスケールするのか、確認してみました。

KEDA に乗せた関数は Queue トリガーで実行されるので、キューにメッセージを追加する HTTP トリガー関数をローカルで、0.1 毎に実行してみました。
その様子がこちらです。

最初のポッドが起動するまでややかかりますが、その後はたまったキュー メッセージを処理するためにどんどんポッドが追加され、スケール アウトしていく様子がわかります。
ほおっておけば、 0 までスケール インします。

まとめ

Azure Functions 用の関数を (AKS 上であったものの) KEAD 上で動作させ、メッセージ量に応じてポッドがスケーリングがされることが確認できました。

今回、Queue トリガーを使いましたが、KEDA では以下のトリガーもサポートされています。

  • Azure Service Bus キュー
  • Azure Event/IoT Hubs
  • Apache Kafka
  • RabbitMQ キュー

HTTP でのスケーリングはサポートされていないようで、別途 Prometheus とかいうのが必要です。 dev.to

最後に公式ドキュメントをご紹介。 docs.microsoft.com