附註:

開始使用 Oracle Cloud Infrastructure 中的 Terraform

簡介

Terraform 是由 Hashicorp 開發的基礎架構即程式碼 (IaC) 工具,可讓您使用 Terraform 語言語法 HCL,跨多個雲端提供者定義、佈建及管理基礎架構。Terraform 可讓您將雲端基礎架構的整個生命週期自動化,讓您以一致且可重現的方式輕鬆建置、更新及調整資源規模。DevOps 團隊廣泛使用 Terraform 來管理雲端資源、提升基礎架構效率、減少手動錯誤及版本控制雲端資源。

本教學課程可協助您開始使用 IaC 來部署及管理雲端基礎架構。

Terraform 架構工作流程

Terraform 架構工作流程

目標

必要條件

工作 1:宣告提供者

Terraform 提供者是指負責瞭解特定類型的基礎架構或服務並與之互動的外掛程式。提供者是 Terraform 與您要管理之服務或平台的 API 之間的橋接器。供應商可讓 Terraform 有效地與雲端平台進行通訊及互動。換句話說,Terraform 提供者就像是協助 Terraform 與不同的雲端服務或系統交談的翻譯人員,允許它建立、管理及刪除虛擬機器、資料庫及網路等資源。

每個提供者通常對應特定的雲端平台 (例如 OCI、AWS、Azure、GCP) 或基礎架構服務 (例如 Kubernetes、Docker)。

  1. 建立名為 terraform-beginners-demo 的資料夾,然後在 VS Code 中開啟。

  2. 在 VS Code 中安裝 HashiCorp Terraform 副檔名。

  3. terraform-beginners-demo 資料夾底下建立 provider.tfvariables.tf 檔案。

  4. 複製 provider.tf 檔案中的下列程式碼。

    terraform {
      required_providers {
        oci = {
          source = "oracle/oci"
          version = "5.30.0"
        }
      }
    }
    
    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
    }
    

    備註:我們已使用官方「Terraform 登錄」頁面的代碼。如需詳細資訊,請參閱 Oracle Cloud Infrastructure 提供者最新版本 (5.30.0)

工作 2:建立 OCI 組態

我們需要 OCI 使用者 Oracle Cloud Identifier (OCID)、租用戶 OCID、區間 OCID 才能設定提供者。

  1. 登入 OCI 主控台

  2. 按一下使用者設定檔圖示,然後選取我的設定檔

  3. 若要取得 API 金鑰組,請依照下列步驟進行:

    1. 資源底下,選取 API 金鑰,然後按一下新增 API 金鑰

    2. 您可以產生新的 API 金鑰組,或使用現有的公鑰來產生 API 金鑰組。選取產生 API 金鑰組。請務必下載私密金鑰和公開金鑰。

    3. 按一下新增。將會顯示組態檔預覽方塊。

      建立 API 金鑰組

    4. 複製組態檔預覽中提供的明細,並將其儲存至某處。這將用於 variables.tf 檔案中。

      如下所示:

      [DEFAULT]
      user=ocid1.user.oc1..xxxxxxxxxxx
      fingerprint=xx:xx:xx:xx:xx
      tenancy=ocid1.tenancy.oc1..xxxxxxxxx
      region=us-phoenix-1 # your region ID
      key_file=<path to your private keyfile> # TODO
      
    5. 按一下關閉

    或者

    若要取得 API 金鑰組,請參閱在 OCI 主控台產生 API 金鑰組態

