こんにちは。GMO NIKKO エンジニアのALPHです。
いよいよ寒くなってきましたね。鍋がおいしい季節です。
最近、不注意で指を痛めたことがあり焦ることがありました。痛烈に自動化の重要性を改めて実感しました。
やはり、GUIからの操作からだけでは運用が辛いですよね。
簡単にコマンドで操作したい、バッチ処理で自動化したいと思うのが人の心。
そのような流れで
今回は、最近話題の「Cloud Run」の操作自動化手法の一例をご紹介します。
なんでCloudRunかというと、まだ情報量がちょっと少なかったので苦戦した記憶があるためです。
Cloud Run の概要はこちら
Cloud RunのAPI とリファレンスはこちら
Cloud Runで操作の自動化をするにあたって、APIの操作をやはり覚える必要があります。
GUIコンソールからできることは、大抵APIからできます。
それぞれ一つ一つ対応するコマンドをシェルに書いて制御したい場合もあると思います。
今回紹介する操作手法は、一連の処理をYAMLファイルにまとめて記載しgcloud builds submit コマンドで実行する形式です。
以下、順序を追って説明していきます。
今回のCloud Runのサービスを起動するまでの手順は
①DockerFileの準備(httpd.conf含む)
②Cloud Shell上でのローカルチェック
③ビルド/デプロイ用YAMLファイル準備
④ビルド/デプロイ実行でサービス起動
というのが大きな流れです。
上記の内容を含めて、ひとまず、今回準備するファイルは次のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 |
#DOCKERファイル ./services/yourbuild/docker/index.html(好きな内容) ./services/yourbuild/docker/Dockerfile(今回は指定) ./services/yourbuild/docker/httpd.conf(port 8080で用意) #BUILD/DEPLOY用YAMLファイル ./services/yourbuild/docker/yaml/build/build.yaml(ビルド操作用) ./services/yourbuild/docker/yaml/yourservice/flags-file.yaml(デプロイ用環境変数) ./services/yourbuild/docker/yaml/yourservice/deploy.yaml(デプロイ操作用) #実行ファイル exec.sh |
【①DockerFileの準備(httpd.conf含む)】
Cloud Run上で動かす、DockerFileの準備をします。
DockerFileを知らない人も多いと思いますが、Cloud RunはこのDockerFileを動かすためのコンテナの一つです。
これを動かすと
https://{あなたのサービス名}-{固定サービスID}-{クラウドファンクションの標準ドメイン}/
のようなURLでブラウザからアクセスすることができます。
※くれぐれも費用面には注意してください。レスポンス容量を最小化する等の工夫が必要です。
Cloud Runの注意事項としては、設定されたメモリ容量内で諸々展開する必要があり、容量との戦いでもあります。
ですので、Dockerベースイメージは、必要最低限のインストールされたものがお勧めです。
今回は、DockerFileのベースイメージに関しては、httpd2.4/alpineを利用します。
httpd2.4/alpine はこちら
ALPINEにHTTPD2.4をインストールしたイメージをベースに指定して好きなライブラリをインストールし、httpd.conf とindex.html をコピペしたものをイメージとして作成します。
1 2 3 4 |
FROM httpd:2.4-alpine RUN apk add --update --no-cache bash COPY httpd.conf /usr/local/apache2/conf/ COPY index.html /usr/local/apache2/htdocs/ |
index.htmlも、アクセスチェックさえできればよいので、空ファイルで用意します。
1 |
<html><body>It works</body></html> |
httpd.conf は、portをCloud Runの標準である8080に変更しておきます。
1 2 3 |
... Listen 8080 ... |
【②Cloud Shell上でのローカルチェック】
Cloud Runで動かす前に、Cloud Shellのローカル環境で事前に挙動をチェックしておくとよいでしょう。
1 2 3 4 |
#Cloud Shellの環境で事前にチェックしておきましょう。 docker build ./services/yourbuild/docker/ --tag yourbuild-local docker run -itd --name yourservice yourbuild-local docker exec -it yourservice bash |
【③-1. ビルド用バッチ build.yamlの準備】
一連のビルド処理をbuild.yamlにまとめます。
内容としては、コンテナをBUILDして、PUSHします。
1 2 3 4 5 6 7 8 9 10 11 |
steps: - name: 'bash' args: ['pwd'] - name: 'bash' args: ['ls'] - name: 'bash' args: ['ls','services/yourbuild/docker'] - name: 'gcr.io/cloud-builders/docker' args: ['build', '-t', 'gcr.io/$PROJECT_ID/yourbuild', './services/yourbuild/docker'] - name: 'gcr.io/cloud-builders/docker' args: ['push', 'gcr.io/$PROJECT_ID/yourbuild'] |
【③-2. デプロイ用バッチ deploy.yamlの準備】
一連のデプロイ処理をdeploy.yamlにまとめます。
今回は、デプロイした後に、念のためインスタンスのトラフィック割合を更新します。
そうすることで、Cloud Runでは異なるインスタンス毎にリクエストの割合を定めることができます。
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 31 32 33 34 35 |
steps: - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk' entrypoint: gcloud args: - 'run' - 'deploy' - '[Your Service Name]' - '--image' - 'gcr.io/$PROJECT_ID/yourbuild:latest' - '--region' - 'asia-northeast1' - '--platform' - 'managed' - '--min-instances' - '1' - '--max-instances' - '3' - '--concurrency' - '40' - '--memory' - '128Mi' - '--flags-file' - 'services/yourbuild/docker/yaml/yourservice/flags-file.yaml' - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk' entrypoint: gcloud args: - 'run' - 'services' - 'update-traffic' - '[Your Service Name]' - '--region' - 'asia-northeast1' - '--platform' - 'managed' - '--to-latest' |
トラフィックを明示的に切り替えたい場合、「–to-latest」を設定する必要があります。
そうすると、100%新しいインスタンスにトラフィックが向くはずです。
少しだけ、古いインスタンスと合わせて平行稼働させたい場合は別途明示的にトラフィック調整をする必要があります。
最大インスタンス数は、サイトの説明を見ると、最大数3はあるのが望ましいっぽいです。
最小インスタンス数は、いつのまにか0指定ができるようになりました。
ただし、0指定すると、アクセスがなくなると停止し、なにかアクセスがあるたびに起動するため、起動時になにか処理をしている場合は注意が必要です。例えば、アクセスがあるたびにインスタンスが起動して、30分に1回とか繰り返し実行してしまいます。もし、起動時に処理するファイルが重いファイルだったら、痛いかもしれません。
メモリに関しては、搭載コンテンツに合わせて、設定する必要があり、可能な限り変動量を予測して、必要なメモリ数を割り出したほうが安全かもしれません。
【③-3. デプロイ用環境変数 flags-file.yaml】
Cloud Run用環境設定パラメータ等をどのようにして設定するか苦慮した記憶があります。
外部環境で外に出すことも可能なので、パラメータが多い場合やエスケープに詰まる場合に下記のように外部ファイルにセットしてみてください。
1 |
--set-env-vars: ^@^A=B@C=D@E=F |
【④ビルド/デプロイ実行でサービス起動】
いよいよ最後に実行します。
順序としては
プロジェクトID設定⇒ビルドバッチ処理⇒デプロイバッチ処理
です。
これでCloud Run上にサービスが起動するはずです。
下の内容をexec.sh として保管し、実行します。
1 2 3 4 5 6 |
#1.PROJECTを設定します gcloud config set project {project名} #2.CLOUDBUILDでBUILDを設定します gcloud builds submit --config services/yourbuild/docker/yaml/build/build.yaml #3. BUILDしたものをyourserviceにDEPLOYします gcloud builds submit --config services/yourbuild/docker/yaml/yourservice/deploy.yaml |
以下、余談ですが
GCPのCloud Load Balancingを通して、サーバレスNEG経由で、たしか、2020年秋口ぐらいからアクセスできるようになりました。
ポイントとしては、付属のCloud CDNが簡単にそのまま使えるのでひょっとしたら大規模な負荷にも耐えられるのではないかと思います。
まだまだこの範囲は発展途中だと思いますが、組み合わせて使ってみるといいかもしれません。
Cloud CDNを使うと、ヘッダーに 「Cache-Control: public, max-age=3600」等を入れるだけで指定された時間のキャッシュ配信が可能になります。
Cloud Runで HTTP STATUS 429 がでてユーザーに同じ静的コンテンツを大量に返している場合は、こちらを利用して回避したほうが料金的にも良いかもしれません。
※CDN配信費用が別途かかるので注意
他にも効率的な方法等はあると思いますが、ひとまず、自分なりに調べてみて、ある程度つかえそうな感触がある部分を紹介させていただきました。
Cloud Runとか使いたいけど、結局、どの程度自動化+サーバレスで、やれるかわからないという点で、そこで保留にしている人も多いかと思います。そういう方には、多少の参考にしていただければ幸いです。
また、自動化やサーバレスのニーズが高いご時世ですのでCloud Runを知らない方も、是非、試して頂ければと思います。
また、いつか次の機会があれば、なにか紹介させて頂ければと思います。
それでは、また次回まで。
もうエンジニアとしてもおじいちゃんの域になってきました。
目もしょぼしょぼ、よく最近なにも見えなくなってきました。
でもまだまだ好奇心はいっぱいで、ちょっとつらくなってきましたが
日々精進している毎日です。