What is Karpenter?

Karpenter is an open-source cluster autoscaler built for Kubernetes. It dynamically launches just the right compute resources to handle your cluster’s workloads and efficiently scales them based on real-time demand.

Unlike traditional autoscalers, Karpenter can provision nodes in seconds and makes scheduling decisions at the pod level, enabling highly dynamic infrastructure scaling.


Why Special Configuration Is Needed with Karpenter

By default, Odigos adds a node affinity rule to all instrumented pods to ensure they only run on nodes where odiglet is installed.

This works fine in static clusters — but in Karpenter-managed clusters, this causes a problem:

  • odiglet is installed by a DaemonSet after the node is created.
  • The label odigos.io/odiglet-installed=true is only added to the node at runtime.
  • Karpenter does not know in advance that this label will appear.
  • So when the scheduler tries to place a pod with this affinity, Karpenter concludes: “no nodes exist (or can be created) that match this label” — and no node is provisioned.

Once you enable the Karpenter integration option (explained below), Odigos will no longer apply node affinity to new instrumented pods. Instead, it relies on a startup taint mechanism:

  • Nodes launched by Karpenter should be initialized with a special taint (odigos.io/needs-init=NoSchedule).
    The exact method for configuring this taint in Karpenter will be explained in the following section.
  • The odiglet removes this taint after it prepares the node for instrumentation.
  • This allows instrumented pods to schedule only after the node is ready — achieving the same safety as affinity, without blocking provisioning.

How to Configure Odigos for Karpenter

To enable seamless integration between Odigos and Karpenter, follow these four steps:

1. Configure the Karpenter NodePool CRD

You must configure your Karpenter NodePool to include a startup taint. This ensures Odigos can prepare each node before instrumented pods are scheduled onto it.

Add the following under spec.template.spec.startupTaints:

spec:
  template:
    spec:
      startupTaints:
      - key: odigos.io/needs-init
        effect: NoSchedule

To safely append this taint without overwriting any existing startupTaints, use the following command:

export NODEPOOL_NAME=<NODEPOOL_NAME>
kubectl patch nodepool $NODEPOOL_NAME --type merge --patch "$(kubectl get nodepool $NODEPOOL_NAME -o json | jq -c '.spec.template.spec.startupTaints = (.spec.template.spec.startupTaints // []) + [{"key":"odigos.io/needs-init","effect":"NoSchedule"}] | {spec: {template: {spec: .spec.template.spec}}}')"

Replace <NODEPOOL_NAME> with the actual name of your Karpenter NodePool.


2. Add the Startup Taint to Existing Nodes

To manually add the startup taint to all current nodes:

kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' | xargs -I {} kubectl taint node {} odigos.io/needs-init=:NoSchedule --overwrite

This ensures existing nodes behave consistently until they’re replaced by Karpenter-managed ones.


3. Enable the Karpenter Integration in Odigos

Once the tainting setup is complete, inform Odigos to disable node affinity and rely on the taint mechanism.

Run the following using the Odigos CLI:

odigos set config karpenter-enabled=true

4. Restart the Odiglet DaemonSet

To ensure that taint-removal logic is triggered on all nodes, perform a rolling restart of the odiglet DaemonSet:

kubectl rollout restart daemonset/odiglet -n odigos-system