pi-100t/main.tf (149 lines of code) (raw):
/**
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
terraform {
backend "gcs" {
bucket = "pi-100t-tf-state"
prefix = "terraform/state"
}
required_providers {
google = {
source = "hashicorp/google"
version = "~> 4.8.0"
}
google-beta = {
source = "hashicorp/google-beta"
version = "~> 4.8.0"
}
}
}
// Base images
data "google_compute_image" "windows_base" {
project = "windows-cloud"
family = "windows-2019"
}
data "google_compute_image" "debian_base" {
project = "debian-cloud"
family = "debian-11"
}
// startup script for storage nodes
data "local_file" "startup_script" {
filename = "${path.module}/startup-script.sh"
}
// Create gVNIC enabled images
resource "google_compute_image" "debian" {
name = "debian-gvnic"
description = "Debian disk image with gVNIC enabled"
source_image = data.google_compute_image.debian_base.self_link
guest_os_features {
type = "GVNIC"
}
guest_os_features {
type = "UEFI_COMPATIBLE"
}
guest_os_features {
type = "VIRTIO_SCSI_MULTIQUEUE"
}
}
// Service accounts
data "google_compute_default_service_account" "default" {
}
resource "random_id" "compute_role" {
byte_length = 8
}
resource "google_service_account" "compute_node" {
account_id = "compute-node-sa"
display_name = "Compute Node SA"
}
resource "google_service_account" "storage_node" {
account_id = "storage-node-sa"
display_name = "Storage Node SA"
}
resource "google_project_iam_custom_role" "snapshot" {
role_id = "snapshot_role_${random_id.compute_role.hex}"
title = "Custom role for the compute node"
permissions = [
"compute.disks.createSnapshot",
"compute.disks.list",
"compute.disks.get",
"compute.snapshots.create",
"compute.snapshots.setLabels",
]
}
resource "google_project_iam_binding" "snapshot_compute" {
project = local.env.project
role = google_project_iam_custom_role.snapshot.name
members = [
"serviceAccount:${google_service_account.compute_node.email}",
]
}
resource "google_project_iam_binding" "storage_compute" {
project = local.env.project
role = "roles/storage.objectAdmin"
members = [
"serviceAccount:${google_service_account.compute_node.email}",
]
}
resource "google_project_iam_binding" "compute_viewer" {
project = local.env.project
role = "roles/compute.viewer"
members = [
"serviceAccount:${google_service_account.compute_node.email}",
"serviceAccount:${google_service_account.storage_node.email}",
]
}
resource "google_project_iam_binding" "storage_object_viewer" {
project = local.env.project
role = "roles/storage.objectViewer"
members = [
"serviceAccount:${google_service_account.storage_node.email}",
]
}
resource "google_project_iam_binding" "logs_writer" {
project = local.env.project
role = "roles/logging.logWriter"
members = [
"serviceAccount:${google_service_account.compute_node.email}",
"serviceAccount:${google_service_account.storage_node.email}",
]
}
resource "google_project_iam_binding" "monitoring_metric_writer" {
project = local.env.project
role = "roles/monitoring.metricWriter"
members = [
"serviceAccount:${google_service_account.compute_node.email}",
"serviceAccount:${google_service_account.storage_node.email}",
]
}
resource "google_project_iam_binding" "guest_policy_viewer" {
project = local.env.project
role = "roles/osconfig.guestPolicyViewer"
members = [
"serviceAccount:${google_service_account.compute_node.email}",
"serviceAccount:${google_service_account.storage_node.email}",
]
}
data "google_compute_network" "default" {
name = "default"
}
// External addresses
resource "google_compute_address" "compute" {
name = "compute-node-ip"
description = "public IP of the compute node"
}
// Disks to store the final results
// Resize the disks once we get closer to the end.
// Make sure to run mkfs again instead of using xfs_grow because
// there are parameters that don't quite scale from 10 GB to 50 TB.
resource "google_compute_disk" "results_dec" {
name = "results-dec-disk"
type = "pd-balanced"
size = var.result_disk_size
labels = {
"snapshot" = "enabled"
"env" = local.env.env_label
}
lifecycle {
ignore_changes = [snapshot]
}
}
resource "google_compute_disk" "results_hex" {
name = "results-hex-disk"
type = "pd-balanced"
size = var.result_disk_size
labels = {
"env" = local.env.env_label
"snapshot" = "enabled"
}
lifecycle {
ignore_changes = [snapshot]
}
}
locals {
total_storage_disk_count = local.env.storage_node_count * local.env.targets_per_node
}
// Disks for y-crunchre swap
resource "google_compute_disk" "storage" {
count = local.total_storage_disk_count
name = "storage-disk-${count.index}"
type = local.env.storage_disk_type
size = ceil(local.env.total_storage_size * 1000 / local.total_storage_disk_count)
labels = {
"snapshot" = "enabled"
"env" = local.env.env_label
}
lifecycle {
ignore_changes = [snapshot]
}
}
// Disk for the y-cruncher directory
resource "google_compute_disk" "y_cruncher" {
name = "y-cruncher-disk"
type = "pd-balanced"
size = 50
labels = {
"snapshot" = "enabled"
"env" = local.env.env_label
}
lifecycle {
ignore_changes = [snapshot]
}
}
// Create the compute instance
resource "google_compute_instance" "compute" {
provider = google-beta
name = "compute-node"
machine_type = local.env.compute_node_type
min_cpu_platform = local.env.compute_cpu_platform
advanced_machine_features {
// Disable SMT for better network throughput
threads_per_core = 1
}
boot_disk {
initialize_params {
size = 20
type = "pd-balanced"
// image = google_compute_image.debian.self_link
image = data.google_compute_image.debian_gvnic.self_link
labels = {
"snapshot" = "enabled"
"env" = local.env.env_label
}
}
}
network_interface {
network = data.google_compute_network.default.self_link
nic_type = "GVNIC"
access_config {
nat_ip = google_compute_address.compute.address
}
}
network_performance_config {
total_egress_bandwidth_tier = "TIER_1"
}
shielded_instance_config {
// enable_secure_boot = true
enable_vtpm = true
enable_integrity_monitoring = true
}
attached_disk {
source = google_compute_disk.y_cruncher.self_link
device_name = "y-cruncher"
}
attached_disk {
source = google_compute_disk.results_dec.self_link
device_name = "results-dec"
}
attached_disk {
source = google_compute_disk.results_hex.self_link
device_name = "results-hex"
}
service_account {
email = google_service_account.compute_node.email
scopes = ["cloud-platform"]
}
metadata = {
startup-script = data.local_file.startup_script.content
}
labels = {
type = "compute"
env = local.env.env_label
}
deletion_protection = local.deletion_protection
lifecycle {
ignore_changes = [boot_disk.0.initialize_params]
}
}
// Create storage nodes for y-cruncher swap
resource "google_compute_instance" "storage" {
count = local.env.storage_node_count
name = "storage-node-${count.index}"
machine_type = local.env.storage_node_type
min_cpu_platform = local.env.storage_cpu_platform
advanced_machine_features {
// Disable SMT for better network throughput
threads_per_core = 1
}
network_interface {
network = data.google_compute_network.default.self_link
nic_type = "VIRTIO_NET"
access_config {}
}
boot_disk {
initialize_params {
size = 10
type = "pd-balanced"
// image = google_compute_image.debian.self_link
image = data.google_compute_image.debian_gvnic.self_link
labels = {
"env" = local.env.env_label
}
}
}
dynamic "attached_disk" {
for_each = slice(google_compute_disk.storage, count.index * local.env.targets_per_node, count.index * local.env.targets_per_node + local.env.targets_per_node)
iterator = iter
content {
source = iter.value.self_link
device_name = "storage-disk-${iter.key}"
}
}
shielded_instance_config {
// enable_secure_boot = true
enable_vtpm = true
enable_integrity_monitoring = true
}
service_account {
email = google_service_account.storage_node.email
scopes = ["cloud-platform"]
}
metadata = {
startup-script = data.local_file.startup_script.content
}
labels = {
"type" = "storage"
"env" = local.env.env_label
}
deletion_protection = local.deletion_protection
lifecycle {
ignore_changes = [boot_disk.0.initialize_params]
}
}
// Create a Cloud Storage bucket to copy the final results
resource "google_storage_bucket" "results" {
name = "${local.env.project}-results"
location = "US"
uniform_bucket_level_access = true
}
// Export the number of nodes as metadata
resource "google_compute_project_metadata_item" "storage_node_count" {
key = "storage-node-count"
value = local.env.storage_node_count
}
resource "google_compute_project_metadata_item" "targets_per_node" {
key = "targets-per-node"
value = local.env.targets_per_node
}
resource "google_compute_project_metadata_item" "snapshot_frequency" {
key = "snapshot-frequency"
value = var.snapshot_frequency
}
resource "google_os_config_guest_policies" "os_agent_debian_11" {
provider = google-beta
guest_policy_id = "ops-agent-debian-11"
packages {
name = "google-cloud-ops-agent"
desired_state = "UPDATED"
}
assignment {
os_types {
os_short_name = "debian"
os_version = "11"
}
}
package_repositories {
apt {
uri = "https://packages.cloud.google.com/apt"
archive_type = "DEB"
distribution = "google-cloud-ops-agent-bullseye-all"
components = ["main"]
gpg_key = "https://packages.cloud.google.com/apt/doc/apt-key.gpg"
}
}
}
resource "google_os_config_guest_policies" "common_packages_deb" {
provider = google-beta
guest_policy_id = "common-packages-deb"
packages {
name = "sysfsutils"
desired_state = "REMOVED"
}
packages {
name = "sysstat"
desired_state = "INSTALLED"
}
assignment {
os_types {
os_short_name = "debian"
os_version = "11"
}
}
}
resource "google_os_config_guest_policies" "compute_packages" {
provider = google-beta
guest_policy_id = "compute-packages"
packages {
name = "open-iscsi"
desired_state = "INSTALLED"
}
packages {
name = "xfsprogs"
desired_state = "INSTALLED"
}
packages {
name = "libnuma1"
desired_state = "INSTALLED"
}
packages {
name = "libhugetlbfs-bin"
desired_state = "INSTALLED"
}
packages {
name = "numactl"
desired_state = "INSTALLED"
}
assignment {
os_types {
os_short_name = "debian"
os_version = "11"
}
group_labels {
labels = {
"type" = "compute"
}
}
}
}