作業 3:使用 OCI 證明資料設定 Terraform 環境

  1. 移至「VS 程式碼」編輯器,然後在 terraform-beginners-demo 資料夾下建立一個名為 variables.tf 的新檔案,然後貼上下列程式碼。

    variable "api_fingerprint" {
      description = "Fingerprint of OCI API private key for Tenancy"
      type        = string
    }
    
    variable "api_private_key_path" {
      description = "Path to OCI API private key used for Tenancy"
      type        = string
    }
    
    variable "tenancy_id" {
      description = "Tenancy ID where to create resources for Tenancy"
      type        = string
    }
    
    variable "user_id" {
      description = "User ID that Terraform will use to create resources for Tenancy"
      type        = string
    }
    
    variable "region" {
      description = "OCI region where resources will be created for Tenancy"
      type        = string
    }
    
  2. 建立另一個名為 terraform.tfvars 的新檔案,並貼上下列程式碼。使用「工作 2.3」的組態檔值,從 variables.tf 定義每個變數。

    # Identity and access parameters
    api_fingerprint      = "REPLACE_BY_YOUR_FINGERPRINT" # Fingerprint of OCI API private key for Tenancy
    api_private_key_path = "~/.oci/oci_api_key.pem"      # Path to OCI API private key used for Tenancy
    region               = "us-phoenix-1"                # OCI region where resources will be created for Tenancy
    tenancy_id           = "REPLACE_YOUR_TENACY_OCID"    # Tenancy ID where to create resources
    user_id              = "REPLACE_BY_YOUR_USER_OCID"   # Path to OCI API private key used for Tenancy
    

    注意:在生產環境中,最好使用 terraform.tfvars 檔案來定義地形變數,以提升安全性和擴展性。如需詳細資訊,請參閱 Variable Definitions (.tfvars) Files

作業 4:測試您 OCI 租用戶的 Terraform 連線

  1. terraform-beginners-demo 資料夾下建立一個名為 data_source.tf 的新檔案,並複製下列程式碼。

    data "oci_identity_availability_domains" "ad" {
        #Required
        compartment_id = var.tenancy_id
    }
    
  2. terraform-beginners-demo 資料夾下建立名為 output.tf 的新檔案,並複製下列程式碼。

    output "list_ads" {
      value = data.oci_identity_availability_domains.ad.availability_domains
    }
    
  3. 在 VS Code 中開啟新的終端機並執行下列命令來執行 terraform 命令檔。

    Command 1: terraform init
    
    Command 2: terraform plan #to view your deployments what is going to be created
    
    Command 3: terraform apply #then type "yes" once prompted alternatively run "apply -auto-approve
    

    Terraform 執行工作流程

    您現在應該能夠在輸出下查看可用性網域清單和與其關聯的區間。

    OCI 可用性網域

    您現在已順利將系統設定為在 Terraform 內的 OCI 租用戶中部署資源。您已傳送變數,但尚未對您的租用戶進行任何變更。我們將逐步介紹一些範例,協助您更加瞭解使用 Terraform 新增、鏈結及銷毀資源的程序。

作業 5:( 範例 ) 使用 Terraform 部署 OCI Compute 執行處理

