Title
#contributors
Tim (Infracost)

Tim (Infracost)

08/30/2022, 1:20 PM
@tom mg thanks for taking on the GCP custom instances issue. I’m going to post in github for better visibility, but feel free to ping me here if that works better.
t

tom mg

08/30/2022, 1:50 PM
Thanks, Tim! I’m looking forward to understand what I should code in order to turn such feature available. Do we already have means of querying for custom instances on cloud pricing API?
Tim (Infracost)

Tim (Infracost)

08/30/2022, 2:04 PM
Ok, I just outline the steps in the GH issue so let me know if it makes sense.
Do we already have means of querying for custom instances on cloud pricing API?
Yes it looks like prices for custom instances are already in the cloud pricing DB. This guide has a good example of how to do the search and map them to a cost component
t

tom mg

08/31/2022, 2:43 PM
I managed to query something like:
query {
  products(
    filter: {
      vendorName: "gcp",
      service: "Compute Engine",
      productFamily: "Compute",
      region: "europe-central2",
      attributeFilters: [
        { key: "resourceGroup", value: "RAM" }
      ]
    },
  ) {
    attributes { key, value }
    prices { USD }
  }
}
But I'm not sure how I could improve the result accuracy in this query πŸ€” I found in the results some descriptions like
Custom Instance Ram running in Warsaw
and I think these should be our case for an object like:
resource "google_container_node_pool" "dev-1" {
  cluster  = "dev"
  name     = "dev-1"
  location = "europe-central2-c"

  autoscaling {
    max_node_count = 20
    min_node_count = 1
  }

  management {
    auto_repair  = true
    auto_upgrade = true
  }

  upgrade_settings {
    max_surge       = 1
    max_unavailable = 0
  }

  node_config {
    preemptible = true
    oauth_scopes = [
      "<https://www.googleapis.com/auth/cloud-platform>"
    ]

    machine_type = "custom-22-20480"

    image_type   = "COS_CONTAINERD"
    disk_type    = "pd-standard"
    disk_size_gb = "100"

    labels = {
      "pool" = "dev-1"
    }

    workload_metadata_config {
      mode = "GKE_METADATA"
    }
  }
}
2:44 PM
btw, I'll elaborate my use case in the issue just to keep it better documented.
4:22 PM
I was getting acquainted to the code base and your suggestion of creating a new function
customComputeCostComponent
took place. You can check my progress in this drafted PR: https://github.com/infracost/infracost/pull/2004 Now, I'll get more acquainted with cloud pricing GraphQL API and see how I should build that
AttributeFilters
list. Btw, I let the personal bias lead me to start with
google_container_node_pool
resource.
Tim (Infracost)

Tim (Infracost)

08/31/2022, 4:24 PM
Cool I’ll check it out πŸš€
8:07 PM
How do you see the output ultimately looking? I’m imagining that there will be three separate cost components for each instance: one for CPU, one from RAM, and one (optional) for Extended RAM
8:13 PM
I’m not sure how I could improve the result accuracy in this query
Yeah it may be that a regex against the description is required. If you look at the
guestAcceleratorCostComponent
helper you can see an example of that.
t

tom mg

09/07/2022, 4:28 PM
I separated the cost components for CPU and RAM since they require different queries on cloud-pricing-api. The weird thing is that I am succeeding on retrieving both CPU and RAM through GraphQL
query {
  products(
    filter: {
      vendorName: "gcp",
      service: "Compute Engine",
      productFamily: "Compute",
      region: "europe-central2",
      attributeFilters: [
				{ key: "description", value_regex: "/^Custom Instance Core.*$/" },
      ]
    },
  ) {
    attributes { key, value }
    prices { USD }
  }
}
---
query {
  products(
    filter: {
      vendorName: "gcp",
      service: "Compute Engine",
      productFamily: "Compute",
      region: "europe-central2",
      attributeFilters: [
				{ key: "description", value_regex: "/^Custom Instance Ram.*$/" },
      ]
    },
  ) {
    attributes { key, value }
    prices { USD }
  }
}
But not on the final pricing
google_container_node_pool.dev-1                                                                          
 β”œβ”€ Standard provisioned storage (pd-standard)                                    300  GB           $14.40 
 β”œβ”€ Custom Instance CPU usage (Linux/UNIX, preemptible, custom-20-20480)        2,190  hours         $0.00 
 └─ Custom Instance RAM usage (Linux/UNIX, preemptible, custom-20-20480)        2,190  hours         $0.00
