idvogadosorg/infra

Estudar viabilidade do GCP

Closed this issue · 16 comments

Descrição

Conforme issue #7, tendemos a usar o GCP, mas antes, precisamos entender se é viável a criação da arquitetura proposta por lá, para tomarmos a decisão de Cloud.

Arquitetura

iDvogados - Infra Free Tier

DoD

  • Prova de conceito (POC) da implementação da arquitetura Elastic Web Server descrita na issue #7

VPC ✔️

Em relação à VPC, é possível criar a configuração acima, conforme a documentação: https://cloud.google.com/vpc/docs/vpc?hl=pt-br

Componentes:

  • Rede privada
  • Subnets públicas e privadas
  • Internet Gateway
  • Router
  • Multi AZ

Além disso, no repositório oficial de módulos do Terraform para o GCP, existe o módulo para criação de VPC: https://github.com/terraform-google-modules/terraform-google-network

Exemplo:

module "vpc" {
    source  = "terraform-google-modules/network/google"
    version = "~> 2.4"

    project_id   = "<PROJECT ID>"
    network_name = "example-vpc"
    routing_mode = "GLOBAL"

    subnets = [
        {
            subnet_name           = "subnet-01"
            subnet_ip             = "10.10.10.0/24"
            subnet_region         = "us-west1"
        },
        {
            subnet_name           = "subnet-02"
            subnet_ip             = "10.10.20.0/24"
            subnet_region         = "us-west1"
            subnet_private_access = "true"
            subnet_flow_logs      = "true"
            description           = "This subnet has a description"
        },
        {
            subnet_name               = "subnet-03"
            subnet_ip                 = "10.10.30.0/24"
            subnet_region             = "us-west1"
            subnet_flow_logs          = "true"
            subnet_flow_logs_interval = "INTERVAL_10_MIN"
            subnet_flow_logs_sampling = 0.7
            subnet_flow_logs_metadata = "INCLUDE_ALL_METADATA"
        }
    ]

    secondary_ranges = {
        subnet-01 = [
            {
                range_name    = "subnet-01-secondary-01"
                ip_cidr_range = "192.168.64.0/24"
            },
        ]

        subnet-02 = []
    }

    routes = [
        {
            name                   = "egress-internet"
            description            = "route through IGW to access internet"
            destination_range      = "0.0.0.0/0"
            tags                   = "egress-inet"
            next_hop_internet      = "true"
        },
        {
            name                   = "app-proxy"
            description            = "route through proxy to reach app"
            destination_range      = "10.50.10.0/24"
            tags                   = "app-proxy"
            next_hop_instance      = "app-proxy-instance"
            next_hop_instance_zone = "us-west1-a"
        },
    ]
}

Load Balancer ✔️

O GCP também tem um serviço para fazer o balanceamento de carga: https://cloud.google.com/load-balancing?hl=pt-br

Da mesma forma, existe um módulo oficial para o Load Balancer: https://github.com/terraform-google-modules/terraform-google-lb-http

module "gce-lb-http" {
  source            = "GoogleCloudPlatform/lb-http/google"
  version           = "~> 3.1"

  name              = "group-http-lb"
  project           = "my-project-id"
  target_tags       = [module.mig1.target_tags, module.mig2.target_tags]
  backends = {
    default = {
      description                     = null
      protocol                        = "HTTP"
      port                            = var.service_port
      port_name                       = var.service_port_name
      timeout_sec                     = 10
      connection_draining_timeout_sec = null
      enable_cdn                      = false
      session_affinity                = null
      affinity_cookie_ttl_sec         = null

      health_check = {
        check_interval_sec  = null
        timeout_sec         = null
        healthy_threshold   = null
        unhealthy_threshold = null
        request_path        = "/"
        port                = var.service_port
        host                = null
        logging             = null
      }

      log_config = {
        enable = true
        sample_rate = 1.0
      }

      groups = [
        {
          # Each node pool instance group should be added to the backend.
          group                        = var.backend
          balancing_mode               = null
          capacity_scaler              = null
          description                  = null
          max_connections              = null
          max_connections_per_instance = null
          max_connections_per_endpoint = null
          max_rate                     = null
          max_rate_per_instance        = null
          max_rate_per_endpoint        = null
          max_utilization              = null
        },
      ]
    }
  }
}

