Karpenter Documentation

repository·main·Indexed 24 days ago

https://github.com/kubernetes-sigs/karpenter

An efficient Kubernetes autoscaler that provisions and removes nodes based on unschedulable pod requirements. This documentation includes details on the DRA KWOK Driver for simulating Dynamic Resource Allocation drivers (such as GPU and FPGA) using DRAConfig CRDs, and the Karpenter KwoK Provider for testing and simulating hypothetical nodes via KWOKNodeClass and NodePools.

Tokens
48.6K
Snippets
65
Records
178
Agent score
83%

What's inside Karpenter

  1. What is the DRA KWOK Driver?

    main
    The DRA KWOK Driver is a Kubernetes Dynamic Resource Allocation (DRA) driver designed for testing. It creates ResourceSlice objects on Karpenter KWOK nodes, allowing developers to simulate multiple DRA drivers (such as gpu.nvidia.com or fpga.intel.com) simultaneously. This enables comprehensive DRA integration testing in environments without actual physical hardware or specialized devices.
  2. Available Karpenter Cloud Implementations

    main

    Karpenter is a multi-cloud project. While the core logic is shared, you must use a provider-specific implementation for your cloud environment. Supported implementations include:

    • AWS
    • Azure
    • AlibabaCloud
    • Bizfly Cloud
    • Clever Cloud
    • Cluster API
    • Exoscale
    • GCP
    • Hetzner
    • Huawei Cloud
    • IBM Cloud
    • Oracle Cloud Infrastructure (OCI) (Officially maintained by Oracle; also maintained by Zoom)
    • Proxmox
    • Akamai/Linode (Alpha)
  3. Understand the scope and responsibilities of Karpenter

    main

    Karpenter is a node autoscaler designed to provision compute capacity for pods and remove unused capacity. To maintain a simple and stable API, the project follows specific boundaries regarding its responsibilities:

    What Karpenter Does

    • Provisions compute capacity to allow pods to run.
    • Removes capacity that is no longer needed.
    • Emits Kubernetes events, status conditions, and Prometheus metrics.
    • Provides configuration to express desired behavior (e.g., consolidation policies or disruption budgets).

    What Karpenter Does NOT Do (Out-of-Scope)

    • Notification Delivery: Karpenter does not send webhooks, Slack, email, or PagerDuty alerts. You must use external tooling to consume its emitted signals.
    • Pod Scheduling: Karpenter provisions nodes, but it does not decide which pod runs on which node; that is the responsibility of the kube-scheduler.
    • Workload Management: Karpenter does not scale pods or manage workload replicas. Use tools like HPA, KEDA, or VPA for workload lifecycle management.
    • Provider-Specific Logic: The kubernetes-sigs/karpenter repository is provider-neutral. Cloud-specific features (e.g., AWS, Azure) are located in their respective provider repositories.
    • Internal Implementation Exposure: Karpenter configuration is designed for users to express what they want (desired state), not how the internal mechanics (like thread concurrency) should operate.
  4. What is Karpenter and how does it work?

    main

    Karpenter is a Kubernetes autoscaler that improves workload efficiency and cost by automating node management. It operates through a continuous loop:

    1. Watching: It monitors for pods that the Kubernetes scheduler has marked as unschedulable.
    2. Evaluating: It analyzes pod scheduling constraints, including:
      • resource requests
      • nodeSelectors
      • affinitys
      • tolerations
      • topologySpreadConstraints
    3. Provisioning: It provisions new nodes that specifically meet the requirements of those unschedulable pods.
    4. Removing: It removes nodes when they are no longer needed to optimize costs.
  5. What is a NodeOverlay and when to use it

    main

    A NodeOverlay is a Karpenter API resource used to inject alternative assumptions into the scheduling simulation. By default, Karpenter relies on cloud provider APIs for instance type offerings and base prices. NodeOverlay allows users to fine-tune these simulations for advanced use cases that the standard API cannot express, such as custom pricing models or extended resource capacities.

    Use Cases

    • Complex Pricing: Adjusting for vendor fees, negotiated discounts, capacity type discounts, or carbon-offset costs.
    • Resource Capacity Management: Accounting for extended resources (like GPUs or HugePages) or custom system overhead that isn't captured by standard CPU/Memory metrics.

    How it works

    NodeOverlay uses a requirements field to match specific instance types or NodePools. When multiple overlays match an offering, they are merged using spec.weight to resolve conflicts. Changes to price, priceAdjustment, or capacity are integrated into Karpenter's scheduling and consolidation cycles automatically.

    apiVersion: karpenter.sh/v1alpha1
    kind: NodeOverlay
    metadata:
      name: default
    spec:
      weight: ...
      requirements:
        ... 
      price: 
      priceAdjustment: ... 
      capacity: 
        ...
    status:
      condition:
      - lastTransitionTime: "..."
        message: ""
        reason: ...
        status: "True"
        type: Ready
  6. Apply Constraint Propagation to NodeClaims

    main

    When a pod with DRA requirements is added to a NodeClaim, two constraints are applied in order during NodeClaim.Add():

    1. Requirement tightening: Topology constraints (e.g., topology.kubernetes.io/zone: us-west-2a) from AllocationResult.Requirements are merged into the NodeClaim requirements using Requirements.Add(), which performs intersection-based narrowing.
    2. Instance type re-evaluation: The full instance type filtering pipeline is re-run. This ensures that tightened requirements (like a specific zone) are checked against all instance type offerings. Additionally, AllocationResult.InstanceTypes is used to filter for only those instance types where the DRA DFS succeeded.
  7. Handle NodeOverlay misconfigurations and conflicts

    main

    If multiple NodeOverlay resources have the same weight and conflicting configurations, Karpenter follows a Fail Open approach to maintain system availability:

    1. Alphabetical Resolution: Conflicts are resolved using alphabetical ordering of the overlay names.
    2. Status Reporting: The overlay's Ready status condition is set to False with a reason of conflict and a message indicating which overlay it conflicted with.
    3. Operational Continuity: Karpenter continues provisioning and consolidation operations even if the overlay configurations do not match the user's intent.

    Note: If an unapplied overlay defines extended resources (like HugePages), pods requiring those resources will fail to provision capacity, consistent with standard Karpenter behavior when required resources are unavailable.

    kind: NodeOverlay
    metadata:
      name: memory-1
    spec:
      weight: 90
      requirements:
      - key: karpenter.k8s.aws/instance-memory
        operator: Gt
        values: ["m5.large", "m5.2xlarge"]
      capacity:
        memory: 50Mi
    status:
      condition:
      - lastTransitionTime: "..."
        message: "conflict with overlay capacity-1"
        reason: "conflict"
        status: "False"
        type: Ready
    ---
    kind: NodeOverlay
    metadata:
      name: capacity-1
    spec:
      weight: 90
      requirements:
      - key: node.kubernetes.io/instance-type
        operator: In
        values: ["c5.large", "c5.2xlarge", "m5.2xlarge"]
      capacity:
        memory: 100Mi
    status:
      condition:
      - lastTransitionTime: "..."
        message: ""
        reason: ...
        status: "True"
        type: Ready
  8. Zonal distribution in Static NodePools

    main

    Static NodePools do not currently support automatic topology-aware spreading. They rely entirely on the requirements defined in the NodePool spec.

    To ensure nodes are spread across specific zones, you must explicitly:

    1. Specify multiple zones in the topology.kubernetes.io/zone requirement using the In operator.
    2. Or, create multiple static NodePools, each pinned to a specific Availability Zone (AZ).
    requirements:
      - key: topology.kubernetes.io/zone
        operator: In
        values: ["zone-2a", "zone-2b", "zone-2c"]
  9. Disruption and Drift in Static NodePools

    main

    Static NodePools inherit Karpenter's dynamic provider integration, including Drift Detection.

    • Drift Replacement: When a node drifts, Karpenter performs a one-for-one replacement (creating the new node before terminating the old one) to honor the replicas count, provided the limits.nodes is not exceeded.
    • Disruption Budgets: Karpenter-driven actions (like drift replacement) respect disruption.budgets. However, user-driven scaling actions (via kubectl scale) are treated as automated forceful disruptions and do not respect disruption budgets.
    • Consolidation: Static nodes are excluded from cost-based consolidation decisions.
  10. Control Forceful Termination with TerminationGracePeriod

    main

    When using Forceful Expiration, Karpenter uses a TerminationGracePeriod (TGP) to ensure nodes are eventually removed even if pods are blocking the drain.

    1. Karpenter adds a NoSchedule taint and a TerminationGracePeriod timestamp to the NodeClaim.
    2. Karpenter begins draining the node, respecting PDBs and do-not-disrupt pods.
    3. Once the TGP timeout is reached, Karpenter performs a forceful termination of the underlying instance, cleaning up daemons and networking applications regardless of remaining pods.
  11. Use pod-deletion-cost to signal disruption sensitivity

    main

    Karpenter uses the Kubernetes controller.kubernetes.io/pod-deletion-cost annotation to weight the disruption cost of a node. This allows you to protect specific pods from being moved during consolidation.

    • Higher values: Increase the disruption cost of the node, making it less likely to be consolidated.
    • Negative values: Decrease the disruption cost. If a pod's EvictionCost is sufficiently negative, it can effectively signal that the pod is 'free to disrupt,' allowing the node to be treated as WhenEmpty for consolidation purposes.

    This annotation is used by the ReplicaSet controller for scale-down ordering and is reused by Karpenter's scoring engine.

  12. Predict pod resource changes via dry-run pod creates

    main

    Karpenter can use dry-run pod creation to determine what a pod's resources will be after recreation (e.g., after a VPA update). This method uses the Kubernetes API server's admission chain (POST /api/v1/namespaces/{ns}/pods?dryRun=All) to simulate pod creation without persisting changes.

    To use this mechanism, pods or their templates must be annotated to signal that their requests are volatile.

    Workflow:

    1. Annotation: Apply autoscaling.k8s.io/volatile-requests: "true" to pods or templates.
    2. Simulation: A background controller identifies annotated pods, groups them by owner (e.g., ReplicaSet), and submits dry-run creates.
    3. Caching: The predicted Ceiling() result is cached, keyed by (namespace, owner-uid). Karpenter uses this cache during consolidation simulation.
    4. Validation: Before eviction, Karpenter re-runs a fresh dry-run. If the result differs from the simulation, the decision is rejected.

    Requirements:

    • Requires create pods RBAC cluster-wide (note: RBAC does not distinguish between dry-run and real creates).
    • Pods must have an owner (e.g., ReplicaSet) to be processed; unowned pods are skipped.