Another issue that I already spotted in my code is that I didn't multiplied the Core/Ram cost by the unities specified in the instance name (i.e 20 cpu and 20480 ram). And I'm not sure how I'll make this right now. I'll get back to this issue some other time in the near future.
Tim (Infracost)

Tim (Infracost)

09/07/2022, 4:36 PM
But not on the final pricing
Looks like you have
ProductFamily: strPtr("Compute Instance"),
in the code, not
ProductFamily: strPtr("Compute"),
6:21 PM
Another issue that I already spotted in my code is that I didn’t multiplied the Core/Ram cost by the unities specified in the instance name (i.e 20 cpu and 20480 ram). And I’m not sure how I’ll make this right now.
Yeah you’ll need to parse the number of cores and amount of ram from the machine type, then multiply the quantity by that. That will give the correct cost but unfortunately also multiply the number of hours reported as units. It’s a little weried but I think you can get around this by setting the UnitMultiplier also equal to the number of cores (or ram). So something like this:
UnitMultiplier:      decimal.NewFromInt(numberOfCores),
		MonthlyQuantity:     decimalPtr(qty.Mul(decimal.NewFromInt(instanceCount * numberOfCores))),
That should make it display the correct cost and hours.
6:23 PM
Also, don’t forget about extended ram which has a different price record in the pricing db. This is from the terraform docs:
There is a limit of 6.5 GB per CPU unless you add extended memory. You must do this explicitly by adding the suffix -ext, e.g. custom-2-15360-ext for 2 vCPU and 15 GB of memory.
t

tom mg

11/20/2022, 3:59 PM
Hey everyone, it took a while but I finally got the code right for querying costs for GCP custom instances. Whenever possible, I'd appreciate a code review here: https://github.com/infracost/infracost/pull/2004 Looking forward to let that code in the best shape for Infracost standards πŸ˜ƒ @Tim (Infracost) @Alistair (Infracost)
Alistair (Infracost)

Alistair (Infracost)

11/20/2022, 5:51 PM
Amazing! Thanks @tom mg! We will have a look this week.
t

tom mg

11/21/2022, 10:07 AM
Now I just realized that I only did that for GKE node pools.. I need to extend the custom handling to regular VMs as well. Will do it asap.
Alistair (Infracost)

Alistair (Infracost)

11/21/2022, 10:36 AM
awesome, hopefully it won’t be too much extra
t

tom mg

11/21/2022, 11:19 AM
I think it would only take a verification like the following here I made a quick test while I was waiting a CI check to run 😬 but weirdly Infracost skipped the google_compute_instance I added. I’ll understand what is missing later.
Alistair (Infracost)

Alistair (Infracost)

11/21/2022, 12:17 PM
t

tom mg

11/21/2022, 12:44 PM
oh thanks for that! I guess we might safely remove this verification as we’ll start handling custom instances, right?
Alistair (Infracost)

Alistair (Infracost)

11/21/2022, 12:47 PM
Yep
t

tom mg

