在OCI上,使用Terraform自动化管理基础资源VCN

这是一个系列,记录了在不同的云厂商中使用Terraform的一些注意事项与常见的问题,以供参考。

认证

概述

Oracle的认证相比其他云要稍微复杂一些,需要的认证信息包括:

  • 租户ID:tenancy_ocid
  • 用户ID:user_ocid
  • API访问需要的秘钥对的私钥
  • API访问需要的秘钥对的指纹(fingerprint)

这些信息可以参考:API Key Authentication@Configuring the Provider@Oracle Cloud Infrastructure Documentation。也注意到,在Oracle Cloud的文档中,有较为完整的Terraform文档,其目录为:Developer Resouces -> DevOps Tools and Plug-ins -> Terraform Provider

在Terraform中的认证

在Terraform中认证,有两种常见的形式,一种是在provider提供完整的信息,如下:

provider "oci" {
  tenancy_ocid     = var.tenancy_ocid
  user_ocid        = var.user_ocid
  fingerprint      = var.fingerprint
  private_key_path = var.private_key_path
  region           = var.region
}

也可以在Bash中使用全局变量:

export TF_VAR_tenancy_ocid="......"
export TF_VAR_user_ocid="......"
export TF_VAR_fingerprint="......"
export TF_VAR_private_key_path="......"

Compartment

概念

海外的云,各个都在“标新立异”…真的很烦。每个云都有着不同的概念,但是似乎都是去解决相同的问题,但实际上,又略有不同。这也许是这个世界是“多元”的又一体现… 我们来看看什么是Oracle Cloud中的Compartment

在官方文档Oracle Cloud FoundationCompartment小结中有着详细的介绍:What is a Compartment?@Oracle Cloud Foundation

文档的架构图,可视化的描述了tenancyregionADFDcompartment之间的关系。

  • Compartment是一组逻辑资源的概念,可以方便的实现权限、账单管理
  • tenancy也是一个Compartment,并且是root Compartment
  • region和其他云厂商一样是大地区的概念
  • AD则是一个大地区内的多个区(FD)组成的一个域
  • FD类似于其他云的zone的概念

在Terraform中如何创建Compartment

完整的脚本和使用可以参考官方文档:。如下是一个简单的、经过验证的实现:

resource "oci_identity_compartment" "oic" {
    #Required
    compartment_id = var.tenancy_id
    description = "for database benchmark"
    name = var.naming
}

在控制台中切换不同的Compartment

初次使用OCI的用户来说,可能会遇到类似的问题,使用Terraform创建完资源后,在控制台中可能会找不到。这是因为,默认的控制台展示的tenancy(也就是root compartment)下的资源,需要在侧栏List scope中切换到对应的Compartment下。

一些问题汇总

问题:compartment_id” is required

│ Error: Missing required argument
│
│   on base.tf line 9, in resource "oci_core_vcn" "ocv":
│    9: resource "oci_core_vcn" "ocv" {
│
│ The argument "compartment_id" is required, but no definition was found.

在创建第一个资源的时候,就遇到了这个问题。虽然在文档中,也看到了这个参数是Required的,不过感觉并没有必要。具体的参考本文的小结:compartment

问题:did not find a proper … private key

OCI的API使用需要使用秘钥对进行加/解密,对于秘钥对key有一定的要求,当使用一个自己生成的私钥对的时候,如果格式不兼容,是无法直接使用的。简单推荐的方式是,在OCI的控制台中生成一个秘钥对。

另外,主要秘钥对需要使用的PKCS#8格式,如果使用了OpenSSH格式则也可能会报如下错误。

│ Error: can not create client, bad configuration: did not find a proper configuration for private key
│
│   with provider["registry.terraform.io/hashicorp/oci"],
│   on provider.tf line 10, in provider "oci":
│   10: provider "oci" {
│

问题: 401-NotAuthenticated

这个问题的原因有很多,这里的是由于fingerprint错误导致的。这里使用了某软件根据pem文件自动生成的fingerprint,而这与Oracle Cloud格式的fingerprint有所不同,plan阶段不会宝座,apply阶段则报如下错误,使用正确兼容格式(来自与Oracle Cloud控制台)的fingerprint后,不再出现该报错。

│ Error: 401-NotAuthenticated, The required information to complete authentication was not provided or was incorrect.
│ Suggestion: Please retry or contact support for help with service: Identity Compartment
│ Documentation: https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_compartment
│ API Reference: https://docs.oracle.com/iaas/api/#/en/identity/20160918/Compartment/CreateCompartment
│ Provider version: 5.42.0, released on 2024-05-19.
│ Service: Identity Compartment
│ Operation Name: CreateCompartment
│ OPC request ID: ...
│
│
│   with oci_identity_compartment.oic,
│   on base.tf line 9, in resource "oci_identity_compartment" "oic":
│    9: resource "oci_identity_compartment" "oic" {
│

默认资源

在Terraform中创建完VCN之后,Oracle会自动在VCN中自动创建一系列的默认资源,以减少手动操作,包括了:安全组、路由表(空)、dhcp options(参考:Managing Default VCN Resources)。所以,在Terraform再创建这些资源的时候,就可以利用原有的这些对象,进行管理。

具体的,可以先按如下方式创建VCN:

resource "oci_core_vcn" "ocv" {
    #Required
    compartment_id = oci_identity_compartment.oic.id
    cidr_block = "172.17.0.0/16"
    display_name = var.naming
}

这时,系统就自动化的创建了,对应的安全组、路由表等对象。这些对象的id,可以在oci_core_vcn.ocv输出的default_security_list_iddefault_dhcp_options_iddefault_route_table_id结果中获取。在Terraform脚本中,则需要三个专门的资源对象来管理,具体的:

  • oci_core_security_list => oci_core_default_security_list
  • oci_core_dhcp_options => oci_core_default_dhcp_options
  • oci_core_route_table => oci_core_default_route_table

例如,管理默认路由表:

resource "oci_core_default_route_table" "route_table_for_internet" {
  manage_default_resource_id = oci_core_vcn.ocv.default_route_table_id
  display_name               = "RouteTableForInternet"

  route_rules {
    destination       = "0.0.0.0/0"
    destination_type  = "CIDR_BLOCK"
    network_entity_id = oci_core_internet_gateway.internet_gateway.id
  }
}

完整的代码参考

那么初始化环境,并创建一个compartment以及一个最简单的VCN,可以使用如下代码:

terraform {
    required_providers {
        oci = {
            source  = "hashicorp/oci"
            version = ">= 4.0.0"
        }
    }
}

provider "oci" {
  # tenancy_ocid     = var.tenancy_ocid
  # user_ocid        = var.user_ocid
  # fingerprint      = var.fingerprint
  # private_key_path = var.private_key_path
  region           = var.region
}

resource "oci_identity_compartment" "oic" {
    #Required
    compartment_id = var.tenancy_id
    description = "for database benchmark"
    name = var.naming
}

resource "oci_core_vcn" "ocv" {
    #Required
    compartment_id = oci_identity_compartment.oic.id
    cidr_block = "172.17.0.0/16"
    display_name = var.naming
}

参考文档

Leave a Reply

Your email address will not be published. Required fields are marked *