Terraform timing out on a GitLab CI shared runner while creating a Google Cloud Run service

I’m trying to set up a pipeline using GitLab CI + Terraform to build a Docker image for a simple webapp, push it to the Google Cloud Registry, test it, deploy to a Cloud Run service, and then destroying the Cloud Run instance (this last one only to be done manually). The first phases (building the image, pushing it to the Google Cloud Registry, testing the image) work just fine, but the deployment phase is giving me a headache. For this I wrote a simple terraform configuration file and I’m trying to use terraform apply as a script. However, the process always times out and never goes through. I will leave the .gitlab-ci.yml and main.tf files I’m using, along with the log of the deploy stage (redacted in some parts to avoid disclosing what could be sensitive data)

.gitlab-ci.yml

image: docker:19.03.12

# pushing and pulling to/from GCP Cloud Registry:
# https://medium.com/@gaforres/publishing-google-cloud-container-registry-images-from-gitlab-ci-23c45356ff0e

# Terraform plan, apply and destroy in different stages:
# https://stackoverflow.com/questions/58728425/gitlab-ci-terraform-destroy-doesnt-destroy

variables:
  STATE: terraform.tfstate

cache:
  paths:
    - .terraform

stages:
  - build
  - test
  - deploy
  - destroy

variables:
  # When you use the dind service, you must instruct Docker to talk with
  # the daemon started inside of the service. The daemon is available
  # with a network connection instead of the default
  # /var/run/docker.sock socket. Docker 19.03 does this automatically
  # by setting the DOCKER_HOST in
  # https://github.com/docker-library/docker/blob/d45051476babc297257df490d22cbd806f1b11e4/19.03/docker-entrypoint.sh#L23-L29
  #
  # The 'docker' hostname is the alias of the service container as described at
  # https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services.
  #
  # Specify to Docker where to create the certificates. Docker
  # creates them automatically on boot, and creates
  # `/certs/client` to share between the service and job
  # container, thanks to volume mount from config.toml
  DOCKER_TLS_CERTDIR: "/certs"

services:
  - docker:19.03.12-dind

before_script:
  - docker info
  # Install CA certs, openssl to https downloads, python for gcloud sdk
  - apk add --update make ca-certificates openssl python3
  - update-ca-certificates
  # Download and install Google Cloud SDK
  - wget https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.tar.gz
  - tar zxf google-cloud-sdk.tar.gz && ./google-cloud-sdk/install.sh --usage-reporting=false --path-update=true
  - google-cloud-sdk/bin/gcloud --quiet components update
  - google-cloud-sdk/bin/gcloud auth activate-service-account --key-file $GCLOUD_SERVICE_KEY_PATH
  - docker login -u _json_key --password-stdin https://eu.gcr.io < $GCLOUD_SERVICE_KEY_PATH

build:
  stage: build
  script:
    - docker build -t $IMAGE_NAME .
    - docker tag $IMAGE_NAME "eu.gcr.io/$GCLOUD_PROJECT_ID/$IMAGE_NAME"
    - docker push "eu.gcr.io/$GCLOUD_PROJECT_ID/$IMAGE_NAME:latest"

test:
  stage: test
  script:
    - docker run "eu.gcr.io/$GCLOUD_PROJECT_ID/$IMAGE_NAME:latest" npm test

# Deplouy with GitLab CI + Terraform:
# https://matavelli.io/posts/2020/01/setup-gitlab-ci-with-terraform/
deploy:
  stage: deploy
  image:
    name: hashicorp/terraform:light
    entrypoint:
      - '/usr/bin/env'
      - 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
  script:
    - terraform apply -state=$STATE -auto-approve
  before_script:
    - terraform --version
    - terraform init

destroy:
  stage: destroy
  image:
    name: hashicorp/terraform:light
    entrypoint:
      - '/usr/bin/env'
      - 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
  script:
    - terraform destroy -state=$STATE -auto-approve
  dependencies:
    - deploy
  when: manual

main.tf

# main.tf
# src: https://ruanmartinelli.com/posts/terraform-cloud-run

variable "gcloud_project_id" {
  description = "Google Project ID"
  type        = string
  default     = [redacted]
}

variable "image_name" {
  description = "The name of the built image"
  type        = string
  default     = [redacted]
}

variable "service_name" {
  description = "The name of the Google Cloud Run service"
  type        = string
  default     = [redacted]
}

terraform {
  required_version = ">= 0.14"

  required_providers {
    # Cloud Run support was added on 3.3.0
    google = ">= 3.3"
  }
}

provider "google" {
  project = var.gcloud_project_id
}

# Enables the Cloud Run API
resource "google_project_service" "run_api" {
  service = "run.googleapis.com"

  disable_on_destroy = true
}

# Create the Cloud Run service
resource "google_cloud_run_service" "run_service" {
  name     = var.service_name
  location = "europe-north1"

  template {
    spec {
      containers {
        image = "eu.gcr.io/${var.gcloud_project_id}/${var.image_name}:latest"
      }
    }
  }

  traffic {
    percent         = 100
    latest_revision = true
  }

  # Waits for the Cloud Run API to be enabled
  depends_on = [google_project_service.run_api]
}