NAT Gateway ✔️

O GCP também tem um serviço de NAT Gateway: https://cloud.google.com/nat?hl=pt-br

Também com um módulo oficial para Terraform: https://github.com/terraform-google-modules/terraform-google-cloud-nat

module "cloud-nat" {
  source     = "terraform-google-modules/cloud-nat/google"
  version    = "~> 1.2"
  project_id = var.project_id
  region     = var.region
  router     = google_compute_router.router.name
}

⚠️ Custo: O NAT Gateway tem um custo de $0,0014 dólares por hora, o que dá o total de $0,0014 * 730 horas/mes = $1,02 por mês.

É possível criar a infra sem o NAT Gateway, mas o custo é minimo e vale a pena, pela segurança que trás. Além disso, o Google nos dá $300 dólares de créditos para serem gastos no ano.

NoSQL Database - Firestore ✔️

Podemos utilizar o Firestore como banco de dados, já que iremos utilizar uma modelagem NoSQL: https://cloud.google.com/firestore?hl=pt-br

Não existe módulo para o Firestore, até porque não é necessário. É possível criar o Firestore no GCP utilizando o próprio recurso disponível no provedor GCP do Terraform: https://www.terraform.io/docs/providers/google/r/filestore_instance.html

resource "google_filestore_instance" "instance" {
  name = "test-instance"
  zone = "us-central1-a"
  tier = "STANDARD"

  file_shares {
    capacity_gb = 2660
    name        = "share1"
  }

  networks {
    network = "default"
    modes   = ["MODE_IPV4"]
  }
}

Cloud CDN ❌

O GCP também possui uma CDN: https://cloud.google.com/cdn/. No entanto, não encontrei nada simples para configurar uma CDN. Não existe um recurso específico no Terraform para tal, nem um módulo oficial para criação da CDN.

Encontrei este artigo no Medium que trás um tutorial para a criação, mas é um workaround, dado que este recurso ainda não é suportado pelo Terraform.

https://medium.com/cognite/configuring-google-cloud-cdn-with-terraform-ab65bb0456a9

Cloud DNS ✔️

O Google possui um gerenciador de DNS: https://cloud.google.com/dns?hl=pt-br#section-5

E também existe um módulo Terraform oficial para gerenciamento DNS: https://github.com/terraform-google-modules/terraform-google-cloud-dns

module "dns-private-zone" {
  source  = "terraform-google-modules/cloud-dns/google"
  version = "3.0.0"
  project_id = "my-project"
  type       = "private"
  name       = "example-com"
  domain     = "example.com."

  private_visibility_config_networks = [
    "https://www.googleapis.com/compute/v1/projects/my-project/global/networks/my-vpc"
  ]

  recordsets = [
    {
      name    = ""
      type    = "NS"
      ttl     = 300
      records = [
        "127.0.0.1",
      ]
    },
    {
      name    = "localhost"
      type    = "A"
      ttl     = 300
      records = [
        "127.0.0.1",
      ]
    },
  ]
}

Monitoramento - Stackdriver ✔️

O GCP também prove'o stackdriver, que é equivalente ao cloudwatch da AWS (porém melhor rsr), conforme: https://cloud.google.com/products/operations?hl=pt-BR#pricing

Não existe módulos oficiais para lidar com o stackdriver, porém existe vários resources do terraform para tal, conforme:

O Stackdriver é uma excelente ferramenta, mas por questões de custo, a ferramenta de monitoramento que iremos utilizar deverá ser discutida em #6

Compute Engine ✔️

O Compute engine é equivalente ao EC2 na AWS e provém máquinas virtuais para computação: https://cloud.google.com/compute

Não existe módulo oficial para lidar com o compute engine, mas existe resources terraform com uma documentação completa de como criar: https://www.terraform.io/docs/providers/google/r/compute_instance.html

