Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add option for extra hourly cost per host #7609

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions charts/karpenter/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ spec:
- name: RESERVED_ENIS
value: "{{ . }}"
{{- end }}
{{- with .Values.settings.extraHourlyCostPerHost }}
- name: EXTRA_HOURLY_COST_PER_HOST
value: "{{ . }}"
{{- end }}
{{- with .Values.controller.env }}
{{- toYaml . | nindent 12 }}
{{- end }}
Expand Down
2 changes: 2 additions & 0 deletions charts/karpenter/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ settings:
# -- Reserved ENIs are not included in the calculations for max-pods or kube-reserved
# This is most often used in the VPC CNI custom networking setup https://docs.aws.amazon.com/eks/latest/userguide/cni-custom-network.html
reservedENIs: "0"
# -- The additional hourly cost per host, added to the total instance cost, is useful for accounting for extra expenses such as Datadog Infrastructure or APM per-host charges.
extraHourlyCostPerHost: 0.0
# -- Feature Gate configuration values. Feature Gates will follow the same graduation process and requirements as feature gates
# in Kubernetes. More information here https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/#feature-gates-for-alpha-or-beta-features
featureGates:
Expand Down
2 changes: 2 additions & 0 deletions pkg/operator/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type Options struct {
VMMemoryOverheadPercent float64
InterruptionQueue string
ReservedENIs int
ExtraHourlyCostPerHost float64
}