現在,我們將根據您在先前任務中建立的內容來部署網路和運算資源。

  1. 建立名為 networking.tf 的檔案並複製下列程式碼。

    resource "oci_core_vcn" "test_vcn" {
      count = (var.create_new_vcn) ? 1 : 0
    
      #Required
      compartment_id = var.compartment_id
    
    
      cidr_block   = var.vcn_cidr_block
      display_name = var.vcn_display_name
      dns_label    = var.vcn_dns_label
    }
    

    注意:如需其他組態的 core-vcn 變數詳細資訊,請參閱 oci_core_vcn

  2. 編輯您的 variables.tf 檔案並新增下列變數。

    #VCN specific variables
    variable "create_new_vcn" {
      description = "Boolean variable to specify whether to create a new VCN or to reuse an existing one."
      type        = bool
    }
    
    variable "compartment_id" {
      description = "OCI compartment where resources will be created"
      type        = string
    }
    
    variable "vcn_cidr_block" {
      description = "The list of IPv4 CIDR blocks the VCN will use"
      type        = string
    }
    
    variable "vcn_display_name" {
      description = "provide a descriptive name for the VCN - this is what you will see displayed in the OCI console"
      type        = string
    }
    
    variable "vcn_dns_label" {
      description = "provide a descriptive alphanumeric name for the DNS - this is what you will see displayed in the OCI console"
      type        = string
    }
    
    variable "vcn_id" {
      description = "provide your existing VCN OCID if create_new_vcn = false"
      type = string
    }
    
    variable "private_subnet_id" {
      description = "provide existing private subnet OCID"
      type = string
    }
    
    variable "public_subnet_id" {
      description = "provide existing public subnet OCID"
      type = string
    }
    
  3. terraform.tfvars 中新增變數,並根據您的租用戶組態定義每個變數。

    # VCN specific variables
    create_new_vcn = true # Set this to true if you want terraform to crearte the network for you, otherwise set it to false.
    compartment_id   = "REPLACE_BY_YOUR_COMPARTMENT_OCID" # add your own compartment id where the vcn will be created 
    vcn_cidr_block   = "10.0.0.0/16"                      # The list of IPv4 CIDR blocks the VCN will use
    vcn_display_name = "terraform_vcn_example"   # provide a descriptive name for the VCN - this is what you will see displayed in the OCI console
    vcn_dns_label    = "terraformvcn"                     # provide a descriptive alphanumeric name for the DNS - this is what you will see displayed in the OCI console
    
    # Configure CIDR Blocks, Subnet(Public, Private) OCIDS for an existing VCN. #
    vcn_id            = "REPLACE_BY_YOUR_VCN_OCID"             #ADD WITH YOUR VCN OCID
    private_subnet_id = "REPLACE_BY_YOUR__PRIVATE_SUBNET_OCID" #ADD WITH YOUR PRIVATE SUBNET
    public_subnet_id  = "REPLACE_BY_YOUR_PUBLIC_SUBNET__OCID"  #AA WITH YOUR PUBLIC SUBNET
    

    注意:如果您已經有現有的 VCN,請將 create_new_vcn 設為 false,然後修改 vcn_idprivate_subnet_idpublic_subnet_id 變數。

  4. 為您的新 VCN 建立子網路

    1. networking.tf 檔案中,新增下列程式碼以建立您的公用和專用子網路。

      resource "oci_core_subnet" "private_subnet" {
        count = (var.create_new_vcn) ? 1 : 0
      
        #Required
        cidr_block     = var.private_subnet_cidr_block
        compartment_id = var.compartment_id
        vcn_id         = oci_core_vcn.test_vcn.*.id[0]
      
        display_name               = var.private_subnet_display_name
        prohibit_public_ip_on_vnic = var.private_subnet_prohibit_public_ip_on_vnic
      }
      
      resource "oci_core_subnet" "public_subnet" {
        count = (var.create_new_vcn) ? 1 : 0
      
        #Required
        cidr_block     = var.public_subnet_cidr_block
        compartment_id = var.compartment_id
        vcn_id         = oci_core_vcn.test_vcn.*.id[0]
      
      
        display_name               = var.public_subnet_display_name
        prohibit_public_ip_on_vnic = var.public_subnet_prohibit_public_ip_on_vnic
        route_table_id             = oci_core_route_table.test_route_table.*.id[0]
      }
      

      注意:如需有關具有其他配置之核心子網路變數的詳細資訊,請參閱 oci_core_subnet

    2. 複製下列程式碼,將新的子網路變數新增至 variables.tf 檔案。

        #Private subnet variables
      variable "private_subnet_cidr_block" {
        description = "OCI private subnet CIDR block range"
        type        = string
      }
      
      
      variable "private_subnet_display_name" {
        description = "provide a descriptive name for the private subnet - this is what you will see displayed in the OCI console"
        type        = string
      }
      
      
      variable "private_subnet_prohibit_public_ip_on_vnic" {
        description = "Allow public IP address to the VNIC"
        type        = bool
      }
      
      
      #Public subnet variables
      variable "public_subnet_cidr_block" {
        description = "OCI public subnet CIDR block range"
        type        = string
      }
      
      
      variable "public_subnet_display_name" {
        description = "provide a descriptive name for the public subnet - this is what you will see displayed in the OCI console"
        type        = string
      }
      
      
      variable "public_subnet_prohibit_public_ip_on_vnic" {
        description = "Allow public IP address to the VNIC"
        type        = bool
      }
      
    3. terrform.tfvars 檔案中宣告新的子網路變數。

      #Private subnet variables
      private_subnet_cidr_block                 = "10.0.1.0/24"                               # OCI private subnet CIDR block range
      private_subnet_display_name               = "terraform_private_subnet_example" # provide a descriptive name for the private subnet - this is what you will see displayed in the OCI console
      private_subnet_prohibit_public_ip_on_vnic = false                                       # Allow public IP address to the VNIC
      
      #Public subnet variables
      public_subnet_cidr_block                 = "10.0.2.0/24"                              # OCI public subnet CIDR block range
      public_subnet_display_name               = "terraform_public_subnet_example" # provide a descriptive name for the public subnet - this is what you will see displayed in the OCI console
      public_subnet_prohibit_public_ip_on_vnic = false 
      
  5. networking.tf 檔案中新增下列程式碼以建立網際網路閘道。

    resource "oci_core_internet_gateway" "test_internet_gateway" {
      count = (var.create_new_vcn) ? 1 : 0
    
      #Required
      compartment_id = var.compartment_id
      display_name   = "INTERNET_GTWFOR_${var.vcn_display_name}"
      vcn_id         = oci_core_vcn.test_vcn.*.id[0]
      #route_table_id = oci_core_route_table.test_route_table.id
    }
    
  6. networking.tf 中為路由表新增下列程式碼,以管理通往網際網路的流量。

    resource "oci_core_route_table" "test_route_table" {
      count = (var.create_new_vcn) ? 1 : 0
    
      #Required
      compartment_id = var.compartment_id
      vcn_id         = oci_core_vcn.test_vcn.*.id[0]
    
    
      route_rules {
        #Required
        network_entity_id = oci_core_internet_gateway.test_internet_gateway.*.id[0]
    
    
        description      = "route rule internet access for ${var.vcn_display_name}"
        destination      = "0.0.0.0/0"
        destination_type = "CIDR_BLOCK"
      }
    }
    
  7. 建立與 VCN 關聯的網路安全群組 (NSG)。將下列代碼複製到 networking.tf 檔案。

    resource "oci_core_network_security_group" "test_nsg" {
      count = (var.create_new_vcn) ? 1 : 0
    
      #Required
      compartment_id = var.compartment_id
      vcn_id         = oci_core_vcn.test_vcn.*.id[0]
      display_name   = "NETWORK_SECURITY_GROUP_${var.vcn_display_name}"
      freeform_tags  = { "Lab" = "Terraofm 101 Guide" }
    }
    
  8. 我們現在將建立 2 個用於部署 Linux VM 和 Windows VM 的新檔案 compute_linux.tfcompute_windows.tf

  9. compute_linux.tf 中,複製下列程式碼以建立具有 Linux 作業系統的運算執行處理。

    resource "oci_core_instance" "test_linux_instance" {
      #Required
      count = var.create_linux_instance ? 1 : 0
    
      availability_domain = data.oci_identity_availability_domains.ad.availability_domains[0].name
      compartment_id      = var.compartment_id
    
    
      create_vnic_details {
        assign_public_ip       = "true"
        display_name           = var.instance_display_name
        nsg_ids                = []
        skip_source_dest_check = "false"
        subnet_id              = var.create_new_vcn ? oci_core_subnet.public_subnet.*.id[0] : var.public_subnet_id
      }
    
      display_name = "${var.instance_display_name}_linux"
    
      metadata = {
        ssh_authorized_keys = "${file(var.public_ssh_key)}"
      }
    
      shape = var.instance_shape
      shape_config {
    
        memory_in_gbs = var.instance_flex_memory_in_gbs
        ocpus         = var.instance_flex_ocpus
      }
    
      launch_options {
        boot_volume_type                    = "PARAVIRTUALIZED"
        firmware                            = "UEFI_64"
        is_consistent_volume_naming_enabled = "true"
        is_pv_encryption_in_transit_enabled = "true"
        network_type                        = "PARAVIRTUALIZED"
        remote_data_volume_type             = "PARAVIRTUALIZED"
    
      }
    
      source_details {
        #Required
        source_id   = var.linux_image_ocid
        source_type = "image"
    
      }
      preserve_boot_volume = false
    }
    
  10. compute_windows.tf 中,複製下列程式碼。

    resource "oci_core_instance" "test_windows_instance" {
      #Required
      count = var.create_windows_instance ? 1 : 0
    
    
      availability_domain = data.oci_identity_availability_domains.ad.availability_domains[0].name
      compartment_id      = var.compartment_id
    
    
    
      create_vnic_details {
        assign_public_ip       = "true"
        display_name           = var.instance_display_name
        nsg_ids                = []
        skip_source_dest_check = "false"
        subnet_id              = var.create_new_vcn ? oci_core_subnet.public_subnet.*.id[0] : var.public_subnet_id
    
    
      }
    
      display_name = "${var.instance_display_name}_windows"
    
      metadata = {
      }
    
      shape = var.instance_shape
      shape_config {
    
        memory_in_gbs = var.instance_flex_memory_in_gbs
        ocpus         = var.instance_flex_ocpus
      }
    
      launch_options {
        boot_volume_type                    = "PARAVIRTUALIZED"
        firmware                            = "UEFI_64"
        is_pv_encryption_in_transit_enabled = "true"
        network_type                        = "PARAVIRTUALIZED"
        remote_data_volume_type             = "PARAVIRTUALIZED"
    
      }
    
      source_details {
        #Required
        source_id   = var.windows_image_ocid
        source_type = "image"
    
      }
      preserve_boot_volume = false
    }
    
  11. 使用 compute_linuxcompute_windows 中的新變數更新 variables.tf

    #Compute variables
    variable "instance_shape" {
      description = "value"
      type        = string
    }
    
    
    variable "instance_flex_memory_in_gbs" {
      description = "(Updatable) The total amount of memory available to the instance, in gigabytes."
      type        = number
    }
    
    
    variable "instance_flex_ocpus" {
      description = "(Updatable) The total number of OCPUs available to the instance."
      type        = number
    }
    
    
    variable "instance_create_vnic_details_assign_public_ip" {
      description = "To allow compute connectivity from internet"
      type        = bool
    }
    
    
    variable "instance_display_name" {
      description = "provide a descriptive name for the compute instance - this is what you will see displayed in the OCI console"
      type        = string
    }
    
    
    variable "public_ssh_key" {
      description = "Add your public ssh key - for provisioning your compute instance"
      type        = string
    }
    
    
    variable "private_ssh_key" {
      description = "Add your private ssh key - for accessing your compute instance after creation"
      type        = string
    }
    
    
    variable "create_linux_instance" {
      description = "Boolean variable to specify whether to provision a Linux instances"
      type        = bool
    }
    
    
    variable "create_windows_instance" {
      description = "Boolean variable to specify whether to provision a Windows instances"
      type        = bool
    }
    
    
    variable "windows_image_ocid" {
      description = "OCID of the Windows image to use"
      type        = string
    }
    
    
    variable "linux_image_ocid" {
      description = "OCID of the Linux image to use"
      type        = string
    }
    
  12. terraform.tfvars 中新增並定義新變數。

    #Compute variables - Make sure to select a compatible shape (e.g.: VM.Standard.E4.Flex)
    instance_shape                                = "VM.Standard.E5.Flex"                # Shape of the compute instance 
    instance_flex_memory_in_gbs                   = 16                                   # (Updatable) The total amount of memory available to the instance, in gigabytes.
    instance_flex_ocpus                           = 1                                    # (Updatable) The total number of OCPUs available to the instance.
    instance_create_vnic_details_assign_public_ip = true                                 # To allow compute connectivity from internet
    instance_display_name                         = "terraform_compute_example" # provide a descriptive name for the compute instance - this is what you will see displayed in the OCI console
    
    #SSH keys https://docs.oracle.com/en/learn/generate_ssh_keys/index.html#introduction
    public_ssh_key  = "~/cloudshellkey.pub" # Add your public ssh key
    private_ssh_key = "~/cloudshellkey"     # Add your private ssh key
    
    create_linux_instance   = true # if set to true a test linux instance will be created and false no linux instance will be deployed.
    create_windows_instance = true # # If set to true a test windows instance will be created and false no windows instance will be deployed.
    
    linux_image_ocid   = "REPLACE_BY_YOUR_REGION_LINUX_IMAGE_OCID"   # OCID for chosen image (Oracle Linux 9 example) specific to the test region (us-phoenix-1)
    windows_image_ocid = "REPLACE_BY_YOUR_REGION_WINDOWS_IMAGE_OCID" # OCID for chosen image (Windows example) specific to each region (us-phoenix-1)
    
    # Here are other image OCIDs for popular region (Ashburn, San Jose, Toronto)
    # Ashburn
    # Oracle linux image_id = ocid1.image.oc1.iad.aaaaaaaau7uaok7n5qd4nivgiyfatfdddhltmxddtfbyqg3bsg3fxk6z6aqq
    # Windows image_id = ocid1.image.oc1.iad.aaaaaaaamaaiupezxbrw6fji5ndk3jdujwhjuexcafheqjqf45g6nzyblz6a
    
    #San Jose
    # Oracle linux image_id = ocid1.image.oc1.us-sanjose-1.aaaaaaaabjixxpfouczgpcnpvgny5pcqtgjgi3nincszbfdkd2xr4jvzahua
    # Windows image_id = ocid1.image.oc1.us-sanjose-1.aaaaaaaatmjlzoqw5gzohjvygzcm5rpugomxyfho5xi6subjchoxnxo4wcfa
    
    #Toronto
    # Oracle linux image_id = ocid1.image.oc1.ca-toronto-1.aaaaaaaai6uhjrtajuuitl5hara5brnvwqvq4aebenmnbehv2cila75xbvzq
    # Windows image_id = ocid1.image.oc1.ca-toronto-1.aaaaaaaaeged3obrrmmwvyruvknszy23btvb2fqu7vn3c5azeecbj2prm64q
    
    # for other image OCIDs: https://docs.oracle.com/en-us/iaas/images/
    

    注意:每個區域都有特定的映像檔 OCID。在上述程式碼中,常用區域有映像檔 OCID,您可以在這裡找到所有其他區域的映像檔 OCID:所有映像檔系列

  13. output.tf 中,複製下列程式碼。這將會列印在終端機中建立的資源。

    # Regions
    output "linux_instance_region" {
      value = oci_core_instance.test_linux_instance.*.region
    }
    
    output "windows_instance_region" {
      value = oci_core_instance.test_windows_instance.*.region
    }
    
    # Networking
    output "network_vcn_name" {
      value = oci_core_vcn.test_vcn.*.display_name
    }
    
    # Compute: Linux Test Instance
    output "output_linux_instance_display_name" {
      value = oci_core_instance.test_linux_instance.*.display_name
    }
    
    output "output_linux_instance_public_ip" {
      value = oci_core_instance.test_linux_instance.*.public_ip
    }
    
    output "output_linux_instance_state" {
      value = oci_core_instance.test_linux_instance.*.state
    }
    
    # Compute: Windows Test Instance
    output "output_windows_instance_display_name" {
      value = oci_core_instance.test_windows_instance.*.display_name
    }
    
    output "output_windows_instance_public_ip" {
      value = oci_core_instance.test_windows_instance.*.public_ip
    }
    
    output "output_windows_instance_state" {
      value = oci_core_instance.test_windows_instance.*.state
    }
    
  14. terraform-example 開啟新的終端機並執行下列命令。

    Command 1: terraform init
    
    Command 2: terraform plan
    
    Commnad 3: terraform apply (and then respond "yes") OR terraform apply -auto-approve
    

    您應該會看到以下輸出,而且應該建立 VCN、專用子網路和公用子網路、路由表、網際網路閘道、nsg、Linux VM 和 Windows VM。

    Terraform 範例終端機執行

  15. 現在已使用 Terraform 部署資源。確認在 OCI 租用戶中建立資源之後,請使用下列命令毀棄所有資源。

    Command: terraform destroy
    

接下來的步驟

您現在已建立與 Terraform 的連線,並透過一個簡單的範例學習部署、更新及銷毀資源。若要在 OCI 中繼續您的 Terraform 旅程,並自行建立 OCI 專業架構師認證,請參閱 Accelerate Oracle Cloud Infrastructure Architect Professional Certification with Terraform

我們歡迎來自閱讀者的貢獻,以改進和擴展此自學課程。對於未來的 Terraform 學員而言,您的貢獻非常重視改善此資源。

認可

其他學習資源

探索 docs.oracle.com/learn 上的其他實驗室,或存取 Oracle Learning YouTube 頻道上的更多免費學習內容。此外,請造訪 education.oracle.com/learning-explorer 以成為 Oracle Learning Explorer。

如需產品文件,請造訪 Oracle Help Center