resource "google_compute_instance" "default" {
  name         = "test"
  machine_type = "n1-standard-1"
  zone         = "us-central1-a"

  tags = ["foo", "bar"]

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-9"
    }
  }

  // Local SSD disk
  scratch_disk {
    interface = "SCSI"
  }

  network_interface {
    network = "default"

    access_config {
      // Ephemeral IP
    }
  }

  metadata = {
    foo = "bar"
  }

  metadata_startup_script = "echo hi > /test.txt"

  service_account {
    scopes = ["userinfo-email", "compute-ro", "storage-ro"]
  }
}

Cloud Storage (Gerenciamento de estado - Terraform) ✔️

Os componentes na infra acima referentes ao gerenciamento de estado do Terraform, que no caso é um bucket encrypitado para armazenar o terraform.state, também são possíves de ser criados e utilizados no GCP, conforme: https://www.terraform.io/docs/backends/types/gcs.html

terraform {
  backend "gcs" {
    bucket  = "tf-state-prod"
    prefix  = "terraform/state"
  }
}

Já existe um recurso para automtizar a criação dos componentes necessários para o gerenciamento do Terraform State: https://www.terraform.io/docs/providers/google/r/compute_backend_bucket.html

resource "google_compute_backend_bucket" "image_backend" {
  name        = "image-backend-bucket"
  description = "Contains beautiful images"
  bucket_name = google_storage_bucket.image_bucket.name
  enable_cdn  = true
}

resource "google_storage_bucket" "image_bucket" {
  name     = "image-store-bucket"
  location = "EU"
}

Conclusões parciais - Componentes

Analisando componente por componente é possível afirmar que o GCP possui serivços equivalentes, em um paralelo com a AWS. Infelizmente, a configuração de uma CDN via Terraform paece não ser tão simples, apesar de possível.

Em teoria, o projeto é viável, mas eu já desconsideraria o uso do CDN.

Análise de custos

VPC 💸

Todos os compontentes são gratuitios, o custo é referente apenas ao data-out. A tabela abaixo identifica o preço por terabyte na região us-central-1:

Monthly Usage Network (Egress) Worldwide Destinations (per GB in USD) Network (Egress) China Destinations (per GB in USD) Network (Egress) Australia Destinations (per GB in USD) Network (Ingress)
0-1 TB $0.12 $0.23 $0.19 Free
1-10 TB $0.11 $0.22 $0.18 Free
10+ TB $0.08 $0.20 $0.15 Free

Load Balancer 💸

Monthly Usage Pricing
First 5 forwarding rules $0.025 Per Hour
Per additional forwarding rule $0.010 Per Hour
Ingress data processed by load balancer $0.008 Per GB

Cloud NAT 💸

Number of assigned VM instances Price per hour Price per GB processed, both egress and ingress
Up to 32 VM instances $0.0014 * the number of VM instances that are using the gateway $0.045
More than 32 VM instances $0.044 $0.045

Firestore 🆓

Free Tier ✔️
1 GB storage
50,000 reads, 20,000 writes, 20,000 deletes per day

Cloud Storage 🆓

Free Tier ✔️
5 GB-months of Regional Storage per month (US regions only — excluding Northern Virginia [us-east4])
5,000 Class A Operations per month
50,000 Class B Operations per month
1 GB network egress from North America to all region destinations per month (excluding China and Australia)

Cloud DNS 💸

Metric Price
Queries: 0-1 billion $0.40 per million queries per month.
Managed Zones*: 0-25 $0.20 per managed zone per month.

Compute Engine 🆓

Free Tier ✔️
1 f1-micro instance per month (US regions only—excluding Northern Virginia [us-east4])
30 GB-months HDD
5 GB-months snapshot in select regions
1 GB network egress from North America to all region destinations per month (excluding China and Australia)

Cloud CDN 💸

Item Price
Cache egress $0.02 - $0.20 per GB
Cache fill $0.04 - $0.15 per GB
HTTP/HTTPS cache lookup requests $0.0075 per 10,000 requests
Cache invalidation $0.005 per invalidation

Stackdriver 💸

