これから始める Cloud Functions 入門
はじめに
本記事は Google Cloud が提供するサーバーレスコンピューティングサービスである「Cloud Functions」の入門記事です。Cloud Functions の詳細な使い方はドキュメントに網羅されていますが、本記事では Cloud Functions の概要をざっくりと知り、使い始めてみる ところに重点を置いて解説したいと思います。Cloud Functions を使い始める上での入り口としてご覧いただきながら、各機能のより詳細な内容はドキュメントを見ながら掘り下げていただければと思います。
Cloud Functions の特長
サーバーレス、FaaS
Cloud Functions はいわゆるサーバーレス、あるいは FaaS (Function-as-a-Service) と呼ばれるサービスです。
サーバーレスとはサーバーの管理を必要としないようなアーキテクチャの総称です。サーバーを用意して常時稼働させるような方式とは異なり、必要に応じて必要な機能だけ呼び出すことができるようなアーキテクチャを取ります。また FaaS はイベント駆動型コンピューティング実行モデルを指し、システム上で発生する様々なイベントを起点としてサーバーサイドロジックを実行する方式を取ります。
サーバーレスと FaaS はとても近い意味を持つ単語になりますが、要点としてサーバー管理不要、従量課金、イベント駆動という点を押さえておくと良いと思います。
フルマネージド
前述のサーバーレスであるポイントと少し被りますが、Cloud Functions はフルマネージドで提供されるサービスです。つまりはサーバーを管理する必要なく運用できます。利用者側はコードを書いてデプロイするだけでアプリケーションを構築できます。
よく言われる話ですが “サーバーレス” ということはサーバーは存在しないのかと言うと、決してそういうわけではありません。実際にはクラウドの裏側にはサーバーは物理的に存在はしているけれども、利用者側はサーバーがあたかも存在していないかのように使うことができる、と言う意味になります。では誰が管理しているのか?と言うと Google が管理しています。そう考えると、頼もしくも思っていただけるかも知れません。
オートスケーリング
Cloud Functions は規模に合わせてインフラストラクチャを自動でスケーリングします。そのため利用者側ではスケーラビリティについて悩む必要はありません。
スケーリングの規模を制御することも可能です。インスタンスの最大数を指定することで想定以上のスケールを抑制できる(必ずしも無限にスケールして欲しくない場合もある)ほか、最小数を設定することでコールドスタートを回避することもできます。
モニタリング、ロギング、デバッグ機能の統合
Cloud Functions は Cloud Operations と統合されています。そのためご自身で個別の設定をする必要なく、モニタリングやロギング、デバッグをすぐに始められます。
サーバーレスアプリケーションを運用する上では、ログの確認のしやすさやデバッグの容易さが重要になってきます。インフラを自分で構築している場合は SSH などでログインしデバッグなどが行えますが、サーバーレスの場合はサービスを通して行う形が基本です。Cloud Operations は運用がしやすいように考えられたサービスですので、Cloud Functions を効果的に運用できるようになっています。
細かなレベルのセキュリティ
Cloud Functions の呼び出しや管理機能などへのアクセスは、IAM (Identity and Access Management) または OAuth 2.0 による認証・認可をサポートしています。IAM についてはユーザーアカウントまたはサービスアカウントにロールを割り当てることで、操作を可能にします。また OAuth 2.0 ではスコープを指定することで、特定の操作の認可することができます。
マルチクラウド向けのネットワーキング機能
Cloud Functions はセキュリティ機能と柔軟性を兼ね備えた Google Cloud のネットワーキングサービスと統合しているため、マルチクラウド環境においても安全に使える環境を実現できます。
サーバーレス VPC アクセスを利用すると、Cloud Functions から VPC 内のリソースと通信することができます。Cloud Interconnect などを併用することでオンプレミスやほかのクラウドのリソースへの VPC アクセスも行うことができます。マルチクラウドやハイブリッドクラウドで構成する上でも、VPC 下でのネットワーキングを実現します。
また VPC Service Controls も適用できるため、万が一クレデンシャルが漏洩したとしても、承認を受けたネットワーク外からの Cloud Functions への呼び出しを遮断することもできます。
基本的な機能
関数の種類
Cloud Functions には2種類の関数があります。
- HTTP 関数
- イベントドリブン関数
HTTP 関数はその名の通り、HTTP リクエストを受けてサーバーサイドロジックを実行する関数です。一方イベントドリブン関数は主に Google Cloud の他のサービスで発火するイベントを契機に実行される関数です。イベントドリブン関数はさらにバックグラウンド関数と CloudEvent 関数に分類されており、使用するランタイムによってどちらの形式で利用できるかが変わってきます。
ランタイム
2021年9月現在、次のランタイムが利用できます。
各ランタイムのサポートバージョンは更新されていきます。現在の推奨バージョンはドキュメントを参照し、最新の情報を得るようにしてください。
開発
関数の開発で重要になってくるのがローカルでの関数の実行についてです。都度クラウド環境にデプロイして動作確認するのではなく、ローカルで確認できるようにしておくことで効率的に開発することができます。
ローカルで関数を実行するには、次のいずれかのレイヤーを設けることで実現できます。これらは抽象化レイヤーと呼び、このレイヤーの存在により作成した関数を Cloud Functions サービスの外部で実行できるようになっています。
コンテナ化が必要な場合は Buildpacks を使用し、そうでない場合は Function Framework を使用することを推奨しています。
デプロイ
Cloud Functions のデプロイ処理は、次の順番で行われます。
- アーカイブされたソースコードが Google Cloud Storage (GCS) にアップロードされる
- Cloud Build にビルドが送信され、コードがコンテナイメージ化される
- Container Registry に 2 のイメージが Push される
- Cloud Functions が 3 のイメージを使用して実行コンテナを作成する
利用者側は Cloud Functions にデプロイ操作を行うだけで、これら 1 ~ 4 の処理は自動で実行されます。
Cloud Functions では次のデプロイ方法を提供しています。
- ローカルマシンからデプロイ (
gcloud
コマンドを使用) - ソースリポジトリからデプロイ (GitHub や BitBucket など)
- Cloud Console からデプロイ
- Cloud Functions API からデプロイ
この中で最も簡単な方法は Cloud Console からデプロイする方法です。本記事では Cloud Console からデプロイする方法を試しています。コードを共有したり複数人で管理したい場合は GitHub などのソースリポジトリからデプロイする方法がおすすめです。
スケーリング
前述の通り、Cloud Functions はリクエスト数増加に伴って自動でスケーリングします。そのためリクエスト数の増加に対応するための特別な操作は必要ありません。
その上で、最大インスタンス数を決めることでスケールする規模を意図的に調整できます。これは、例えば Cloud Functions のバックエンドで接続するデータベースの同時接続数に制限がある場合などに有効です。
また最小インスタンス数を設定することでコールドスタート(インスタンスを準備するための初期化処理によるレイテンシ遅延)を回避することができます(現在プレビュー提供)。特にモバイルアプリや Web アプリなどのバックエンドとして利用する場合に有効です。
テスト
Cloud Functions の関数をテストするには、テストの段階や観点に応じて様々な手段を利用できます。単体テストであっても統合テストであっても、サービス間の連携(ほかの Google Cloud のサービスを使用している場合、それらを組み合わせたテスト)をローカルでどのようにテストするかは大事なポイントです。
ランタイム(言語)で提供されているモックやスタブ用のフレームワークを使う形で比較的簡単に実現できますし、テストの実行時間も短くて済みます。また一部のサービスではエミュレーターを提供していますので、テスト内で仮想的に実行することもできます。
ロギングとモニタリング
Cloud Functions のログは Cloud Logging に送信、保存されます。また、Cloud Functions の実行に関するメトリクスは Cloud Monitoring に送信、保存されます。ログや指標のデータは Cloud Functions のコンソールで見ることができますので、運用・監視についても簡単に始めることができるようになっています。
また関数に何かしらの問題が起きた場合にすぐに気づけるよう、アラートを設定することができます。アラートは特定のエラーログが記録された場合や指標が特定の閾値に達した場合などの条件で仕込むことができます。
Cloud Run との違い
Cloud Functions を使い始めるにあたって、よく話を伺うのが Cloud Run との違いについてです。Cloud Run はコンテナベースのサーバーレスコンピューディングサービスです。基本的な立ち位置としては Cloud Functions と非常に近しいので、どちらを選ぶのか悩まれる方も多いのではないかと思います。
その一つの解は Google Cloud Blog「Cloud Run: サーバーレス コンテナの話」に述べられていますので引用します。ざっくり、より簡単に使えるのが Cloud Functions、柔軟性・拡張性がより高いのが Cloud Run、といったところが違いと言えます。
- Cloud Functions では、限られたプログラミング言語のセットで記述されたコード(関数)のスニペットをデプロイできます。Cloud Run では、選択したプログラミング言語を使用してコンテナ イメージをデプロイ可能です。
- Cloud Run は、アプリケーションからの任意のツールまたはシステム ライブラリの使用もサポートします。Cloud Functions は、カスタム実行可能ファイルを使用できません。
- Cloud Run は、最大 60 分の長いリクエスト タイムアウト時間を提供します。一方で Cloud Functions のリクエスト タイムアウトは最大で 9 分です。
- Cloud Functions は、各関数インスタンスに一度に 1 つのリクエストのみを送信します。一方で Cloud Run は、デフォルトで、各コンテナ インスタンスで複数の同時リクエストを送信するように構成されています。これは、大量のボリュームが予想される場合に、レイテンシを改善し、コストを削減するのに役立ちます。
また Cloud Run には Cloud Run for Anthos という選択肢もあるため、Kubernates の延長線上でサーバーレス構成を取りたい場合は選定する上での観点の一つになるかと思います。
Cloud Functions for Firebase との違い
Cloud Functions には「Cloud Functions for Firebase」と言う、Firebase 向けの Cloud Functions も提供しています。Google Cloud で構築する Cloud Functions とは明確に異なっており、主にどのような種類のイベントを扱うかによってどちらかを選択する必要があります。
Cloud Functions (Google Cloud)
Google Cloud の各サービスをつなぎ合わせる接続層として機能します。主に各サービスのイベントを受け取り、サーバーロジックを実行し、他のサービスに連携したりする場合に使用します。
Cloud Functions for Firebase
モバイルアプリまたは Web アプリ向けのクラウドプラットフォームである「Firebase」の環境上で使用することに最適化された Cloud Functions です。Firebase Authentication や Google Analytics for Firebase などといった Firebase プロダクトのイベントを受け取り、これらの機能を拡張する目的で使用します。
Cloud Functions の用途として「Google Cloud 上で構築するアーキテクチャの一部」なのか「Firebase の機能拡張」なのか、と言う点が選定のポイントになります。
使ってみる
それでは早速 Cloud Functions を使い始めてみましょう。本記事では HTTP アクセスで起動する、非常にシンプルなサーバーレスアプリケーションを作ってみましょう。
関数を作成する
まずは関数を作成するところから。Google Cloud を使用する Google アカウントでログインした状態で、以下にアクセスします。
まずは [関数を作成] ボタンをクリックします。
関数の作成ウィザードが立ち上がります。[関数名] は first-function
、[リージョン] は asia-northeast1
(Tokyo) にします。
[トリガーのタイプ] は HTTP、つまりHTTP アクセスをトリガーに動作する関数とします。[認証] は「未認証の呼び出しを許可」にします。つまり、認証なしで誰でも呼び出せる API となります。また [HTTPS が必須] にチェックを付けることで、HTTP のアクセスを HTTPS にリダイレクトさせることができます。入力が完了したら [保存] をクリックしたあと [次へ] をクリックします。
トリガーに HTTP を選ぶと、インラインエディタでシンプルなコードが自動的に作成されます。ランタイムは Node.js で作成されているので、そのまま使用します。
コードをちょっと見てみましょう。エントリーポイントである helloWorld
に関数が定義されています。クエリパラメータは req.query
から、リクエストボディは req.body
から取得しています。このコードでは、クエリパラメータやリクエストボディに message
が設定されたらレスポンスボディが変わるような挙動になっています。
exports.helloWorld = (req, res) => {
let message = req.query.message || req.body.message || 'Hello World!';
res.status(200).send(message);
};
なお、コードエディタのページで下記のようなエラーが出ている場合、Cloud Build API が有効化されていないためデプロイが行えません。[API を有効にする] をクリックし、開いたページにて Cloud Build API を有効にしてください。
[デプロイ] をクリックすると関数のデプロイが実行されます。
関数名をクリックすると、関数詳細画面が開きます。詳細画面ではコードの修正やモニタリング、テストなどが行えます。ログのモニタリング自体は Cloud Operations で行われていますが、Cloud Functions のコンソール上でモニタリングが行えるようになっています。
関数を呼び出してみましょう。グローバルメニューの右側にあるボタンをクリックし Cloud Shell を立ち上げます。
cURL を使って次のコマンドを実行すると Hello, World!
がレスポンスとして返ってきます。
$ curl https://asia-northeast1-{project-id}.cloudfunctions.net/first-function
Hello, World!
また、先ほどコードで確認したようにクエリパラメータやリクエストボディを指定すると、その文字列がレスポンスで返ってくるように動作が変わります。
$ curl https://asia-northeast1-{project-id}.cloudfunctions.net/first-function?message=goodevening!
goodevening!$ curl https://asia-northeast1-{project-id}.cloudfunctions.net/first-function -d message=goodafternoon!
goodafternoon!
まとめ
本記事では Cloud Functions の概要と基本的な機能のご紹介、そして初めの一歩としてのチュートリアルを解説しました。Cloud Function はコードを書くだけですぐにデプロイし実行できるサービスであり、シンプルなバックエンドのほか、さまざまなサービスとの “つなぎ” として使えるサービスです。
どのような繋ぎ方ができるかというと、チュートリアルをご覧いただけるとお分かりいただけるかと思います。ほかの Google Cloud サービスと連携したアーキテクチャや Pub/Sub や Workflows を使ったイベント駆動アーキテクチャ、Slack などとの連携方法などを紹介しています。ぜひ参考にサーバーレスアーキテクチャを構築してみてください。