User guide

User guide

Keel maintains files and installed packages on Kubernetes nodes. You describe one task per NodeConfig; the Keel agent on each matching node applies it and checks it again periodically. Services can be restarted after a change.

NodeConfig authors administer the host OS. A namespace does not restrict which nodes a configuration can affect. Agree ownership and target nodes with your cluster administrator before applying changes.

Before you start

An administrator must install Keel and its CRD using the deployment guide. You need kubectl connected to that cluster and permission to manage NodeConfigs in your chosen namespace. These commands use tak-os; replace it consistently when using another namespace.

kubectl config current-context
kubectl auth can-i create nodeconfigs.keel.tlspu.io -n tak-os
kubectl get nodes --show-labels
kubectl -n tak-os get nodeconfigs

Choose labels that already identify your intended nodes. If you cannot list nodes, ask the administrator for the approved selector. Keel reads NodeConfigs across all namespaces, and an omitted or empty selector matches every node running an agent, including control-plane nodes in the supplied deployment.

Apply your first file configuration

Save this as keel-node-info.yaml. Replace replace-with-approved-node-name with the value of kubernetes.io/hostname on one approved node. The example writes a separate informational file and requests no service restarts.

apiVersion: keel.tlspu.io/v1
kind: NodeConfig
metadata:
  name: keel-node-info
  namespace: tak-os
spec:
  type: file
  interval: 10m
  nodeSelector:
    matchLabels:
      kubernetes.io/hostname: replace-with-approved-node-name
  params:
    filename: /etc/keel-node-info
    mode: "0644"
    contents: |
      Managed by Keel
      Node: {{ .Node.Name }}
      OS: {{ .Node.OSName }} {{ .Node.OSVersion }}
      Kubernetes: {{ .Cluster.KubernetesVersion }}

All parameter values are strings. Quote octal file modes and package versions. Paths are host paths such as /etc/keel-node-info; do not prepend /host.

kubectl apply --dry-run=server -f keel-node-info.yaml
kubectl apply -f keel-node-info.yaml
kubectl -n tak-os get nodeconfig keel-node-info -o yaml
kubectl -n tak-os describe nodeconfig keel-node-info

Server-side dry-run checks the CRD and, when installed, the admission webhook. It does not execute templates against node facts or test host writes. A successful kubectl apply means the API accepted the object; check per-node status for the host result. If the selector matches no node, the object can be accepted without any node status entries.

Read the result

For every intended node, inspect status.nodes[<node-name>]:

Field What to check
lastResult success means that run completed; error needs investigation
observedGeneration Compare with metadata.generation to check the node processed the current spec
changed Whether that recorded run modified host state
restartPending true means services still require a successful restart
message Application, no-change or error details
lastRunTime Time of the recorded outcome, not a continuously updated heartbeat

Steady no-change runs do not keep rewriting status. The top-level status.observedGeneration is not proof that every node processed the spec. Excluded or removed nodes can retain old entries. Check the current target node list and each node's entry. See troubleshooting for missing status or failed runs; operations explains Events and metrics.

Change and expand a configuration

Edit the saved manifest, repeat dry-run, apply it, and check the canary node's status and host behavior. A spec change runs without waiting for the normal interval. Once verified, replace the single-node selector with an approved pool label and apply again. NodeConfigs have no cluster-wide rolling-update or disruption-budget mechanism: matching nodes can all apply the change at once.

Use one owner for each host file or package. Different NodeConfigs have no dependency ordering; serialization on one node does not resolve conflicting desired states or coordinate different nodes. A package configuration followed by a file configuration is not an ordered installation workflow.

Normal successful runs repeat on spec.interval (default 10m). Failures retry with controller backoff. A node label update reevaluates selection, but does not guarantee an immediate rerun of a previously successful configuration whose interval has not elapsed. Node facts refresh independently from application.

Restart services after changes

For a configuration that needs a service restart, add its exact host systemd unit name:

  services:
    - example-agent.service

This is a fragment of spec, not a complete resource. Replace the example unit with one installed on your nodes. Keel runs systemctl daemon-reload and then restarts the listed units when the handler reports a change. Unchanged runs do not restart services unless an earlier restart is pending. Adding a service to an otherwise unchanged file configuration does not by itself force a restart.

A restart failure leaves the file/package change in place and records restartPending: true. Keel retries restarts on subsequent runs. There is no automatic rollback. Service names can be templated, but must render to literal unit names, without paths, options, whitespace or glob patterns.

Install a package

Use a separate NodeConfig with the same approved selector:

apiVersion: keel.tlspu.io/v1
kind: NodeConfig
metadata:
  name: keel-htop
  namespace: tak-os
spec:
  type: package
  interval: 6h
  nodeSelector:
    matchLabels:
      kubernetes.io/hostname: replace-with-approved-node-name
  params:
    package_name: htop

Package installation uses the host's repositories and package manager. Omitting version ensures presence; it does not continually upgrade an installed package. Review the handler reference before pinning versions or using different node distributions.

Request a run using a ConfigMap

Add a same-namespace trigger reference under spec:

  watchConfigMaps:
    - name: keel-refresh

After applying that spec, a trusted operator can create or update the trigger:

kubectl -n tak-os create configmap keel-refresh --from-literal=request=initial
kubectl -n tak-os annotate configmap keel-refresh keel.tlspu.io/request=manual-1 --overwrite

Use a new annotation value for a subsequent request. Creation, update, deletion and recreation trigger a run without waiting for the interval. The ConfigMap contains no template inputs: Keel does not copy its data into file contents or facts. Metadata-only edits to the NodeConfig itself do not force a run.

Stop managing or undo a change

kubectl -n tak-os delete nodeconfig keel-node-info

Deletion stops future reconciliation once agents observe it. It does not undo an operation already in progress, delete the host file, uninstall a package or restore service state. Removing a node from selection has the same persistence of host state. There is no suspend field.

To restore earlier file contents, apply the previous manifest while Keel still manages it, verify results, and then remove the NodeConfig if desired. Deleting a file or removing a package requires a separate administrator action; the built-in handlers do not support an absent state. Keep manifests and previous desired values in version control. For one-off filesystem work, see the local CLI guide.