Configuration

June 16, 2026 · View on GitHub

This guide details the configuration options for the Karpenter Provider for Linode, covering environment variables, operating modes, and the LinodeNodeClass Custom Resource.

Environment Variables

VariableDescriptionRequired?Default
LINODE_TOKENYour Linode API Personal Access Token.Yes-
CLUSTER_NAMEThe name of your LKE cluster. Used to discover the cluster ID in lke mode.Yes (in lke mode)-
LINODE_REGIONThe Linode region code. See available regions.Nous-east
CLUSTER_ENDPOINTThe external Kubernetes cluster endpoint. Discovered automatically if not provided.No-
KARPENTER_MODEOperating mode: lke or instance. See Modes below.Nolke
LINODE_CLIENT_TIMEOUTTimeout in seconds for Linode API client requests.No-
VM_MEMORY_OVERHEAD_PERCENTAdditional memory overhead to simplify calculation (0.075 = 7.5%).No0.075
DISABLE_DRY_RUNSet to true to disable dry-run validation for LinodeNodeClasses.Nofalse

These environment variables are injected into the controller pod via a Kubernetes Secret. By default, the Helm chart creates a secret called karpl-credentials from the apiToken, apiURL, apiVersion, and region values.

Note: Using an external secret (GitOps)

For GitOps workflows where credentials should not be stored in Helm values, you can set credentialsSecretRef to point to a pre-existing Secret instead. When set, the chart skips creating its own secret and uses the referenced one. This is useful when secrets are managed externally via ExternalSecrets, SealedSecrets, Vault, or similar tools.

The externally managed secret must contain the following keys: LINODE_TOKEN, LINODE_URL, LINODE_API_VERSION, and optionally CLUSTER_REGION.

helm upgrade --install karpenter charts/karpenter \
    --set settings.clusterName=my-cluster \
    --set credentialsSecretRef=my-linode-credentials

Modes

The provider can operate in two distinct modes, controlled by the KARPENTER_MODE environment variable.

LKE Mode (lke)

  • Default Mode.
  • Provisions nodes by creating LKE Node Pools with a count of 1.
  • The nodes are automatically joined to your LKE cluster.
  • Pros: Simplest setup, managed by LKE.
  • Cons: Limited customization (cannot use custom images or advanced networking/storage options usually available to raw Linodes).

Instance Mode (instance)

  • Provisions nodes by creating raw Linode Instances.
  • Status: ⚠️ In Development. Not Fully Functional
    • This mode represents the roadmap for full instance control but is not currently functional for creating working cluster nodes.
    • It currently lacks bootstrapping and cluster joining logic (such as User Data injection). Instances will start but will not join the Kubernetes cluster.
  • Pros: Full control over the instance configuration (SSH keys, placement groups, etc.).
  • Note: VPCID and custom disk configurations are defined in the API but not yet fully implemented in the provider logic.

LinodeNodeClass Spec

The LinodeNodeClass allows you to configure specific settings for the nodes managed by Karpenter. Support for specific fields depends on the Mode you are running.

Field Reference

FieldTypeSupported ModesDescription
tags[]stringAllList of tags to apply to instances. In LKE mode, Karpenter-managed pools keep only core provider tags.
firewallIDintAllThe ID of the Cloud Firewall to attach.
lkeK8sVersionstringLKESpecific Kubernetes version for LKE Enterprise worker nodes. Upgrade the cluster control plane to this version first; otherwise reconciliation fails and replacement NodeClaims will not come up on the requested version. For Enterprise clusters, the update strategy automatically defaults to on_recycle.
imagestringInstanceThe Image ID to deploy (default: linode/ubuntu22.04).
authorizedKeys[]stringInstanceSSH Public Keys to add to the root user.
authorizedUsers[]stringInstanceList of Linode usernames whose SSH keys will be added.
backupsEnabledboolInstanceEnable backups service for the instance.
diskEncryptionenumInstanceenabled or disabled.
swapSizeintInstanceSize of the swap disk in MiB.
placementGroupobjectInstancePlace instance in a specific Placement Group (see below).

