aks

package
v0.4.11 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 22, 2024 License: Apache-2.0 Imports: 18 Imported by: 0

README

AKS Module

This module is responsible for collecting pricing information for AKS clusters.

Pricing Map

Because Azure has not yet implemented the pricing API into it's SDK :shame:, this package uses the 3rd party Azure Retail Prices SDK to grab the prices.

This is based on Azure's pricing model, where different prices are determined by a combination of those factors.

Price Stratification

The PricingMap is built out with the following structure:

root -> {
  regionName -> {
    machinePriority -> {
      operatingSystem -> {
        skuName -> information
      }
    }
  }
}

That way, in order to uniquely identify a price, we will have to have the following attributes of any VM:

  • the region it is deployed into
  • it's priority (spot or on-demand)
  • the operating system it is running
  • it's SKU (e.g. E8-4as_v4)

Machine Map

In order to collect the VMs that are relevant for AKS, this package grabs a list of relevant machines in the following way:

  • A list of AKS clusters for the subscription are obtained
  • Each VMSS (Virtual Machine Scale Set) that creates worker nodes is collected for the resource groups that Azure uses to provision VMs
  • Each VM for the VMSS is collected
  • VMSS and their metadata (namely their pricing SKU) is stored in a map with the following structure:
root -> {
  vmUniqueName -> information
}

In parallel, machine types and their relevant info are collected, stored in a map with the following structure:

root -> {
  region -> {
    sizeIdentifier -> sizingInformation
  }
}


The information contained on the VM Information is enough to uniquely identify both the machine itself and the price that accompanies it. The sizing information allows CPU and Memory price calculation.

Documentation

Index

Constants

View Source
const (
	AzurePriceSearchFilter = `serviceName eq 'Virtual Machines' and priceType eq 'Consumption'`
	AzureMeterRegion       = `'primary'`
	DefaultInstanceFamily  = "General purpose"

	MiBsToGiB = 1024
)
View Source
const (
	AZ_API_VERSION string = "2023-01-01-preview" // using latest API Version https://learn.microsoft.com/en-us/rest/api/cost-management/retail-prices/azure-retail-prices
)
View Source
const (
	ConcurrentGoroutineLimit = 10
)

Variables

View Source
var (
	ErrClientCreationFailure         = errors.New("failed to create client")
	ErrPageAdvanceFailure            = errors.New("failed to advance page")
	ErrPriceStorePopulationFailure   = errors.New("failed to populate price store")
	ErrMachineStorePopulationFailure = errors.New("failed to populate machine store")
	ErrVmPriceRetrievalFailure       = errors.New("failed to retrieve price info for VM")
)

Errors

View Source
var (
	InstanceCPUHourlyCostDesc = prometheus.NewDesc(
		prometheus.BuildFQName(cloudcost_exporter.MetricPrefix, subsystem, "instance_cpu_usd_per_core_hour"),
		"The cpu cost a compute instance in USD/(core*h)",
		[]string{"instance", "region", "machine_type", "family", "cluster_name", "price_tier", "operating_system"},
		nil,
	)
	InstanceMemoryHourlyCostDesc = prometheus.NewDesc(
		prometheus.BuildFQName(cloudcost_exporter.MetricPrefix, subsystem, "instance_memory_usd_per_gib_hour"),
		"The memory cost of a compute instance in USD/(GiB*h)",
		[]string{"instance", "region", "machine_type", "family", "cluster_name", "price_tier", "operating_system"},
		nil,
	)
	InstanceTotalHourlyCostDesc = prometheus.NewDesc(
		prometheus.BuildFQName(cloudcost_exporter.MetricPrefix, subsystem, "instance_total_usd_per_hour"),
		"The total cost of an compute instance in USD/h",
		[]string{"instance", "region", "machine_type", "family", "cluster_name", "price_tier", "operating_system"},
		nil,
	)
)

Prometheus Metrics

View Source
var (
	ErrMachineNotFound       = errors.New("machine not found in map")
	ErrMachineFamilyNotFound = errors.New("machine family not able to be determined by SKU")
	ErrMachineTierNotFound   = errors.New("machine tier not found in VMSS object")

	// As annoying as this is, I am unable to find an API call for this
	// and performance of a map lookup will be quite faster
	// than maintaining lists of each family
	//
	// Based on this logic https://learn.microsoft.com/en-us/azure/virtual-machines/vm-naming-conventions
	MachineFamilyTypeMap map[byte]string = map[byte]string{
		'A': "General purpose",
		'B': "General purpose",
		'D': "General purpose",
		'F': "Compute optimized",
		'E': "Memory optimized",
		'M': "Memory optimized",
		'L': "Storage optimized",
		'N': "GPU accelerated",
		'H': "High performance compute",
	}
)
View Source
var (
	ErrPriceInformationNotFound = errors.New("price information not found in map")
	ErrMaxRetriesReached        = errors.New("max retries reached")
)