# Allow unauthenticated users to invoke the service
resource "google_cloud_run_service_iam_member" "run_all_users" {
  service  = google_cloud_run_service.run_service.name
  location = google_cloud_run_service.run_service.location
  role     = "roles/run.invoker"
  member   = "allUsers"
}

# Display the service URL
output "service_url" {
  value = google_cloud_run_service.run_service.status[0].url
}

Log of the deploy stage:

Running with gitlab-runner 13.12.0-rc1 (b21d5c5b)
  on docker-auto-scale ed2dce3a
  feature flags: FF_GITLAB_REGISTRY_HELPER_IMAGE:true, FF_SKIP_DOCKER_MACHINE_PROVISION_ON_CREATION_FAILURE:true
section_start:1624620462:prepare_executor
Preparing the "docker+machine" executor
Using Docker executor with image hashicorp/terraform:light ...
Starting service docker:19.03.12-dind ...
Pulling docker image docker:19.03.12-dind ...
Using docker image sha256:66dc2d45749a48592f4348fb3d567bdd65c9dbd5402a413b6d169619e32f6bd2 for docker:19.03.12-dind with digest docker@sha256:674f1f40ff7c8ac14f5d8b6b28d8fb1f182647ff75304d018003f1e21a0d8771 ...
Waiting for services to be up and running...
Pulling docker image hashicorp/terraform:light ...
Using docker image sha256:0499120216024b8ded2abeb4b66973263b8ea7b1d21ff5128e89ec231afac032 for hashicorp/terraform:light with digest hashicorp/terraform@sha256:bb0b038253ae094d8058c3eaa94d89779901bb3b60d5c0b0ea6af5aa3b0b4d26 ...
section_end:1624620484:prepare_executor
section_start:1624620484:prepare_script
Preparing environment
Running on runner-ed2dce3a-project-27627406-concurrent-0 via runner-ed2dce3a-srm-1624620416-5fb00eb5...
section_end:1624620485:prepare_script
section_start:1624620485:get_sources
Getting source from Git repository
$ eval "$CI_PRE_CLONE_SCRIPT"
Fetching changes with git depth set to 50...
Initialized empty Git repository in [redacted]
Created fresh repository.
Checking out [redacted] as testing...

Skipping Git submodules setup
section_end:1624620487:get_sources
section_start:1624620487:restore_cache
Restoring cache
Checking cache for default...
Downloading cache.zip from https://storage.googleapis.com/gitlab-com-runners-cache/project/27627406/default 
Successfully extracted cache
section_end:1624620488:restore_cache
section_start:1624620488:step_script
Executing "step_script" stage of the job script
Using docker image sha256:0499120216024b8ded2abeb4b66973263b8ea7b1d21ff5128e89ec231afac032 for hashicorp/terraform:light with digest hashicorp/terraform@sha256:bb0b038253ae094d8058c3eaa94d89779901bb3b60d5c0b0ea6af5aa3b0b4d26 ...
$ terraform --version
Terraform v1.0.1
on linux_amd64
+ provider registry.terraform.io/hashicorp/google v3.73.0
$ terraform init

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/google from the dependency lock file
- Installing hashicorp/google v3.73.0...
- Installed hashicorp/google v3.73.0 (signed by HashiCorp)

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.
$ terraform apply -state=$STATE -auto-approve

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:

  # google_cloud_run_service.run_service will be created
  + resource "google_cloud_run_service" "run_service" {
      + autogenerate_revision_name = false
      + id                         = (known after apply)
      + location                   = "europe-north1"
      + name                       = [redacted]
      + project                    = (known after apply)
      + status                     = (known after apply)

      + metadata {
          + annotations      = (known after apply)
          + generation       = (known after apply)
          + labels           = (known after apply)
          + namespace        = (known after apply)
          + resource_version = (known after apply)
          + self_link        = (known after apply)
          + uid              = (known after apply)
        }

      + template {
          + metadata {
              + annotations      = (known after apply)
              + generation       = (known after apply)
              + labels           = (known after apply)
              + name             = (known after apply)
              + namespace        = (known after apply)
              + resource_version = (known after apply)
              + self_link        = (known after apply)
              + uid              = (known after apply)
            }

          + spec {
              + container_concurrency = (known after apply)
              + serving_state         = (known after apply)
              + timeout_seconds       = (known after apply)

              + containers {
                  + image = [redacted]

                  + ports {
                      + container_port = (known after apply)
                      + name           = (known after apply)
                      + protocol       = (known after apply)
                    }

                  + resources {
                      + limits   = (known after apply)
                      + requests = (known after apply)
                    }
                }
            }
        }

      + traffic {
          + latest_revision = true
          + percent         = 100
        }
    }

  # google_cloud_run_service_iam_member.run_all_users will be created
  + resource "google_cloud_run_service_iam_member" "run_all_users" {
      + etag     = (known after apply)
      + id       = (known after apply)
      + location = "europe-north1"
      + member   = "allUsers"
      + project  = (known after apply)
      + role     = "roles/run.invoker"
      + service  = [redacted]
    }

  # google_project_service.run_api will be created
  + resource "google_project_service" "run_api" {
      + disable_on_destroy = true
      + id                 = (known after apply)
      + project            = (known after apply)
      + service            = "run.googleapis.com"
    }

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