Taints and Standard Labels

It is important to distinguish between Karpenter configuration and Linode-specific configuration:

  • Taints: Taints are defined in the Karpenter NodePool resource (spec.template.spec.taints), not in the LinodeNodeClass.
    • LKE Mode: Taints are passed to the LKE Node Pool configuration and applied to nodes by LKE.
  • Kubernetes Labels: Standard scheduling labels are defined in the Karpenter NodePool (spec.template.metadata.labels). Karpenter ensures these are applied to the Node object.
  • LKE Labels: LKE Node Pool labels are derived from the labels resolved onto the NodeClaim (originating from NodePool template metadata labels).

Example: LKE Mode

apiVersion: karpenter.k8s.linode/v1alpha1
kind: LinodeNodeClass
metadata:
  name: default
spec:
  tags:
    - "karpenter-node"
    - "env:production"
  firewallID: 12345

Example: Instance Mode

apiVersion: karpenter.k8s.linode/v1alpha1
kind: LinodeNodeClass
metadata:
  name: custom-instance
spec:
  tags:
    - "custom-workload"
  image: "linode/ubuntu22.04"
  authorizedUsers:
    - "my-user"
  backupsEnabled: true
  swapSize: 512
  diskEncryption: "enabled"

Selecting nodes

With nodeSelector you can ask for a node that matches selected key-value pairs. This can include well-known labels or custom labels you create yourself.

You can use affinity to define more complicated constraints, see Node Affinity for the complete specification.

Labels

Well-known labels may be specified as NodePool requirements or pod scheduling constraints. You can also define your own custom labels by specifying requirements or labels on your NodePool and select them using nodeAffinity or nodeSelectors on your Pods.

Well-Known Labels

LabelExampleDescription
topology.kubernetes.io/regionus-eastRegions are defined by your cloud provider (linode)
node.kubernetes.io/instance-typeg6-dedicated-16Instance types are defined by your cloud provider (linode)
kubernetes.io/oslinuxOperating systems are defined by GOOS values on the instance
kubernetes.io/archamd64Architectures are defined by GOARCH values on the instance
karpenter.k8s.linode/instance-generation6[Linode Specific] Instance type generation number
karpenter.k8s.linode/instance-cpu32[Linode Specific] Number of CPUs on the instance
karpenter.k8s.linode/instance-memory32768[Linode Specific] Number of megabytes of memory on the instance
karpenter.k8s.linode/instance-disk655360[Linode Specific] Number of megabytes of storage on the instance
karpenter.k8s.linode/instance-gpu-namegtx6000[Linode Specific] Name of the GPU on the instance, if available
karpenter.k8s.linode/instance-gpu-count1[Linode Specific] Number of GPUs on the instance
karpenter.k8s.linode/instance-transfer16000[Linode Specific] Number of gigabytes for network transfer
karpenter.k8s.linode/instance-network-out10000[Linode Specific] Number of megabits per second for network outbound bandwidth
karpenter.k8s.linode/instance-accelerated-devices-count1[Linode Specific] Number of accelerated devices on the instance
karpenter.k8s.linode/instance-classdedicated[Linode Specific] Instance class types include nanode, standard, dedicated, highmem, and gpu

User-Defined Labels

Karpenter is aware of several well-known labels, deriving them from instance type details. If you specify a nodeSelector or a required nodeAffinity using a label that is not well-known to Karpenter, it will not launch nodes with these labels and pods will remain pending. For Karpenter to become aware that it can schedule for these labels, you must specify the label in the NodePool requirements with the Exists operator:

requirements:
  - key: user.defined.label/type
    operator: Exists

Node selectors

Here is an example of a nodeSelector for selecting nodes:

nodeSelector:
  topology.kubernetes.io/region: us-east
  karpenter.sh/capacity-type: dedicated

This example features a well-known label (topology.kubernetes.io/region) and a label that is well known to Karpenter (karpenter.sh/capacity-type).

If you want to create a custom label, you should do that at the NodePool level. Then the pod can declare that custom label.

See nodeSelector in the Kubernetes documentation for details.