Skip to main content

Command Palette

Search for a command to run...

Oci Terraform

Updated
12 min read
Oci Terraform

¿Qué es terraform?

Terraform es un framework IAC "Infrastructure as Code” que nos permite administrar y definir la infraestructura en OCI de forma escalable. Además, nos permite describir la infraestructura en archivos de configuración “Terraform configuration file”, automatizando los procesos de forma segura con la ejecución de dichos archivos, evitando así cambios manuales y repetitivos en nuestra infraestructura. Estos archivos tienen extensión “.tf”.

Pero, ¿Qué beneficios nos da realmente Terraform?

  • Definir nuestra infraestructura mediante codificación.

  • Multiplataforma. Terraform no es exclusivo en OCI, sino que es compatible con muchísimos proveedores, como es Azure, AWS “Amazon Web Services” o GCP “Google Cloud Platform” etc., dándonos flexibilidad para trabajar con estos entornos de manera híbrida y multicloud.

  • Versionado. Terraform implemente Git, lo que nos brinda la oportunidad de tener un control de versiones de la configuración que tenemos en nuestra infraestructura con la posibilidad de revertir a versiones distintas.

Una vez hecha una pequeña introducción de que es Terraform y que beneficios nos brinda, vamos a entrar en detalle con algún ejemplo sencillo en OCI, así que vamos a ello.

¿Cómo trabajar con Terraform? La manera de trabajar con Terraform es con comandos. Estos comandos interactúan con Terraform para facilitar la creación, administración o desplegar recursos en nuestra infraestructura mediante el código que hemos definido. Algunos comandos son:

  • version con este comando podremos ver la versión de Terraform que estamos usando

  • init con este comando inicializamos nuestra configuración y debe ser siempre el primer comando que ejecutemos para cualquier desarrollo que hagamos, ya sea nueva o uno existente.

  • validate para validar los ficheros de terraform. Este comando realizará un checkeo a nivel de sintaxis mostrando error en aquellos archivos que no pasen dicha validación.

  • plan para crear los planes de ejecución.

  • apply para aplicar los cambios en la infraestructura. Este comando siempre debe ejecutarse después del comando plan.

  • destroy como bien dice la palabra, este comando se utiliza para eliminar los recursos definidos en Terraform.

  • output para redirigir o mostrar la información de las variables definidas en terraform.

  • fmt para reescribir los ficheros de configuración al estándar de Terraform.

Las variables en terraform nos permiten hacer configuraciones más dinámicas y reusables, permitiendo separar la configuración de los datos de nuestra infraestructura a ficheros individuales. Un ejemplo de variable podría ser el siguiente código:

variable " availability_domain" {

  description= “availability_domain”

  validation {

    condition = length(var. availability_domain) > 0

    error_message = "Debe estar informado el availability_domain"

  }

}

variable " display_name" {

  description = " display_name"

}

resource “oci_core_instance” “ogg_instance” {

 availability_domain= var.availability_domain

compartment_id=”compartment_id”

shape=”VM.Standard.2.1”

display_name=var.display_name

image_id=”instancia_image_id”

metadata {

ssh_authorized_keys=”my_public_ssh”

}

}

En este ejemplo estamos definiendo dos variables availability_domain y display_name más un resource. En la primera variable availability_domain hemos definido un valor por defecto. También hemos indicado una peculiaridad, que es una regla de validación “validation”, con esta regla comprobaremos que la longitud del valor será superior a cero. En caso que sea cero, retornará un mensaje de error “error_message”. Principalmente, la validación es para comprobar que viene informada y no va nula.

La segunda variable que hemos definido tiene únicamente informado la descripción.

Por último, podemos ver un recurso de bloque para una instancia de OCI con nombre ogg_instance.

Con este ejemplo, podemos ver los dos componentes que consta un recurso, son:

  • Tipo de Recurso, esto nos ayuda a identificar el tipo de recurso que vamos a definir/crear. En nuestro caso, lo que estamos definiendo es “oci_core_instace”. Estamos definiendo una instancia dentro de Oracle Cloud Infraestructura Compute Instance.

  • Nombre del Recurso, sería un identificador único dentro de la configuración. En nuestro caso, el identificador sería “ogg_instance”.

Dentro de este recurso definimos la atributos que tendrá el recurso junto con sus respectivos valores. Como información adicional incluimos metadata, indicando la parte de las claves rsa para acceder a la instancia que estamos definiendo. Como peculiaridad, estamos usando las variables definidas previamente dentro del recurso, la manera de invocarlas es “var.” acompañado del nombre.

Una vez que tenemos definidos las variables junto con el recurso que define nuestra instancia, el siguiente punto que tendríamos que ver es el provider. El provider es un plugin que actúa como puente entre terraform y el destino, en este caso, el destino es OCI, permitiendo así a Terraform administrar los recursos y configuraciones.

Con lo primero con lo que debemos contar para hacer este ejemplo, es tener una cuenta en OCI.

Vamos a crear un ejemplo sencillo para entender un poco mejor todo lo que hemos visto, para ello vamos a definir una infraestructura para desplegarla dentro de nuestra tenancy.

Lo primero que vamos hacer es entrar en OCI y abrir el Code Editor. Para abrir el Code Editor, tenemos que ir a Developer Tools, que esta justo en la parte superior izquierda.

Tomará algo de tiempo si es la primera vez que accedes aquí, una vez dentro veremos algo así:

Aquí podrás ver una lista de ficheros que están presentes en home. Desde raíz crearemos la carpeta study y dentro de la carpeta definiremos el fichero main.tf. He definido el nombre de la capeta con el mismo nombre que el compartiment, pero podemos poner el nombre que queramos.

Dentro de maint.tf definiremos nuestra configuración.

terraform {

  required_providers{

    oci = {

        source = "oracle/oci"

    }

  }

}

provider "oci" {

    region="eu-frankfurt-1"

}

Aquí podemos ver un bloque con la configuración requerida. Una cosa importante, nosotros tenemos el provider especificando únicamente region porque estamos dentro del propio Cloud Shell. Si esto lo hacemos desde nuestro local sin usar el Cloud Shell, debemos especificar lo siguiente:

  • OCID tenancy

  • OCID User

  • Ruta de nuestra clave rsa

  • Fingerprint.

Indicando estos cuatro puntos nos quedaría algo así:

terraform {

  required_providers{

    oci = {

        source = "oracle/oci"

    }

  }

}

provider "oci" {

    tenancy_ocid=  <ocid_tenancy>

    user_ocid=  <ocid_user>

    private_key_path = <path>

    fingerprint =  <fingerprint>

    region="eu-frankfurt-1"

}

En nuestro caso al ser dentro del propio Cloud Shell no haría falta.

Ahora faltaría definir el recurso que queremos

resource "oci_core_virtual_network" "vcnterra" {

    compartment_id= "ocid1.compartment.oc1..aaaaaaaaey6p747h55c2uzlwdvzetwmbod2pqmthk74es3ozwbds2ciwygua"

    cidr_block = "10.0.0.0/16"

    dns_label="vcnterra"

    display_name="vcnterra"

}

En ese bloque indicamos a terraform el tipo de recurso que queremos crear/definir, “oci_core_virtual_network” y un nombre único dentro de la tenancy “vcnterra”.

Esta sería como quedaría nuestro main.tf

terraform {

  required_providers{
    oci = {
        source = "oracle/oci"
    }
  }
}
provider "oci" {
    region="eu-frankfurt-1"
}

resource "oci_core_virtual_network" "vcnterra" {
    compartment_id = "ocid1.compartment.oc1..aaaaaaaaey6p747h55c2uzlwdvzetwmbod2pqmthk74es3ozwbds2ciwygua"
    cidr_block = "10.0.0.0/16"
    dns_label="vcnterra"
    display_name="vcnterra"
}

Después de guardar el fichero, inicializaremos nuestro entorno de trabajo. Para hacerlo, deberemos arrancar un terminal. En la parte superior, iríamos a Terminar y nuevo Terminal

En la parte inferior aparecerá una nueva ventana con acceso al cloud Shell.

Nos cambiamos al directorio study. Dentro del directorio, tendremos nuestro fichero main.tf definido más arriba.

Ejecutamos terraform init. Con este comando descargaremos los plugins necesarios junto con las configuraciones que quizás necesitemos.

XXXXXX@codeeditor:STUDY (eu-frankfurt-1)$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding latest version of oracle/oci...
- Installing oracle/oci v6.13.0...
- Installed oracle/oci v6.13.0 (signed by a HashiCorp partner, key ID 1533A49284137CEB)
Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
XXXXXX@codeeditor:STUDY (eu-frankfurt-1)$

Una vez finalizado, la configuración del terraform ha sido inicializada satisfactoriamente.

Si echamos un vistazo al directorio, podemos ver el fichero de log junto con el directorio de terraform.