Functions

This section is empty.

Types

type Collector

type Collector struct {
	PriceStore   *PriceStore
	MachineStore *MachineStore
	// contains filtered or unexported fields
}

Collector is a prometheus collector that collects metrics from AKS clusters.

func New

func New(ctx context.Context, cfg *Config, azClientWrapper azureClientWrapper.AzureClient) (*Collector, error)

func (*Collector) Collect

func (c *Collector) Collect(ch chan<- prometheus.Metric) error

Collect satisfies the provider.Collector interface.

func (*Collector) CollectMetrics

func (c *Collector) CollectMetrics(_ chan<- prometheus.Metric) float64

CollectMetrics is a no-op function that satisfies the provider.Collector interface. Deprecated: CollectMetrics is deprecated and will be removed in a future release.

func (*Collector) Describe

func (c *Collector) Describe(ch chan<- *prometheus.Desc) error

func (*Collector) Name

func (c *Collector) Name() string

func (*Collector) Register

func (c *Collector) Register(_ provider.Registry) error

type Config

type Config struct {
	Logger      *slog.Logger
	Credentials *azidentity.DefaultAzureCredential

	SubscriptionId string
}

type MachineOperatingSystem added in v0.1.6

type MachineOperatingSystem int
const (
	Linux MachineOperatingSystem = iota
	Windows
)

func (MachineOperatingSystem) String added in v0.1.6

func (mo MachineOperatingSystem) String() string

type MachinePrices added in v0.3.0

type MachinePrices struct {
	PricePerCore float64
	PricePerGiB  float64
}

type MachinePriority added in v0.1.6

type MachinePriority int
const (
	OnDemand MachinePriority = iota
	Spot
)

func (MachinePriority) String added in v0.1.6

func (mp MachinePriority) String() string

type MachineSku added in v0.3.0

type MachineSku struct {
	RetailPrice float64

	MachinePricesBreakdown *MachinePrices
}

type MachineStore added in v0.2.2

type MachineStore struct {
	MachineSizeMap map[string]map[string]*armcompute.VirtualMachineSize

	MachineMap map[string]*VirtualMachineInfo
	// contains filtered or unexported fields
}

func NewMachineStore added in v0.2.2

func NewMachineStore(parentCtx context.Context, parentLogger *slog.Logger, azClientWrapper azureClientWrapper.AzureClient) (*MachineStore, error)

func (*MachineStore) GetListOfVmsForSubscription added in v0.3.3

func (m *MachineStore) GetListOfVmsForSubscription() []*VirtualMachineInfo

func (*MachineStore) PopulateMachineStore added in v0.2.2

func (m *MachineStore) PopulateMachineStore(ctx context.Context)

type PriceByOperatingSystem added in v0.1.6

type PriceByOperatingSystem map[MachineOperatingSystem]PriceBySku

type PriceByPriority added in v0.1.6

type PriceByPriority map[MachinePriority]PriceByOperatingSystem

type PriceBySku added in v0.1.6

type PriceBySku map[string]*MachineSku

type PriceStore added in v0.1.6

type PriceStore struct {
	RegionMap map[string]PriceByPriority
	// contains filtered or unexported fields
}

func NewPricingStore added in v0.1.6

func NewPricingStore(ctx context.Context, parentLogger *slog.Logger, azClientWrapper azureClientWrapper.AzureClient) *PriceStore

func (*PriceStore) PopulatePriceStore added in v0.1.6

func (p *PriceStore) PopulatePriceStore(ctx context.Context)

type VirtualMachineInfo added in v0.2.2

type VirtualMachineInfo struct {
	Name            string
	Id              string
	Region          string
	OwningVMSS      string
	OwningCluster   string
	MachineTypeSku  string
	MachineFamily   string
	OperatingSystem MachineOperatingSystem
	Priority        MachinePriority

	NumOfCores     float64
	MemoryInMiB    float64 // Note, the Azure Docs say MiB, the golang docs say MB, we're going with the Azure Docs :nervous:
	OsDiskSizeInMB float64
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL