ラベル Docker の投稿を表示しています。 すべての投稿を表示
ラベル Docker の投稿を表示しています。 すべての投稿を表示

2025/07/18

さくらのクラウドとサーバレスアーキテクチャ

さくらのクラウドの注目記事

 私が現在利用しているクラウドはGoogle Cloudのみですが、その他には国産クラウドである「さくらのクラウド」にも興味を持っています。現在ガバメントクラウド認定を目指して整備が進められているさくらのクラウドですが、そのアプリケーション実行基盤である「AppRun」はサーバレスであることが発表されています。

さくらインターネット、アプリケーション実行基盤「AppRun β版」にて製品版のトライアルを開始

さくらのクラウド、コンテナをサーバレスで実行する「AppRun」製品版トライアルを開始。トライアル中は全機能が無料に


サーバレスアーキテクチャとは

2008年のApp Engineリリースから使えるようになったものなので、まだご存じない技術者も見かけます。理解が簡単ではないので、普及はこれからといった印象です。またFaaS(Function as a Service)と混同しやすいので注意が必要です。


サーバレスアーキテクチャは、このブログの記事「サーバレスアーキテクチャ」でも説明しています。コンピューティングにおいては、アプリケーションの実行インスタンスは常に起動しているわけではなく、必要な時に必要な分だけのリソースを割り当ててアプリケーションの実行を行うアーキテクチャです。リソースの管理はプラットフォームがやってくれるので、ユーザは意識する必要がありません。

サーバレス アーキテクチャとは

サーバーレス・コンピューティングとは

クラウド以前の従来のサーバは想定された利用状況に応じてあらかじめリソースを割り当てておきます。リソースの管理は、夜間など利用の少ない時間帯にバッチ処理を走らせるなど、計画的で柔軟性はありません。

クラウドでも非サーバレス場合は、最低1つ以上の実行インスタンスが常に割り当てられます。夜間バッチの実装など従来と変わらない設計が主流です。

それに対してサーバレスアーキテクチャでは、リアルタイムで必要なだけリソースを割り当て/開放します。これによりランニングコストの低減や、サーバビジーによる一時的なサービス提供不能の発生低減が期待できます。これはユーザにとって大きなメリットとなります。


しかしクラウドベンダー目線で考えると、上記とは違う特徴を実現することが目的ではないかと考えられます。

リアルタイムにリソース割り当てを変更できることから、データセンター全体でリソースを有効利用できるようになります。またリソースの割り当ては基本的に永続的ではなくなるので、ハードウェアのメンテナンスをしやすくなる(ユーザにとってもメンテナンスの影響を受けにくくなる)利点も考えられます。


「みんなのクラウド」と表現されることがありますが、データセンターのリソースをユーザみんなで共有し、その割り当てをより柔軟にして(非サーバレス以上の)最大限の効果を狙うのがサーバレスアーキテクチャであると言えると思います。


サーバレスアーキテクチャの現状

現在の日本のwebアプリケーションは、まだサーバレスアーキテクチャを採用したものは少ないように見えます。キーワードとしてKubernetesが出てくるアプリケーションは、サーバレスアーキテクチャではありません。それどころかクラウドに最適化されていなくて従来の延長線上でしかないものもあるようです。

現在クラウドの利用方法の主流は、Docker+Kubernetesの構成と思われます。この構成が流行った要因は以下のようなものと考えられます。

  • どのクラウドベンダーでも同じように実装でき、ベンダーロックインが発生しない。これは特に受託開発やSESにとって好都合。
  • クラウド以前の従来の技術・知識・プロダクト(ライブラリ、フレームワーク)を使いまわせる。新たに覚えるべきことはDockerとKubernetesのみ。
  • Kubernetesによって一応スケーリングも可能なので、スケーリングの恩恵も得られる。
主に開発者の都合が中心です。ひどい場合はDockerコンテナにクラウド以前のレガシーな構成をそのまま詰め込んだだけのケースもありそうです。Kubernetesでスケーリングさせているつもりが、その効果さえ確認していないケースもあるようです。クラウドに最適化しないのであれば、クラウドによる恩恵も最低限しか受けられません。


サーバレスアーキテクチャではコンテナオーケストレーションにはKubernetesではなく、Knative(あるいは相当のもの)を用います。


ランニングコストについて

「クラウドに移行したもののランニングコストが予測よりずっと高く、期待したように下がらない」という話を時々聞きます。

自治体システム標準化、ガバクラ移行で運用コスト2~4倍に悲鳴「議会に通らない」(有料記事ですが1ページ目のみ無料で閲覧可能)

 ガバメントクラウド移行で自治体の年間コストが5.7倍に…計画の重要性

 ガバメントクラウド移行で自治体の運用コストは本当に下がるのか?


上記の引用はガバメントクラウドに関するものですが、過去に私が関わった民間企業のwebアプリケーションでも同様の現象が起きていました。この企業で使っていたのもKubernetes(GKE)ですが、「思うようにスケーリングできない」ので無駄にリソースを割り当ててアプリケーションを実行しているという状況でした。

