Published on

Google Cloud Compute Engine ハンズオン

はじめに

この記事は以下書籍の勉強メモです。

知ったことメモ

IAPのTCPフォワーディング

  • この機能は、パブリックIPアドレスを持たないVMインスタンスに対して、インターネット経由で安全にSSHやRDP接続を行うための機能。
  • 使い方
    • IAP用ファイアウォールルールの作成
      • TCP3389番ポート
      • ソースレンジ:35.235.240.0/20 (Google が所有するパブリックIPアドレスレンジ)
      • ターゲット:タグrdp-server
    • 接続ユーザーへの権限付与(roles/iap.tunnelResourceAccessor)
    • 接続コマンド実行
      • gcloud compute start-iap-tunnel windows-vm 3389 --local-host-port=localhost:13389 --zone=asia-northeast1-a
      • コマンドを実行したままRDPアプリでlocalhost:13389に接続するとVMにつながる
  • メリット
    • VMにパブリックIPが不要になりセキュリティが向上する
    • IAMの認証認可によりポリシーを細かく制御できる
    • 踏み台サーバーが不要になる
  • デメリット
    • 制限事項がある
      • この機能は、データの一括転送を対象としていない。悪用を防ぐためにレート制限を設定できる権限を有する。
      • この機能は、非アクティブ状態が1時間続くとセッションを自動的に切断する。前述のコマンドでは再確立を試みる。

やったこと

※書籍のGCEの章をGeminiに入力したうえで、記載内容がハンズオン形式で確認できる手順を出力させたものです。
このハンズオンでは、Google Cloud Compute Engine(Azure における同等のサービス名:Azure Virtual Machines)を使用して、Windows および Linux の仮想マシン(VM)を作成・管理する方法を学びます。Terraform を使用してリソースを作成し、各ステップでカスタマーエンジニア向けのポイントと解説を提供します。

まとめ

このハンズオンでは、Google Cloud Compute Engine を使用して、以下の内容を学習します:
  1. Windows および Linux VM の作成: Terraform を使用して VM を作成する方法
  2. スタートアップスクリプト: VM 起動時に自動的にソフトウェアをインストールする方法
  3. IAP を使用した安全な接続: 外部 IP なしで VM に接続する方法
  4. Managed Instance Group: 複数の VM を 1 つのグループとして管理する方法
  5. ロードバランサー: 複数の VM にトラフィックを分散する方法
  6. VM Manager: パッチ管理を行う方法

主要なポイント

  • 最小権限の原則: サービスアカウントには必要最小限の権限のみを付与
  • Infrastructure as Code: Terraform を使用してインフラをコード化
  • セキュリティ: IAP や OS Login を使用してセキュリティを強化
  • 高可用性: MIG とロードバランサーを使用して高可用性を実現
  • コスト最適化: 不要なリソースは速やかに削除

リソース構成図

このハンズオンで作成するリソースの構成を以下に示します。
構成図の説明:
  • IAM & セキュリティ: サービスアカウントとアクセス制御に関するリソース
  • ネットワーク: ファイアウォールルールによるトラフィック制御
  • 単一 VM インスタンス: 個別の VM インスタンス(Windows、Linux、OS Login 有効)
  • Managed Instance Group: 複数 VM の管理と自動スケーリング
  • ロードバランシング: トラフィック分散とヘルスチェック
  • バックアップ: スナップショットによるバックアップと復元
  • 外部接続: ユーザーからの接続経路(IAP、直接接続、ロードバランサー)