11/21/2022, 5:50 PM
I noticed that the node pool is 3x times bigger than the actual instance.
google_compute_instance.vm-dev-1
 β”œβ”€ Custom Instance CPU usage (Linux/UNIX, on-demand, custom-20-20480)                 730  hours               $583.90
 └─ Custom Instance RAM usage (Linux/UNIX, on-demand, custom-20-20480)                 730  gibibyte hour       $170.97

 google_compute_instance.vm-dev-2
 β”œβ”€ Custom Instance CPU usage (Linux/UNIX, on-demand, custom-20-20480-ext)             730  hours               $583.90
 β”œβ”€ Custom Instance RAM usage (Linux/UNIX, on-demand, custom-20-20480-ext)             730  gibibyte hour       $170.97
 └─ Standard provisioned storage (pd-standard)                                          10  GB                    $0.48

 google_compute_instance.vm-dev-3
 β”œβ”€ Custom Instance CPU usage (Linux/UNIX, on-demand, n2-custom-20-20480)              730  hours               $434.58
 └─ Custom Instance RAM usage (Linux/UNIX, on-demand, n2-custom-20-20480)              730  gibibyte hour        $63.69

 google_compute_instance.vm-dev-4
 β”œβ”€ Custom Instance CPU usage (Linux/UNIX, on-demand, n2-custom-20-20480-ext)          730  hours               $434.58
 β”œβ”€ Custom Instance RAM usage (Linux/UNIX, on-demand, n2-custom-20-20480-ext)          730  gibibyte hour       $119.00
 └─ Standard provisioned storage (pd-standard)                                          10  GB                    $0.48

 google_container_node_pool.dev-1
 β”œβ”€ Standard provisioned storage (pd-standard)                                         300  GB                   $14.40
 β”œβ”€ Custom Instance CPU usage (Linux/UNIX, on-demand, custom-20-20480)               2,190  hours             $1,751.69
 └─ Custom Instance RAM usage (Linux/UNIX, on-demand, custom-20-20480)               2,190  gibibyte hour       $512.90

 google_container_node_pool.dev-2
 β”œβ”€ Standard provisioned storage (pd-standard)                                         300  GB                   $14.40
 β”œβ”€ Custom Instance CPU usage (Linux/UNIX, on-demand, custom-20-20480-ext)           2,190  hours             $1,751.69
 └─ Custom Instance RAM usage (Linux/UNIX, on-demand, custom-20-20480-ext)           2,190  gibibyte hour       $512.90

 google_container_node_pool.dev-3
 β”œβ”€ Standard provisioned storage (pd-standard)                                         300  GB                   $14.40
 β”œβ”€ Custom Instance CPU usage (Linux/UNIX, on-demand, n2-custom-20-20480)            2,190  hours             $1,303.73
 └─ Custom Instance RAM usage (Linux/UNIX, on-demand, n2-custom-20-20480)            2,190  gibibyte hour       $191.07

 google_container_node_pool.dev-4
 β”œβ”€ Standard provisioned storage (pd-standard)                                         300  GB                   $14.40
 β”œβ”€ Custom Instance CPU usage (Linux/UNIX, on-demand, n2-custom-20-20480-ext)        2,190  hours             $1,303.73
 └─ Custom Instance RAM usage (Linux/UNIX, on-demand, n2-custom-20-20480-ext)        2,190  gibibyte hour       $356.99
A quick troubleshoot lead me to this https://github.com/7onn/infracost/blob/master/internal/providers/terraform/google/container_node_pool.go#L64-L74 In fact, there are three possible zones.. but this doesn't mean that three nodes will be provisioned. If the autoscaling.min_count is 1 and the cluster is cool, we'll have a single machine in some of the AZs of the selected region and not three πŸ€” I believe this is wrongly multiplying the resource consumption for GKE node pools πŸ€” Please, correct me If I'm wrong.
Alistair (Infracost)

Alistair (Infracost)

11/21/2022, 5:58 PM
As far as I remember it differs depending on what the
location
is set to. If it’s set to a region (us-central1) then it creates 3 nodes. If it’s set to a AZ (us-cental1-a) then it creates 1.
t

tom mg

11/21/2022, 6:03 PM
Makes sense. But still, I am passing the zone
europe-central2-c
. Therefore 1 node would be provisioned, right? I'll see how I can handle this and avoid multiplying this result by 3. But don't worry. I won't end up πŸͺ’πŸ‚ shaving the yak hahaha
Alistair (Infracost)

Alistair (Infracost)

11/21/2022, 6:04 PM
what does the terraform look like that you are testing?
t

tom mg

11/21/2022, 6:06 PM
All node pools are set to a zone and not a region.
3:01 PM
Btw, I pushed the changes for enabling custom VM instance pricing on the PR πŸ˜ƒ
Alistair (Infracost)

Alistair (Infracost)

11/22/2022, 3:27 PM
πŸ˜›artyparrot: