見出し画像

【GCP】Terraformでロードバランサーたててwebサーバーと疎通するログをBigQueryに連携する


Terraformでロードバランサーに必要なリソース

terraformでロードバランサーを実装する場合は疎結合の複数リソースを組み合わせることで実現します。

* google_compute_health_check : ヘルスチェック
* google_compute_backend_service : バックエンドサービス
* google_compute_url_map : ロードバランサ名となるリソース
* google_compute_target_http_proxy : プロキシ
* google_compute_global_address : グローバル IP アドレス
* google_compute_global_forwarding_rule : ポートマッピングによるフォワーディングルール

作業ディレクトリの構成はこちら

.
├── main.tf
├── outputs.tf
├── terraform.tfstate
├── terraform.tfstate.backup
├── terraform.tfvars
└── variables.tf

作業ディレクトリでterraform initコマンドを打つとtfstate系のファイルが作成されます。
main.tfは実装、outputs.tfは出力するパラメータの定義、variables.tfは入力値の定義、terraform.tfvarsは変数の値の定義ファイルです。

インスタンスの構築

まずmain.tfに疎通するサーバーを配置するインスタンスを構築します

main.tf

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "4.51.0"
    }
  }
}

provider "google" {
  credentials = file(var.credentials_file)

  project = var.project
  region  = var.region
  zone    = var.zone
}

provider "google-beta" {
  credentials = file(var.credentials_file)
  project     = var.project
}

# VPC
resource "google_compute_network" "this" {
  name                    = "test-network"
  provider                = google-beta
  auto_create_subnetworks = false
}

resource "google_compute_firewall" "ssh" {
  name = "allow-ssh"
  allow {
    ports    = ["22"]
    protocol = "tcp"
  }
  direction     = "INGRESS"
  network       = google_compute_network.this.id
  priority      = 1000
  source_ranges = ["0.0.0.0/0"]
  target_tags   = ["ssh"]
}

resource "google_compute_firewall" "this" {
  name = "allow-http-https"
  allow {
    ports    = ["80", "443"]
    protocol = "tcp"
  }
  direction     = "INGRESS"
  network       = google_compute_network.this.id
  priority      = 1000
  source_ranges = ["0.0.0.0/0"]
  target_tags   = ["web"]
}

# backend subnet
resource "google_compute_subnetwork" "this" {
  provider      = google-beta
  name          = "test-subnet"
  ip_cidr_range = "10.0.1.0/24"
  region        = var.region
  network       = google_compute_network.this.id
}

resource "google_compute_health_check" "this" {
  provider           = google-beta
  name               = "test-health-check"
  timeout_sec        = 1
  check_interval_sec = 1

  tcp_health_check {
    port = "80"
  }
}

resource "google_compute_instance" "this" {
  name         = "test-web-server"
  machine_type = "e2-micro"
  zone         = var.zone

  tags = ["web"]

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-10"
      size  = "10"
      type  = "pd-standard"
    }
  }

  network_interface {
    network    = google_compute_network.this.id
    subnetwork = google_compute_subnetwork.this.id
    access_config {
      # add external ip to fetch packages
    }
  }

  metadata_startup_script = "sudo apt update; sudo apt install nginx -y; sudo systemctl start nginx"
}


resource "google_compute_instance_group" "this" {
  name        = "test-webserver-group"
  description = "test webserver instance group"

  instances = [
    "${google_compute_instance.this.self_link}",
  ]

  named_port {
    name = "http"
    port = "80"
  }

  zone = var.zone
}

terraform.tfvars

project          = 自身のgcpのprojectID
credentials_file = /credential/file/path

variables.tf

variable "project" {}

variable "credentials_file" {}

variable "region" {
  default = "asia-northeast1"
}

variable "zone" {
  default = "asia-northeast1-a"
}

これでwebサーバーは単純にinstance作成時にnginxが起動するように設定しています

ロードバランサーの設定

main.tf

# Load Balancer
resource "google_compute_health_check" "this" {
    name = "tracking-lb"
    description = "test lb health check"

    timeout_sec = 5
    check_interval_sec = 5
    healthy_threshold   = 4
    unhealthy_threshold = 5

    http_health_check {
        port = 80
    }
}

resource "google_compute_backend_service" "this" {
    name = "tracking-backend"
    description = "test lb backend"

    port_name = "http"
    protocol = "HTTP"
    enable_cdn = false
    timeout_sec = 10
    health_checks = [google_compute_health_check.this.self_link]
    backend {
        group = "${google_compute_instance_group.this.self_link}"
    }
}

resource "google_compute_url_map" "this" {
  name        = "test-url-map"
  description = "test lb url map"

  default_service = google_compute_backend_service.this.id
}

# Target HTTP proxy
resource "google_compute_target_http_proxy" "this" {
  name    = "test-http-proxy"
  url_map = google_compute_url_map.this.id
}

# Global forwarding rule
resource "google_compute_global_forwarding_rule" "this" {
  name        = "test-forwarding-rule"
  description = "test lb forwarding rule"

  target     = google_compute_target_http_proxy.this.id
  port_range = "80"

  ip_address  = google_compute_global_address.this.address
  ip_protocol = "TCP"

  depends_on = [
    google_compute_target_http_proxy.this,
    google_compute_global_address.this
  ]
}

# Global address
resource "google_compute_global_address" "this" {
  provider   = google-beta
  name       = "test-lb-address"
  ip_version = "IPV4"
}

# Firewall fro Backend
resource "google_compute_firewall" "webserver" {
  name    = "backend-http-server"
  network = google_compute_network.this.id

  allow {
    protocol = "tcp"
    ports = [
      "80", # http
    ]
  }

  source_ranges = [
    "130.211.0.0/22", # Google LB *公式から引用
    "35.191.0.0/16",  # Google LB *公式から引用
  ]

  target_tags = [
    "web",
  ]
}

ロードバランサーのグローバルIPと疎通先のバックエンドサービスの定義だけではロードバランサは通信できないため、firewall, proxyの定義やforwarding rule、url mapの設定を行なっています。

outputs.tf

output "lb-ip" {
  value = "http://${google_compute_global_address.this.address}"
}

公開するロードバランサーのip addressを出力するようにします

GCPにapplyする

ここまできたらterraform applyコマンドで実装をgcpに適用します

出力されたアドレスに接続してnginxのindexページにアクセスされればok! (apply後すぐには表示されない場合は数分待つと表示されるようになります)

ロードバランサーのログをBigQueryに連携する

main.tf

# Logging Sink
resource "google_bigquery_dataset" "this" {
  dataset_id  = "test_dataset"
  description = "テスト用データセット"
  location    = "asia-northeast1"
}

resource "google_logging_project_sink" "this" {
  name                   = "logsync-test"
  destination            = "bigquery.googleapis.com/${google_bigquery_dataset.this.id}"
  filter                 = "resource.type=http_load_balancer AND resource.labels.url_map_name=\"${google_compute_url_map.this.name}\" AND httpRequest.status=200"
  unique_writer_identity = true

  bigquery_options {
    use_partitioned_tables = true
  }
}

resource "google_bigquery_dataset_iam_binding" "this" {
  dataset_id = "test_dataset"
  role       = "roles/bigquery.dataEditor"
  members = [
    google_logging_project_sink.this.writer_identity,
  ]
}

ログをシンクする先のデータセットを作成し、そこに指定した条件(filter)のログを格納する設定をしています。
google_bigquery_dataset_iam_bindingは書き込み権限のために必要です

GCPにapplyする

apply後、ロードバランサーのIPに接続してGCPのBigQueryを開きます
自分のプロジェクト名のディレクトリ配下に作成されたデータセットが存在し、出力されたログがデータセットのpreviewなどで確認できればOK!



この記事が気に入ったらサポートをしてみませんか?