tag:crieit.net,2005:https://crieit.net/tags/GoogleCloudRun/feed 「GoogleCloudRun」の記事 - Crieit Crieitでタグ「GoogleCloudRun」に投稿された最近の記事 2020-08-15T23:22:32+09:00 https://crieit.net/tags/GoogleCloudRun/feed tag:crieit.net,2005:PublicArticle/16030 2020-08-14T23:54:11+09:00 2020-08-15T23:22:32+09:00 https://crieit.net/posts/Cloud-Run-Rate-exceeded Cloud RunでRate exceededエラーになる <p>ある日突然Cloud Runにデプロイしているサービス(当サービス)にアクセスすると無情にも「Rate exceeded.」とだけ表示されるようになっていた。エラーログを見てみるとステータスは429、エラー詳細を開くと「The request was aborted because there was no available instance」と表示されている。</p> <p>原因自体は初めてデプロイした時あたりにも出ていたのでわかる。Cloud Runには最大インスタンス数の設定があるのだが、それが足りないため。たしか最初は1~3あたりにしていたような気がする。それだと時々Rate exceededとなるため10くらいに増やしていた。それ以来自分は見ることがなくなった。</p> <p>しかし突然の再発。原因は分からないが、引き金はクローラのアクセスが集中したりしたのかもしれない。想像でしか無いが、ただ時々クローラがアクセスしてきてエラーが大量に出ているのは見かける。</p> <p>しかし今回は復旧する様子がない。22時くらいに発生し、色々と確認した。しかし原因はよく分からず。最大インスタンス数は20とか100とかにして試した気がするが、それでも復旧しなかった。原因が原因だけにもしかしたら放置しておけばいつの間にか治るかな、と思い、とりあえずねた。しかし次の日になっても治っていなかった。もしかすると時差の関係もあるのかなと思い一応夕方くらいまで待ってみたが、相変わらずだった。</p> <h2 id="解決した方法"><a href="#%E8%A7%A3%E6%B1%BA%E3%81%97%E3%81%9F%E6%96%B9%E6%B3%95">解決した方法</a></h2> <p>最終的に、最大インスタンス数の設定を1000にしたら動くようになった。さすがにそんなにアクセスが続いているわけもないと思うのでなぜそこまで上げなければならないのか結局よくわからないまま……。</p> <p>気づいたのは、Cloud Runにあるデモイメージを試してみたら動いたため。それは何の設定もいじっていなかったので最大インスタンス数が1000になっていた。</p> <p>とにかく困ったら上限の1000まで上げてみるとよいかもしれない。</p> <h2 id="今回は一時的な問題かも"><a href="#%E4%BB%8A%E5%9B%9E%E3%81%AF%E4%B8%80%E6%99%82%E7%9A%84%E3%81%AA%E5%95%8F%E9%A1%8C%E3%81%8B%E3%82%82">今回は一時的な問題かも</a></h2> <p>というか、今回のこれは僕以外も何人か発生してるのを観測したので一時的に発生している問題かもしれない。(多分書いている時点では未解決)</p> だら@Crieit開発者 tag:crieit.net,2005:PublicArticle/15813 2020-04-06T07:53:02+09:00 2020-06-01T16:18:36+09:00 https://crieit.net/posts/GCE-Cloud-Run GCEからCloud Runに引っ越してみた <p>当サービスCrieitをGoogle Compute EngineからCloud Runに引っ越ししてみました(2020/4)。選定理由、実際にやったこと、懸念点などを色々書いてみます。</p> <p>費用についても書きたいのですが、まだ引っ越ししたばかりのためわかりません。1,2ヶ月ほど経ったら追記しますので気になる方はフォローやブックマークなどしておいてください。</p> <p>※当記事は一部有料です。後半の実際にRunを使う方しか興味がなさそうな内容あたりは有料となっています。使ってみた感じやRunに関係ない引っ越しメモ等は無料です。費用については無料部分に書きます。</p> <h2 id="元々の構成"><a href="#%E5%85%83%E3%80%85%E3%81%AE%E6%A7%8B%E6%88%90">元々の構成</a></h2> <p>Compute Engineの1台構成です。f1-microインスタンスを利用しておりMySQLもこの中にインストールしているのでAlways FreeのおかげでWebサーバー、DBサーバー自体は無料運用です。ファイルなどはStorageです。</p> <p>ちなみにLaravelで作られており、詳しい構成は下記に書かれています。<br /> <a href="https://crieit.net/posts/Crieit-5b8e526e13820">Crieitの構成</a></p> <h2 id="新しい構成"><a href="#%E6%96%B0%E3%81%97%E3%81%84%E6%A7%8B%E6%88%90">新しい構成</a></h2> <p>WebサーバーにCloud Run、DBサーバーはCloud SQL(db-f1-micro)にしました。Cloud SQLは無料枠がないため費用がかかりますが、とりあえず広告費用内でまかなえるので以前からそのうち使おうと思っていました。全部1台のサーバーに入れているのはやはりなんとなく怖かったため。</p> <h2 id="なぜ引っ越したのか"><a href="#%E3%81%AA%E3%81%9C%E5%BC%95%E3%81%A3%E8%B6%8A%E3%81%97%E3%81%9F%E3%81%AE%E3%81%8B">なぜ引っ越したのか</a></h2> <h3 id="たまに落ちる"><a href="#%E3%81%9F%E3%81%BE%E3%81%AB%E8%90%BD%E3%81%A1%E3%82%8B">たまに落ちる</a></h3> <p>Compute Engineは普通のサーバーですので、やはり何らかの状況によって時々落ちるというかフリーズします。多分なにかボットのアクセスが激しい時にスワップしてしまってそのままになってしまうのだと思いますが。</p> <p>とは言っても約2年くらい運営してきてそんな感じで止まることはめったにありませんでした。たまに数分だけ重いとMackerelから通知が来たりはしていましたが。ただ、最近1日に2回も大きなフリーズがあったので、さすがに怖くなったのが引っ越すことになった一番のきっかけかもしれません。</p> <h3 id="むちゃくちゃ遅い"><a href="#%E3%82%80%E3%81%A1%E3%82%83%E3%81%8F%E3%81%A1%E3%82%83%E9%81%85%E3%81%84">むちゃくちゃ遅い</a></h3> <p>リリースする時に深く考えず、us-eastに構築してしまいました。これのせいでもうとにかくすごく遅い。あらゆるページで表示されるまでに1秒位かかっていました。こちらも元々そのうちwestに引っ越したいなと思っていました。</p> <h2 id="なぜCloud Runを選択したのか"><a href="#%E3%81%AA%E3%81%9CCloud+Run%E3%82%92%E9%81%B8%E6%8A%9E%E3%81%97%E3%81%9F%E3%81%AE%E3%81%8B">なぜCloud Runを選択したのか</a></h2> <h3 id="サーバーを管理したくなかった"><a href="#%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%92%E7%AE%A1%E7%90%86%E3%81%97%E3%81%9F%E3%81%8F%E3%81%AA%E3%81%8B%E3%81%A3%E3%81%9F">サーバーを管理したくなかった</a></h3> <p>最初から決めていたわけではなく、App EngineとCloud Runを試して決めよう、という感じでやっていました。どちらもマネージドで、自分でサーバーを管理する必要がありません。とにかくCloud SQLに費用を払うことになってでもサーバーを管理したくなくなったというのが一番の理由です。</p> <p>結局Runの方を選んだのですが、理由としてはApp Engineはデプロイするために、結構ローカル開発環境を本番向けに変えたりスイッチしたりする必要があります。もちろんデプロイを自動化すればいい話ですが、そもそもその前に一旦試してみるのが面倒になってやめました。最初にCloud Runの実験をしていたのですが、そちらはDockerイメージ内で適当にファイルを調整すればいいのでローカル環境を汚さず簡単に試せて非常に良いと感じました。</p> <h3 id="デプロイが簡単"><a href="#%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%8C%E7%B0%A1%E5%8D%98">デプロイが簡単</a></h3> <p>ローカルでコマンドをいくつか実行するだけでデプロイできます。バッチとしてまとめているので1コマンドで行けるようになりました。</p> <pre><code class="bat">@echo off FOR /F %%i in ('git rev-parse HEAD') do set HASH=%%i set IMAGE=gcr.io/プロジェクトID/イメージ名:%HASH% @echo on call gcloud builds submit --tag %IMAGE% --project プロジェクトID call gcloud run deploy Runのサービス名 --image %IMAGE% --project プロジェクトID --region asia-northeast1 --platform managed --quiet </code></pre> <p>今回はやっていませんがCIによる自動化もコマンドベースなので簡単そうです。</p> <p><a target="_blank" rel="nofollow noopener" href="https://qiita.com/szk3/items/38a3dba7fdfed189f4c9">GitHub Actionsを使うとCloud Runへのデリバリが最高に捗るぞ🚀 - Qiita</a></p> <h3 id="東京リージョンが使える"><a href="#%E6%9D%B1%E4%BA%AC%E3%83%AA%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%81%8C%E4%BD%BF%E3%81%88%E3%82%8B">東京リージョンが使える</a></h3> <p>App EngineもCloud Runも東京リージョンが使えます。GCEのようにアメリカだけ無料、とかではないので安心です。ただまあネットワーク料がかかってくると思いますのでそちらは気になりますが。</p> <p>実験したところ元々1秒くらいかかっていたページの表示が300~500ミリ秒くらいになっていました。すごく速いというわけではなさそうですが、とりあえず元々遅すぎたのでだいぶいい感じにはなりました。</p> <h3 id="安い?"><a href="#%E5%AE%89%E3%81%84%EF%BC%9F">安い?</a></h3> <p>Cloud Run自体はこんな感じで実際に使ったリソースの分しか消費されないので無料枠内で結構いけてしまうのかな…? と感じました。これはでも実際どうかわからないため、1、2ヶ月ほどしたら追記します。</p> <p><a href="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e8a66b399cb9.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e8a66b399cb9.png?mw=700" alt="" /></a></p> <p>追記)ネットワーク料金が14円で、CPU、メモリは費用内で無料でした。やはりデプロイ時に設定するメモリ料での計算でなく、実際に使った量だけみたいです。</p> <h3 id="ロールバックも簡単"><a href="#%E3%83%AD%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E3%82%82%E7%B0%A1%E5%8D%98">ロールバックも簡単</a></h3> <p>これは実際に使ってみて気づきましたが、デプロイのリビジョンが残っているため何か不具合などがあってロールバックしたくなったときも簡単に戻すことができます。このあたりはGAE等ほかの簡単デプロイ系サービスでも同じかもしれませんが。</p> <p><a href="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e8b1d1ce2b55.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e8b1d1ce2b55.png?mw=700" alt="" /></a></p> <h2 id="実際にやったこと"><a href="#%E5%AE%9F%E9%9A%9B%E3%81%AB%E3%82%84%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8">実際にやったこと</a></h2> <h3 id="ストレージの引っ越し"><a href="#%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8%E3%81%AE%E5%BC%95%E3%81%A3%E8%B6%8A%E3%81%97">ストレージの引っ越し</a></h3> <p>まずはアップロードされた画像が入っているストレージだけ先に引っ越しました。というのも、Crieitの場合アップロード画像は直接ストレージのURLを使うわけではなく、Now経由でCDNキャッシュさせて費用を節約させています(<a href="https://crieit.net/posts/Now-Cloud-Storage">NowのエッジキャッシュでCloud Storage節約サーバー作成</a>)。ということで、引っ越しても画像のURLが変わるわけではありませんし、独立して先に引っ越しできるため先に移動しました。</p> <p>具体的には下記の方法です。転送機能が用意されています。S3やAzureからも可能のようです。Cloud Storage間であればコマンドでも可能です。僕の場合は1GBもなかったので一瞬で終わりました。</p> <p><a target="_blank" rel="nofollow noopener" href="https://cloud.google.com/storage/docs/moving-buckets?hl=ja">バケットの移動と名前変更</a></p> <p>通信料金も変わると思いますが、引っ越すまでの期間であればたいして影響も無いでしょう。とりあえずこれで一つやることが完全に減らせました。</p> <h3 id="ファイル保存している部分の調整"><a href="#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E4%BF%9D%E5%AD%98%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E9%83%A8%E5%88%86%E3%81%AE%E8%AA%BF%E6%95%B4">ファイル保存している部分の調整</a></h3> <p>セッションやキャッシュはデフォルトでファイル保存になっています。しかしCloud Runは必要に応じてインスタンスが立ち上がったりするためファイルだと正常にセッションの維持などができません。そのためデータベース保存に変更しました。具体的にはまず下記でマイグレーションファイルを生成して実行します。</p> <pre><code>php artisan session:table php artisan cache:table </code></pre> <p>そしてあとは環境変数をdatabaseに変えます。</p> <pre><code class="ini">CACHE_DRIVER=database SESSION_DRIVER=database </code></pre> <p>まあここは他にもRedisを使ったり自由で良いと思います。</p> <p>あとはログの出力も変更しておきます。これもファイルだとログを見ることもできないため、stderrにしておきます。こうすると自動的にCloud Runのコンソール上でログを見ることができます(その他にもいくつか方法はあります)。</p> <pre><code class="ini">LOG_CHANNEL=stderr </code></pre> <h3 id="DBの設定"><a href="#DB%E3%81%AE%E8%A8%AD%E5%AE%9A">DBの設定</a></h3> <p>今回はCloud SQLを使っています。接続にはCloud SQL Proxyを使っています。例えばLaravelの場合、下記のようにソケットを指定します。</p> <pre><code class="ini">DB_SOCKET=/cloudsql/インスタンス接続名 </code></pre> <p>インスタンス名はCloud SQLの詳細画面で確認できます。</p> <h3 id="DBの移行"><a href="#DB%E3%81%AE%E7%A7%BB%E8%A1%8C">DBの移行</a></h3> <p>DBの移行は、元々使っているGoole Compute EngineにMySQLをインストールしていたので、mysqldumpを利用しました。サーバー上のデータをmysqldumpでダンプし、そしてcloud_sql_proxyを実行するとCloud SQLにソケットでアクセスできるようになりますので、それでインポートしました。具体的なインポート方法は下記のようになります。</p> <pre><code>mysql -u ユーザー名 -p -S /cloudsql/インスタンス接続名 < dump.sql </code></pre> <p>参考)<br /> <a target="_blank" rel="nofollow noopener" href="https://cloud.google.com/sql/docs/mysql/connect-compute-engine?hl=ja#gce-connect-proxy">Cloud SQL Proxy を使用した接続</a><br /> <a href="https://crieit.net/posts/GCE-cloud-sql-proxy">GCEでcloud_sql_proxyが実行できない時</a></p> <h3 id="メンテナンスモード"><a href="#%E3%83%A1%E3%83%B3%E3%83%86%E3%83%8A%E3%83%B3%E3%82%B9%E3%83%A2%E3%83%BC%E3%83%89">メンテナンスモード</a></h3> <p>ストレージもDBも、ユーザー操作中に移行を行うと一部データが失われてしまう可能性があります。そのためメンテナンスモードにしておく必要があります。</p> <p>Laravelの場合、メンテナンスモードのコマンドが元々あるようなのでそちらを利用しました。メンテナンスモードに入るときは <code>php artisan down</code> 復帰するときは <code>php artisan up</code> です。</p> <p>downの場合はメッセージや許可IPなども指定できます。</p> <p><a target="_blank" rel="nofollow noopener" href="https://laravel.com/docs/7.x/configuration#maintenance-mode">Maintenance Mode - Configuration - Laravel - The PHP Framework For Web Artisans</a></p> <p>引っ越しの場合は新しいサーバーにアクセスが行くようになったらもう古いサーバーは使われませんので、upする必要もないかもしれません。</p> <p>結局ネックとなるのはDBの同期です。Cloud Runの設定も含め、これ以外で事前にできることはなるべく済ましておきました。</p> <h3 id="プロキシ用の設定"><a href="#%E3%83%97%E3%83%AD%E3%82%AD%E3%82%B7%E7%94%A8%E3%81%AE%E8%A8%AD%E5%AE%9A">プロキシ用の設定</a></h3> <p>元々Nginxを使っていた場合などは関係ない場合もありますが、プロキシ経由でなく直接アプリケーションにアクセスさせていた場合、このあたりの設定をする必要があります。例えばLaravelではTrustProxiesというミドルウェアのproxiesを許可するように設定しておく必要があります。</p> <pre><code> protected $proxies = '*'; </code></pre> <p>その他うまく動かない場合はSSLやホスト名の設定も問題ないか見てみる必要があります。Nginxのパターンとはちょっと違う可能性もありそうです。</p> <h3 id="バッチ等はどうしたか"><a href="#%E3%83%90%E3%83%83%E3%83%81%E7%AD%89%E3%81%AF%E3%81%A9%E3%81%86%E3%81%97%E3%81%9F%E3%81%8B">バッチ等はどうしたか</a></h3> <p>Cloud RunはSSHアクセスできませんので、コマンドの実行や定期処理などは考える必要があります。一応公式としてはCloud Schedulerを使うということになっています。</p> <p><a target="_blank" rel="nofollow noopener" href="https://cloud.google.com/run/docs/triggering/using-scheduler?hl=ja">Running services on a schedule</a></p> <p>ただし、httpアクセスになるためちょっとコードを調整したりする必要もあり面倒です。そのため、今回はGCEからの移転ということもあり、定期処理や時々コマンドを実行したいときはもうそのGCE上で行うようにすることにしました。アプリケーションのDB接続もCloud SQLに行うようにしてあります。リージョンも違うので遅いとは思いますがどれも一瞬実行するだけなので問題は恐らく無いでしょう。Cloud SQLへの接続はcloud_sql_proxyをSystemdでサービス化して行っています(参考 <a target="_blank" rel="nofollow noopener" href="https://sys-guard.com/post-15640/">GCP Cloud SQLにCloud SQL Proxyで接続しよう。Systemd化してデーモン化! | システムガーディアン株式会社</a>)。</p> <p>以下は有料です。下記のような内容を書いています。</p> <ul> <li>実際に作ったDockerfileの例(Laravel & Apache)</li> <li>vendorフォルダが無視されることへの対処</li> <li>.envファイルが無視されることへの対処</li> <li>ポートの指定について</li> <li>Dockerイメージのビルド方法(Cloud Buildの利用)</li> <li>Cloud Runのサービスを作成する具体的な手順とエラーにならないようにするための注意点</li> <li>独自ドメインの利用方法</li> <li>ステージング環境の作成例</li> <li>Cloudflareで525 SSL handshake failedエラーが出た場合</li> </ul> だら@Crieit開発者