注意:

使用 Terraform 使用 PostgreSQL 服务部署 OCI 托管数据库

简介

PostgreSQL 是一个广受赞誉的开源对象关系数据库,由于其强大的架构和坚定不移的数据完整性,因此具有突出的地位,使其成为企业景观中的首选。它在 Oracle Cloud Infrastructure (OCI) 上的可用性引入了完全托管的高性能数据库服务,具有智能大小、经济高效的优化和持久性。PostgreSQL 支持企业、中小型企业 (SMB) 和各种开发环境,展示了其适应性和稳健性。

在本教程中,我们将了解如何在 OCI 云租户中部署 OCI 托管 PostgreSQL 数据库系统的三个节点,并使用 Terraform 脚本通过计算实例进行专用连接。

目标

:如果所选区域具有单个可用性域,创建高可用性数据库系统将在该区域中的所有故障域中分布所有 PostgreSQL 实例,无论它们是特定于 AD 的子网还是区域子网。

先决条件

任务 1:在文件夹中创建 Terraform 脚本文件

  1. 创建 providers.tf 脚本。

    让我们从创建 providers.tf 文件开始。创建本地文件夹并在创建的文件中复制以下代码。tenancy_id、user_id、region 等的值将在 variables.tf 文件中替换,我们将在后面的步骤中创建该文件。要获取 OCI 配置值,请通过访问用户设置在 OCI 中生成 API 密钥,创建 API 密钥对,安全下载私有密钥,然后将其与 Terraform 代码中的用户和租户 OCID 一起使用,以进行身份验证以部署 OCI 资源。有关详细信息,请参阅生成 API 签名密钥

    terraform {
        required_providers {
        oci =  {
            source = "oracle/oci"
            version = "5.22.0"
        }
      }
    }
    # Provider configuration for Tenancy
    provider "oci" {
    tenancy_ocid          = var.tenancy_id
    user_ocid             = var.user_id
    fingerprint           = var.api_fingerprint
    private_key_path      = var.api_private_key_path
    region                = var.region
    }
    
    
  2. 创建 vcn.tf 脚本。

    我们需要具有专用子网和公共子网的 VCN 网络来部署和访问 OCI PostgreSQL 数据库系统,并记住 PostgreSQL 数据库将仅部署在专用子网上。使用以下代码创建名为 vcn.tf 的文件。该代码将确保只有 VCN CIDR 才能访问 PostgreSQL 的端口 5432,并且允许通过安全列表中的端口 22 上的 SSH 访问计算实例。无需担心在此处替换值,您可以在 variables.tf 文件中执行此操作。

    resource oci_core_vcn psql_vcn_tf {
        #Required
        compartment_id = var.compartment_id
    
        #Optional
        cidr_block = var.vcn_cidr_block
        display_name = var.vcn_display_name
    }
    
    resource oci_core_subnet public_subnet {
        #Required
        cidr_block = var.public_subnet_cidr_block
        compartment_id = var.compartment_id
        vcn_id = oci_core_vcn.psql_vcn_tf.id
    
        #Optional
        display_name = var.public_subnet_display_name
        route_table_id = oci_core_route_table.tf_public_route_table.id
    }
    
    resource oci_core_subnet private_subnet {
        #Required
        cidr_block = var.private_subnet_cidr_block
        compartment_id = var.compartment_id
        vcn_id = oci_core_vcn.psql_vcn_tf.id
    
        display_name = var.private_subnet_display_name
        route_table_id = oci_core_route_table.tf_private_route_table.id
        prohibit_internet_ingress = true
        security_list_ids = [oci_core_security_list.tf_private_security_list.id]
    }
    
    resource oci_core_internet_gateway vcntf_igw {
      vcn_id       = oci_core_vcn.psql_vcn_tf.id
      compartment_id = var.compartment_id
      display_name = var.internet_gateway_name
    }
    
    resource oci_core_nat_gateway tf_nat_gateway {
      vcn_id       = oci_core_vcn.psql_vcn_tf.id
      compartment_id = var.compartment_id
      display_name = example-ngw
      # Add route tables to direct traffic through this NAT gateway
    }
    
    data oci_core_services test_services {
    }
    
    variable create_service_gateway {
      description = whether to create a service gateway. If set to true, creates a service gateway.
      default     = true
      type        = bool
    }
    
    data oci_core_services all_oci_services {
      filter {
        name   = name
        values = [All .* Services In Oracle Services Network]
        regex  = true
      }
      count = var.create_service_gateway == true ? 1 : 0
    }
    
    resource oci_core_service_gateway service_gateway {
      compartment_id = var.compartment_id
      display_name   = var.service_gateway_displayname
      services {
        service_id = lookup(data.oci_core_services.all_oci_services[0].services[0], id)
      }
      vcn_id = oci_core_vcn.psql_vcn_tf.id
      count = var.create_service_gateway == true ? 1 : 0
    }
    
    resource oci_core_security_list tf_public_security_list {
      vcn_id         = oci_core_vcn.psql_vcn_tf.id
      compartment_id = var.compartment_id
      display_name   = var.public_subnet_security_list_display_name
    
      ingress_security_rules {
        protocol    = 6  # TCP protocol for SSH
        source      = 0.0.0.0/0  # Allow inbound traffic from all sources
        tcp_options {
                #Optional
                max = 22
                min = 22
            }
        description = Allow SSH from all sources
      }
    }
    
    resource oci_core_security_list tf_private_security_list {
      vcn_id         = oci_core_vcn.psql_vcn_tf.id
      compartment_id = var.compartment_id
      display_name   = var.private_subnet_security_list_disply_name
    
      ingress_security_rules {
        protocol    = 6  # TCP protocol to connect Postgress service from compute instance in public subnet
        source      = oci_core_vcn.psql_vcn_tf.cidr_block  # Allow inbound traffic from CIDR Block of VCN sources
        tcp_options {
                #Optional
                max = 5432
                min = 5432
            }
        description = Allow psql service connections from all ranges cidr vcn
      }
    }
    
    resource oci_core_route_table tf_public_route_table {
      vcn_id     = oci_core_vcn.psql_vcn_tf.id
      compartment_id = var.compartment_id
      display_name = var.public_subnet_route_table_display_name
      route_rules {
        // Define route rules for public subnet
        network_entity_id = oci_core_internet_gateway.vcntf_igw.id
        destination = 0.0.0.0/0
        destination_type = CIDR_BLOCK
      }
    }
    
    resource oci_core_route_table tf_private_route_table {
      vcn_id     = oci_core_vcn.psql_vcn_tf.id
      compartment_id = var.compartment_id
      display_name = var.private_subnet_route_table_display_name
      route_rules {
        // Define route rules for private subnet
        network_entity_id = oci_core_nat_gateway.tf_nat_gateway.id
        destination = 0.0.0.0/0
        destination_type = CIDR_BLOCK
      }
      route_rules {
        network_entity_id = oci_core_service_gateway.service_gateway.0.id
        destination = all-iad-services-in-oracle-services-network
        destination_type  = SERVICE_CIDR_BLOCK
      }
      }
    
    resource oci_core_route_table_attachment public_route_table_attachment {
      #Required
      subnet_id = oci_core_subnet.public_subnet.id
      route_table_id =oci_core_route_table.tf_public_route_table.id
    }
    
    resource oci_core_route_table_attachment private_route_table_attachment {
      #Required
      subnet_id = oci_core_subnet.private_subnet.id
      route_table_id =oci_core_route_table.tf_private_route_table.id
      depends_on = [oci_core_service_gateway.service_gateway]
    }
    
  3. 创建 instance.tf 脚本。

    要访问 PostgreSQL 数据库,我们需要公共子网中的计算实例。我们将连接到实例,然后访问 PostgreSQL,因为它只能通过专用子网进行访问。为此,请使用以下代码创建一个名为 instance.tf 的文件。以后可以在 variables.tf 文件中轻松更新计算变量值。

    
    # Resources
    data "oci_identity_availability_domains" "ads" {
      compartment_id = var.compartment_id
    }
    
    resource "oci_core_instance" "tf_compute" {
      # Required
      availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
      compartment_id      = var.compartment_id
      shape               = var.compute_shape
      source_details {
        source_id         = var.source_operating_system_image_id
        source_type       = "image"
      }
      display_name        = var.compute_instance_display_name
      shape_config {
        ocpus         = var.compute_cpus
        memory_in_gbs = var.compute_memory_in_gbs
      }
      create_vnic_details {
        subnet_id = oci_core_subnet.public_subnet.id
        assign_public_ip  = true
      }
      metadata = {
        ssh_authorized_keys = file(var.compute_ssh_authorized_keys)
      }
      preserve_boot_volume = false
      provisioner "remote-exec" {
        inline = [
          "sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm",
          "sudo dnf -qy module disable postgresql",
          "sudo dnf install -y postgresql16-server",
          "sudo /usr/pgsql-16/bin/postgresql-16-setup initdb",
          "sudo systemctl enable postgresql-16",
          "sudo systemctl start postgresql-16"
        ]
        connection {
          type        = "ssh"
          host        = self.public_ip
          user        = "opc"
          private_key = file(var.api_private_key_for_ssh)
        }
      }
    
    }
    
    # Outputs
    output "compute_id" {
      value = oci_core_instance.tf_compute.id
    }
    
    output "compute_state" {
      value = oci_core_instance.tf_compute.state
    }
    
    output "compute_public_ip" {
      value = oci_core_instance.tf_compute.public_ip
    }
    
    
    
  4. 创建 postgresql.tf 脚本。

    让我们通过将 Terraform 代码添加到名为 postgresql.tf 的文件中来设置 OCI PostgreSQL 数据库系统。此代码详细介绍了系统的配置,包括配置、核心和节点。对于优化的设置,请考虑三节点数据库系统:一个主节点和两个跨不同可用性区域的副本。首先创建 postgresql.tf 文件并插入提供的代码。可以轻松地在 variables.tf 文件中添加 PostgreSQL 数据库的变量值以满足特定要求。

    resource "oci_psql_db_system" "test_db_system" {
        #Required
        compartment_id = var.compartment_id
        db_version = var.db_system_db_version
        display_name = var.db_system_display_name
        network_details {
            #Required
            subnet_id = oci_core_subnet.private_subnet.id
        }
        shape = var.db_system_shape
        storage_details {
            #Required
            is_regionally_durable = var.db_system_storage_details_is_regionally_durable
            system_type = var.db_system_storage_details_system_type
            #Optional
            # availability_domain = var.db_system_storage_details_availability_domain
            # iops = var.db_system_storage_details_iops
        }
        credentials {
            #Required
            password_details {
                #Required
                password_type = var.db_system_credentials_password_details_password_type
                #Optional
                password = var.db_system_credentials_password_details_password
            }
            username = var.db_system_credentials_username
        }
        instance_count = var.db_system_instance_count
        instance_memory_size_in_gbs = var.db_system_instance_memory_size_in_gbs
        instance_ocpu_count = var.db_system_instance_ocpu_count
    
    }
    
    
    
  5. 创建 variables.tf 脚本。

    在此部分中,用户需要调整和更新要在 OCI 租户中创建的资源的值。创建 variables.tf 文件并添加以下代码。请记住,这是要在同一文件夹中创建的最后一个文件。根据您的要求仔细查看和修改每个变量。某些值将在每个代码的“值”部分中预先填充,而其他值则需要您输入。在文件中添加或修改了所有值后,继续执行阶段。

    
    # Provider identity parameters - Replace these values from API Key Values from OCI User
    
    variable "api_fingerprint" {
      description = "Fingerprint of OCI API private key for Requestor Tenancy"
      type        = string
      default     = ""
    }
    
    variable "api_private_key_path" {
      description = "Path to OCI API private key used for Requestor Tenancy"
      type        = string
      default     = ""
    }
    
    variable "tenancy_id" {
      description = "Tenancy ID where to create resources for Requestor Tenancy"
      type        = string
      default     = ""
    }
    
    variable "user_id" {
      description = "User ID that Terraform will use to create resources for Requestor Tenancy"
      type        = string
      default     = ""
    }
    
    variable "region" {
      description = "OCI region where resources will be created for Requestor Tenancy"
      type        = string
      default     = "us-ashburn-1"  # example value
      # check this document, if you want to use different region - https://docs.oracle.com/en-us/iaas/Content/General/Concepts/regions.htm#About
    }
    
    
    # compartment OCID - Replace these values
    
    variable "compartment_id" {
      description = "Compartment ID where to create resources for Requestor Tenancy"
      type        = string
      default     = ""
    }
    
    variable "db_system_db_version" {
      description = "Version"
      type = number
      default = 14
    }
    
    variable "db_system_display_name" {
      description = "postgress db service name"
      type = string
      default = "psqlfromterraform" # example value
    }
    
    
    variable "db_system_shape" {
        description = "shape"
        type = string
        default = "PostgreSQL.VM.Standard.E4.Flex.4.64GB"  # example value
        #change the shape value as per your requirements
    }
    
    variable "db_system_instance_count" {
      description = "instance count"
      type = number
      default = 3  # example value
    }
    
    variable "db_system_instance_memory_size_in_gbs" {
      description = "RAM"
      type = number
      default = 64  # example value
    }
    
    variable "db_system_instance_ocpu_count" {
      description = "OCPU count"
      type = number
      default = 4  # example value
    }
    
    variable "db_system_storage_details_is_regionally_durable" {
      description = "regional"
      type = bool
      default = true
    }
    variable "db_system_credentials_password_details_password_type" {
        description = "type"
        type = string
        default = "PLAIN_TEXT"
    
    }
    
    variable "db_system_credentials_password_details_password" {
      description = "password"
      type = string
      default = ""
    }
    
    variable "db_system_credentials_username" {
      description = "username"
      type = string
      default = "admin" # example value
    }
    
    variable "db_system_storage_details_system_type" {
      description = "type"
      type = string
      default = "OCI_OPTIMIZED_STORAGE"
    }
    
    
    
    # OCI VCN parameters - psql instance deployed on this
    
    variable "vcn_cidr_block" {
      description = "vcn cidr"
      type = string
      default = "172.16.0.0/16" # example value
    }
    
    variable "vcn_display_name" {
      description = "vcn name"
      type = string
      default = "vcn-from-tf-psql" # example value
    }
    
    variable "public_subnet_cidr_block" {
        description = "subnet cidr range"
        type = string
        default = "172.16.1.0/24" # example value
    }
    
    variable "private_subnet_cidr_block" {
        description = "subnet cidr range"
        type = string
        default = "172.16.2.0/24" # example value
    }
    
    variable "public_subnet_display_name" {
      description = "public subnet name"
      type = string
      default = "public-subnet" # example value
    
    }
    
    variable "private_subnet_display_name" {
      description = "public subnet name"
      type = string
      default = "private-subnet" # example value
    
    }
    
    variable "internet_gateway_name" {
      description = "internet gateway name"
      type = string
      default = "internetgateway" # example value
    }
    
    variable "service_gateway_displayname" {
      description = "Service Gateway Display Name"
      type = string
      default = "servicegateway" # example value
    }
    
    variable "public_subnet_security_list_display_name" {
      description = "Public Subnet Security List Display Name"
      type = string
      default = "public_subnet_security_list" # example value
    }
    
    variable "private_subnet_security_list_display_name" {
      description = "Public Subnet Security List Display Name"
      type = string
      default = "public_subnet_security_list" # example value
    }
    
    variable "public_subnet_route_table_display_name" {
      description = "Public Subnet Route table Display Name"
      type = string
      default = "public_subnet_route_table" # example value
    }
    
    variable "private_subnet_route_table_display_name" {
      description = "Public Subnet Route table Display Name"
      type = string
      default = "private_subnet_route_table" # example value
    }
    
    
    # OCI Compute Instance parameters - We will use this instance to connect postgreSQL db instance
    
    variable "compute_shape" {
      type    = string
      default = "VM.Standard.E4.Flex" # example value
    }
    
    variable "compute_cpus" {
      type    = string
      default = "1" # example value
    }
    
    variable "compute_memory_in_gbs" {
      type    = string
      default = "1" # example value
    }
    
    variable "compute_ssh_authorized_keys" {
      type = string
      default = ""
    }
    
    variable "api_private_key_for_ssh" {
      type = string
      default = ""
    }
    
    variable "source_operating_system_image_id" {
      description = "Oracle Linux 8 image ocid"
      type = string
      default = "ocid1.image.oc1.iad.aaaaaaaaszr5wpipg6qskiol3fhbitm56qdmumpbcpv6irzxuofi2nfmlhma" # example value
      # if you change the region , then change the default value from the region you have selected from this document -https://docs.oracle.com/en-us/iaas/images/image/998f1273-d4fd-4e16-8673-dd2517ddd724/
    }
    
    variable "compute_instance_display_name" {
      description = "display name of the compute name"
      type = string
      default = ""
    }
    
    

    创建所需文件并使用必要值调整 variables.tf 文件后,文件夹结构将反映以下屏幕截图中显示的设置。

    tf 文件夹

