Google Cloudで実践! クラウドネイティブな開発

Google Cloudの概要とモダンなアプリケーション開発

本連載では、Google Cloudのアプリ開発とDBプロダクトにおけるスペシャリスト達が、Google Cloudプロダクトを利用した、クラウドネイティブな開発を実践する方法を解説していきます。

第1回では、Google Cloudで実践するモダンなアプリケーション開発に焦点を当てます。Google Cloudのサービスや利点について紹介し、マイクロサービスアーキテクチャやTwelve-Factor Appの重要性を探求し、Google Cloudがモダンなアプリケーション開発にどのように役立つかを理解できます。

主に対象となる読者は、クラウドを利用してアプリケーションを開発するエンジニア、またはその基盤を構築するエンジニア、サービス開発に携わるプロダクトマネージャーを想定しています。

なぜモダンなアプリケーション開発が必要なのか

DevOpsという手法がありますが、これは開発と運用が協調することで、スピーディな開発サイクルを実現する方法です。Googleが2018年に買収した、DevOps Research and Assessment(DORA)チームでは、ソフトウェアデリバリーと組織のパフォーマンスを改善するための能力を調査、検証しており、以下3つの能力をDevOpsの能力と定めています。

技術に関する能力
クラウドアーキテクチャ、バージョン管理、継続的インテグレーション、継続的デリバリー、トランクベース開発、テスト自動化、疎結合アーキテクチャ、コードの保守性、セキュリティ、DBの変更管理
プロセスに関する能力
小さいバッチ単位の作業、変更承認の効率化、モニタリング、Work in Progressの制限、作業の可視化、機能別アウトソーシングの抑制
文化に関する能力
Westrum型の組織、学習文化、自律的であること、振り返りの重視

「State of DevOps」2022年のレポートによると、これらを基にした4つのパフォーマンス指標の結果が出ています。

図:State of DevOps 2022

この結果から言えることは、高パフォーマンスに分類されたチームは速度と安定性も高く、低パフォーマンスに分類されたチームは速度も安定性も低いということです。

開発速度が高いといっても、整備された環境がないと高頻度のデプロイサイクルは実現できません。組織の大小に関わらず、低い運用コストで実現可能な、マネージドな環境を利用して効率良く実現しましょう。

安定した運用を継続的に実現する方法としては、GoogleのSREの考え方があります。サービス指標を定量化することで、安定した運用を可視化できます。

つまり、モダンなアプリケーション開発は、ビジネスをマーケットに展開する速度を上げると同時に、安定したサービス運用を実現することが目的です。ゆえに、フルマネージドなプロダクトを利用した、クラウドネイティブな開発をすることが実現の近道であると言えます。

Google Cloudでアプリケーションを動かす

一般的に、アプリケーション開発では、IDE、DB、CI/CD、実行基盤、監視やロギングツールなど、必要なものが多々あります。Google Cloudでは、アプリケーションの実装から運用までの一連の流れをフルマネージドで構築できます。

本連載ではアプリケーションの実行基盤やDB、また、それらを組み合わせたアーキテクチャなどを詳細に解説していく予定ですが、今回はプロダクトの概要を紹介します。

Google Cloudのアプリケーションを動かす基盤

アプリケーションを実行するComputeプロダクトは、以下の5つがあります。左(Compute Engine)から右(Cloud Functions)にかけて、柔軟性が下がる一方、抽象度が高くなり、管理コストが低くなります。