Feature Price1 per month Free allotment per month
Logging ingestion3 $0.50/GiB First 50 GiB per project
Logging storage3 Currently free.Effective March 31, 2021: $0.01/GiB above default retention periods. See default retention periods.
Monitoring data4 $0.2580/MiB: 150–100,000 MiB$0.1510/MiB: 100,000–250,000 MiB$0.0610/MiB: above 250,000 MiB First 150 MiB per billing accountfor chargeable metrics.
Monitoring API calls4 $0.01/1,000 API calls First 1 million API calls per billing account
Trace ingestion5 $0.20/million spans First 2.5 million spans per project
Trace spans scanned5 $0.02/million spans First 25 million spans per project. Pricing to be announced.

Projeção

Vou realizar uma projeção de custos bem básica baseada no achômetro do quer seria consumido em uma aplicação pequena. Caso alguém perceba que os números que joguei para a estimativa não façam sentido, por favor me avise hehe

Conforme descrito em #9 (comment), atualmente não existe módulo para a criação de um Cloud CDN no GCP, por isso, considerarei uma infra sem CDN.

VPC: Uma aplicação pequena dificilmente chegaria a 1TB de data-out por mês. Para esta projeção irei jogar pra cima e considerar 5TB.

Load Balancer: 2 regras de emcaminhamento, um para HTTP e outro para HTTPS. Jogando pra cima, vou assumir 20GB de data-in.

Cloud NAT: 1 Vm instance e também jogando pra cima, 5GB de data in/out.

Firestore: Uso menor do que os limites da camada gratuituta

Cloud DNS: Jogando pra cima, considerarei 2 milhões de queries no mês. Além disso, teríamos 1 zona.

Cloud Storage: Uso bem menor do que os limites da camada gratuituta

Compute Engine: Supondo que uma instância F1-micro supre as necessidades do projeto

Stackdriver: 5GB logs. Não será criado nenhum data point de monitoramento personalizado.

Custo do projeto 💸

Item Calc Price
VPC 0.12 * 5 $0.60
Load Balancer (0.025 * 2) + (0.008 * 20) $0.21
Cloud NAT (0.0014 * 1) + (0.045 * 5) $0.2264
Firestore - $0.00
Cloud DNS (0.40 * 2) + (0.20 * 1) $1.00
Cloud Storage - $$0.00
Compute Engine - $0.00
Stackdriver 0.50 * 5 $2.50

Total: $4.54 / mês

Conclusões parciais - Custos

Em relação aos custos, é possível ver que o GCP possui alguns serviços que não estão na camada gratuita, e que, diferente da AWS não é possível construir a infra totalmente na camada gratuita.

Por outro lado, o custo final da projeção jogando o uso de recursos pra cima ainda é um custo muito viável, sendo $4.54 por mês. Em reais, considerando a cotação atual do dólar de R$ 5,31, temos um custo final mensal de R$ 24,09.

Este custo é coberto pelo crédito do GCP por 1 ano, mas mesmo assim, após o término do crédito, é um valor muito baixo que é totalmente possível de ser mantido no nosso projeto.

Conclusões parciais - Componentes

Analisando componente por componente é possível afirmar que o GCP possui serivços equivalentes, em um paralelo com a AWS. Infelizmente, a configuração de uma CDN via Terraform paece não ser tão simples, apesar de possível.

Em teoria, o projeto é viável, mas eu já desconsideraria o uso do CDN.

Não conseguir configurar o CDN implica no que exatamente para o cenário da aplicação? Se fossemos prosseguir sem por exemplo.

@rodrigondec Ter um CDN na frente aumenta a parformance quando servimos arquivos estáticos (front-end) e reduz custo com data-out da nossa cloud. No cenário do backend, a CDN também cachea requisições HTTP. No entanto, para o nosso contexto, o impacto de ter uma CDN na frente não vai ser tão grande, dado o tamanho da aplicação e dado que até então o front será servido pelo Netlify.

Não é mais necessário aplicar a POC da arquitetura EWS no GCP, dado quer redefinimos a arquitetura a ser utilizada #7 (comment)