前提条件

  • Google Cloud アカウントとプロジェクトが作成済み(Project ID: cookbook-251226
  • Windows 端末(PowerShell)と Cursor エディタを使用
  • Terraform がインストールされていること
  • gcloud CLI がインストールされ、認証済みであること

ステップ 1: 作業環境の準備

1.1 作業ディレクトリの作成

md ファイルと同じフォルダ(Chapter5)に、Terraform 用とアプリ用のフォルダを作成します。
# Terraform用のディレクトリを作成
mkdir terraform
# アプリ用のディレクトリを作成(必要に応じて)
mkdir app
ポイント: 作業ディレクトリを明確に分けることで、プロジェクトごとの管理が容易になります。Terraform 用とアプリ用のフォルダを分けることで、コードの管理が簡素化されます。

1.2 必要な API の有効化

Terraform でリソースを作成する前に、必要な Google Cloud API を有効化する必要があります。
作業ディレクトリ: 任意(gcloud コマンドはどこからでも実行可能)
# Compute Engine APIを有効化(VMインスタンス作成に必要)
gcloud services enable compute.googleapis.com --project=cookbook-251226

# IAM APIを有効化(サービスアカウント作成に必要)
gcloud services enable iam.googleapis.com --project=cookbook-251226

# OS Config APIを有効化(OS Login、VM Managerに必要)
gcloud services enable osconfig.googleapis.com --project=cookbook-251226

# Container Registry APIを有効化(コンテナイメージ使用に必要)
gcloud services enable containerregistry.googleapis.com --project=cookbook-251226
ポイント: API の有効化は、Terraform でリソースを作成する前に必要です。各 API の用途をコメントで記述しています。
解説: Google Cloud では、各サービスを使用する前に API を有効化する必要があります。これにより、セキュリティとコスト管理が向上します。

ステップ 2: Terraform 設定ファイルの作成

2.1 メインの Terraform ファイル(main.tf)

terraform/main.tfファイルを作成します。このファイルには、すべてのリソース定義を含めます。
ファイル: terraform/main.tf
# Terraformのバージョンとプロバイダの設定
terraform {
  required_version = ">= 1.3.0"
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 6.0.0"  # 最新の安定版を指定
    }
  }
}

# Google Cloudプロバイダの設定
provider "google" {
  project = "cookbook-251226"
  region  = "asia-northeast1"  # デフォルトのリージョンを指定
}

# 変数の定義
variable "project_id" {
  description = "Google Cloud Project ID"
  type        = string
  default     = "cookbook-251226"
}

variable "region" {
  description = "Region for GCE resources"
  type        = string
  default     = "asia-northeast1"
}

variable "zone" {
  description = "Zone for GCE resources"
  type        = string
  default     = "asia-northeast1-a"
}
ポイント: Terraform のバージョンとプロバイダのバージョンを明示的に指定することで、再現性が向上します。
解説: required_providersブロックで、使用するプロバイダのバージョンを指定します。これにより、異なる環境間で一貫した動作が保証されます。

2.2 VPC ネットワークの作成

VM インスタンスを作成する前に、VPC ネットワークとサブネットを作成します。
ファイル: terraform/main.tf(上記のファイルに追加)
# VPCネットワークの作成
resource "google_compute_network" "vpc_network" {
  name                    = "vpc-network"
  auto_create_subnetworks = false
}

resource "google_compute_subnetwork" "vpc_subnet" {
  name          = "vpc-subnet"
  ip_cidr_range = "10.0.0.0/24"
  region        = var.region
  network       = google_compute_network.vpc_network.id
}
ポイント: auto_create_subnetworks = falseを設定することで、手動でサブネットを作成できます。これにより、ネットワーク構成をより細かく制御できます。
解説: VPC ネットワークは、VM インスタンスが接続するネットワークです。サブネットは、VPC ネットワーク内の IP アドレス範囲を定義します。

2.3 ファイアウォールルール(RDP 用)の作成

ファイル: terraform/main.tf(上記のファイルに追加)
# RDPトラフィックを許可するファイアウォールルール(Azureにおける同等のサービス名:Azure Network Security Groups)
resource "google_compute_firewall" "allow_rdp" {
  name    = "allow-rdp"
  network = google_compute_network.vpc_network.name

  allow {
    protocol = "tcp"
    ports    = ["3389"]  # RDPポート
  }

  source_ranges = ["0.0.0.0/0"]  # すべてのIPアドレスから許可(本番環境では制限推奨)
  target_tags  = ["rdp-server"]
}
ポイント: 本番環境では、source_rangesを特定の IP アドレスに制限することを推奨します。
解説: ファイアウォールルールは、ネットワークレベルでトラフィックを制御します。target_tagsを使用することで、特定の VM にのみルールを適用できます。

