Professional Cloud Developer認定試験対策として、Google Cloud上で高品質なアプリケーションを開発・運用するための重要な技術を理解しておくことは欠かせません。
本記事では、TerraformによるInfrastructure as Code(IaC)の実践的な運用方法、Binary Authorizationを活用したセキュアなCI/CDパイプラインの構築、そしてFirestoreを利用したリアルタイムかつオフライン対応アプリケーションの開発手法を解説します。
これらは単なるサービスの知識にとどまらず、クラウドネイティブなアプリケーション設計や運用自動化、セキュリティ強化を実現するための重要なベストプラクティスです。試験対策としてはもちろん、実際の開発現場でも役立つ内容として学んでいきましょう。
今回も音声ファイルも挿入していますので、ブログの内容を音声でご確認いただけます。通勤中などにご利用いただければと思います。
是非、最後までご覧いただけると嬉しいです。
Google Cloud で始める失敗しない Terraform 運用
Terraformは、Google Cloud環境をコードで管理し、再現性の高いインフラ運用を実現するための代表的なIaC(Infrastructure as Code)ツールです。しかし、単にTerraformを導入するだけでは、安全で効率的な運用は実現できません。
本記事では、Google Cloudが推奨するTerraformのディレクトリ構成や命名規則、Stateファイル管理のベストプラクティスを解説します。さらに、Cloud Storageを利用したリモートバックエンド構成や、CI/CDを活用した運用自動化の考え方についても紹介します。
Terraformをこれから導入する方はもちろん、既存環境の運用を改善したい方にも役立つ内容です。Professional Cloud Developer試験対策としても押さえておきたいIaC運用の基本を学んでいきましょう。
1. なぜTerraform(IaC)なのか?
Google CloudはTerraformをインフラ管理の戦略的ツールとして位置づけており、ほぼすべての新機能がリリースと同時にTerraformプロバイダに対応します。IaCを導入することで、以下のメリットが手に入ります。
- 自動化とスピード:コマンド一つで、ネットワーク、仮想マシン、データベースを数分で一括生成。
- 一貫性と安全性の担保:「開発環境と本番環境で、ファイアウォールの設定が1箇所だけ違っていた」というような、手動運用でありがちな事故を根絶します。
- GitOpsによる可視化:インフラの変更履歴がすべてGitのコミットログとして残るため、いつでも過去の状態にロールバックが可能です。
2. 確実性を高める「スタイルと構造」の鉄則
読みやすく、壊れにくいコードを書くことが、確実なプロビジョニングの第一歩です。Google Cloudのスタイルガイドでは、以下の構造が推奨されています。
標準的なディレクトリ構成
Google Cloud公式ドキュメントでは、サービスのTerraform構成を modules/ ディレクトリ(実際のリソース定義)と environments/ ディレクトリ(環境ごとのルート設定)の2つに分離することが推奨されています。
SERVICE-DIRECTORY/
├── modules/
│ └── <service-name>/
│ ├── main.tf
│ ├── variables.tf
│ ├── outputs.tf
│ ├── provider.tf
│ └── README.md
└── environments/
├── dev/
│ ├── backend.tf ← 環境ごとのバックエンド設定
│ └── main.tf
├── stg/
│ ├── backend.tf
│ └── main.tf
└── prod/
├── backend.tf
└── main.tf
標準的なファイル構成(モジュール内)
Terraformモジュールは標準的なモジュール構造に従う必要があり、main.tf ファイルから始めます。各ファイルの役割は以下の通りです。
main.tf:リソース(VPC、Compute Engineなど)の定義を記述する主ファイル。variables.tf:入力変数の定義(リージョン名やマシンタイプなど)。outputs.tf:他のモジュールやユーザーに渡したい出力値(インスタンスの外部IPなど)。provider.tf:Google Cloudプロバイダのプロジェクト・リージョンなどの基本設定。(※単数形provider.tfが公式の表記)versions.tf:Terraform本体およびプロバイダの最小バージョン制限(required_version・required_providers)。backend.tf:各環境ディレクトリにはbackend.tfファイルが必要で、Terraformのバックエンドとなるリモートステートの設定を宣言します。
⚠️provider.tfとversions.tfの使い分け
バージョン制約(required_providers)はversions.tfに記述し、provider.tfにはプロジェクトIDやリージョンなどのプロバイダ設定のみを記述します。混在させないよう注意してください。
命名規則のクリーン化
リソースの論理名(Terraform内部での識別名)は、オブジェクトの種類を重複させず、シンプルに保ちます。
<Terraform>
# ❌ 悪い例:resource typeに "network" が含まれているのにラベルにも "vpc_network" と重複
resource "google_compute_network" "vpc_network" {}
# ✅ 良い例:シンプルで文脈から明確
resource "google_compute_network" "main" {}
3. インフラ管理(Resource Management)の生命線
Terraformを本番運用する上で、最も慎重に扱うべきが「State(状態ファイル)」です。Terraformは、コードと実際のクラウド資源の紐付けを terraform.tfstate というファイルで管理しています。
確実なプロビジョニングを行うために、以下の2点を必ず実施してください。
① リモートバックエンド(Cloud Storage)の利用
StateファイルをローカルPCに置いたままにしてはいけません。チーム開発で競合が発生したり、PCの故障でデータが紛失したりします。Google CloudユーザーにはCloud StorageのStateバックエンドの使用を推奨します。このアプローチはStateをロックしてチームでの共同作業を安全に行えるようにし、Stateとその潜在的な機密情報をバージョン管理から分離します。
<Terraform>
# backend.tf
terraform {
backend "gcs" {
bucket = "your-terraform-state-bucket"
prefix = "terraform/state"
}
}
② ステートロックの有効化
GCSをバックエンドにすると、Terraformは自動的に「ステートロック」をサポートします。これは、開発者Aが terraform apply を実行している最中に、開発者Bが同時に変更を加えてStateが破壊されるのを防ぐ強力な防御壁です。
4. IaC成熟度モデルでチームを育てる
Terraformの導入は一朝一夕には完成しません。段階的に運用のレベルを引き上げていきましょう。
| レベル | 状態 | 次のステップへのアクション |
|---|---|---|
| レベル1 手動・アドホック | コンソールでの手動構築がメイン。一部のみスクリプト化。 | すべての新規リソースをTerraformで書くルールを作る。 |
| レベル2 静的・コード化 | インフラがコード化され、Gitで管理されている。実行はローカル環境。 | Cloud Storage バックエンドを導入し、チーム間でStateを共有する。 |
| レベル3 自動化(CI/CD) | プルリクエストをトリガーに、Cloud Build等で自動検証・デプロイが走る。 | ポリシー・アズ・コード(危険な設定を自動拒否する仕組み)の導入。 |
| レベル4 ガバナンスの確立 | 組織全体で再利用可能な「カスタムモジュール」が共通化されている。 | 継続的なドリフト検出(コードと実環境のズレの自動検知)。 |
本番環境で「確実性」を担保するには、一刻も早くレベル3(CI/CDによるプロビジョニング)に到達することが望まれます。人間のタイポや実行環境の差異を排除するため、最終的な apply は常に信頼されたCI/CDパイプラインに委ねるべきです。
Google Cloud で始める失敗しない Terraform 運用のまとめ
Terraformを活用することで、Google Cloudのインフラをコードとして管理し、高い再現性と運用品質を実現できます。
特に、modulesとenvironmentsを分離した構成や、provider.tf・versions.tf・backend.tfの適切な役割分担は、保守性の高いコードベースを作る上で重要です。また、StateファイルはCloud Storageで一元管理し、ロック機能を活用することで安全なチーム開発を実現できます。
さらに、Terraformの実行をCI/CDパイプラインへ移行することで、ヒューマンエラーを減らし、安定したインフラ運用が可能になります。
これらのベストプラクティスを取り入れることで、スケーラブルかつ信頼性の高いGoogle Cloud環境を効率的に構築・運用できるようになるでしょう。
ゼロトラスト時代のセキュアCI/CDパイプライン構築ガイド
ゼロトラスト時代のCI/CDパイプラインでは、「誰でもデプロイできる仕組み」ではなく、「検証済みの成果物だけがデプロイできる仕組み」が求められます。
Google Cloudでは、Cloud Build・Cloud Deploy・Binary Authorizationを組み合わせることで、ソフトウェアサプライチェーン全体の信頼性を高めることができます。特にBinary Authorizationは、コンテナイメージに付与された証跡(Attestation)を検証し、承認済みのイメージのみを本番環境へ展開できる強力な仕組みです。
また、Cloud KMSによる署名鍵管理やSecret Managerによる機密情報管理を組み合わせることで、認証情報の安全性も向上します。
本記事では、ゼロトラストの考え方に基づくセキュアなCI/CDパイプラインの構築方法と運用のポイントを解説します。
1. 信頼の強制作用:Binary Authorizationのコア概念
Binary Authorizationは、コンテナのデプロイ時に「ゲートキーパー」として機能するセキュリティサービスです。GKEやCloud Runとシームレスに統合され、以下の3つの概念で動きます。
- ポリシー (Policy):デプロイを許可するためのルールです。「特定の認証者によるデジタル署名(証跡)が存在するイメージのみデプロイを許可する」といった制約を定義します。
- 認証者 (Attestor):イメージの安全性を検証し、保証する権限を持ったエンティティです。今回のパイプラインでは、「セキュリティスキャンやテストをパスしたCloud Build」が認証者として振る舞います。
- 証跡 (Attestation):認証者がコンテナイメージの暗号ハッシュ(ダイジェスト)に対して行う、暗号学的なデジタル署名です。この署名が存在することが、安全性の証明になります。
2. 署名鍵の管理:Cloud KMSとSecret Managerの使い分け
セキュアなパイプラインを構築する上で、「認証情報や暗号鍵の適切な管理」が重要です。Binary AuthorizationとSecret Managerの役割を正しく理解しましょう。
Cloud KMS(署名鍵の管理)
Binary Authorizationの証跡署名には、Cloud KMSで生成・管理される非対称鍵ペア(PKIX形式)を使用します。秘密鍵で証跡に署名し、対応する公開鍵を認証者に登録します。Cloud KMSまたはローカル鍵を使用できますが、本番環境ではCloud KMSキーの使用が推奨されます。
<gcloudコマンド>
# Cloud KMSで署名用非対称鍵を作成
gcloud kms keyrings create [KEYRING_NAME] --location=global
gcloud kms keys create [KEY_NAME] \
--keyring=[KEYRING_NAME] \
--location=global \
--purpose=asymmetric-signing \
--default-algorithm=ec-sign-p256-sha256
Secret Manager(その他の機密情報の管理)
Secret Managerは、署名鍵ではなく、第三者スキャンツールのAPIトークン・外部サービスの認証情報など、その他の機密情報の安全な一元管理に使用します。
- 集中管理と監査:誰がいつ秘密情報にアクセスしたかのログ(Cloud Audit Logs)が残るため、厳格なコンプライアンス要件を満たせます。
- 最小権限の適用:Cloud Buildのサービスアカウントに対して、
roles/secretmanager.secretAccessorのみをIAMで付与します。
3. セキュア・デプロイパイプラインの全体像
[Cloud Build] ──> [Artifact Registry] ──> [Cloud Deploy] ──> [GKE / Cloud Run]
│ │ │ ▲
├─> 脆弱性スキャン │ │ │
└─> 証跡の署名 ────────┴──> (証跡を保存) └─> デプロイ要求 ───┤
(Cloud KMSの鍵を使用) │
[Binary Authorization]
(署名がなければブロック)
ステップ1:Cloud Buildに必要なIAMロールの付与
Cloud BuildサービスアカウントがBinary Authorization証跡を作成するには、以下の3つのIAMロールが必要です。
<gcloudコマンド>
PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format='value(projectNumber)')
# 認証者の参照権限
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/binaryauthorization.attestorsViewer"
# Cloud KMSでの署名権限
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/cloudkms.signerVerifier"
# Container Analysisへの証跡記録権限
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/containeranalysis.notes.attacher"
ステップ2:Cloud Buildでのビルドとスキャン
ソースコードからコンテナイメージをビルドし、Artifact Registryへプッシュします。プッシュされたイメージに対して脆弱性スキャンを実行し、スキャン結果が合格基準を満たすか判定します。
ステップ3:Cloud KMSと連携した「証跡」の作成
スキャンに合格した場合のみ、Cloud BuildはCloud KMSの鍵を使用してイメージのSHA256ダイジェストに対するデジタル署名(証跡)を作成し、Container Analysisに記録します。
<gcloudコマンド>
gcloud container binauthz attestations sign-and-create \
--artifact-url="${IMAGE_PATH}@${IMAGE_DIGEST}" \
--attestor="${ATTESTOR_NAME}" \
--attestor-project="${PROJECT_ID}" \
--keyversion-project="${KMS_KEY_PROJECT_ID}" \
--keyversion-location="${KMS_KEY_LOCATION}" \
--keyversion-keyring="${KMS_KEYRING_NAME}" \
--keyversion-key="${KMS_KEY_NAME}" \
--keyversion="${KMS_KEY_VERSION}"
ステップ4:Cloud Deployによるリリースと自動検証
Cloud Deployはデプロイを試みる際、Binary Authorizationが署名の有無を検証します。署名が正しければデプロイが完了し、署名がなければ即座に拒否されます。
4. 運用のベストプラクティス
- ドライラン(監査モード)からの開始:まずBinary Authorizationのポリシーを「監査モード(AUDIT_LOG_ONLY)」に設定し、ログを確認しながらパイプラインの動作検証を行うのが鉄則です。
- 例外規定(ブレイクグラス)の準備:緊急のパッチ当てなど、通常のCI/CDプロセスを経由せずに即時デプロイが必要なケースに備え、特定の権限を持つユーザーだけが使える「ブレイクグラス(緊急バイパス)」の設定をあらかじめ仕込んでおきましょう。実行時にはアラートが飛ぶように構成します。
ゼロトラスト時代のセキュアCI/CDパイプライン構築ガイドのまとめ
Binary Authorizationを導入することで、正規のビルド・テスト・スキャン工程を通過したコンテナイメージのみをデプロイできる仕組みを実現できます。
Cloud BuildとCloud KMSを連携させれば、脆弱性スキャンに合格したイメージへ自動的に証跡を付与し、デプロイの信頼性を高めることが可能です。また、Secret Managerを利用することで、APIトークンや外部サービスの認証情報を安全に管理できます。運用開始時は監査モードで動作確認を行い、緊急時に備えたブレイクグラス運用も準備しておくことが重要です。
これらの仕組みを組み合わせることで、人手による確認に依存しない、ゼロトラスト時代に適した堅牢なCI/CD基盤を構築できるようになります。
Firestoreで作るオフライン対応リアルタイムToDoアプリ
モバイルアプリでは、ネットワークの状態に左右されず快適に利用できることが重要です。特にToDoアプリのような日常的に利用されるサービスでは、オフライン環境でも操作でき、複数デバイス間でリアルタイムに同期される仕組みが求められます。
Firestoreは、リアルタイムデータ同期、オフラインアクセス、自動スケーリングといった機能を標準で備えており、サーバーを構築することなく高品質なアプリケーションを開発できます。
本記事では、FirestoreのSDKを活用してオフライン対応のリアルタイムToDoアプリを実装する方法を解説します。
データ構造の設計やクエリの作成方法、運用時に意識したいベストプラクティスについても紹介していきます。
1. 要件をすべてクリアするFirestoreの3大機能
① 異なるデバイス間での自動データ保存・同期
Firestoreはクラウドネイティブなデータベースであり、ユーザーがスマホAでタスクを追加すると、そのデータは即座にクラウドへ保存されます。同じアカウントでタブレットBからログインすれば、特別な同期ロジックを組まなくても、常に最新のデータが手元に降ってきます。開発者が同期サーバーのインフラを保守する必要はありません。
② 標準装備の「オフラインアクセス」サポート
一般的なデータベースでは、電波が切れると接続タイムアウトやネットワーク到達不能エラーが発生し、アプリが動かなくなります。しかし、FirestoreのSDKはローカルキャッシュ(オフライン永続化)をサポートしています。
- オフライン時:ユーザーが地下鉄などでタスクを「完了」にすると、SDKはローカルのキャッシュを即座に書き換え、アプリのUIをサクサク動かします。
- オンライン復帰時:端末が再びネットに繋がった瞬間、SDKが自動でクラウド側のデータベースと同期を行い、データの整合性を保ちます。
⚠️ プラットフォームによるデフォルト設定の違い
オフライン永続化はAndroidおよびApple(iOS)プラットフォームのSDKではデフォルトで有効です。一方、Web SDKではオフライン永続化はデフォルトで無効であり、明示的に有効化する必要があります。
<javascript>
// Web SDKでオフライン永続化を有効にする場合
import { initializeFirestore, persistentLocalCache } from "firebase/firestore";
const db = initializeFirestore(app, {
localCache: persistentLocalCache()
});
③ ユーザーを虜にする「リアルタイム更新(リスナー)」
通常のAPIのように、画面を開いた時に1回だけデータを取得(get())する手法では、他端末での変更をリアルタイムに検知できません。Firestoreでは、データの一覧に「スナップショットリスナー(onSnapshot)」を付与できます。これにより、データベースにローカルまたはリモートの変更があった瞬間、アプリに通知が届き、ToDoリストの画面が自動的に更新されます。
2. ToDoリストのためのデータ構造とクエリ設計
データ構造の設計
ユーザーごとのタスクを管理するため、users コレクションの下に todos というサブコレクションを配置する構造がクリーンで、セキュリティルールも書きやすいため推奨されます。
users (コレクション)
└── user_XYZ (ドキュメント)
└── todos (サブコレクション)
└── todo_123 (ドキュメント)
タスクを賢く取得するクエリ操作(Web SDK)
<javascript>
// JavaScript / Firebase Web SDK(v9 モジュラー構文)
import { collection, query, where, orderBy, limit, onSnapshot } from "firebase/firestore";
// 1. クエリの組み立て(未完了のタスクを、作成日時の降順で、最大50件取得)
const q = query(
collection(db, "users/user_XYZ/todos"),
where("status", "==", "uncompleted"), // フィルタリング
orderBy("createdAt", "desc"), // 並べ替え
limit(50) // 取得件数の制限
);
// 2. リアルタイムリスナーの開始
const unsubscribe = onSnapshot(q, (querySnapshot) => {
const todos = [];
querySnapshot.forEach((doc) => {
todos.push({ id: doc.id, ...doc.data() });
});
updateTodoListView(todos);
});
💡 Android / iOS の場合
モバイルネイティブアプリでは言語・APIが異なります。Android(Kotlin)、iOS(Swift)それぞれの公式SDKを使用してください。基本的なクエリの概念(whereEqualTo、orderBy、limit)は同様です。
3. 開発・運用で失敗しないためのベストプラクティス
鉄則①:複合インデックスの自動生成を活用する
where と orderBy を異なるフィールドに組み合わせたクエリには複合インデックスが必要です。手動で管理する必要はありません。開発中にクエリを実行するとエラーメッセージ内に「インデックス作成用のURL」が自動生成されるので、そのURLをクリックするだけでGoogleCloud側でインデックスがデプロイされます。
鉄則②:ドキュメントの更新頻度に注意する
Firestoreは大量の同時読み取りには非常に強いですが、「1つのドキュメントに対する書き込みは1秒間に1回まで」という推奨制限があります。ToDoアプリであれば問題ありませんが、アプリのログや総タスク数カウンターなどを1つのドキュメントに持たせる設計は避けましょう。
Firestoreで作るオフライン対応リアルタイムToDoアプリのまとめ
モバイルToDoアプリの要件を満たすための正解アプローチは、「FirestoreのネイティブSDKを使い、バックエンドサーバFirestoreを活用することで、オフライン環境でも快適に利用できるリアルタイムToDoアプリを効率的に構築できます。
特に、onSnapshotによるリアルタイム更新や、SDKに組み込まれたオフラインキャッシュ機能によって、ユーザー体験を大幅に向上させることが可能です。また、ユーザーごとのサブコレクション設計や適切なクエリ設計を採用することで、安全かつ拡張性の高いデータ管理を実現できます。複合インデックスの活用やドキュメント更新頻度への配慮など、Firestore特有の設計ポイントを理解しておくことも重要です。
これらの機能を活用することで、バックエンド運用の負荷を抑えながら、リアルタイム性と可用性を兼ね備えたクラウドネイティブなアプリケーションを実現できるでしょう。
まとめ
今回は、下記3点について説明しました。
- Google Cloud で始める失敗しない Terraform 運用
- ゼロトラスト時代のセキュアCI/CDパイプライン構築ガイド
- Firestoreで作るオフライン対応リアルタイムToDoアプリ
Terraform、Binary Authorization、Firestoreは、それぞれ異なる領域を担いながらも、Google Cloudにおけるモダンなアプリケーション開発を支える重要な技術です。
TerraformによるIaCは再現性と運用品質を高め、CI/CDとの連携によって安定したインフラ管理を実現します。Binary Authorizationはソフトウェアサプライチェーンの信頼性を向上させ、ゼロトラスト時代に求められる強固なセキュリティ基盤を提供します。また、Firestoreはリアルタイム同期やオフライン機能によって優れたユーザー体験を実現します。
これらのサービスの役割と設計思想を理解することで、Professional Cloud Developer試験で問われるアプリケーション開発・運用・セキュリティに関する知識を体系的に身に付けることができるでしょう。
これからも、Macのシステムエンジニアとして、日々、習得した知識や経験を発信していきますので、是非、ブックマーク登録してくれると嬉しいです!
それでは、次回のブログで!
