はじめまして、オプティムのインダストリー事業本部 医療チームの高橋(@ukitiyan)です。
所属部門では、産業カットのサービスや案件を展開しており、私はマネージメントやアーキテクト、更には実装も担当しています。
Twitterをそろそろちゃんと始める予定です。
さて、今回は普段サーバーレスアーキテクチャを実現するためのファクタの1つとして活用しているSpring Cloud Functionで
実装したFunctionをAzure FunctionsにServerless Frameworkを利用してデプロイしてみたいと思います。
また、気になるAzure FunctionsでのJavaの取り扱いについても記事中で触れてみます。
この記事について
手順を通して、Azure上でのサーバーレスな画像リサイズシステムの構築・デプロイを体験します。
例えば不定期に取得された画像をリサイズ・最適化して AI画像解析をかけるといったユースケースにおいてEvent-Drivenに処理、つまりはサーバーレスな構成とすることで様々な恩恵を受けられます。 ただ、サーバーレスなシステムを構成した場合、Functionのプロビジョニングは割と容易に行えますが、以下の点にペインを感じることがあります。*1
- ローカルでの動作確認
- コード、デプロイメントのマルチクラウド対応
- コードベースと既存CI/CDとの統合
- Functionの周辺リソース管理
- 環境変数の設定*2
上記ソリューションとして、Spring Cloud FunctionやServerless Frameworkを活用することが考えられます。
今回はサーバーレスプラットフォームにAzure Functionsを採用して説明していきたいと思います。
尚、AWS Lambdaや他プラットフォームで当たり前のように対応しているといった方も、Azure Functionsは2018年9月にversion2.0がGAとなったことや、Javaがプレビュー段階にあることから
情報自体が少ない状況にあるので、今回の組み合わせについては今更感の無い内容になると思います。
Spring Cloud Functionとは
Spring によるサーバーレスなFunctionを実装するためのフレームワークで、以下の特徴があります。
- Spring Boot上で動作します。
- 同じコードでHTTPエンドポイントやKafka, RabbitMQ等のPub/Sub ストリームプロセッサ、タスクが実行できます。
- 分離されたクラスローダーでデプロイすることができます。(JVM Packing)
- AWS Lambda, Azure Functions, Riff 等に対するServerless Providerが用意されています。
以下の手順では、Serverless PratformへのアダプタとなるServerless Providerを通して、Azure Functionsでの実行を実現しています。
Azure Functionsとは
- Azureのサーバーレスプラットフォームです。柔軟で強力なマネージドサーバーレス環境を提供してくれます。
- AWS で言うところの、AWS Lambdaと訳されることが多いと思います。
- 料金体系として、従量課金プランとApp Serviceプランの2種類が存在することが特徴的です。
- また、 Azure Application Insights との統合やDevOps のエクスペリエンス、Function のオーケストレータであるDurable Fucntionsといったサーバーレスアーキテクチャを構成する上での様々なトピックが存在します。これらについては次回以降に深堀りしていければと考えています。
現在サポートしている言語は以下の通りです。
Language | version 1.x | version 2.x |
---|---|---|
C# | GA (.NET Framework 4.7) | GA (.NET Core 2) |
JavaScript | GA (Node 6) | GA (Node 8、10) |
F# | GA (.NET Framework 4.7) | GA (.NET Core 2) |
Java | 該当なし | プレビュー (Java 8) |
Python | 試験段階 | 該当なし |
TypeScript | 試験段階 | JavaScript へのトランスパイリングによってサポートされます |
PHP | 試験段階 | 該当なし |
バッチ (.cmd、.bat) |
試験段階 | 該当なし |
Bash | 試験段階 | 該当なし |
PowerShell | 試験段階 | 該当なし |
最新情報は、以下をチェックしてください。
Azure Functions でサポートされている言語 | Microsoft Docs
現在Javaについてはプレビュー段階にあり、ランタイムバージョンはJava 8です。
尚、今回のサンプルコードの実行ログからAzure Functions上で利用しているJavaビルドを確認出来るようにしています。
内容を確認すると、vendorが Azul Systems, Inc,
と表示されており、Azul SystemsがビルドしたJavaであることが分かります。
当該ビルドはLTS版で2026年までサポートされるロードマップとなっており、直近でJava8のサポートが打ち切られることは無いと思われますが、併せて次バージョンの対応が待ち望まれます。
Serveless Frameworkとは
- 各種サーバレスプラットフォームに対してFunctionをデプロイすることのできるCLIツールです。
- AWS, Azure, GCP等のマルチクラウドプロバイダーをサポートしています。
- Functionのデプロイ以外に周辺リソースやEnviromentの管理も可能です。
実はAzureにはJavaで実装したFunctionをデプロイするためのCLIツールが用意されています。
コマンド ラインから Java 関数を作成する - Azure Functions | Microsoft Docs
本記事のまとめにも記載しますが、現時点ではServerless Frameworkよりも純正のCLIの方がデプロイにおける性能が良いです。
しかしながら、マルチクラウドを意識したCI/CD環境を目指したかったことや、デプロイフェーズでのEnviromentを設定することに
都合が良いと判断したことから、今回はServerless Frameworkを採用しています。
サーバーレスな画像リサイズシステムのサンプル
Requirement
ローカル環境に以下がインストールされていることを確認してください。
- Jdk 1.8
- Maven 3.6.0
- Node >= v6.5.0
環境変数に個別IDを設定
いくつかユニークIDを必要とする部分があるので事前に定義しておきます
$ export SLS_ID=$(($RANDOM % 9999)) $ echo $SLS_ID
Azure上に周辺リソースを構築
Azure CLIのインストール
以下を参考にAzure CLIをインストールしてください。
Azure CLI をインストールする方法 | Microsoft Docs
インストール後、 az login
コマンドによりAzureへのログインを行います。
Azure BLOB Storageへの画像アップロード
以下の手順でAzure BLOB Storageのコンテナ*3を作成し、PNGファイルをアップロードしてください。
リソース グループの作成
$ az group create \ --name slsResourceGroup \ --location centralus
ストレージ アカウントの作成
$ az storage account create \ --name slsstorageaccount$SLS_ID \ --resource-group slsResourceGroup \ --location centralus \ --sku Standard_LRS \ --encryption blob
Funcstionから接続するための資格情報の取得
$ az storage account keys list \ --account-name slsstorageaccount$SLS_ID \ --resource-group slsResourceGroup \ --output table
資格情報をローカルPCの環境変数に設定
$ export AZURE_STORAGE_ACCOUNT="slsstorageaccount$SLS_ID" $ export AZURE_STORAGE_ACCESS_KEY="{{上記で取得したkey1の値}}"
コンテナーの作成
$ az storage container create \ --name slsstoragecontainer
画像のアップロード
- 250px*250px以上のPNG画像をアップロードしてください。
$ az storage blob upload \ --container-name slsstoragecontainer \ --name image \ --file image.png
ローカルのSpring Boot上での実行
ソースのダウンロード
- 今回用意したサンプルコードをcloneします。
$ git clone https://github.com/optim-corp/thumbnail-azure-sample.git
$ cd thumbnail-azure-sample
プロパティファイルの確認
- 必要に応じて適宜修正してください。
- 尚、
spring.cloud.function.scan.packages
の指定によりFunctionScanするパッケージを指定しています。
$ cat src/main/resources/application.yml
ローカルSpringBoot用の資格情報を環境変数に設定
azure.storage.account-name
、azure.storage.account-key
に該当するプロパティ値を環境変数にて指定します。
$ export AZURE_STORAGE_ACCOUNT-NAME=$AZURE_STORAGE_ACCOUNT $ export AZURE_STORAGE_ACCOUNT-KEY=$AZURE_STORAGE_ACCESS_KEY
Mavenによるビルド・パッケージ
$ ./mvnw clean package
SpringBootの起動
$ java -jar target/thumbnail-0.0.1-SNAPSHOT.jar
ローカルへのテストリクエスト
- ローカルで起動したSpringBootに対してcurlします。
- 成功するとリサイズされた画像のBLOB名が返却されます。
$ curl -w '\n' -H 'Content-Type:application/json' -d '{"blobName":"image"}' \ http://localhost:8080/thumbnail { "blobName": "image-thumbnail" }
サムネイル画像のダウンロード
- 上記のBLOB名でAzure BLOB Storageにリサイズされた画像が配置されているので、ダウンロードし、リサイズされているかを確認します。
$ az storage blob download \ --container-name slsstoragecontainer \ --name image-thumbnail \ --file image-thumbnail.png
無事リサイズされていればOKです 👍
Serverless FrameworkによるAzure Functionへのデプロイ
Serverless Framework、Azure Pluginのインストール
- 以下を参考にServerless FrameworkとAzure Pluginをインストールします。
Serverless Framework - Azure Functions Guide - Installing The Serverless Framework
Credentialsの設定
- 以下を参考にServerless Frameworkに割り当てるAzureのCredentialsを設定します。
Serverless Framework - Azure Functions Guide - Credentials
Application settingsの設定
- 直下の
serverless.yml
を確認しておきます。 - provider.environmentセクションがApplication settingsに該当します。
- yamlに記載すべき内容でない場合、外部から値を指定することが可能です。
provider: name: azure location: centralus environment: AZURE_STORAGE_ACCOUNT_NAME: ${self:custom.storage-account-name} AZURE_STORAGE_ACCOUNT_KEY: ${self:custom.storage-account-key} FUNCTIONS_WORKER_RUNTIME: java MAIN_CLASS: example.Application
デプロイ
- コマンド実行後
resource group
,function app
,upload function
,Running Kudu commnad
に続いてSuccessfully created Function App
と表示されれば成功です。
$ serverless deploy \ --id $SLS_ID \ --storage-account-name "${AZURE_STORAGE_ACCOUNT-NAME}" \ --storage-account-key "${AZURE_STORAGE_ACCOUNT-KEY}"
Function Keyの確認
- Azure Functionsの Functionに対する設定である
src/main/azure/thumbnail-function.json
*4 を確認すると、当該FunctionのauthLevelがfunction
となっていることがわかります。 - authLevel=functionのEndpointにアクセスする場合には、Function Keyが必要となるため、AzureのマネージドコンソールからFunction Keyを取得します。
Azureへのテストリクエスト
- Azure Functionsで起動しているFunctionに対してcurlします。
- 成功するとリサイズされた画像のBLOB名が返却されます。
$ curl -w '\n' -H 'Content-Type:application/json' -d '{"blobName":"image"}' \ https://thumbnail-azure-$SLS_ID.azurewebsites.net/api/thumbnail?code={function key} { "blobName": "image-thumbnail" } $ az storage blob download \ --container-name slsstoragecontainer \ --name image-thumbnail \ --file image-thumbnail.png
サムネイル画像のダウンロード
- 上記のBLOB名でAzure BLOB Storageにリサイズされた画像が配置されているので、ダウンロードし、リサイズされているかを確認します。
$ az storage blob download \ --container-name slsstoragecontainer \ --name image-thumbnail \ --file image-thumbnail.png
無事リサイズされていればOKです 👍 👍
リソースの削除
- 以下のコマンドで今回作成したリソースを削除します。
$ serverless remove \ --id $SLS_ID \ --storage-account-name "${AZURE_STORAGE_ACCOUNT-NAME}" \ --storage-account-key "${AZURE_STORAGE_ACCOUNT-KEY}" $ az storage container delete \ --name slsstoragecontainer $ az storage account delete \ --name slsstorageaccount$SLS_ID \ --resource-group slsResourceGroup $ az group delete \ --name slsResourceGroup
おわりに
今回は、Spring Cloud Function、Azure Functions、Serveless Frameworkの利用を前提とした構成のサンプルについて説明しました。
慣れ親しんだSpringベースのコードでサーバーレスが出来る事、SpringBootによるローカル実行が可能であることは大きなメリットです。
本記事のアウトプットをベースにEventの変更や既存 CI/CDの統合等についても、チャンレンジしてもらえればと考えています。
今回の構成では、文中にも記載した通り現時点では設定が一部冗長である等の課題はありますので、アップデートがあれば本記事を更新していきたいと思います。
オプティムでは、このようなアーキテクチャの設計・構築やOSSを活用した開発・実装に興味がある・作ってみたい人を募集しています。興味のある方は、是非こちらをご覧ください。