Troubleshooting

Troubleshooting

Start with the affected NodeConfig and node. An API write succeeding, an agent being Ready and a host configuration succeeding are separate observations. Commands below use tak-os; use the NodeConfig's actual namespace when different.

Collect evidence

KEEL_CONFIG='replace-with-config-name'
KEEL_POD='replace-with-agent-pod-on-affected-node'
kubectl config current-context
kubectl -n tak-os get nodeconfig "$KEEL_CONFIG" -o yaml
kubectl -n tak-os describe nodeconfig "$KEEL_CONFIG"
kubectl -n tak-os get pods -l app.kubernetes.io/name=keel -o wide
kubectl -n tak-os logs "$KEEL_POD" --since=30m
kubectl -n tak-os describe pod "$KEEL_POD"
kubectl -n tak-os get events --sort-by=.metadata.creationTimestamp

Replace the two variable values with the affected resource names. The pod list shows which node each agent runs on.

Compare metadata.generation with the target node's status.nodes[<node-name>].observedGeneration. Read lastResult, message, changed and restartPending. Old status entries can remain after nodes cease matching the selector. Unchanged successful runs can leave lastRunTime old; use logs, Events and metrics to assess ongoing execution. Events expire and are best-effort, so collect relevant evidence promptly. Redact sensitive configuration and command output before sharing logs or snapshots.

Installation and readiness

Symptom Check and action
no matches for kind NodeConfig Install config/crd/bases/ before applying NodeConfigs and confirm the kubectl context
No agent on a node Compare DaemonSet desired/current/ready counts, pod node selectors, taints, admission policy and node availability
ImagePullBackOff Inspect pod Events for the image reference, registry reachability, architecture and pull credentials
Pod admission denied The agent needs privileged root, hostPID and writable hostPath; review the platform's permitted trusted-namespace policy
Required node name error Restore downward-API NODE_NAME or set --node-name to the local Kubernetes Node name
Not Ready; facts collection fails Check the agent's API connectivity, RBAC, local Node name and access to kube-system
Ready but later facts refresh fails Inspect collector logs; readiness records initial collection, not continuing freshness
OOMKilled or repeated pod restarts Inspect resource use and package subprocesses; follow the sizing procedure in security

The supplied role must allow list/watch on Nodes, Namespaces, ConfigMaps and NodeConfigs, plus NodeConfig status patching and Event writes. A cached client can need list/watch even when a particular operation looks like a single get. If permitted to impersonate service accounts, an administrator can verify:

kubectl auth can-i list nodes --as=system:serviceaccount:tak-os:keel
kubectl auth can-i list namespaces --as=system:serviceaccount:tak-os:keel
kubectl auth can-i watch configmaps --all-namespaces --as=system:serviceaccount:tak-os:keel
kubectl auth can-i patch nodeconfigs.keel.tlspu.io --subresource=status -n tak-os --as=system:serviceaccount:tak-os:keel

Restore the reviewed role from deploy/rbac.yaml rather than granting general cluster-admin access to the agent.

Accepted configuration with no result

Check that the selector matches the current Node labels and that an agent runs there. Confirm the NodeConfig namespace and check all namespaces with kubectl get nodeconfigs -A. Look for facts-not-ready, selector, ConfigMap read or status-patch errors in that node's agent logs. Failures before handler execution can be logged without a new per-node status outcome.

If the same spec and ConfigMap digest already succeeded, Keel waits for the interval. Metadata-only NodeConfig edits do not force application. A referenced ConfigMap change or a spec change can request an earlier run. ConfigMaps must be in the NodeConfig's namespace; their data never becomes template input.

Validation and templates

unknown type means the executing image lacks the named handler. Use file or package, or deploy the custom build consistently to agents and webhook. Missing parameters must use the exact handler keys; all values must be strings. Use quoted octal modes and a positive Go duration such as 30m or 24h.

Template parse errors indicate malformed syntax or an unknown function. Execution errors indicate a missing field, missing direct map key or incorrect argument type. See facts and templates for field names and index with fallbacks. Admission validates syntax only; it cannot prove a template will render on each node. Empty known facts do not necessarily cause an execution error.

Files and packages

For file errors, use an absolute host filename, omit the /host prefix, check octal mode syntax, parent paths, mount writability, disk space and filesystem behavior. Replacement needs a temporary file in the same directory. Parent symlinks and special files need particular care. Specify mode explicitly; replacing changed contents without one uses 0644. File-format validation and ownership management are outside this handler.

For package errors, inspect the host /etc/os-release ID, installed package tools, repositories, network/DNS access, locks and free space. Commands run against the host through chroot. Version strings must match the backend's installed representation and be available from its repositories. A successful install command is not followed by version verification, so verify important pins on the host. The handler reference lists exact backends and their limitations. Use the host's normal package-repair procedure for interrupted transactions; repeated agent restarts do not repair a package database.

Service restart pending

applied but service restart failed means the host configuration changed before systemctl failed. Check the host unit name, systemctl status and journal, unit syntax, dependencies and access to the running host systemd. The unit may be called ssh on one distribution and sshd on another.

Correct the service or configuration and watch restartPending clear. Keel retries the current service list even if the file or package is already in the desired state. Each attempt performs daemon-reload and can restart units that previously succeeded. Removing services can clear the pending state without performing the originally intended restart; that is not service recovery. Keel does not restore earlier host state automatically.

Admission rejects or blocks API writes

An explicit field-validation error requires correcting the NodeConfig. A webhook connection or TLS error requires repairing the optional admission server:

kubectl -n tak-os get deployment keel-webhook
kubectl -n tak-os get pods -l app.kubernetes.io/name=keel-webhook
kubectl -n tak-os logs deployment/keel-webhook --since=30m
kubectl -n tak-os get certificate keel-webhook
kubectl -n tak-os get endpointslices -l kubernetes.io/service-name=keel-webhook
kubectl get validatingwebhookconfiguration keel-nodeconfig -o yaml

The certificate command applies to the cert-manager installation. Check DNS names, certificate readiness, mounted TLS Secret, Service endpoints, CA injection and API-server reachability to port 443 (target 9443). Do not print the private key while collecting diagnostics.

The registration uses failurePolicy: Fail; an outage blocks NodeConfig creates and updates. Existing agent reconciliation and status updates are separate from that admission path. If an administrator chooses to disable admission during recovery, remove deploy/webhook-admission.yaml first as documented in admission, then restore the registration after the server is healthy. Runtime validation remains on the agents, but admission-time rejection is unavailable while the registration is absent.

Unexpected repeated changes

Look for multiple NodeConfigs or external host tools managing the same path or package, dynamic template values, file drift or failed restarts. Compare per-node results rather than the shared top-level generation. Do not install multiple Keel agents on one node to improve availability: their locks are process-local. The administrator guide explains stopping reconciliation and restoring previous desired state.