Skip to content

Component customization#

This page explains how to customize Kubernetes resources generated by k0smotron.

Overview#

k0smotron creates the Kubernetes resources (for example StatefulSet, Service, and ConfigMap) documented in Generated Resources through a k0smotron.io/v1beta2 Cluster. You can customize those generated resources by defining patches.

  • Standalone: You create the k0smotron.io/v1beta2 Cluster directly. See Create a cluster.
  • Cluster API integration: When k0smotron acts as a control plane provider (in-cluster), K0smotronControlPlane creates a k0smotron.io/v1beta2 Cluster, which then produces the same set of generated resources. See k0smotron as Cluster API provider.

In both modes, the resources that can be customized are the same, and you define patches in the same field (.spec.patches); only the resource that has that spec differs (Cluster in standalone, K0smotronControlPlane in Cluster API).

Where to define patches#

Define patches in spec.patches on the resource that owns the generated resources:

Mode Resource Field
Standalone k0smotron.io/v1beta2 Cluster Cluster.spec.patches
Cluster API (control plane provider - in-cluster) K0smotronControlPlane K0smotronControlPlane.spec.patches

The patch format and targeting rules are identical in both modes.

Examples#

Standalone#

The following example uses a k0smotron.io/v1beta2 Cluster (standalone). It targets the k0s configuration ConfigMap and adds a custom label using a merge patch.

apiVersion: k0smotron.io/v1beta2
kind: Cluster
metadata:
  name: docker-test
spec:
  version: v1.34.3-k0s.0
  patches:
  - target:
      kind: ConfigMap
      component: cluster-config
    patch:
      type: merge
      content: |
        metadata:
          labels:
            custom-label: "my-value"

Cluster API#

The following example builds on the Docker (HCP) example and adds patches. It demonstrates all three patch types (strategic, json, merge) targeting different components. Before starting, ensure that you have met the general prerequisites and initialized the Docker infrastructure provider as described in the Docker (HCP) guide.

Note: The K0smotronControlPlane spec embeds the k0smotron.io/v1beta2 ClusterSpec, so the patches field and all other fields follow the v1beta2 schema.

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: docker-test
  namespace: default
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
      - 192.168.0.0/16
    serviceDomain: cluster.local
    services:
      cidrBlocks:
      - 10.128.0.0/12
  controlPlaneRef:
    apiGroup: controlplane.cluster.x-k8s.io
    kind: K0smotronControlPlane
    name: docker-test-cp
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: DockerCluster
    name: docker-test
---
apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: K0smotronControlPlane
metadata:
  name: docker-test-cp
  namespace: default
spec:
  version: v1.34.3-k0s.0
  persistence:
    type: emptyDir
  service:
    type: LoadBalancer
  patches:
  # Set resource requests/limits and probe timing on the control-plane pods
  - target:
      kind: StatefulSet
      component: control-plane
    patch:
      type: strategic
      content: |
        spec:
          template:
            spec:
              containers:
                - name: controller
                  resources:
                    requests:
                      memory: "256Mi"
                      cpu: "250m"
                    limits:
                      memory: "512Mi"
                      cpu: "500m"
                  readinessProbe:
                    initialDelaySeconds: 10
                  livenessProbe:
                    initialDelaySeconds: 10
  # Increase the etcd readiness probe initial delay
  - target:
      kind: StatefulSet
      component: etcd
    patch:
      type: json
      content: '[{"op":"add","path":"/spec/template/spec/containers/0/readinessProbe/initialDelaySeconds","value":15}]'
  # Add an annotation to the control-plane Service
  - target:
      kind: Service
      component: control-plane
    patch:
      type: merge
      content: |
        metadata:
          annotations:
            example.com/managed-by: "k0smotron-customized"
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: DockerCluster
metadata:
  name: docker-test
  namespace: default
  annotations:
    cluster.x-k8s.io/managed-by: k0smotron
spec: {}
---
apiVersion: cluster.x-k8s.io/v1beta2
kind: MachineDeployment
metadata:
  name: docker-test-md
  namespace: default
spec:
  clusterName: docker-test
  replicas: 1
  selector:
    matchLabels:
      cluster.x-k8s.io/cluster-name: docker-test
      pool: worker-pool-1
  template:
    metadata:
      labels:
        cluster.x-k8s.io/cluster-name: docker-test
        pool: worker-pool-1
    spec:
      clusterName: docker-test
      version: v1.34.3
      bootstrap:
        configRef:
          apiGroup: bootstrap.cluster.x-k8s.io
          kind: K0sWorkerConfigTemplate
          name: docker-test-machine-config
      infrastructureRef:
        apiGroup: infrastructure.cluster.x-k8s.io
        kind: DockerMachineTemplate
        name: docker-test-mt
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: DockerMachineTemplate
metadata:
  name: docker-test-mt
  namespace: default
spec:
  template:
    spec: {}
---
apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
kind: K0sWorkerConfigTemplate
metadata:
  name: docker-test-machine-config
spec:
  template:
    spec:
      version: v1.34.3+k0s.0

After the cluster is provisioned, verify that the patches were applied. Resource names follow the conventions described in Generated Resources.

# Verify resource limits on the control-plane StatefulSet
kubectl get statefulset kmc-docker-test -o jsonpath='{.spec.template.spec.containers[0].resources}'

# Verify the control-plane probe timing
kubectl get statefulset kmc-docker-test -o jsonpath='{.spec.template.spec.containers[0].readinessProbe.initialDelaySeconds}'
kubectl get statefulset kmc-docker-test -o jsonpath='{.spec.template.spec.containers[0].livenessProbe.initialDelaySeconds}'

# Verify the etcd readiness probe initial delay
kubectl get statefulset kmc-docker-test-etcd -o jsonpath='{.spec.template.spec.containers[0].readinessProbe.initialDelaySeconds}'

# Verify the annotation on the control-plane Service
kubectl get service kmc-docker-test-lb -o jsonpath='{.metadata.annotations}'

Targeting resources#

To keep targeting predictable and maintainable, each patch entry has a target block that selects resources by:

  • kind: Kubernetes Kind (for example StatefulSet, Service, ConfigMap)
  • component: value of the app.kubernetes.io/component label on the generated resource

This avoids string-based targeting via names and avoids template-based targeting. See the Examples above.

Patch types#

Each patch entry has a patch block containing type and content. The format of content depends on type:

  • json: a JSON Patch array, an array of add/remove/replace operations
  • strategic: a Kubernetes strategic merge patch object, like merge but with array merge semantics based on patchStrategy tags
  • merge: a JSON Merge Patch object, a partial JSON/YAML object that is merged into the target resource

Component values#

k0smotron labels generated resources with app.kubernetes.io/component to describe their purpose. Use these values in the target.component field when targeting patches. For the full list of component values, resource types, and their naming conventions, see Generated Resources.

Note: A (kind, component) combination is not always unique. For example, component: monitoring is shared by two ConfigMaps (Prometheus and Nginx). A patch targeting such a combination will be applied to all matching resources.

Notes and limitations#

  • Patches are applied in list order after k0smotron generates each resource and before it is applied to the cluster. Multiple patches that match the same resource (same kind and component) are applied in sequence.
  • A patch is applied to all generated resources that match the given kind and component combination.
  • Only resources created and managed by the K0smotron Cluster (documented in Generated Resources) are patch targets. Other resources are not; for example, when using Cluster API, certificate Secrets are created by Cluster API controllers and follow Cluster API naming conventions, so they are not patch targets.