func (o *Options) AddFlags(fs *coreoptions.FlagSet) {
Expand All @@ -53,6 +54,7 @@ func (o *Options) AddFlags(fs *coreoptions.FlagSet) {
fs.Float64Var(&o.VMMemoryOverheadPercent, "vm-memory-overhead-percent", utils.WithDefaultFloat64("VM_MEMORY_OVERHEAD_PERCENT", 0.075), "The VM memory overhead as a percent that will be subtracted from the total memory for all instance types when cached information is unavailable.")
fs.StringVar(&o.InterruptionQueue, "interruption-queue", env.WithDefaultString("INTERRUPTION_QUEUE", ""), "Interruption queue is the name of the SQS queue used for processing interruption events from EC2. Interruption handling is disabled if not specified. Enabling interruption handling may require additional permissions on the controller service account. Additional permissions are outlined in the docs.")
fs.IntVar(&o.ReservedENIs, "reserved-enis", env.WithDefaultInt("RESERVED_ENIS", 0), "Reserved ENIs are not included in the calculations for max-pods or kube-reserved. This is most often used in the VPC CNI custom networking setup https://docs.aws.amazon.com/eks/latest/userguide/cni-custom-network.html.")
fs.Float64Var(&o.ExtraHourlyCostPerHost, "extra-hourly-cost-per-host", utils.WithDefaultFloat64("EXTRA_HOURLY_COST_PER_HOST", 0.0), "The additional hourly cost per host, added to the total instance cost, is useful for accounting for extra expenses such as Datadog Infrastructure or APM per-host charges.")
}

func (o *Options) Parse(fs *coreoptions.FlagSet, args ...string) error {
Expand Down
7 changes: 6 additions & 1 deletion pkg/operator/options/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ var _ = Describe("Options", func() {
"--isolated-vpc",
"--vm-memory-overhead-percent", "0.1",
"--interruption-queue", "env-cluster",
"--reserved-enis", "10")
"--reserved-enis", "10",
"--extra-hourly-cost-per-host", "0.66")
Expect(err).ToNot(HaveOccurred())
expectOptionsEqual(opts, test.Options(test.OptionsFields{
ClusterCABundle: lo.ToPtr("env-bundle"),
Expand All @@ -72,6 +73,7 @@ var _ = Describe("Options", func() {
VMMemoryOverheadPercent: lo.ToPtr[float64](0.1),
InterruptionQueue: lo.ToPtr("env-cluster"),
ReservedENIs: lo.ToPtr(10),
ExtraHourlyCostPerHost: lo.ToPtr[float64](0.66),
}))
})
It("should correctly fallback to env vars when CLI flags aren't set", func() {
Expand All @@ -82,6 +84,7 @@ var _ = Describe("Options", func() {
os.Setenv("VM_MEMORY_OVERHEAD_PERCENT", "0.1")
os.Setenv("INTERRUPTION_QUEUE", "env-cluster")
os.Setenv("RESERVED_ENIS", "10")
os.Setenv("EXTRA_HOURLY_COST_PER_HOST", "0.88")

// Add flags after we set the environment variables so that the parsing logic correctly refers
// to the new environment variable values
Expand All @@ -96,6 +99,7 @@ var _ = Describe("Options", func() {
VMMemoryOverheadPercent: lo.ToPtr[float64](0.1),
InterruptionQueue: lo.ToPtr("env-cluster"),
ReservedENIs: lo.ToPtr(10),
ExtraHourlyCostPerHost: lo.ToPtr[float64](0.88),
}))
})

Expand Down Expand Up @@ -131,4 +135,5 @@ func expectOptionsEqual(optsA *options.Options, optsB *options.Options) {
Expect(optsA.VMMemoryOverheadPercent).To(Equal(optsB.VMMemoryOverheadPercent))
Expect(optsA.InterruptionQueue).To(Equal(optsB.InterruptionQueue))
Expect(optsA.ReservedENIs).To(Equal(optsB.ReservedENIs))
Expect(optsA.ExtraHourlyCostPerHost).To(Equal(optsB.ExtraHourlyCostPerHost))
}
13 changes: 12 additions & 1 deletion pkg/providers/pricing/pricing.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,24 @@ func (p *DefaultProvider) UpdateOnDemandPricing(ctx context.Context) error {

err := multierr.Append(onDemandErr, onDemandMetalErr)
if err != nil {
return fmt.Errorf("retreiving on-demand pricing data, %w", err)
return fmt.Errorf("retrieving on-demand pricing data, %w", err)
}

if len(onDemandPrices) == 0 || len(onDemandMetalPrices) == 0 {
return fmt.Errorf("no on-demand pricing found")
}

extraHourlyCost := options.FromContext(ctx).ExtraHourlyCostPerHost

// Adjust on-demand prices to include the extra hourly cost
for instanceType, price := range onDemandPrices {
onDemandPrices[instanceType] = price + extraHourlyCost
}

for instanceType, price := range onDemandMetalPrices {
onDemandMetalPrices[instanceType] = price + extraHourlyCost
}

p.onDemandPrices = lo.Assign(onDemandPrices, onDemandMetalPrices)
if p.cm.HasChanged("on-demand-prices", p.onDemandPrices) {
log.FromContext(ctx).WithValues("instance-type-count", len(p.onDemandPrices)).V(1).Info("updated on-demand pricing")
Expand Down
1 change: 1 addition & 0 deletions pkg/test/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type OptionsFields struct {
VMMemoryOverheadPercent *float64
InterruptionQueue *string
ReservedENIs *int
ExtraHourlyCostPerHost *float64
}

func Options(overrides ...OptionsFields) *options.Options {
Expand Down
1 change: 1 addition & 0 deletions website/content/en/preview/reference/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Karpenter surfaces environment variables and CLI parameters to allow you to conf
| MEMORY_LIMIT | \-\-memory-limit | Memory limit on the container running the controller. The GC soft memory limit is set to 90% of this value. (default = -1)|
| METRICS_PORT | \-\-metrics-port | The port the metric endpoint binds to for operating metrics about the controller itself (default = 8080)|
| RESERVED_ENIS | \-\-reserved-enis | Reserved ENIs are not included in the calculations for max-pods or kube-reserved. This is most often used in the VPC CNI custom networking setup https://docs.aws.amazon.com/eks/latest/userguide/cni-custom-network.html. (default = 0)|
| EXTRA_HOURLY_COST_PER_HOST | \-\-extra-hourly-cost-per-host | The additional hourly cost per host, added to the total instance cost, is useful for accounting for extra expenses such as Datadog Infrastructure or APM per-host charges. |
| VM_MEMORY_OVERHEAD_PERCENT | \-\-vm-memory-overhead-percent | The VM memory overhead as a percent that will be subtracted from the total memory for all instance types when cached information is unavailable. (default = 0.075)|

[comment]: <> (end docs generated content from hack/docs/configuration_gen_docs.go)
Expand Down