2.4 サービスアカウントの作成

最小権限の原則に従い、VM 用のサービスアカウントを作成します。
ファイル: terraform/main.tf(上記のファイルに追加)
# VM用のサービスアカウントの作成
resource "google_service_account" "vm_service_account" {
  account_id   = "vm-service-account"
  display_name = "Service Account for VM instances"
  description  = "Service account for Compute Engine instances"
}

# サービスアカウントに必要な権限を付与(最小権限の原則)
resource "google_project_iam_member" "vm_service_account_roles" {
  for_each = toset([
    "roles/compute.instanceAdmin.v1",  # インスタンス管理に必要
    "roles/iam.serviceAccountUser"     # サービスアカウントの使用に必要
  ])
  project = var.project_id
  role    = each.key
  member  = "serviceAccount:${google_service_account.vm_service_account.email}"
}
ポイント: 最小権限の原則に従い、必要最小限の権限のみを付与しています。
解説: サービスアカウントを使用することで、VM インスタンスが Google Cloud API を呼び出す際の認証が簡素化されます。また、最小権限の原則に従うことで、セキュリティリスクを低減できます。
ベストプラクティス: IAM のベストプラクティス

ステップ 3: Windows 仮想マシンの作成

3.1 Windows VM の定義

ファイル: terraform/main.tf(上記のファイルに追加)
# Windows仮想マシンの作成(Azureにおける同等のサービス名:Azure Virtual Machines)
resource "google_compute_instance" "windows_vm" {
  name         = "windows-vm"
  machine_type = "e2-medium"  # 必要に応じて変更可能
  zone         = var.zone

  boot_disk {
    initialize_params {
      image = "windows-cloud/windows-2022"  # Windows Server 2022イメージファミリー(常に最新版を使用)
      size  = 50  # ディスクサイズ(GB)
      type  = "pd-standard"  # ディスクタイプ
    }
  }

  network_interface {
    network    = google_compute_network.vpc_network.name
    subnetwork = google_compute_subnetwork.vpc_subnet.name
    access_config {
      # 外部IPを自動割り当て(RDP接続に必要)
    }
  }

  service_account {
    email  = google_service_account.vm_service_account.email
    scopes = ["https://www.googleapis.com/auth/cloud-platform"]
  }

  metadata = {
    enable-oslogin = "TRUE"  # OS Loginを有効化(後述のIAP接続で使用)
  }

  tags = ["windows-server", "rdp-server"]
}
ポイント:
  • イメージファミリー(windows-cloud/windows-2022)を使用することで、常に最新の Windows Server 2022 イメージが使用されます
  • enable-osloginを有効化することで、OS Login 機能が使用可能になります
  • 作成した VPC ネットワークとサブネットを使用することで、ネットワーク構成を制御できます
解説:
  • access_configを設定することで、外部 IP が自動的に割り当てられ、RDP 接続が可能になります
  • tagsを使用して、ファイアウォールルールと連携できます
  • VPC ネットワークとサブネットを使用することで、ネットワーク構成をより細かく制御できます
トレードオフ:
  • 外部 IP あり: メリット:直接接続可能、デメリット:セキュリティリスクが高い
  • 外部 IP なし + IAP: メリット:セキュリティが高い、デメリット:IAP の設定が必要

ステップ 4: Linux 仮想マシンの作成と NGINX のインストール

4.1 Linux VM の定義(スタートアップスクリプト付き)