図:Computeプロダクト一覧
Compute Engine (GCE)
IaaS(Infrastructure-as-a-Service)のプロダクトで、Googleのインフラストラクチャでホストされる柔軟なセルフマネージドの仮想マシン(VM)を提供します。
アプリケーションを実行する場合、ソースコードを配置することも可能ですし、Container-Optimized OSイメージを使用して、VMにコンテナをデプロイすることもできます。
他のプロダクトと比べると管理する範囲が広くなりますが、柔軟なカスタマイズが可能な環境を作成できます。
Google Kubernetes Engine (GKE)
KaaS(Kubernetes as a Service)のプロダクトで、フルマネージドなKubernetes基盤を構築できます。
コンテナ化されたアプリをKubernetes APIでオーケストレーションし、Kubernetesのエコシステムを最大限に利用することで、多くの機能やセキュリティなどを組み込むことができます。
Kubernetesを管理するチームが存在し、中規模から大規模なシステムでコンテナを稼働させる場合によく利用されますが、GKE Autopilotを利用した運用モードによって、小規模なシステムでも少ない運用負荷で利用可能となっています。
Cloud Run
CaaS(Container as a Service)のプロダクトで、サーバーレス環境でコンテナを実行することが可能なプロダクトです。
サーバーレスは従量課金の課金モデルがあり、リソースを作成しても、外部リクエストやアプリの実行が行われない限り、コストが掛からない特徴があります。また、無料枠も存在します。
Cloud Runには、WebアプリやAPIなどの構築に最適な「サービス」と、バッチ処理などのバックグラウンド処理に最適な「ジョブ」の2つが存在します。どちらも高速にスケールする基盤として稼働するため、大規模なシステムはもちろん、ビジネスを小さく始めて、徐々にスケールさせる用途としても最適です。
App Engine (GAE)
PaaS(Platform as a Service)のプロダクトで、App Engineが提供するSDKを利用してアプリケーションを実装し、ソースコードをデプロイするだけでWebアプリなどが容易にデプロイ可能です。
実行環境はスタンダード環境とフレキシブル環境があります。フレキシブル環境ではコンテナを稼働させることができますが、GCEを基盤として稼働するため、スタンダード環境のほうがスケール性能が高い特性があります。App Engineのスケール性能をフルに活用したい場合は、スタンダード環境を利用するのが良いでしょう。
利用するプログラミング言語やバージョンによってランタイムが違ったり、サポートバージョンのライフサイクルが定義されている点に注意が必要です。
Cloud Functions
FaaS(Functions as a Service)のプロダクトで、呼び出される関数を実装するだけで、アプリケーションを動かすことが可能です。他のプロダクトと比較して抽象度が一番高く、管理コストは非常に少なく運用できます。
イベント駆動で処理を実行、プロダクト間を繋げるための処理の実行、Firebase SDKを利用した関数の呼び出しなど、細かな粒度の関数を多くのユースケースで呼び出すのに適しています。
Cloud Functionsは実行環境の世代が選択でき、第2世代はCloud Runを基盤として関数が実行されます。Cloud Runの性能とCloud Functionsの管理の容易さ、といった良いところを組み合わせた環境を利用できます。

Google CloudのマネージドDB

多くのアプリケーションはDBと一緒に展開することが多いですが、Google Cloudが提供するマネージドDBの選択肢は、OSS互換のDBや、特色のあるクラウドネイティブDBなど豊富にあります。

図:マネージドDBの選択肢

