使用 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),直接在组织中构建管理项目。
关于项目名称,请参考企业级指南中的项目名称,并添加您自己的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
根据文件分类、解释和记录每个文件的结构和内容
建立
我们按照下面的顺序进行实施。
-
- 前期准备 / 域名获取·CloudIdentity启用(手动)
-
- 创建terraform管理项目(prestage/)
-
- 组织设置(organaization.tf)
-
- 创建主机项目(host.tf)
-
- 创建服务项目(service1.tf)
-
- 创建子网(subnet.tf)
-
- 设置防火墙(firewall.tf)
-
- 设置DNS(限定公开Google访问)(dns.tf)
-
- 创建HA VPN(vpn.tf)
-
- 设置面向互联网的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
在工作环境中,事先安装 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)
在这里,我们可以进行整体设置、给予用户组权限,还可以创建第一层文件夹。
由于以前的组织和共享VPC的手动创建中,没有进行以下管理用户组、组织策略和文件夹管理,因此在这里记录下其内容。
管理用户组
管理的群組參考企業專用指南
由於我只需要自己創建並進行測試,因此此次只需選取部分並在兩個群組中進行設置(服務專案將在另一個群組中創建)
CloudIdentity 的設定並未納入此次的 Terraform 對象,因此需要事先創建群組。
由于需要对Terraform服务账户进行相同的操作,因此需要授予相同的权限。
此外,我们也给予了组织和文件夹的浏览权限于整个域中(包括文件夹架构,使得域用户都可以看到)。
组织政策
以前的時候並未設定,然而在創建服務專案等等時,為了不預設創建除了共享 VPC 以外的網路,設定一個不在項目創建時預設創建網路的策略。
启用compute.skipDefaultNetworkCreation(以下是在Web控制台上查看的相关策略)。
文件夹
在中文中,为负责主机项目的部门创建一个名为”基础设施”的文件夹,为负责服务项目的部门创建一个名为”服务”的文件夹。
组织。
变量使用以下内容
* 为了方便后续添加,将类型设置为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
本次代码中包含了以下两个防火墙规则,用以执行防火墙配置。
ここでは例として、外部テザリング環境などでログインする際にソフトバンク携帯のアドレスとして公開されているサイト iphone/ipadはこちらでした(追記) から抜粋したアドレスを許可している許可するグローバルアドレスリスト(参照) iphone/ipadはこちらでした(追記)サービス1プロジェクト向け Public サービスアカウント
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状态的反映
在 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