Configura una Google Cloud Function con Terraform

por Raul De La RosaJulio 21, 20205 minutos

Prerrequisitos

Introducción

En esta guía crearemos una Cloud Function escrita en Python, usando Terraform. Puedes descargar el código fuente aquí.

Acerca de Google Cloud Functions

Google Cloud Functions es una plataforma de Funciones como Servicios (FaaS). Este tipo de plataformas permite crear funciones que son ejecutadas como respuestas a un evento, por ejemplo, un simple llamado HTTP podría invocar tu función. Uno de los beneficios más grandes es que no hay que hacer provisión de servidores, la plataforma se encarga de instanciar contenedores para ejecutar las funciones. De esta manera se puede reducir el costo ya que solo se cobra por los recursos asignados (CPU y memoria) durante el tiempo de ejecución.

Acerca de Terraform

Terraform es una herramienta que nos permite tener infraestructura como código. Al definir los recursos en archivos de texto, tenemos la facilidad de agregarlos a un sistema de versionamiento, compartirlos y reutilizarlos. Terraform crea un plan de ejecución al aplicar cada cambio y nos muestra en detalle qué modificaciones serán aplicadas y en qué orden.

Crea una cuenta de servicio

50bc68 image 01 service account menu

Selecciona Create Service Account.

50bc68 image 02 create service account button

Ingresa “terraform” en Service account name (puede ser cualquier nombre) y da click en Create.

50bc68 image 03 create service account step 01

En la siguiente pantalla puedes asignar los permisos para la cuenta. Por motivos de simplicidad, en esta guía utilizaremos los roles “Project → Editor” y “Cloud Functions Admin”. Para producción, asegúrate de solamente asignar los permisos necesarios. Da click en continuar.

i50bc68 mage 04 create service account step 02

Por último, haz click en Done.

50bc68 image 05 create service account step 03

Crea una clave de cuenta de servicio

Esta clave permite a Terraform autenticarse en Google Cloud. Guarda esta clave en un lugar seguro y elimínala cuando ya no la necesites.

En la pantalla de Cuenta de Servicio Selecciona Create Key.

50bc68 image 06 create key

En key type, selecciona JSON y da click en Create. Guarda la clave en una ubicación que puedas recordar.

50bc68 image 07 key type

Escribe el código fuente de la función

Crea un directorio de trabajo con el nombre que elijas y agrega un archivo de texto main.py con el siguiente código de ejemplo:

def handler(request):
    return 'Hola mundo!'

Crea un archivo zip con el código fuente

Almacenaremos el código fuente en un bucket en Cloud Storage. Para esto deberás crear un archivo zip (source.zip) que incluya main.py. Sin el directorio padre.

| - main.py

En Mac OS puedes ejecutar el siguiente comando en una terminal ubicado en el directorio del proyecto:

$ zip source.zip main.py

Agrega la configuración de Terraform

# Proveedor
provider "google" {
  version = "3.5.0"

  # Archivo JSON descargado desde la consola
  credentials = file("<NAME>.json")
  # ID del proyecto en GCP
  project = "<PROJECT_ID>"  region  = "us-central1"
  zone    = "us-central1-c"
}

# Bucket para almacenar el código fuente
resource "google_storage_bucket" "source_bucket" {
  name     = "hello-world-source"
  location = "us-central1"
}

# Almacenar source.zip al bucket
resource "google_storage_bucket_object" "archive" {
  name   = "source.zip"
  bucket = google_storage_bucket.source_bucket.name
  source = "./source.zip"
}

# Cloud Function
resource "google_cloudfunctions_function" "function" {
  name        = "function-test"
  description = "Hola Mundo"
  runtime     = "python37"

  available_memory_mb   = 128
  source_archive_bucket = google_storage_bucket.source_bucket.name
  source_archive_object = google_storage_bucket_object.archive.name
  trigger_http          = true
  entry_point           = "handler"
}

# Permiso para invocar la función
resource "google_cloudfunctions_function_iam_member" "invoker" {
  project        = google_cloudfunctions_function.function.project
  region         = google_cloudfunctions_function.function.region
  cloud_function = google_cloudfunctions_function.function.name

  role           = "roles/cloudfunctions.invoker"
  member         = "allUsers"
}

En la línea 6 reemplaza <NAME> por la ruta del archivo de la clave que descargaste en el paso anterior.

En la línea 9 reemplaza <PROJECT_ID> por el ID de tu proyecto de Google Cloud. Puedes encontrar esta información en la consola.

Inicializa Terraform

Antes de crear los recursos, Terraform necesita inicializarse. Este proceso creará una carpeta “.terraform” en el directorio actual con los archivos necesarios. Verás en tu consola un mensaje como muestra la imagen.

$ terraform init

50bc68 image 08 terraform init

Aplica los cambios

En este punto ya podemos indicarle a Terraform que cree los recursos. Para esto ejecuta el siguiente comando, Terraform te mostrará la lista de recursos a crear y te pedirá que confirmes los cambios.

$ terraform apply

50bc68 image 09 terraform apply

Prueba tu función

Ya puedes probar tu función!. Ingresa a la consola de Google Cloud, selecciona tu función y en el tab “Trigger”, verás una URL. Utiliza esta URL para llamar tu función.

50bc68 image 10 test function

Deberías ver algo como esto:

50bc68 image 11 test function result

Opcional: Desplegar un cambio en el código de la función

Ya que Terraform solo detecta cambios de infraestructura pero no de código fuente es necesario desplegar los cambios como un paso adicional después de crear los recursos.

  • Modifica el código de la función
def handler(request):
    return 'Hola América Latina!'
  • Crea el archivo zip y súbelo al bucket

    En Mac OS puedes ejecutar para crear el zip:

    $ zip source.zip main.py

    Para subirlo, simplemente ejecuta:

    $ terraform apply

  • Despliega la función

    Utilizando el Google Cloud SDK:

    $ gcloud functions deploy function-test --entry-point handler --source gs://hello-world-source/source.zip

    50bc68 image 12 gcloud functions deploy

Destruye los recursos creados

Cuando ya no necesites los recursos Terraform te permite eliminarlos en un solo paso ejecutando:

$ terraform destroy