他の原因の1つは、クラウド以前の従来のアーキテクチャを引きずったまま移行していることにあるのではないかと考えられます。クラウドに最適化しないのであれば、クラウドに乗り換える効果も限定的でしかないのは想像に難しくありません。


その他にも、従来の手作業・紙ベースの手順をそのままにしておくことを優先したため、コンピュータ処理に適さない手順を無理やり実装したことによる弊害もあると考えられます。これは今に始まったことではなく、クラウドやアーキテクチャによるものでもない別次元の話なので、本記事ではこれ以上取り上げません。


サーバレスアーキテクチャでの実装

実際にサーバレスアーキテクチャで実装するには、対応するPaaSのプロダクトを利用することになります。しかしそれだけでは実装後に以下のような性能上の問題が発生することがあります。

  • レスポンスが悪い、または悪くなることがある。
  • バッチ処理などバックエンドの処理に時間がかかる。
  • ランニングコストが下がらない。
    (使い方を間違うと効果は得られない)
  • コストの予測が困難。
    (スケーリングする限り非サーバレスでも同じだが、より変化が大きい)


サーバレスアーキテクチャを有効に使いこなすためには、それに対応した設計が必要となります。ここでのノウハウにはサーバレスアーキテクチャを実装した経験からしか得られないものもあります。具体的にここで書ききれる量ではないので別の機会に。

しかしサーバレスアーキテクチャを使いこなせば、スケーリングを最大限に活用できて以下の効果を得られる可能性があります。

  • ランニングコストの削減。
  • サーバビジーによる一時的なサービス不可の減少。


技術的課題

従来のサーバは「起動しておいて必要とされるのを待つ」思想で実装されています。しかしサーバレスアーキテクチャでは「必要とされたから起動する」という思想に変わります。そのためwebサーバのような「ユーザが待っている」ケースでは、起動の遅い実装はユーザを待たせる悪いユーザエクスペリエンスにつながります。バックエンドのような起動の遅延が影響しないケースでは無視できます。

これにより従来のプロダクト(サーバレスアーキテクチャを考量していないライブラリやフレームワーク)が使い物にならなくなっているケースがあります。フレームワークの場合はそれを理解せず使用してしまうと、ほぼすべて再実装でしか改善できないほどの影響も考えられます。たとえ人気で過去に実績もあるプロダクトといえど、サーバレスアーキテクチャを考量してなくて悪影響となるものは、早めに清く捨て去る必要があります。

この思想の違いは開発者にとっては、パラダイムシフトとも言えるほどの影響です。これはサーバレスアーキテクチャの理解や使いこなしを難しくしています。


またクラウドベンダーにより対応の方法がバラバラです。簡単にサーバレスアーキテクチャへの対応をまとめると、以下のようになります。

  • Google Cloud
    • App Engine(Standard Environment):独自コンテナ+Knative、webサーバ。
    • Cloud Run:Docker+Knative。
      • Service:webサーバ。
      • Function:FaaSとしての利用形態で実態はServiceと同じ。
    • GKE + Knative serving:もうCloud Runでよくない?
  • AWS:Serverless Application Modelに基づいてLambdaで実装。
  • Azure:Azure Functionsを利用。
  • さくらのクラウド
    • AppRun:Docker+Knative

そのほかにIBM、Oracleも対応しているようです。

AWS, AzureはFaaS(Function as a Service)の流用にとどまっており、あまりサーバレスアーキテクチャの採用に関して積極的に見えません。

Google CloudはFaaSだけでなくPaaSも用意されており、対応が最も進んでいます。またwebサーバでなくバッチ処理でも同じように使えるプロダクト(Batch, Cloud Run Job)が用意されいます。これらは本来サーバでないのでサーバレスアーキテクチャと呼びませんが、「必要な時に必要な分だけ」リソースを使うことができる点においては同じです。


さくらのクラウドに対する期待

さくらのクラウドでは今後はサーバレスアーキテクチャが普及していくものと予測しているそうです。これは私も同意見で、世の中の技術者たちがサーバレスアーキテクチャの理解を進め、普及していくように活動しています。


2025/06/03

Container RegistryからArtifact Registryへの変更の影響

動機

 少し古い話ですが、Container Registryは2025/3くらいから徐々に停止しています。プロダクトによって具体的な停止のタイミングはいくらか異なるようです。これに伴いContainer Registry→Artifact Registryへの移行が必須となるのですが、この移行により思わぬ影響があったので、ここに記しておきます。


手順

移行は「Container Registry から Artifact Registry に自動的に移行する」による自動移行ではなく、「標準リポジトリへの移行」に従って手作業で移行しています。具体的に変わるのは、Cloud Buildによるコンテナのレジストリへの保存や、レジストリから取り出してCloud Runにデプロイする部分のみだと認識していました。

実際のコマンドだと以下のようになります。

Container Registry

gcloud builds submit --tag gcr.io/プロジェクト名/イメージ名

gcloud run deploy apply --image gcr.io/プロジェクト名/イメージ名 --region=リージョン名

 