XXXXXX@codeeditor:STUDY (eu-frankfurt-1)$ ls -laSh
total 12K
drwxr-xr-x. 12 XXXX oci 4.0K Oct 17 11:17 ..
-rw-r--r--.  1 XXXX oci 1.4K Oct 17 11:17 .terraform.lock.hcl
-rw-r--r--.  1 XXXX oci  378 Oct 17 10:54 main.tf
drwxr-xr-x.  3 XXX oci   66 Oct 17 11:17 .
drwxr-xr-x.  3 XXX oci   23 Oct 17 11:17 .terraform
XXXXXX@codeeditor:STUDY (eu-frankfurt-1)$

Y el contenido del directorio .terraform sería el siguiente.

XXXXXX@codeeditor:STUDY (eu-frankfurt-1)$ find .terraform
.terraform
.terraform/providers
.terraform/providers/registry.terraform.io
.terraform/providers/registry.terraform.io/oracle
.terraform/providers/registry.terraform.io/oracle/oci
.terraform/providers/registry.terraform.io/oracle/oci/6.13.0
.terraform/providers/registry.terraform.io/oracle/oci/6.13.0/linux_arm64
.terraform/providers/registry.terraform.io/oracle/oci/6.13.0/linux_arm64/terraform-provider-oci_v6.13.0

Aquí podemos ver que el proveedor para OCI tiene la versión 6.13.0 junto con los ficheros que lo forman.

Con esto habremos finalizado el segundo paso. Después de ejecutar terraform init, hay que ejecutar terraform plan.

XXXXX@codeeditor:STUDY (eu-frankfurt-1)$ terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create
Terraform will perform the following actions:
  # oci_core_virtual_network.vcnterra will be created
  + resource "oci_core_virtual_network" "vcnterra" {
      + byoipv6cidr_blocks               = (known after apply)
      + cidr_block                       = "10.0.0.0/16"
      + cidr_blocks                      = (known after apply)
      + compartment_id                   = "ocid1.compartment.oc1..aaaaaaaaey6p747h55c2uzlwdvzetwmbod2pqmthk74es3ozwbds2ciwygua"
      + default_dhcp_options_id          = (known after apply)
      + default_route_table_id           = (known after apply)
      + default_security_list_id         = (known after apply)
      + defined_tags                     = (known after apply)
      + display_name                     = "vcnterra"
      + dns_label                        = "vcnterra"
      + freeform_tags                    = (known after apply)
      + id                               = (known after apply)
      + ipv6cidr_blocks                  = (known after apply)
      + ipv6private_cidr_blocks          = (known after apply)
      + is_ipv6enabled                   = (known after apply)
      + is_oracle_gua_allocation_enabled = (known after apply)
      + security_attributes              = (known after apply)
      + state                            = (known after apply)
      + time_created                     = (known after apply)
      + vcn_domain_name                  = (known after apply)
    }
Plan: 1 to add, 0 to change, 0 to destroy.
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.

Gracias a este comando mostrará un plan de acción de lo que va a crear, eliminar o actualizar. En la parte final, podremos ver un pequeño resumen de lo que se va hacer, en nuestro caso es solamente crear un nuevo recurso, no vamos a realizar ninguna modificación en los recursos, ni tampoco la opción de eliminar.

Plan: 1 to add, 0 to change, 0 to destroy.

Como nota final de este comando, tenemos la opción de guardar este plan en un fichero, en la ejecución del comando, como nota final nos lo indica así:

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.

Aplicamos nuestro cambio con el comando terraform apply. Con este comando veremos el mismo resumen que vimos con el comando terraform plan pero con la salvedad que tendremos que introducir “yes” para confirmar que queremos crear el recurso.

xxxxx@codeeditor:STUDY (eu-frankfurt-1)$ terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
 + create
Terraform will perform the following actions:
  # oci_core_virtual_network.vcnterra will be created
  + resource "oci_core_virtual_network" "vcnterra" {
      + byoipv6cidr_blocks               = (known after apply)
      + cidr_block                       = "10.0.0.0/16"
      + cidr_blocks                      = (known after apply)
      + compartment_id                   = "ocid1.compartment.oc1..aaaaaaaaey6p747h55c2uzlwdvzetwmbod2pqmthk74es3ozwbds2ciwygua"
      + default_dhcp_options_id          = (known after apply)
      + default_route_table_id           = (known after apply)
      + default_security_list_id         = (known after apply)
      + defined_tags                     = (known after apply)
      + display_name                     = "vcnterra"
      + dns_label                        = "vcnterra"
      + freeform_tags                    = (known after apply)
      + id                               = (known after apply)
      + ipv6cidr_blocks                  = (known after apply)
      + ipv6private_cidr_blocks          = (known after apply)
      + is_ipv6enabled                   = (known after apply)
      + is_oracle_gua_allocation_enabled = (known after apply)
      + security_attributes              = (known after apply)
      + state                            = (known after apply)
      + time_created                     = (known after apply)
      + vcn_domain_name                  = (known after apply)
    }
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.
  Enter a value: yes