アプリケーション開発、ということを前提とした場合に、よく利用されるDBは以下の4つです(キャッシュ用途は除いています⁠⁠。

Cloud SQL (Enterprise / Enterprise Plus)
フルマネージド型のリレーショナルDBサービスです。
MySQLやPostgreSQL、SQL ServerなどのDBエンジンをサポートしており、スケーラビリティ、パフォーマンス、バックアップなどの管理がGoogleによって自動化されています。
AlloyDB
Google Cloudが提供するPostgreSQL互換DBサービスです。
Googleの内部DB技術を使用して構築されており、より優れたパフォーマンス、スケーリング、可用性を提供しており、高速なリアルタイム分析情報も可能です。
Cloud Spanner
グローバルスケールで分散データを管理するためのフルマネージド型のDBサービスです。
リレーショナルとNoSQLの特長を結合し、トランザクション処理と水平スケーリングを可能にします。
複数の地理的リージョンにわたるデータの一貫性と可用性を保ちながら、高いパフォーマンスを実現するため、グローバルなアプリケーションの要件を満たすのにも適しています。
Firestore
Google CloudのNoSQL DBサービスです。
柔軟でスケーラブルなデータベースであり、リアルタイムのデータ同期とオフライン対応機能を提供します。
Webやモバイルアプリなど、クラウドネイティブなアプリケーションを構築する際に、リアルタイムでのデータの収集や共有が必要な場合に適しています。
互換性、耐久性、可用性、レイテンシ、スケール性、運用コストなどの観点はもちろん、Firestoreが提供するClientとのリアルタイム同期の機能などで採用することもあります。

アプリケーション開発からデプロイまで

Google Cloudは、アプリケーションを開発する環境(IDE)やIDEプラグイン、コンテナやパッケージの保管、セキュリティやCI/CDなど、一連のソフトウェアサプライチェーンを実現する機能をマネージドで提供しています。

図:Google Cloudが提供する、ソフトウェアサプライチェーン

以下、各プロダクトやプラグインについて説明します。

  1. Cloud Workstations
    Google Cloud上で仮想デスクトップ環境(主にリモート開発を目的とした環境)を提供するサービスです。
    Visual Studio CodeやJetBrains IDEを利用している開発者が、ローカルにおける開発体験をそのままに、より柔軟なスペックのマシンでセキュアに開発を行うことを可能にします。

  2. Cloud Code
    Google Cloudでアプリケーションを開発するためのIDE拡張機能で、無料で利用可能です。
    主に、GKEやCloud RunなどのGoogle Cloudのサービスと連携して、アプリケーションの開発、デプロイ、デバッグ、テストなどの作業を支援します。

  3. Assured OSS
    Google Cloudが提供する、OSSをより信頼性の高いバージョンで提供するサービスです。
    セキュリティの向上やエンタープライズレベルのサポートを含む、信頼性と安定性を重視する組織に向けて提供されています。

  4. Cloud Build
    Google Cloud上で継続的インテグレーションとデリバリー(CI/CD)を行うためのサービスです。
    コードのビルド、テスト、デプロイなどを自動化し、アプリケーションの開発サイクルを迅速化します。

  5. Artifact Registry
    コンテナイメージやパッケージなどのアーティファクトのプライベートリポジトリを提供するサービスです。セキュアで信頼性の高い方法でアーティファクトを保存、管理、共有できます。
    保存したアーティファクトに脆弱性があるかどうかをスキャンするArtifact Analysisという機能もあります。これは、アーティファクトが保存されると同時に実行、またはオンデマンドでの実行が可能です。

  6. Cloud Deploy
    GKE、Cloud Run、Anthos clusterへの継続的を簡単かつ強力なものにするサービスです。リリースを定義し、テスト環境、ステージ環境、本番環境を経てリリースを進めることができます。
    デプロイの成功と失敗の数が表示され、DORAで定義された4つの主な指標の1つであるデプロイ頻度の指標を計測できるのも、特徴の1つです。

  7. Binary Authorization
    GKEやCloud Runのコンテナイメージのセキュリティを強化するためのサービスです。
    デプロイ前にコンテナイメージの署名とポリシーチェックを行い、信頼できるイメージのみをデプロイできます。これにより、悪意のあるコードや脆弱性のあるイメージの使用を防ぎます。

開発からデプロイまでの一連のフローを整備することで、テストや脆弱性チェックなどがCIによって自動化され、人によって実施する工数をシステムに移譲可能です。

実装したコードが正しく動くかどうかの保証にもなり、安心して開発にフォーカスできるとともに、一連のフローを通したことが保証されることにより、信頼性のあるデプロイが実施可能となります。結果的に、これらは高速な開発と安定した運用に繋がります。

一度フローを整備すると、大きな変更は頻繁にあるわけではないため、開発タスクの序盤でこれらを構築しておくことをおすすめします。序盤に構築することで、早い段階でエラーや脆弱性を検知でき、開発の手戻りも少なくなります。

クラウドネイティブなアプリケーション開発手法について

クラウドネイティブな開発をすることがモダンなアプリケーション開発の実現の近道であると冒頭で述べましたが、この節ではクラウドネイティブな開発の手法について説明します。

アプリの開発手法

CNCFによるクラウドネイティブ技術の定義は、コンテナやサービスメッシュ、マイクロサービスなどによって、スケーラブルなアプリケーションを構築および実行するための能力を組織にもたらすもので、これらの手法により、回復性、管理力、および可観測性のある疎結合システムが実現する、とあります。

これは、GKEを利用してKubernetesのエコシステムを最大限に活用する、または、Cloud Runのようなサーバーレス環境でマネージドな機能に寄せることでも実現可能です。ただし、基盤を整えるだけで完成というわけではなく、その基盤の上で取り組む手法に対して、解決すべき目的を持つことは必要です。

有名な開発手法として、Twelve-Factors Appがあります。これらの特性はプログラミング言語やソフトウェアスタックに依存しないため、さまざまなアプリに適用できます。仮にマイクロサービス化するなどの手法を取り入れる場合、この概念をまず理解した上で設計したほうが良いでしょう。

  1. コードベース
    バージョン管理システム(Git)を使うことで、アプリのコード変更を追跡し、チームとして作業しやすくなり、CI/CDが可能になります。リポジトリ内のコードを基にして不変なリリースが作成され、固有の構成と組み合わされてデプロイが行われます。
    複数のデベロッパーが開発する場合、トランクベース開発を参考に開発を行うと、開発サイクルの速度向上に繋がります。

  2. 依存関係
    依存関係の明示的な宣言(npmやpipなど)と、コンテナ化による依存関係の分離が重要です。アプリとその依存関係を環境から分離し、開発環境、ステージング環境の違いにかかわらず一律に、アプリを動作させることができます。

  3. 設定
    モダンなアプリには、環境ごとに異なる構成が必要であり、これらの構成を環境変数などを利用してコードから外部化し、バージョン管理に含めないようにすることが重要です。これにより、同じバージョンのコードを複数の環境にデプロイできます。

  4. バックエンドサービス
    アプリが通常のオペレーションとして使用するファイルシステム、DB、キャッシュ、メッセージキューなどのサービスは、アタッチされたリソースとして扱います。これにより、リソースの抽象化が可能で、アプリコードの変更なしに異なるストレージに移行できます。

  5. ビルド、リリース、実行
    ソフトウェアのデプロイプロセスは、ビルド、リリース、実行の3つの段階に分けられ、各ステージで一意に識別できるアーティファクトが生成されます。
    ビルドではテストに合格したコードが自動的にトリガーされ、アーティファクトが生成されます。
    その後、リリースステージでアーティファクトと特定の環境の構成が組み合わされてリリースが生成され、自動的に環境にデプロイされるか、あるいはトリガーされます。
    これにより、本番環境デプロイメントの履歴を簡単にロールバックしたり監査証跡することが可能になります。

  6. プロセス
    アプリは環境内で複数のステートレスなプロセスとして実行される必要があり、データを共有せずに動作します。
    永続化する必要のあるすべてのデータはバックエンドサービス(DB)に、セッション状態のデータは有効期限を持つデータストア(MemcachedやRedis)に格納する必要があります。

  7. ポートバインディング
    外部のアプリコンテナに依存せず、Webサーバーライブラリをバンドルすることで、ポート番号を公開し、環境変数を使用してポートバインディングを行います。これにより、GKEやCloud Runなどにアプリを柔軟にデプロイできます。

  8. 並行性
    バックグラウンドプロセス、ウェブプロセス、ワーカープロセスなどのプロセスタイプに基づいて、アプリを独立したプロセスに分割する必要があります。
    これにより、個々のワークロード要件に基づいてアプリをスケールアップ、またはスケールダウンできます。
    複数の分散プロセスとしてアプリを設計し、独立して作業ブロックを実行し、プロセスを追加することでスケールアウトできるようにします。

  9. 廃棄容易性
    クラウドインフラで実行されるアプリの場合は、そのアプリと基盤となるインフラを廃棄可能なリソースとして扱う必要があります。
    アプリは、基盤となるインフラの一時的な消失に対して対処が可能であり、正常なシャットダウンおよび再起動が可能である必要があります(SIGTERMシグナルの利用など⁠⁠。

  10. 開発/本番一致
    アプリの開発ライフサイクルでは、開発、テスト、ステージング、本番環境など、さまざまな環境を行き来します。
    環境一致の重要性は広く認識されており、ソース管理や構成管理、テンプレート化された構成ファイルなどのツールによって維持することが容易になっています。

  11. ログ
    ログを使用することでアプリの状態を把握できますが、アプリのコアロジックとログの収集、処理、分析を切り離す(デカップリング)ことが重要です。
    ログを切り離すことで、ログの保存場所やエフェメラルな分散VMからの集計の管理オーバーヘッドが解消されます。
    例えば、GKEやCloud Runなどでは、Cloud Loggingにログをストリーミングする機能が統合されています。これは動的スケーリングが必要でパブリッククラウドで実行される場合に有用です。

  12. 管理プロセス
    管理者プロセス(レポートの生成、バッチスクリプトの実行、データベースのバックアップの開始、スキーマの移行など)は1回限りのタスクや時間指定の繰り返しタスクで構成されます。
    アプリが複数のタイムゾーンに分散している場合、メンテナンスと調整が必要になるため、管理者プロセス用に設計する場合は、これらのタスクの管理をアプリ自体から切り離す(デカップリング)必要があります。

マイクロサービス

マイクロサービスアーキテクチャは、アプリケーション開発におけるアーキテクチャスタイルの一つです。マイクロサービスによって、大きなアプリケーションをそれぞれが独自の責任範囲を持つ独立した小さなサービスに分割できます。

コンテナは、依存関係に気を取られることなくサービスの開発に集中できるため、マイクロサービスに非常に適しています。最新のクラウドネイティブアプリケーションは、通常、コンテナを使用してマイクロサービスとして構築されます。

気をつけておきたい点は、コンテナ化する、またはマイクロサービス化する、といったことを目的にしないことです。マイクロサービスは、データアクセスやメッセージングなどの水平レイヤではなく、ビジネス機能を中心に設計する必要があります。ビジネス(業務)を中心にデータをモデリングし、サービス境界を明確に分離し、サービス間の通信はAPIによる同期通信や、Pub/Subなどの非同期通信によって実現されます。

マイクロサービス化することが最適でない場合もあります。例えば、マイクロサービスが増えすぎて、1人の開発者が複数のサービスを兼務しているような場合です。このような場合、開発やデプロイが効率化されず、マイクロサービスのメリットである、開発アジリティの向上に繋がらないこともあります。

Google CloudのGitHubリポジトリに、マイクロサービスのサンプルがあります。このアーキテクチャをベースに、マイクロサービスの設計、構築、デプロイ、また、モノリスからの移行に関して解説しているリファレンスガイドもあるので、参考にしてみてください。

まとめ

繰り返しになりますが、モダンなアプリケーション開発は、ビジネスをマーケットに展開する速度を上げると同時に、安定したサービス運用を実現することが目的です。よって、フルマネージドなプロダクトを利用した、クラウドネイティブな開発をすることが実現の近道です。

Google CloudではDORAの研究結果から定義されたDevOpsの能力を最大化するためのプロダクトや、Googleの技術を支える大規模分散コンテナ基盤をプロダクトとして提供しており、開発速度の向上と安定した運用の実現を助けます。

本連載では、今後もクラウドネイティブなアプリケーション開発に必要な機能を解説していきます。是非ご覧いただき、実際にプロダクトを試してみてください。

おすすめ記事

記事・ニュース一覧