今回は日頃からいくつものサイト配信で大変お世話になっているCloudflare社が提供するCloudflare Workersを試してみました。
普段はあまりここでサービス紹介系の記事は書かないのですが、いくつかのドメインを運用している都合上、コンテンツ生成に必要なアプリケーションサーバの用意が最近少しずつ大変になってきたので、今回紹介するCloudflare Workersの活用で開発リソース削減を検討するための備忘録として記事にしています。
Cloudflare Workers
Cloudflare WorkersはCloudflareが提供するサーバレスコンピューティング環境です。
AWS LambdaやGoogle Cloud Functionと同様のサービスでFaaS(Function as a Service)と呼ばれることもあります。Cloudflare公式の説明はこちら。
Cloudflareは大規模なCDN事業をやってますから世界中にエッジサーバを持っています(2020/07現在は約200とのこと)。WorkersアプリケーションはCloudflareのグローバルネットワーク上に展開されるので、世界中のどこからアクセスしても低いレイテンシーで実行することができます。
想定利用者
後述しますが、FaaSプロダクトとしては機能面において他社プロダクトに劣っている部分はあるので、高機能で多機能なFaaS環境が必要であれば他社プロダクトを使うはずです。Cloudflare Workersの想定利用者としては既にCloudflareのCDNを使ってコンテンツ配信しているサイト制作者が該当するのではないでしょうか。つまり自身のドメインを持っていてなんらかのサーバ運用もしている技術者にとっては使いやすいサービスなのだと思います。既にCloudflareのCDNでコンテンツ配信やHTTPS対応している人ならば、Cloudflare Workers導入のハードルは低くなっています。
あるいはCloudflareのグローバルネットワーク上で動作するFaaS環境を本気で必要としているサービス提供者でしょうか。AWSとかのパブリッククラウドだと結局はリージョン毎に区切られてリソースが割り当てられているので、どこでも同じパフォーマンスでサービス提供するのは困難です。Cloudflareのエッジにコードを載せることができれば、いつでもどこでも高いパフォーマンスでのサービス提供を実現できます。
無料利用枠
無料利用枠では以下のようなリソースが使えるようです。開発用のサブドメインが無料で使えるのはうれしいですね。
Cloudflare Workers | サーバーレスコンピューティング | Cloudflare
- 1日あたりリクエスト:10万(UTC+0)
- 最大30個のスクリプトをリリース
- すべての200データセンターで実行
- 無料のworkers.devサブドメイン
- リクエストあたりのCPU処理時間:10ミリ秒未満
- 最初のリクエスト後に最小レイテンシー
環境構築
前述の通り、Cloudflare Workersを使ってみようと考える人はCloudflareのCDNサービスを利用済みという前提があるので、アカウント作成などの手順は省略してWorkersアプリケーション構築に必要な情報のみ整理してみます。2020/07現在、利用できるランタイムはJavaScript(Node.JS)/Rust/C/C++の4つです。今回は手軽なJavaScriptでWorkerを作ってみます。
Wranglerのインストール
まずはCloudflare Workersのプロジェクト管理用CLIツール(Cloudflare公式) Wrangler をインストールします。パッケージマネージャーは好きなものを使えば良いです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
## wranglerのインストール $ yarn global add @cloudflare/wrangler $ wrangler --help wrangler 1.10.3 The Wrangler Team <wrangler@cloudflare.com> USAGE: wrangler [SUBCOMMAND] FLAGS: -h, --help Prints help information -V, --version Prints version information SUBCOMMANDS: kv:namespace Interact with your Workers KV Namespaces kv:key Individually manage Workers KV key-value pairs kv:bulk Interact with multiple Workers KV key-value pairs at once route List or delete worker routes. secret Generate a secret that can be referenced in the worker script generate Generate a new worker project init Create a wrangler.toml for an existing project build Build your worker preview Preview your code temporarily on cloudflareworkers.com dev Start a local server for developing your worker publish Publish your worker to the orange cloud config Set up wrangler with your Cloudflare account subdomain Configure your workers.dev subdomain whoami Retrieve your user info and test your auth config tail Aggregate logs from production worker help Prints this message or the help of the given subcommand(s) |
wrangler という名前のCloudflareと関係ないモジュールも存在しているので @cloudflare/wrangler と指定します。ちなみにwrangler自体はRustで書かれているようです。
API Tokenの取得
1 2 |
To find your API Token, go to https://dash.cloudflare.com/profile/api-tokens and create it using the "Edit Cloudflare Workers" template. |
Global API KeyではなくAPI Tokenを使いましょうとwranglerに注意されるので指示通りにAPI Tokenを作ります。以下のページ上部の Create Token ボタンからトークン発行できます。
指示に従ってトークンを作り、wranglerに記憶させておきます。
1 2 3 4 5 6 |
$ wrangler config ... 省略 Enter API Token: ## ここに発行したAPI Tokenを入力 Validating credentials... Successfully configured. You can find your configuration file at: /home/ryo/.wrangler/config/default.toml |
プロジェクト作成
引き続きwranglerを使ってWorkersプロジェクトを作ります。手動で必要なファイル群を揃えることはもちろんできますが、generateサブコマンドを使えばプロジェクト一式を生成できるので活用しましょう。
1 2 3 4 5 6 7 8 9 10 |
$ wrangler generate hello Installing cargo-generate v0.5.0... Creating project called `hello`... Done! New project created /home/ryo/workspace/dev/cloudflare-worker/hello You will need to update the following fields in the created wrangler.toml file before continuing: You can find your account_id in the right sidebar of your account's Workers page, and zone_id in the right sidebar of a zone's overview tab at https://dash.cloudflare.com - account_id $ ls CODE_OF_CONDUCT.md LICENSE_APACHE LICENSE_MIT README.md index.js package.json wrangler.toml |
まずアカウントIDを設定ファイル wrangler.toml に書いておく必要があるとのことなので、アカウントIDを確認します。これはCloudflareのダッシュボードページに行かなくても wrangler コマンドから取得できます。
1 2 3 4 5 6 7 |
$ wrangler whoami +------------------------------+----------------------------------+ | Account Name | Account ID | +------------------------------+----------------------------------+ | {登録メールアドレス}m's Account | {アカウントID} | +------------------------------+----------------------------------+ |
whoamiサブコマンドで表示されるAccount IDを wrangler.toml 内に書いておきます。
1 2 3 4 5 6 7 8 |
$ cd hello $ cat wrangler.toml name = "hello" type = "javascript" account_id = "{アカウントIDをここに書く}" workers_dev = true route = "" zone_id = "" |
zone_idは開発環境では指定必須ではありません。ここでは後回しにします。
実装
generateサブコマンドではテンプレートを指定することができますが、何も指定しない場合は以下のようなhello worldのプログラムが出力されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ cat index.js addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)) }) /** * Respond with hello worker text * @param {Request} request */ async function handleRequest(request) { return new Response('Hello worker!', { headers: { 'content-type': 'text/plain' }, }) } |
Cloudflare Workersは独自のランタイム/API仕様ではなくService Workers仕様で動作するので、Service WorkersのAPI仕様に則ってアプリケーションを実装することができます。
また、workerテンプレートのギャラリーサイトがあるので眺めてみると良いです。もちろんJavaScriptだけでなくRustなど他言語のテンプレートも揃っています。
動作確認
devサブコマンドでローカルサーバを起動できます。今回は静的なレスポンスを返すだけなので確認も簡単です。
1 2 3 4 |
$ wrangler dev JavaScript project found. Skipping unnecessary build! watching "./" Listening on http://127.0.0.1:8787 |
127.0.0.1:8787で起動するようです、curlで確認しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ curl -v http://127.0.0.1:8787 * About to connect() to 127.0.0.1 port 8787 (#0) * Trying 127.0.0.1... * Connected to 127.0.0.1 (127.0.0.1) port 8787 (#0) > GET / HTTP/1.1 > User-Agent: curl/7.29.0 > Host: 127.0.0.1:8787 > Accept: */* > < HTTP/1.1 200 OK < content-length: 13 < content-type: text/plain < date: Fri, 10 Jul 2020 08:40:58 GMT < * Connection #0 to host 127.0.0.1 left intact Hello worker! |
Hello worker! と出力されたので問題なさそうです。
デプロイ
workers.dev
まずはこのhello worldプログラムを開発環境 workers.dev にデプロイしてみます。既にアプリケーションIDは前述の手順で設定済みなのであとは公開するだけです。publishサブコマンドを使います。
1 2 3 |
$ wrangler publish JavaScript project found. Skipping unnecessary build! Successfully published your script to https://hello.wellflat.workers.dev |
{プロジェクト名}.{アカウント名}.workers.dev のドメインで開発環境でのアプリケーションが公開されるようです。ブラウザでアクセスすると、Hello worker! と表示されるはずです。
また、Cloudflareのダッシュボードページにも登録・公開したworkerがリストされます。(僕のブラウザではダークモード表示してるので黒いですが実際は白いサイトです)
production 本番環境
次はproduction環境にデプロイしてみましょう。自身のドメインで公開されますので、既にCloudflareにドメイン設定している前提となります。production環境へのデプロイには別途Zone IDが必要ですが、こちらはwranglerコマンドでは取得できない(?ようなので、仕方なくダッシュボードページでZone IDを調べます。Overviewタブのページ右下のAPIのセクションにZone IDとAccount IDが表示されているので控えておいて wrangler.toml に書いておきます。以下の例のようにproduction環境用のセクションを追加してそこにZone IDとルーティングのパターンを書くだけです。routeにはもちろん自身のドメイン下のパスを指定します。
1 2 3 4 5 6 7 8 9 |
name = "hello" type = "javascript" account_id = "{Account ID}" workers_dev = true [env.production] route = "rest-term.com/worker/hello" zone_id = "{Zone ID}" |
公開するにはpublishサブコマンドのオプションでproduction指定するだけです。
1 2 3 4 |
$ wrangler publish --env production JavaScript project found. Skipping unnecessary build! Deployed to the following routes: rest-term.com/worker/hello => created |
指定したrouteにアクセスして Hello worker! が表示されればOKです。
おわりに
workers.dev環境で動かしているとイマイチ面白くないのですが、やっぱり自分のドメイン上で動くのを見るとサーバレスの良さを実感しますね。オリジンにコードもランタイムも置かなくていいのは助かります。
一方で冒頭でも少し述べたように、単なるFaaS環境としてみると機能面では他社プロダクトより劣っている部分はあります。設定できる項目は2020/07現在だと環境変数とWorkers KVの名前空間だけですし(Workers KVは今回の記事では紹介対象外)、収集されるメトリクス情報もリクエスト数やエラー数、CPU時間くらいです。
また、今回試したプロジェクト一式はGitHubにも一応上げてありますので興味があれば。今後もCloudflare Worker関連のソースコードは適宜こちらのレポジトリに上げていく予定です。
今回はJavaScriptでworkerを作ってみましたが、次はRust(Rust-generated WebAssembly)でも作ってみたいですね。Wrangler本体もRust製ですしCloudflare社内でも積極採用されてるのでしょうか。公式ブログでもRustカテゴリの記事がいろいろあります。
Cloudflareのリリースアナウンスのブログにもあるように、リージョンなどに縛られること無く、コードがグローバルネットワーク上のどこでも動くことこそがクラウドコンピューティングの夢であると。前述の通り、現時点では機能面で不足があるかもしれませんが、Cloudflareの巨大なグローバルネットワーク上でサーバレスアプリケーションを公開できることが最大のメリットなのだと思います。今後の発展に期待ですね。
We believe the true dream of cloud computing is that your code lives in the network itself. Your code doesn’t run in “us-west-4” or “South Central Asia (Mumbai)”, it runs everywhere.
* Everyone can now run JavaScript on Cloudflare with Workers