使用 Terraform 在GCP上建立组织设置、共享VPC和VPN

请将以下内容用中文进行释义。

因为用 Terraform 工具将以前手动构建的 GCP(Google Cloud Platform)部署转变为基础设施即代码,所以在此记录这些变化的详细内容。

迄今为止,以手动方式(包括Web控制台、gcloud等)执行的任务(Terraform代码化目标)。

建立內容

实施前述的「之前进行的内容(Terraform 代码化目标)」的链接内容。
内容如下,已经写明的内容省略解释,补充的内容则标注了补充说明的部分。

    • 組織の作成と共有 VPC 構築

ホストプロジェクト作成
サービスプロジェクト作成
共有 VPC
Subnet の設定
[追加] 組織のポリシー追加
[追加] 権限の追加

HA VPN

自宅ラボ向けに HA VPN を構築する
自宅ラボ向けに設定Config例を出力する (EdgeRouer向け)

VPC Service Controls

サービス境界の作成

限定公開 Google アクセス

googleapis.com 向けの Private 向け DNS 設定

GCP资源配置

在组织中创建文件夹(类似于部门),并将项目组织成属于文件夹的结构(参考写法)。
按照 Terraform 的指导(参考链接:https://cloud.google.com/community/tutorials/managing-gcp-projects-with-terraform),直接在组织中构建管理项目。

スクリーンショット 2021-03-27 12.36.14.png

关于项目名称,请参考企业级指南中的项目名称,并添加您自己的ID以确保与其他项目不重复(ID必须唯一)。
– 项目名称(ID):[组织名称]-[服务名称]-[环境名称]

Terraform 目录结构

由于不知道正确的解决方法,因此简单地进行了文件分割。(模块化等以后再考虑。似乎没有事先定义的标准。)
有关预先操作和Terraform项目的创建,将其放在单独的文件夹(prestage)中。
由于全部都写在了Qiita中会很长,所以进行了省略描述,整体在GitHub上公开了(URL:https://github.com/suzuyu/terraform-public)。
※backend.tf将根据prestage/执行的输出进行创建(GitHub上没有)。

.
├── README.md
├── backend.tf
├── cloudnat.tf
├── dns.tf
├── firewall.tf
├── host.tf
├── main.tf
├── organization.tf
├── prestage
│   ├── main.tf
│   ├── output.tf
│   ├── variables.tf
├── service1.tf
├── subnet.tf
├── terraform_pj
├── variables.tf
├── vpc_service_controls.tf
└── vpn.tf

スクリーンショット 2021-03-27 12.36.32.png

根据文件分类、解释和记录每个文件的结构和内容

建立

我们按照下面的顺序进行实施。

    1. 前期准备 / 域名获取·CloudIdentity启用(手动)

 

    1. 创建terraform管理项目(prestage/)

 

    1. 组织设置(organaization.tf)

 

    1. 创建主机项目(host.tf)

 

    1. 创建服务项目(service1.tf)

 

    1. 创建子网(subnet.tf)

 

    1. 设置防火墙(firewall.tf)

 

    1. 设置DNS(限定公开Google访问)(dns.tf)

 

    1. 创建HA VPN(vpn.tf)

 

    1. 设置面向互联网的NAT(cloudnat.tf)

 

    创建VPC服务控制(vpc_service_controls.tf)

1. 准备工作/购买域名和启用云身份(手动方式)

直到域名注册和组织生效都需要手动操作。

    • ドメイン取得

https://qiita.com/suzuyui/items/947867f52897417ee31b#1-%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E5%8F%96%E5%BE%97

組織の作成 (Cloud Identity, 組織の作成までを完了させる)

https://qiita.com/suzuyui/items/947867f52897417ee31b#2-%E7%B5%84%E7%B9%94%E3%81%AE%E4%BD%9C%E6%88%90

スクリーンショット 2021-03-21 21.19.32.png

在工作环境中,事先安装 Terraform 和 gcloud。

安装方法:https://qiita.com/suzuyui/items/231b39a60ff545032bc6#terraform-安装

% terraform version
Terraform v0.14.6
% gcloud --version
Google Cloud SDK 327.0.0
alpha 2021.02.05
beta 2021.02.05
bq 2.0.64
core 2021.02.05
gsutil 4.58

继续使用terraform进行构建

2. 创建terraform管理项目(预阶段/)

参考了Google Cloud社区中Google员工编写的教程,在Terraform中创建管理项目。
将教程中手动执行的部分转化为prestage中的Terraform代码并执行(也可以手动执行)。
由于还未创建适用于Terraform的服务帐号,因此将使用gcloud的认证信息来访问GCP。

创建 Terraform 管理项目:https://cloud.google.com/community/tutorials/managing-gcp-projects-with-terraform

以下内容已经在上述URL中参考并进行了编码。

    • Create the Terraform Admin Project

terraform admin project の作成
組織配下の指定をする

Create the Terraform service account

terraform を動かすための service account を作成する
prestage は gcloud の認証アカウントで動かすが、今後サーバ等で動かすことが可能になる
service account の認証キー (json) はファイルとして出力し、その後の必要コマンドは output で出力する
terraform で必要な API を有効化する

Add organization/folder-level permissions

terraform service account にプロジェクト作成権限と課金ユーザ権限などを付与する

terraform state の保存先ストレージの作成 / Set up remote state in Cloud Storage

terraform の backend にする Cloud Storage を作成する
backend 設定の記載方法は output で出力する

├── prestage
│   ├── main.tf
│   ├── output.tf
│   ├── variables.tf

作为变量,准备以下内容:
根据评论所写,在被标记为 xxx 并遮蔽的地方进行更改。

# org_id (下記で出力される "ID" を "org_id" の値にする)
## gcloud organizations list
# billing_account (下記で出力される "ACCOUNT_ID" を "billing_account" の値にする)
## gcloud beta billing accounts list
# gcp-terraform-admin@[xxx.xxx]
## 組織で使用するドメイン(xxx.xxx)の Cloud Identity で事前に Terraform 管理ユーザグループのアカウントグループを作成しておく(同じ権限にして切り分けよう)
# org_name
## 組織の識別子、プロジェクトの命名に必要なだけで何でも良い

variable "gcp_common" {
  type = object({
    org_name        = string
    org_id          = string
    billing_account = string
  })
  default = {
    org_name        = "xxxxxx"
    org_id          = "xxxxxxxxxxxx"
    billing_account = "xxxxxx-xxxxxx-xxxxxx"
  }
}

variable "admin_user_group" {
  type = object({
    email = string
  })
  default = {
    email = "gcp-terraform-admin@[xxx.xxx]"
  }
}

variable "terraform_pj" {
  type = object({
    identity_name = string
  })
  default = {
    identity_name = "terraformadmin"
  }
}

在 terraform 中的执行内容如下所示的 main.tf 文件所示
根据注释进行预先操作(执行命令请参考注释)

    • 課金アカウントへ権限を付与する

課金アカウント(variables.tfでbilling_account)へ今回 gcloud を実施する組織管理者アカウントへ権限を付与する

組織管理者アカウントで gcloud 設定をする
組織ポリシーを操作できるように権限を付与する
workspace の名前で環境名としてプロジェクトに名称付与するので、terraform workspace を切り替える

workspace を使ったほうがいいかは悩みどころだが試しに使用してみている

## 内容
# Terraform 用のプロジェクトを作成する
# 参照 https://cloud.google.com/community/tutorials/managing-gcp-projects-with-terraform
## 前提
# 組織を作成済み
# 課金アカウント作成済み
# 管理ユーザグループを admin.google で作成済み
## 組織管理者が課金アカウントへ権限付与できるようにする
# gcloud config set account [課金アカウントのアドミンアカウント]
# gcloud beta billing accounts list
# gcloud beta billing accounts add-iam-policy-binding [var.gcp_common.billing_account] --member=user:[org admin user account] --role roles/billing.admin
## 組織管理者のアカウントで gcloud コマンドを利用できるようにする
# gcloud auth login [org admin user account]
# gcloud config set account [org admin user account]
# gcloud auth application-default login
## 組織管理者が組織ポリシーを編集できるようにする
# gcloud organizations list
# gcloud organizations add-iam-policy-binding [var.gcp_common.org_id] --member=user:[org admin user account] --role=roles/orgpolicy.policyAdmin
## workspace を "dev", "prd" などにする
# terraform workspace new dev

provider "google" {}

# Terraform Project 作成
resource "google_project" "terraform" {
  name                = join("-", [var.gcp_common.org_name, var.terraform_pj.identity_name, terraform.workspace])
  project_id          = join("-", [var.gcp_common.org_name, var.terraform_pj.identity_name, terraform.workspace])
  org_id              = var.gcp_common.org_id
  billing_account     = var.gcp_common.billing_account
  auto_create_network = false
}

# Sevice API 有効化 (google_project と同じ terraform で実施が必須)
resource "google_project_service" "terraform" {
  project                    = google_project.terraform.id
  disable_dependent_services = true

  for_each = toset([
    "cloudresourcemanager.googleapis.com",
    "serviceusage.googleapis.com",
    "cloudidentity.googleapis.com",
    "cloudbilling.googleapis.com",
    "iam.googleapis.com",
    "compute.googleapis.com",
    "container.googleapis.com",
    "accesscontextmanager.googleapis.com", # VPC Service Controls に必要
  ])
  service = each.value

  depends_on = [
    google_project.terraform,
  ]
}

# Terraform サービスアカウントの作成
resource "google_service_account" "terraform" {
  account_id   = "terraform"
  display_name = "Terraform IaC Account"
  project      = google_project.terraform.project_id

  depends_on = [
    google_project.terraform,
  ]
}

# Terraform へホストプロジェクトの閲覧ロールを付与
resource "google_project_iam_binding" "storage_serviceusage" {
  project = google_project.terraform.project_id
  for_each = toset([
    "roles/storage.admin",
    "roles/serviceusage.serviceUsageAdmin",
  ])

  role = each.value

  members = [
    join(":", ["serviceAccount", google_service_account.terraform.email]),
    join(":", ["group", var.admin_user_group.email]),
  ]

  depends_on = [
    google_service_account.terraform,
  ]
}

# Terraform へホストプロジェクトの閲覧ロールを付与
resource "google_project_iam_binding" "viewer" {
  project = google_project.terraform.project_id
  for_each = toset([
    "roles/viewer",
  ])

  role = each.value

  members = [
    join(":", ["serviceAccount", google_service_account.terraform.email]),
  ]

  depends_on = [
    google_service_account.terraform,
  ]
}

# Terraform へホストプロジェクトの編集ロールを付与
resource "google_project_iam_binding" "editor" {
  project = google_project.terraform.project_id
  for_each = toset([
    "roles/editor",
  ])

  role = each.value

  members = [
    join(":", ["group", var.admin_user_group.email]),
  ]

  depends_on = [
    google_service_account.terraform,
  ]
}

# Terraform へ組織内のプロジェクト作成権限を付与
resource "google_organization_iam_binding" "terraform" {
  org_id = google_project.terraform.org_id
  for_each = toset([
    "roles/resourcemanager.projectCreator",
    #    "roles/billing.projectManager",
    "roles/billing.user",
    "roles/compute.xpnAdmin",
    "roles/resourcemanager.projectIamAdmin",
    "roles/resourcemanager.organizationAdmin",
    "roles/orgpolicy.policyAdmin",
    "roles/resourcemanager.folderAdmin",
    "roles/accesscontextmanager.policyAdmin", # VPC SC 時に必要
  ])
  role = each.value

  members = [
    join(":", ["serviceAccount", google_service_account.terraform.email]),
    #    join(":", ["user", var.admin_user.email]),
    join(":", ["group", var.admin_user_group.email])
  ]

  depends_on = [
    google_project.terraform,
    google_service_account.terraform,
  ]
}

# Terraform へ課金アカウントの利用権限を付与
resource "google_billing_account_iam_binding" "user" {
  billing_account_id = google_project.terraform.billing_account
  role               = "roles/billing.user"
  members = [
    join(":", ["serviceAccount", google_service_account.terraform.email]),
    #    join(":", ["user", var.admin_user.email]),
    join(":", ["group", var.admin_user_group.email])
  ]

  depends_on = [
    google_project.terraform,
  ]
}

# Terraform のステートファイル置き場の作成
resource "google_storage_bucket" "terraform" {
  name          = join("-", [google_project.terraform.project_id, "terraform-backet"])
  project       = google_project.terraform.project_id
  location      = "US"
  force_destroy = true
  storage_class = "STANDARD"

  lifecycle_rule {
    condition {
      num_newer_versions = 5
    }
    action {
      type = "Delete"
    }
  }

  depends_on = [
    google_project.terraform,
  ]
}

确保输出以下内容。

    • 作成したterraform サービスアカウント名

 

    • backend.tf の作成コマンド

 

    terraform 用のサービスアカウントのキーファイル作成コマンド、移動コマンド
output "A001_Terraform_Service_Account" {
  value       = google_service_account.terraform.email
  description = "Terraform Account"
}

output "A002_GCP_BACKEND" {
  value = join("\n", [
    "cat > backend.tf << EOF",
    "terraform {",
    "  backend \"gcs\" {",
    "    bucket = \"${google_storage_bucket.terraform.name}\"",
    "    prefix = \"terraform/state\"",
    "  }",
    "}",
    "EOF",
    "mv backend.tf ../",
  ])
}

output "A003_Next_Commands" {
  value       = join("", ["gcloud iam service-accounts keys create terraform_serviceacoount_credential.json --iam-account ", google_service_account.terraform.email, ";cp terraform_serviceacoount_credential.json ../;cd ../"])
  description = "Next"
}

执行

请使用下述命令在 prestage 环境中执行 Terraform。

cd prestage
terraform workspace new dev
terraform apply

根据上述执行后的输出信息,创建backend.tf文件和terraform的凭证JSON文件。

以上的話,可以說在執行 Terraform 前的準備工作已經完成了(即手動設定,參考 Terraterm 執行步驟)。

3. 组织的设定 (organaization.tf)

在这里,我们可以进行整体设置、给予用户组权限,还可以创建第一层文件夹。

スクリーンショット 2021-03-21 23.42.29.png

由于以前的组织和共享VPC的手动创建中,没有进行以下管理用户组、组织策略和文件夹管理,因此在这里记录下其内容。

管理用户组

管理的群組參考企業專用指南
由於我只需要自己創建並進行測試,因此此次只需選取部分並在兩個群組中進行設置(服務專案將在另一個群組中創建)
CloudIdentity 的設定並未納入此次的 Terraform 對象,因此需要事先創建群組。

グループ内容gcp-organization-admins組織の設定を管理するgcp-network-adminsネットワークを管理する。共有 VPC など管理する

由于需要对Terraform服务账户进行相同的操作,因此需要授予相同的权限。

此外,我们也给予了组织和文件夹的浏览权限于整个域中(包括文件夹架构,使得域用户都可以看到)。

组织政策

以前的時候並未設定,然而在創建服務專案等等時,為了不預設創建除了共享 VPC 以外的網路,設定一個不在項目創建時預設創建網路的策略。

启用compute.skipDefaultNetworkCreation(以下是在Web控制台上查看的相关策略)。

スクリーンショット 2021-03-21 23.36.58.png

文件夹

在中文中,为负责主机项目的部门创建一个名为”基础设施”的文件夹,为负责服务项目的部门创建一个名为”服务”的文件夹。

组织。

变量使用以下内容
* 为了方便后续添加,将类型设置为object,但这样行数增加了…
在xxx处添加掩码,类似于2.通过terraform管理项目的创建(prestage/),填写与实施环境相匹配的内容
terraform-service-accounts放置了2.通过terraform管理项目的创建(prestage/)最后输出的账户
在创建资源时,填写默认使用的区域/区域(这里设置为us-west1,以便更容易适用免费资源配额)

variable "gcp_common" {
  type = object({
    org_name        = string
    org_id          = string
    billing_account = string
    region          = string
    zone            = string
  })
  default = {
    org_name        = "xxxxxx"
    org_id          = "xxxxxxxxxxxx"
    billing_account = "xxxxxx-xxxxxx-xxxxxx"
    region          = "us-west1"
    zone            = "us-west1-b"
  }

  validation {
    condition     = (length(regexall(var.gcp_common.region, var.gcp_common.zone)) > 0)
    error_message = "Zone must be in region."
  }
}

variable "terraform-service-accounts" {
  type    = string
  default = "terraform@[terraform管理プロジェクト名].iam.gserviceaccount.com"
}

variable "organization_admin_group" {
  type = object({
    email = string
  })
  default = {
    email = "gcp-organization-admin@[xxx.xxx:ドメイン名]"
  }
}

variable "network_admin_group" {
  type = object({
    email = string
  })
  default = {
    email = "gcp-network-admin@[xxx.xxx:ドメイン名]"
  }
}

variable "domain" {
  type    = string
  default = "[xxx.xxx:ドメイン名]"
}

主要代码如下所示。

## 組織ポリシー
### デフォルトネットワーク作成の無効化
resource "google_organization_policy" "skipDefaultNetworkCreation" {
  org_id     = var.gcp_common.org_id
  constraint = "compute.skipDefaultNetworkCreation"

  boolean_policy {
    enforced = true
  }
}

# ドメインユーザに組織・フォルダ構成の閲覧権限付与
resource "google_organization_iam_binding" "organization_domain_viewer" {
  org_id = var.gcp_common.org_id
  for_each = toset([
    "roles/resourcemanager.organizationViewer",
    "roles/resourcemanager.folderViewer",
  ])
  role = each.value

  members = [
    join(":", ["domain", var.domain]),
  ]
}

# 組織管理者への管理権限付与
resource "google_organization_iam_binding" "organization_org_admin" {
  org_id = var.gcp_common.org_id
  for_each = toset([
    "roles/resourcemanager.organizationAdmin",
    "roles/billing.admin",
    "roles/resourcemanager.folderAdmin",
    "roles/resourcemanager.projectCreator",
    "roles/iam.organizationRoleAdmin",
    "roles/orgpolicy.policyAdmin",            # 組織ポリシー管理者
    "roles/accesscontextmanager.policyAdmin", # VPC SC 時に必要
  ])
  role = each.value

  members = [
    join(":", ["group", var.organization_admin_group.email]),
    join(":", ["serviceAccount", var.terraform-service-accounts]),
  ]

  # 削除すると管理者が削除されてしまうので偶発的な破壊を防ぐ
  # 全体を削除する場合は、管理系を手動で逃してあげる必要がある
  lifecycle {
    prevent_destroy = true
    # ignore_changes = all
  }
}

# ネットワーク管理者への共有VPC等の権限付与
resource "google_organization_iam_binding" "organization_network_admin" {
  org_id = var.gcp_common.org_id
  for_each = toset([
    "roles/compute.networkAdmin",
    "roles/compute.xpnAdmin",
    "roles/compute.securityAdmin",
  ])
  role = each.value

  members = [
    join(":", ["group", var.network_admin_group.email]),
    join(":", ["serviceAccount", var.terraform-service-accounts]),
  ]
}

# インフラ向けフォルダ
resource "google_folder" "organization_infrastructure_folder" {
  display_name = "infrastructure"
  parent       = join("/", ["organizations", var.gcp_common.org_id])

  depends_on = [
    google_organization_policy.skipDefaultNetworkCreation,
  ]
}

# サービス向けフォルダ
resource "google_folder" "organization_service_folder" {
  display_name = "service"
  parent       = join("/", ["organizations", var.gcp_common.org_id])

  depends_on = [
    google_organization_policy.skipDefaultNetworkCreation,
  ]
}

由于代码过长,编写所有代码会显得冗长。因此,请只列出特别指定的代码,并在其他地方参考GitHub(每个章节提供代码参考链接)。

4. 创建主机项目(host.tf)

正在创建主机项目和进行API和IAM设置。
将主机项目的管理组地址放入variables.tf文件的host_project_admin_group的电子邮件字段中。
使用google_compute_shared_vpc_host_project来启用共享VPC的主机功能。

resource "google_compute_shared_vpc_host_project" "host" {
  project = google_project.host_project.name

  depends_on = [
    google_project.host_project,
    google_project_service.host_api_enable,
  ]
}

5. 创建服务项目(service1.tf)

创建服务项目、进行API和IAM设置
将service1_project_admin_group的email地址设置为服务项目管理组的地址
使用google_compute_shared_vpc_service_project将服务项目连接到host_project
此外,还创建了两个服务账号,一个用于公共用途,一个用于私有用途,例如GCE
这样做是为了在防火墙中进行区分

# サービスプロジェクト設定
resource "google_compute_shared_vpc_service_project" "service1" {
  host_project    = google_project.host_project.name
  service_project = google_project.service1.name

  depends_on = [
    google_project_service.service1_api_enable,
    google_compute_shared_vpc_host_project.host,
  ]
}

# サービスアカウント
## Public 向け
resource "google_service_account" "service1_public_account" {
  account_id   = "service1-public-account-id"
  display_name = "Service1 Public Account"
  project      = google_project.service1.name
}
## Private 向け
resource "google_service_account" "service1_private_account" {
  account_id   = "service1-private-account-id"
  display_name = "Service1 Private Account"
  project      = google_project.service1.name
}

6. 创建子网 (subnet.tf)

使用 `google_compute_subnetwork` 命令来创建子网。
将地址设置为示例中的172.18.0.0/24(可以根据运维需求将其配置到 variables.tf 或 tfvars 文件中)。

为了在服务项目中可以使用共享 VPC 的子网,使用 google_compute_subnetwork_iam_binding 为服务项目用户组授予网络用户权限
※虽然也可以在主机项目中授予整个子网的权限,但在这里选择了按子网进行权限管理。

resource "google_compute_subnetwork_iam_binding" "service1-gce-subnets" {
  project    = google_compute_subnetwork.service1-gce-subnets.project
  region     = google_compute_subnetwork.service1-gce-subnets.region
  subnetwork = google_compute_subnetwork.service1-gce-subnets.name
  role       = "roles/compute.networkUser"
  members = [
    join(":", ["group", var.service1_project_admin_group.email]),
  ]
}

7. 防火墙的设定 (firewall.tf) de

本次代码中包含了以下两个防火墙规则,用以执行防火墙配置。

name内容送信元送信先private-private-001Privateアドレス内のアクセス許可.ゆるい設定なので環境によって要修正192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8サービス1プロジェクト向け Private/Public サービスアカウントinternet-public-001インターネットから INGRESS で許可する IP 設定
ここでは例として、外部テザリング環境などでログインする際にソフトバンク携帯のアドレスとして公開されているサイト iphone/ipadはこちらでした(追記) から抜粋したアドレスを許可している許可するグローバルアドレスリスト(参照) iphone/ipadはこちらでした(追記)サービス1プロジェクト向け Public サービスアカウント
スクリーンショット 2021-03-22 0.15.40.png
resource "google_compute_firewall" "private-permit" {
  name        = "private-private-001"
  description = "Private Subnet Permit"
  network     = google_compute_network.host_sharedvpc.name
  priority    = 1000
  direction   = "INGRESS"
  project     = google_project.host_project.name

  source_ranges = ["192.168.0.0/16", "172.16.0.0/12", "10.0.0.0/8"]
  target_service_accounts = [
    google_service_account.service1_public_account.email,
    google_service_account.service1_private_account.email,
  ]


  allow {
    protocol = "icmp"
  }

  allow {
    protocol = "tcp"
    ports    = ["22"]
  }

  depends_on = [
    google_compute_network.host_sharedvpc,
    google_project_service.host_api_enable,
    google_service_account.service1_public_account,
    google_service_account.service1_private_account,
  ]

}

resource "google_compute_firewall" "softbank-mobile" {
  name        = "internet-public-001"
  description = "Softbank Moible Global Address Permit"
  network     = google_compute_network.host_sharedvpc.name
  priority    = 1000
  direction   = "INGRESS"
  project     = google_project.host_project.name
  # https://www.support.softbankmobile.co.jp/partner/home_tech1/index.cfm
  # 2021.03.20 時点
  source_ranges = [
    "123.108.237.128/28",
  #...(省略)...
  ]
  target_service_accounts = [
    google_service_account.service1_public_account.email,
  ]

  allow {
    protocol = "tcp"
    ports    = ["22"]
  }

  depends_on = [
    google_compute_network.host_sharedvpc,
    google_project_service.host_api_enable,
    google_service_account.service1_public_account,
    google_service_account.service1_private_account,
  ]
}

8. DNS配置(仅限Google访问)(dns.tf)

为限定公开的Google访问设置DNS。
设置内容基本上遵循文档。
另外(文档中还有额外说明),也同时进行了对gcr.io的配置。
此外,由于cloudbillingAPI不支持限制访问,所以进行了私有访问的设置。

# cloudbilling へのアクセスがrestricted に未対応のため
resource "google_dns_record_set" "googleapis_cname2" {
  name         = "cloudbilling.googleapis.com."
  managed_zone = google_dns_managed_zone.googleapis.name
  type         = "CNAME"
  ttl          = 300
  rrdatas      = ["private.googleapis.com."]
  project      = google_project.host_project.name
  depends_on = [
    google_dns_managed_zone.googleapis,
    google_dns_record_set.googleapis_cname,
  ]
}

9. 创建HA VPN(vpn.tf)。

使用几乎与下面描述相同的结构和参数创建(详细请参见下面)。

输出:通过反映HA VPN的全球IP等信息,我们使EdgeRouter配置示例与在上述qiita上所写的相同。

根据环境的不同,更新变量时请使用以下内容。

variable "vpn" {
  type = object({
    peer_global_ip_address  = string
    peer_private_ip_address = string
    shared_secret           = string
    peer_asn                = number
    asn                     = number
  })
  default = {
    peer_global_ip_address  = "自宅ラボ側グローバルIP"
    peer_private_ip_address = "自宅ラボ側ルータ プライベートIP"
    shared_secret           = "シークレット(右コメントで生成)" # openssl rand -base64 24
    peer_asn                = 65001
    asn                     = 65101
  }
}

10. 互联网 NAT 设置(cloudnat.tf)

设置了CloudNAT,使私有IP实例能够与互联网进行通信。

11. 创建 VPC 服务控制 (vpc_service_controls.tf)

我已经总结了有关VPC服务控制的内容。

作为试验,我们将storage.googleapis.com托管的服务项目保护在边界之内。

resource "google_access_context_manager_access_policy" "access-policy" {
  parent = "organizations/${var.gcp_common.org_id}"
  title  = "my policy"

  depends_on = [
    google_organization_iam_binding.organization_org_admin,
  ]
}

resource "google_access_context_manager_service_perimeters" "service-perimeter" {
  parent = "accessPolicies/${google_access_context_manager_access_policy.access-policy.name}"

  service_perimeters {
    name           = "accessPolicies/${google_access_context_manager_access_policy.access-policy.name}/servicePerimeters/Perimeter1"
    title          = "Service Production Perimeter1"
    perimeter_type = "PERIMETER_TYPE_REGULAR"
    status {
      restricted_services = ["storage.googleapis.com"]
      resources = [
        "projects/${google_project.host_project.number}",
        "projects/${google_project.service1.number}",
      ]
    }
  }
}

本次准备的代码说明到此为止。

如果环境是开发环境,则使用以下命令执行。

terraform workspace new dev
terraform apply

最后

可以使用Terraform将以前手动进行的GCP构建转化为基础设施即代码(IaC)。
※由于时间不足,中途记录有些凌乱,稍后想要整理一下…

由于Terraform 的文档整理得很好,且提供了易于理解的示例,所以基本上只需阅读文档就能大致了解如何使用。
(文档提供者 google 的部分:https://registry.terraform.io/providers/hashicorp/google/latest/docs)

如果了解Terraform的初学者,希望可以了解良好的编写方法和良好的目录结构,然后进行修正。

由于Google Cloud提供了Terraform模块,我希望考虑利用它们。[Google Cloud的Terraform模块链接:https://github.com/terraform-google-modules] [在Terraform官方网站也有介绍:https://registry.terraform.io/providers/hashicorp/google/latest]

下面分享我个人在实施过程中遇到的困难点。

让您烦恼的实践建议

IAM状态的反映

スクリーンショット 2021-02-22 22.27.03.png

在 Terraform 中设置角色的配置是为了保持具有角色权限的用户的记录状态,如果存在未记录的现有用户配置,则会将其删除。
因此,例如,在 Terraform 中设置组织管理员后,执行 terraform destroy 不会将配置恢复为默认状态,而是删除角色所属用户的配置,这需要注意。
虽然在修改现有角色时需要注意,但新建的角色也会默认创建,第二次修改时只需修改记录的内容,因此仍然需要注意。

项目API

尝试在另一个 Terraform 中创建项目google_project和设置APIgoogle_project_service时,发现仅有google_project时,项目的API处于零状态,导致无法通过terraform启用google_project_service所需的API的状态。
必须在同一个Terraform中执行google_project和google_project_service。

请参考

使用Terraform创建Google Cloud项目
https://cloud.google.com/community/tutorials/managing-gcp-projects-with-terraform

身份和访问管理 > 文档 > 概述 > 资源层级
https://cloud.google.com/iam/docs/overview?hl=ja#resource-hierarchy

企业组织的最佳实践
https://cloud.google.com/docs/enterprise/best-practices-for-enterprise-organizations

广告
将在 10 秒后关闭
bannerAds