ファイル: terraform/main.tf(上記のファイルに追加)
# Linux仮想マシンの作成(Azureにおける同等のサービス名:Azure Virtual Machines)
resource "google_compute_instance" "linux_vm" {
  name         = "linux-vm"
  machine_type = "e2-medium"
  zone         = var.zone

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-12-bookworm-v20240110"  # 最新のDebian 12イメージ
      size  = 30
      type  = "pd-standard"
    }
  }

  network_interface {
    network    = google_compute_network.vpc_network.name
    subnetwork = google_compute_subnetwork.vpc_subnet.name
    access_config {
      # 外部IPを自動割り当て(SSH接続に必要)
    }
  }

  service_account {
    email  = google_service_account.vm_service_account.email
    scopes = ["https://www.googleapis.com/auth/cloud-platform"]
  }

  metadata = {
    enable-oslogin = "TRUE"  # OS Loginを有効化
  }

  # スタートアップスクリプトでNGINXをインストール
  metadata_startup_script = <<-EOT
    #!/bin/bash
    apt-get update
    apt-get install -y nginx
    systemctl start nginx
    systemctl enable nginx
    # ホスト名を表示するようにカスタマイズ
    sed -i "s/nginx/Google Cloud Cookbook - $HOSTNAME/" /var/www/html/index.nginx-debian.html
  EOT

  tags = ["http-server", "linux-server"]
}
ポイント:
  • metadata_startup_scriptを使用することで、VM 起動時に自動的にソフトウェアをインストールできます
  • これにより、手動でのインストール作業が不要になり、再現性が向上します
解説: スタートアップスクリプトは、VM の初回起動時に実行されます。これにより、インフラストラクチャのコード化(Infrastructure as Code)が実現できます。

4.2 HTTP 用ファイアウォールルールの作成

ファイル: terraform/main.tf(上記のファイルに追加)
# HTTPトラフィックを許可するファイアウォールルール
resource "google_compute_firewall" "allow_http" {
  name    = "allow-http"
  network = google_compute_network.vpc_network.name

  allow {
    protocol = "tcp"
    ports    = ["80"]  # HTTPポート
  }

  source_ranges = ["0.0.0.0/0"]  # すべてのIPアドレスから許可
  target_tags   = ["http-server"]
}
ポイント: HTTP トラフィックを許可することで、ブラウザから NGINX にアクセスできます。

ステップ 5: Identity-Aware Proxy(IAP)を使用した Windows VM への安全な接続

5.1 IAP 用ファイアウォールルールの作成

ファイル: terraform/main.tf(上記のファイルに追加)
# IAP TCP Forwarding用のファイアウォールルール
# IAPを使用することで、外部IPなしでも安全にVMに接続可能
resource "google_compute_firewall" "allow_iap_rdp" {
  name    = "allow-iap-rdp"
  network = google_compute_network.vpc_network.name

  allow {
    protocol = "tcp"
    ports    = ["3389"]  # RDPポート
  }

  # IAPのTCP Forwardingで使用されるCIDR範囲
  # この範囲は、Google Cloud IAPが使用するIPアドレスを含みます
  source_ranges = ["35.235.240.0/20"]
  target_tags   = ["rdp-server"]
}
ポイント:
  • IAP を使用することで、外部 IP アドレスを公開せずに VM に接続できます
  • 35.235.240.0/20は、Google Cloud IAP が使用する CIDR 範囲です
解説: IAP(Identity-Aware Proxy)は、Google Cloud の認証・認可機能を活用して、安全に VM に接続するためのサービスです。これにより、VPN や外部 IP アドレスなしでも、Google アカウントの認証情報を使用して VM に接続できます。
トレードオフ:
  • IAP 使用: メリット:セキュリティが高い、外部 IP 不要、デメリット:IAP Desktop アプリのインストールが必要
  • 直接 RDP: メリット:標準的な RDP 接続、デメリット:外部 IP が必要、セキュリティリスクが高い
ベストプラクティス: IAP のベストプラクティス

5.2 IAP 権限の付与

