🗂

Azure Container Apps ジョブを動作させる (イベント ドリブン トリガー編)

2024/01/01に公開

概要

以前に以下を記載しましたが、今回はイベントによってトリガーされる Azure Container Apps ジョブを作成してみます。

Azure Container Apps ジョブを動作させる (手動トリガー編)
Azure Container Apps ジョブを動作させる (スケジュール トリガー編)

詳細

イメージとストレージ キューの準備

今回は以下のサンプル プログラムを使用してみます。

見やすい形で内容を一旦確認したいので、一旦ローカルに落とします。

git clone 例
D:\projects>git clone https://github.com/Azure-Samples/container-apps-event-driven-jobs-tutorial.git
Cloning into 'container-apps-event-driven-jobs-tutorial'...
remote: Enumerating objects: 41, done.
remote: Counting objects: 100% (41/41), done.
remote: Compressing objects: 100% (31/31), done.
Receiving objects:  58% (24/41)used 33 (delta 8), pack-reused 0
Receiving objects: 100% (41/41), 17.57 KiB | 5.86 MiB/s, done.
Resolving deltas: 100% (11/11), done.

Visual Studio Code 等で開いて、どのような内容なのか見てみます。
Dockerfile は以下の内容でした。

Dockerfile
FROM node:lts-alpine
ENV NODE_ENV=production
WORKDIR /usr/src/app
COPY ["package.json", "package-lock.json*", "npm-shrinkwrap.json*", "./"]
RUN npm install --production --silent && mv node_modules ../
COPY . .
RUN chown -R node /usr/src/app
USER node
CMD ["node", "index.js"]

index.js を確認すると、メッセージをデキューし、処理してから削除するという事をしているのがわかります。

index.js
require("dotenv").config();
const { QueueClient, QueueServiceClient } = require("@azure/storage-queue");

const connectionString = process.env.AZURE_STORAGE_CONNECTION_STRING;
const queueName = process.env.AZURE_STORAGE_QUEUE_NAME;

async function main() {
    const queueServiceClient = QueueServiceClient.fromConnectionString(connectionString);
    const queueClient = queueServiceClient.getQueueClient(queueName);
    
    // 1. Dequeue one message from the queue
    const response = await queueClient.receiveMessages({
        numberOfMessages: 1,
        visibilityTimeout: 60, // set this to longer than the expected processing time (in seconds)
    });

    if (response.receivedMessageItems.length === 0) {
        console.log("No message received. Exiting...");
        return;
    }

    const message = response.receivedMessageItems[0];
    console.log(`Processing message: ${message.messageText}`);

    // 2. Process the message here

    // 3. Delete the message from the queue
    await queueClient.deleteMessage(message.messageId, message.popReceipt);
    console.log("Message processed");

    // 4. Exit
}
main();

また、ストレージ アカウントへの接続文字列やキュー名の取得のために、以下環境変数から値を取得しています。

AZURE_STORAGE_CONNECTION_STRING
AZURE_STORAGE_QUEUE_NAME

概要は確認したのでイメージをビルドして、ACR へログインしてから push します。

実行例
docker build -t <Image Name> .
docker push <Image Name>:<Tag>

なお、直接 ACR から build する事もできますが、その場合は以下を実施します。

az acr build --registry "<Name of ACR>.azurecr.io" --image "<Image Name>" "https://github.com/Azure-Samples/container-apps-event-driven-jobs-tutorial.git"

最後にストレージ アカウントとキューも作成しておきます。

ジョブの作成

下準備ができたところで、Azure Container Apps ジョブを作成します。
Azure Container Apps ジョブを動作させる (手動トリガー編) 及び、
Azure Container Apps ジョブを動作させる (スケジュール トリガー編)ではポータルから作成しましたが、今回は、Azure CLI で行います。イベント ドリブンという事もありパラメーターも多くなります。

az containerapp job create 実行例
az containerapp job create --name "<Job Name>" \
--resource-group "<Resource Groupe Name>" \
--environment "<Container Apps Environemnt Full Resource ID>" \
--trigger-type "Event" \
--replica-timeout "1800" \
--replica-retry-limit "1" \
--replica-completion-count "1" \
--parallelism "1" \
--min-executions "0" \
--max-executions "10" \ 
--polling-interval "60" \ 
--scale-rule-name "<Scale Rule Name>" \ 
--scale-rule-type "azure-queue" \
--scale-rule-metadata "accountName=<Storage Account Name>" "queueName=<Storage Account Queue Name>" "queueLength=1" \
--scale-rule-auth "connection=connection-string-secret" \
--image "<ACR Name>.azurecr.io/<Image Name>" \ 
--cpu "0.25" \
--memory "0.5Gi" \
--secrets "connection-string-secret=<Storage Account Connection String>" \
--registry-server "<ACR Name>.azurecr.io" \
--env-vars "AZURE_STORAGE_QUEUE_NAME=<Storage Account Queue Name>" "AZURE_STORAGE_CONNECTION_STRING=secretref:connection-string-secret" \

いくつかピックアップして考察します。

--trigger-type "Event"

今回はイベント ドリブン トリガーを作成したいので、Event にします。

--scale-rule-name "<Scale Rule Name>"

スケーリング ルールを決める必要があるのですが、その名前になります。任意の名前を設定します。

--scale-rule-type "azure-queue"

今回キューでトリガーするジョブを作成するので、その場合には azure-queue とします。

以下公式ドキュメントが参考になります。

動作確認

作成完了しましたので、キューにメッセージを入れて動作を見てみます。
以下のようにメッセージを入れてみました。(暫く時間を置いて、2 回実施してみました)

成功しました。

更に詳細を見てみます。ContainerAppSystemLogs_CL から見てみます。

クエリ例
ContainerAppSystemLogs_CL
| where TimeGenerated >= datetime(2024-01-01 10:40:00) and TimeGenerated <= datetime(2024-01-01 11:00:00)
| where ExecutionName_s has "das-job-0001"
| project TimeGenerated, Reason_s, JobName_s, ExecutionName_s,EventSource_s,ReplicaName_s,Log_s,Count_d
| order by TimeGenerated asc

KEDA が動作している事がわかります。

次に、ContainerAppConsoleLogs_CL を見てみます。

クエリ例
ContainerAppConsoleLogs_CL
| where TimeGenerated >= datetime(2024-01-01 10:40:00) and TimeGenerated <= datetime(2024-01-01 11:50:00)
| where * contains "das-job-0001"
| order by TimeGenerated asc     

1 回目の実行

2 回目の実行

index.js に記載した以下の部分のログが出力されている事がわかります。

index.js より抜粋
console.log(`Processing message: ${message.messageText}`);
console.log("Message processed");

まとめ

今回はイベント ドリブン トリガーで動作する、Azure Container Apps ジョブを作成してみました。機会があれば、次は KEDA によるスケーリング等について、もっと深堀してみたいと思います。

Discussion