Artifact Registry

gcloud builds submit . --pack image=リージョン名-docker.pkg.dev/プロジェクト名/リポジトリ名/イメージ名

gcloud run deploy apply --image リージョン名-docker.pkg.dev/プロジェクト名/リポジトリ名/イメージ名 --region=リージョン名


その他のソースなどは変更不要の認識です。


現象

ところがCloud Runでデプロイしたイメージを実行してみると、動作が違います。ソースとログから解析して、環境変数がなくなっていると判断しました。
Container Registryを使っていたころの該当環境変数は、以下のような感じでDockerfileで指定していました。

ENV 環境変数名 値の文字列


Artifact RegistryだとDockerfileの環境変数は反映されない様子です。


対処

DockerfileをあきらめてgcloudコマンドでCloud Runにデプロイする際に環境変数を指定することにしました。これはContainer Registryでも実績がある方法です。
実際の指定は以下のような感じ。
gcloud run deploy apply --image リージョン名-docker.pkg.dev/プロジェクト名/リポジトリ名/イメージ名 --set-env-vars="環境変数名=値の文字列" --region=リージョン名


これで解決しました。 

ちなみに、複数の環境変数を定義したい場合、"--set-env-vars"の値をコンマで区切って並べます。こんな感じ。

--set-env-vars="環境変数名1=値の文字列1","環境変数名2=値の文字列2"

 

2024/02/29

Cloud Runのインスタンス起動時間

 動機

Cloud Runのドキュメント「実行環境について」については以下の記述があります。
第 2 世代の実行環境は、一般に持続的な負荷の下では迅速に動作しますが、ほとんどのサービスでは、第 1 世代よりもコールド スタート時間が長くなります。
このように書かれると、第1世代/第2世代ともどの程度インスタンスの起動時間がかかるのか、どの程度違うのか気になります。また第2世代のジョブはバックグラウンドで動作するものなので起動時間はあまり気にされるものではありませんが、これも知りたくなってきます。
実行速度は目的によって測定方法も変えることになるので面倒ですが、インスタンスの起動時間については過去の記事「GAEのインスタンス起動時間」「GAEのインスタンス起動時間 #2」と同様に測定できますので測ってみました。


測定方法・条件

今回はCloud Runなので言語やランタイムのバージョンについては、使う人がDockerコンテナを作る際にいいようにすればいいだけの話です。なので純粋にCloud Runのインスタンス起動時間として、Hello World相当のGoでリクエスト→処理開始までを測ることにします。
  • リージョン : 大阪
  • ネットワーク : NTT Flets光 隼、実効300Mbps程度
  • サービス : 
    • ブラウザからAjaxでリクエストし、JavaScriptでレスポンスが返るまでの時間を測定。
    • スピンアップあり/なしの2パターンで、それぞれ10回測定し、平均値を算出。
    • 前記2パターンの差から、インスタンス起動時間を計算。
  • ジョブ : 
    • GAEからジョブを起動し、GAE/Cloud Runそれぞれに仕込んだログから、インスタンス起動時間を測定。
    • スピンアップは毎回行われるのでサービスのような「スピンアップなし」に該当するパターンは無いはず。念のため検証目的で、前回起動から15分以上時間空けてをスピンアップあり相当、前回起動から時間空けずにをスピンアップなし相当として、2パターンでそれぞれ10回測定し、平均値を算出。

測定結果

単位はすべてmsです。測定結果をtableにするのが面倒だったので、今回もExcelのキャプチャ画像です。

スピンアップあり。

スピンアップなし。

そしてインスタンス起動時間。

第1世代第2世代
serviceservicejob
158.7452.59344.4


まとめ


Cloud Runの世代間

公式ドキュメントの記載どおり、インスタンス起動時間は第1世代のほうが速いという結果です。
ジョブの起動時間はおおむね10秒程度でした。ちなみにジョブ終了→GAEで終了を検知も、おおむね10秒程度でした。

GAEとの比較

GAEのインスタンス起動時間 #2」と比較してみるとCloud Runは全体的に遅く、第2世代のサービスだとGAEの素のJavaよりいいくらいになっています。
本稿の趣旨からちょっと外れますが、スピンアップなしのケースではGoだろうがJavaだろうがほぼ確実に100msを切れるGAEに対して、Cloud Runだと3倍程度のレイテンシが発生しています。Webフロントエンド専用のプロダクトとしてgVisorという独自コンテナ技術まで作っただけあって面目躍如といったところで、汎用のDockerコンテナを利用するCloud Runは一歩及びません。

GoのコードはそのままでGAE/Goに実装したRESTful APIを、Cloud Runサービス/Goに変えたところ、ちょっともっさりするようになった気がした経験があります。これは気のせいではなかったと改めて認識しました。
Firebase Hostingには動的コンテンツをCloud Runで配信する機能「Cloud Run を使用した動的コンテンツの配信とマイクロサービスのホスティング」があるのですが、今回の結果を見ると、App Engineにも対応してほしいと思います。