使用Terraform为Google Cloud SQL PostgreSQL数据库创建架构

5

我是 Terraform 新手,想要为在 Google Cloud SQL 上创建的 PostgreSQL 9.6 实例中创建一个 postgres 数据库模式。

我在 main.tf 中有如下代码以创建 PostgreSQL 实例:

resource "google_sql_database_instance" "my-database" {
  name = "my-${var.deployment_name}"
  database_version = "POSTGRES_9_6"
  region = "${var.deployment_region}"

  settings {
      tier = "db-f1-micro"
      ip_configuration {
          ipv4_enabled = true
      }
  }
}

我尝试创建一个像这样的PostgreSQL对象:

provider "postgresql" {
  host            = "${google_sql_database_instance.my-database.ip_address}"
  username        = "postgres"
}

最终创建模式:

resource "postgresql_schema" "my_schema" {
  name  = "my_schema"
  owner = "postgres"
}

然而,这些配置无法正常工作。当我运行terraform plan时出现以下情况:

Inappropriate value for attribute "host": string required.

如果我删除了Postgres对象:

Error: Error initializing PostgreSQL client: error detecting capabilities: error PostgreSQL version: dial tcp :5432: connect: connection refused

此外,我想为默认创建的名为postgres的用户添加密码,该用户是在创建PostgreSQL实例时自动创建的。 编辑:使用的版本
Terraform v0.12.10
+ provider.google v2.17.0
+ provider.postgresql v1.2.0

有什么建议吗?


你能添加使用的Terraform和提供程序版本吗? - Andy Shinn
添加在问题上。 - gr7
2个回答

5

您上面的terraform设置存在一些问题。

  1. 您的实例没有定义任何授权网络。您应该将实例资源更改为以下内容:(注意:我只是用0.0.0.0/0进行测试)
    resource "google_sql_database_instance" "my-database" {
      name = "my-${var.deployment_name}"
      database_version = "POSTGRES_9_6"
      region = "${var.deployment_region}"

      settings {
          tier = "db-f1-micro"
          ip_configuration {
            ipv4_enabled = true
            authorized_networks {
              name = "all"
              value = "0.0.0.0/0"
            }
          }
      }
      depends_on = [
        "google_project_services.vpc"
      ]
    }

此处所述,您需要创建一个账户并设置强密码。
resource "google_sql_user" "user" {
  name     = "test_user"
  instance = "${google_sql_database_instance.my-database.name}"
  password = "VeryStrongPassword"

  depends_on = [
    "google_sql_database_instance.my-database"
  ]
}
  1. 您应该使用实例的 "public_ip_address" 或 "ip_address.0.ip_address" 属性来访问 IP 地址。还要更新您的提供程序和模式资源,以反映上面创建的用户。
provider "postgresql" {
  host            = "${google_sql_database_instance.my-database.public_ip_address}"
  username        = "${google_sql_user.user.name}"
  password        = "${google_sql_user.user.password}"
}

resource "postgresql_schema" "my_schema" {
  name  = "my_schema"
  owner = "test_user"
}

您的postgresql提供程序依赖于google_sql_database_instance资源先完成才能设置提供程序:
所有提供程序都在计划/应用程序开始时初始化,因此如果其中一个配置无效(在这种情况下为空主机),Terraform将失败。 无法在另一个提供程序中定义提供程序和资源之间的依赖关系。 但是,可以通过使用目标参数来解决问题 terraform apply -target=google_sql_user.user 这将创建数据库用户(以及它的所有依赖项——在这种情况下是数据库实例),一旦完成后,就会跟随它: terraform apply 这样做应该会成功,因为实例已经被创建,ip_address可供postgresql提供程序使用。
最后注意:不建议在生产实例中使用公共ip地址而不是SSL连接到Cloud SQL实例。

谢谢。它起作用了,但我采取了不同的方法。我创建了一个数据库和用户,然后在用户创建后运行psql命令连接到数据库并创建模式。我也会发布我的答案。 - gr7

1
这是我的解决方案,这样我只需要运行:terraform apply
// POSTGRESQL INSTANCE
resource "google_sql_database_instance" "my-database" {
  database_version = "POSTGRES_9_6"
  region = var.deployment_region

  settings {
      tier = var.db_machine_type
      ip_configuration {
          ipv4_enabled = true
          authorized_networks {
              name = "my_ip"
              value = var.db_allowed_networks.my_network_ip
          }
      }
  }
}

// DATABASE USER
resource "google_sql_user" "user" {
  name     = var.db_credentials.db_user
  instance = google_sql_database_instance.my-database.name
  password = var.db_credentials.db_password
  depends_on = [
    "google_sql_database_instance.my-database"
  ]

  provisioner "local-exec" {
    command = "psql postgresql://${google_sql_user.user.name}:${google_sql_user.user.password}@${google_sql_database_instance.my-database.public_ip_address}/postgres -c \"CREATE SCHEMA myschema;\""
  }
}

local-exec 很好用,但请记住,terraform 不会知道你创建的 postgresql 模式。这取决于你如何使用它以及你计划在 terraform 中做什么,但我只是想提醒一下。如果由于任何原因模式被删除但用户仍然存在,则 terraform 将认为一切都很好,并且不会在“terraform apply”上重新创建它。 - Amina Mansour
是的,我在实现过程中已经学到了。感谢您提供的信息。对于我要实现的内容,这没有问题。但我会将其记在心中,以备将来之需。 - gr7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接