oci_core_virtual_network.vcnterra: Creating...
oci_core_virtual_network.vcnterra: Creation complete after 1s [id=ocid1.vcn.oc1.eu-frankfurt-1.amaaaaaaii7prlaa77yeuh3rkfmhsbfpuecab7zbzkolznpz4zcan5o5wpbq]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed

Listo, hemos creado el nuevo recurso dentro de nuestra tenancy. También podemos ver el OCID con el que fue generado.

Ahora volvemos a OCI para comprobar que se ha creado nuestro nuevo recurso.

Vista detallada, aquí podemos ver que la información definida en el main.tf es la que refleja nuestra vcn en oci.

Y el OCID que vimos en el resumen del terraform apply coincide con el que tiene el recurso en OCI

Si queremos eliminar el recurso, lo podemos hacer con el comando terraform destroy. El comando creará un plan necesario para ser destruido el recurso y al igual que el comando terraform apply, pedirá confirmación.

xxxxx@codeeditor:STUDY (eu-frankfurt-1)$ terraform destroy
oci_core_virtual_network.vcnterra: Refreshing state... [id=ocid1.vcn.oc1.eu-frankfurt-1.amaaaaaaii7prlaa77yeuh3rkfmhsbfpuecab7zbzkolznpz4zcan5o5wpbq]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  - destroy
Terraform will perform the following actions:
  # oci_core_virtual_network.vcnterra will be destroyed
  - resource "oci_core_virtual_network" "vcnterra" {
  - byoipv6cidr_blocks       = [] -> null
  - cidr_block               = "10.0.0.0/16" -> null
  - cidr_blocks              = [
          - "10.0.0.0/16",
        ] -> null
  - compartment_id           = "ocid1.compartment.oc1..aaaaaaaaey6p747h55c2uzlwdvzetwmbod2pqmthk74es3ozwbds2ciwygua" -> null
  - default_dhcp_options_id  = "ocid1.dhcpoptions.oc1.eu-frankfurt-1.aaaaaaaajnekef3fovrrqgedqgtonvpurwzclt7exiilpb3vlnuttvueki6q" -> null
  - default_route_table_id   = "ocid1.routetable.oc1.eu-frankfurt-1.aaaaaaaajlxx7xs7w5fn7xan37q72ihgc7fa22rnjgh5aebisoihgq7llw7q" -> null
  - default_security_list_id = "ocid1.securitylist.oc1.eu-frankfurt-1.aaaaaaaakuaak3ikoqqtf6xsubcv7fo3xwhtoklnl6atb4ndm3l4y4tgl3ka" -> null
  - defined_tags             = {
          - "Oracle-Tags.CreatedBy" = "default/casillaspilar@gmail.com"
          - "Oracle-Tags.CreatedOn" = "2024-10-17T11:52:39.403Z"
        } -> null
  - display_name             = "vcnterra" -> null
  - dns_label                = "vcnterra" -> null
  - freeform_tags            = {} -> null
  - id                       = "ocid1.vcn.oc1.eu-frankfurt-1.amaaaaaaii7prlaa77yeuh3rkfmhsbfpuecab7zbzkolznpz4zcan5o5wpbq" -> null
  - ipv6cidr_blocks          = [] -> null
  - ipv6private_cidr_blocks  = [] -> null
  - is_ipv6enabled           = false -> null
  - security_attributes      = {} -> null
  - state                    = "AVAILABLE" -> null
  - time_created             = "2024-10-17 11:52:39.489 +0000 UTC" -> null
  - vcn_domain_name          = "vcnterra.oraclevcn.com" -> null
 }
Plan: 0 to add, 0 to change, 1 to destroy.
Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.
  Enter a value: yes
oci_core_virtual_network.vcnterra: Destroying... [id=ocid1.vcn.oc1.eu-frankfurt-1.amaaaaaaii7prlaa77yeuh3rkfmhsbfpuecab7zbzkolznpz4zcan5o5wpbq]
oci_core_virtual_network.vcnterra: Destruction complete after 1s
Destroy complete! Resources: 1 destroyed.

Si volvemos a OCI, podemos comprobar que la VCN no existe.

Con este ejemplo proporcionado, se puede ver cómo podemos crear nuevos recursos en nuestra tenancy de manera fácil, rápida y dinámica.