Changes to Outputs:
  + service_url = (known after apply)
google_project_service.run_api: Creating...
google_project_service.run_api: Still creating... [10s elapsed]
google_project_service.run_api: Still creating... [20s elapsed]
google_project_service.run_api: Still creating... [30s elapsed]
google_project_service.run_api: Still creating... [40s elapsed]
google_project_service.run_api: Still creating... [50s elapsed]
google_project_service.run_api: Still creating... [1m0s elapsed]
google_project_service.run_api: Still creating... [1m10s elapsed]
google_project_service.run_api: Still creating... [1m20s elapsed]
google_project_service.run_api: Still creating... [1m30s elapsed]
google_project_service.run_api: Still creating... [1m40s elapsed]
google_project_service.run_api: Still creating... [1m50s elapsed]
google_project_service.run_api: Still creating... [2m0s elapsed]
google_project_service.run_api: Still creating... [2m10s elapsed]
google_project_service.run_api: Still creating... [2m20s elapsed]
google_project_service.run_api: Still creating... [2m30s elapsed]
google_project_service.run_api: Still creating... [2m40s elapsed]
google_project_service.run_api: Still creating... [2m50s elapsed]
google_project_service.run_api: Still creating... [3m0s elapsed]
google_project_service.run_api: Still creating... [3m10s elapsed]
google_project_service.run_api: Still creating... [3m20s elapsed]
google_project_service.run_api: Still creating... [3m30s elapsed]
google_project_service.run_api: Still creating... [3m40s elapsed]
google_project_service.run_api: Still creating... [3m50s elapsed]
google_project_service.run_api: Still creating... [4m0s elapsed]
google_project_service.run_api: Still creating... [4m10s elapsed]
google_project_service.run_api: Still creating... [4m20s elapsed]
google_project_service.run_api: Still creating... [4m30s elapsed]
google_project_service.run_api: Still creating... [4m40s elapsed]
google_project_service.run_api: Still creating... [4m50s elapsed]
google_project_service.run_api: Still creating... [5m0s elapsed]
google_project_service.run_api: Still creating... [5m10s elapsed]
google_project_service.run_api: Still creating... [5m20s elapsed]
google_project_service.run_api: Still creating... [5m30s elapsed]
google_project_service.run_api: Still creating... [5m40s elapsed]
google_project_service.run_api: Still creating... [5m50s elapsed]
google_project_service.run_api: Still creating... [6m0s elapsed]
google_project_service.run_api: Still creating... [6m10s elapsed]
google_project_service.run_api: Still creating... [6m20s elapsed]
google_project_service.run_api: Still creating... [6m30s elapsed]
google_project_service.run_api: Still creating... [6m40s elapsed]
google_project_service.run_api: Still creating... [6m50s elapsed]
google_project_service.run_api: Still creating... [7m0s elapsed]
google_project_service.run_api: Still creating... [7m10s elapsed]
google_project_service.run_api: Still creating... [7m20s elapsed]
google_project_service.run_api: Still creating... [7m30s elapsed]
google_project_service.run_api: Still creating... [7m40s elapsed]
google_project_service.run_api: Still creating... [7m50s elapsed]
google_project_service.run_api: Still creating... [8m0s elapsed]
google_project_service.run_api: Still creating... [8m10s elapsed]
google_project_service.run_api: Still creating... [8m20s elapsed]
google_project_service.run_api: Still creating... [8m30s elapsed]
google_project_service.run_api: Still creating... [8m40s elapsed]
google_project_service.run_api: Still creating... [8m50s elapsed]
google_project_service.run_api: Still creating... [9m0s elapsed]
google_project_service.run_api: Still creating... [9m10s elapsed]
google_project_service.run_api: Still creating... [9m20s elapsed]
google_project_service.run_api: Still creating... [9m30s elapsed]
google_project_service.run_api: Still creating... [9m40s elapsed]
google_project_service.run_api: Still creating... [9m50s elapsed]
╷
│ Error: Error when reading or editing Project Service : Request [redacted] timed out after 10m0s
│ 
│   with google_project_service.run_api,
│   on main.tf line 36, in resource "google_project_service" "run_api":
│   36: resource "google_project_service" "run_api" {
│ 
╵
section_end:1624621711:step_script
section_start:1624621711:cleanup_file_variables
Cleaning up file based variables
section_end:1624621711:cleanup_file_variables
ERROR: Job failed: exit code 1

What is puzzling me is that the scripts are straightforward, and on my machine terraform apply works just fine using the same main.tf file. I’m using Gitlab.com, and in the .gitlab-ci.yml and the main.tf files that I posted here you can see some links sprinkled here and there as comments that point to places I took inspiration from while writing my configuration files. I would really appreciate any help with this.