ファイル: terraform/main.tf(上記のファイルに追加)
# IAP-Secured Tunnel Userロールを付与(IAP TCP Forwardingに必要)
# このロールは、ユーザーまたはグループに付与する必要があります
# 注意: 実際のユーザーやグループのメールアドレスに置き換えてください
resource "google_project_iam_member" "iap_tunnel_user" {
  project = var.project_id
  role    = "roles/iap.tunnelResourceAccessor"  # IAP TCP Forwardingに必要なロール
  member  = "user:your-email@example.com"  # 実際のユーザーメールアドレスに置き換え
}
ポイント: IAP を使用するには、ユーザーまたはグループに適切な IAM ロールを付与する必要があります。
解説: roles/iap.tunnelResourceAccessorロールは、IAP TCP Forwarding を使用して VM に接続するために必要です。

ステップ 6: Managed Instance Group(MIG)の作成

6.1 インスタンステンプレートの作成

ファイル: terraform/main.tf(上記のファイルに追加)
# インスタンステンプレートの作成(Azureにおける同等のサービス名:Azure Virtual Machine Scale Sets)
# テンプレートを使用することで、同一設定のVMを複数作成可能
resource "google_compute_instance_template" "nginx_template" {
  name         = "nginx-template"
  machine_type = "e2-medium"
  zone         = var.zone

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-12-bookworm-v20240110"
      size  = 30
      type  = "pd-standard"
    }
  }

  network_interface {
    network    = google_compute_network.vpc_network.name
    subnetwork = google_compute_subnetwork.vpc_subnet.name
    access_config {
      # 外部IPを自動割り当て
    }
  }

  service_account {
    email  = google_service_account.vm_service_account.email
    scopes = ["https://www.googleapis.com/auth/cloud-platform"]
  }

  metadata_startup_script = <<-EOT
    #!/bin/bash
    apt-get update
    apt-get install -y nginx
    systemctl start nginx
    systemctl enable nginx
    sed -i "s/nginx/Google Cloud Cookbook - $HOSTNAME/" /var/www/html/index.nginx-debian.html
  EOT

  tags = ["http-server"]
}

# Managed Instance Groupの作成(Azureにおける同等のサービス名:Azure Virtual Machine Scale Sets)
resource "google_compute_instance_group_manager" "nginx_group" {
  name               = "nginx-group"
  base_instance_name = "nginx"
  zone               = var.zone
  target_size        = 2  # 初期インスタンス数

  version {
    instance_template = google_compute_instance_template.nginx_template.id
  }

  # 自動修復を有効化
  auto_healing_policies {
    health_check      = google_compute_health_check.nginx_health_check.id
    initial_delay_sec = 300
  }
}
ポイント:
  • Managed Instance Group(MIG)を使用することで、複数の VM を 1 つのグループとして管理できます
  • 自動修復機能により、障害が発生した VM を自動的に再作成できます
解説: MIG は、同一設定の VM を複数作成し、ロードバランシングや自動スケーリングを実現するための機能です。
トレードオフ:
  • MIG: メリット:高可用性、自動スケーリング、自動修復、デメリット:設定が複雑
  • 単一 VM: メリット:シンプル、デメリット:可用性が低い

6.2 ヘルスチェックの作成

ファイル: terraform/main.tf(上記のファイルに追加)
# ヘルスチェックの作成(MIGの自動修復に必要)
resource "google_compute_health_check" "nginx_health_check" {
  name               = "nginx-health-check"
  check_interval_sec = 10
  timeout_sec         = 5
  healthy_threshold  = 2
  unhealthy_threshold = 3

  http_health_check {
    port         = 80
    request_path = "/"
  }
}
ポイント: ヘルスチェックにより、VM の状態を監視し、障害が発生した VM を自動的に修復できます。

6.3 ロードバランサーの作成

ファイル: terraform/main.tf(上記のファイルに追加)
# バックエンドサービスの作成
resource "google_compute_backend_service" "nginx_backend" {
  name                  = "nginx-backend"
  protocol              = "HTTP"
  port_name             = "http"
  load_balancing_scheme = "EXTERNAL"
  timeout_sec           = 30

  backend {
    group = google_compute_instance_group_manager.nginx_group.instance_group
  }

  health_checks = [google_compute_health_check.nginx_health_check.id]
}