任务 2:执行 Terraform 脚本

使用终端或命令提示符,运行以下命令以初始化 Terraform,并在 OCI 租户中创建资源。这些命令将初始化 Terraform,并在您的 OCI 租户中部署指定的资源。

terraform init

terraform plan

terraform apply

postgreSQLdb_oci_console

任务 3:连接到 OCI PostgreSQL 数据库

完成后,导航到 OCI 控制台以查找 OCI PostgreSQL 和预加载了 psql 客户端的计算实例。使用公共 IP 通过 SSH 访问计算实例,然后执行提供的命令与 OCI PostgreSQL 数据库系统建立连接(SSH 端口 22 和数据库端口 5432 都通过 vcn.tf 脚本自动创建;端口管理不需要任何操作)。更新可从 OCI PostgreSQL 数据库控制台获取的专用端点 IP,以及您在 variable.tf 文件中指定的用户名和密码。执行该命令后,将提示输入口令进行连接。

psql --version
psql -h endpoint_ip -U admin_username -d postgres

执行以上命令后,用户应能够看到与托管 PostgreSQL 数据库建立的连接。

psqldb_access_from_instance

用户成功部署了 OCI 托管 PostgreSQL 数据库的三个节点,并使用计算实例私下连接它们。

确认

更多学习资源

浏览 docs.oracle.com/learn 上的其他实验室,或者通过 Oracle Learning YouTube 频道访问更多免费学习内容。此外,请访问 education.oracle.com/learning-explorer 以成为 Oracle Learning Explorer。

有关产品文档,请访问 Oracle 帮助中心