# グローバル転送ルールの作成(ロードバランサーのIPアドレスを公開)
resource "google_compute_global_forwarding_rule" "nginx_lb" {
  name       = "nginx-lb"
  target     = google_compute_backend_service.nginx_backend.id
  port_range = "80"
}
ポイント: ロードバランサーを使用することで、複数の VM にトラフィックを分散できます。
解説: グローバルロードバランサーは、複数のリージョンにまたがる VM にトラフィックを分散できます。

ステップ 7: VM Manager を使用したパッチ管理

7.1 OS Config API の有効化

作業ディレクトリ: 任意(gcloud コマンドはどこからでも実行可能)
# OS Config APIを有効化(VM Managerに必要)
gcloud services enable osconfig.googleapis.com --project=cookbook-251226
ポイント: VM Manager を使用するには、OS Config API を有効化する必要があります。

7.2 プロジェクトメタデータの設定

作業ディレクトリ: 任意(gcloud コマンドはどこからでも実行可能)
注意: この設定は、gcloud コマンドで行う必要があります。Terraform では、google_compute_project_metadataリソースを使用できますが、この設定は既存の VM にも影響するため、慎重に設定してください。
# プロジェクトメタデータを設定(VM Managerを有効化)
gcloud compute project-info add-metadata --metadata=enable-osconfig=TRUE --project=cookbook-251226
gcloud compute project-info add-metadata --metadata=enable-guest-attributes=TRUE --project=cookbook-251226
ポイント: プロジェクトメタデータを設定することで、すべての VM で VM Manager が有効化されます。
解説: VM Manager は、OS Config API を使用して VM のパッチ管理を行うサービスです。これにより、複数の VM を一括でパッチ適用できます。
ベストプラクティス: VM Manager のベストプラクティス

ステップ 8: Terraform の実行

8.1 Terraform の初期化

作業ディレクトリ: terraform/
# Terraform用ディレクトリに移動
cd terraform

# Terraformの初期化
# このコマンドで、必要なプロバイダのプラグインがダウンロードされます
terraform init
ポイント: terraform initは、Terraform の設定ファイルを読み込み、必要なプロバイダのプラグインをダウンロードします。

8.2 実行プランの確認

作業ディレクトリ: terraform/
# 実行プランの確認
# このコマンドで、作成・変更・削除されるリソースが表示されます
terraform plan
ポイント: terraform planは、実際にリソースを作成する前に、変更内容を確認できます。

8.3 リソースの作成

作業ディレクトリ: terraform/
# リソースの作成
# このコマンドで、定義したリソースが作成されます
terraform apply
ポイント: terraform applyは、定義したリソースを作成または更新します。確認プロンプトが表示されるので、内容を確認してから承認してください。

8.4 リソースの確認

作業ディレクトリ: 任意(gcloud コマンドはどこからでも実行可能)
# 作成されたVMの一覧を表示
gcloud compute instances list --project=cookbook-251226

# 特定のVMの詳細を表示
gcloud compute instances describe linux-vm --zone=asia-northeast1-a --project=cookbook-251226
ポイント: gcloudコマンドを使用して、作成されたリソースを確認できます。

ステップ 9: リソースの削除

9.1 Terraform destroy の実行

作業ディレクトリ: terraform/
# Terraform用ディレクトリに移動
cd terraform

# すべてのリソースを削除
# このコマンドで、Terraformで作成したすべてのリソースが削除されます
terraform destroy
ポイント:
  • terraform destroyは、Terraform で作成したすべてのリソースを削除します
  • 削除前に確認プロンプトが表示されるので、内容を確認してから承認してください
解説: 作業が完了したら、不要なリソースを削除することで、コストの発生を防ぎます。

9.2 個別リソースの削除

特定のリソースのみを削除する場合は、Terraform の設定ファイルから該当リソースを削除し、terraform applyを実行します。
ポイント: 個別リソースの削除は、設定ファイルから該当リソースを削除することで行えます。