kubernetes/kops · warning
error listing /etc/containerd: %v
Error message
error listing /etc/containerd: %v
What it means
Accumulated by logDumperNode.dump (pkg/dump/dumper.go:505) when n.findFiles(ctx, "/etc/containerd") fails. This step lists containerd configuration files (config.toml, CNI templates, certs.d hosts.toml) on the node so their .toml/.template files can be copied into the artifacts. The failure is logged as a warning and the rest of the dump proceeds without containerd configs.
Source
Thrown at pkg/dump/dumper.go:505
if err := n.shellToFile(ctx, "cat /etc/hosts", filepath.Join(n.dir, "etchosts")); err != nil {
errors = append(errors, err)
}
if err := n.shellToFile(ctx, "sysctl -a", filepath.Join(n.dir, "sysctls")); err != nil {
errors = append(errors, err)
}
if err := n.shellToFile(ctx, "cat /var/lib/kubelet/kubelet.conf", filepath.Join(n.dir, "kubelet.conf")); err != nil {
errors = append(errors, err)
}
if err := n.shellToFile(ctx, "cat /proc/modules", filepath.Join(n.dir, "modules")); err != nil {
errors = append(errors, err)
}
// Capture containerd configuration files (config.toml, CNI templates, certs.d hosts.toml).
containerdFiles, err := n.findFiles(ctx, "/etc/containerd")
if err != nil {
errors = append(errors, fmt.Errorf("error listing /etc/containerd: %v", err))
}
for _, f := range containerdFiles {
if !strings.HasSuffix(f, ".toml") && !strings.HasSuffix(f, ".template") {
continue
}
rel := strings.TrimPrefix(f, "/etc/containerd/")
dest := filepath.Join(n.dir, "containerd", rel)
cmd := "sudo cat '" + strings.ReplaceAll(f, "'", `'\''`) + "'"
if err := n.shellToFile(ctx, cmd, dest); err != nil {
errors = append(errors, err)
}
}
return errors
}
// findFiles lists files under the specified directory (recursively)
func (n *logDumperNode) findFiles(ctx context.Context, dir string) ([]string, error) {View on GitHub (pinned to 4c8573c808)
Solutions
- Confirm the node actually uses containerd: `ssh <node> ls /etc/containerd`; on docker-runtime nodes this warning is expected and can be ignored.
- SSH in and run `sudo find /etc/containerd -type f -print0` to capture the real error (exit code, permissions).
- If the timeout is the cause, increase --node-dump-timeout.
- Re-run the dump if the failure was transient (session drop); the per-node dump is idempotent.
- Ensure sudo works non-interactively on the node (NOPASSWD) — a sudo password prompt over the piped session surfaces as a command failure.
Defensive patterns
Strategy: fallback
Validate before calling
// only list containerd config when containerd is in use
if err := client.ExecPiped(ctx, "test -d /etc/containerd", io.Discard, io.Discard); err != nil {
klog.V(2).Infof("no /etc/containerd on node; skipping containerd config dump")
} Try / catch
containerdFiles, err := n.findFiles(ctx, "/etc/containerd")
if err != nil {
klog.Warningf("containerd config capture skipped: %v", err)
containerdFiles = nil
} Prevention
- Skip the /etc/containerd listing on docker-runtime nodes.
- Confirm containerd runtime in cluster spec before expecting these artifacts.
- Keep sudo NOPASSWD configured for non-interactive find execution.
When it happens
Trigger: ExecPiped of `sudo find /etc/containerd -type f -print0` errors: the directory does not exist (docker-based or non-containerd node), find exits non-zero because of the missing path, the SSH session drops, or the nodeDumpTimeout context expires before the command completes.
Common situations: Clusters still using the docker runtime (pre-containerd kOps versions) or custom runtime layouts where /etc/containerd is absent; upgrading a cluster where some nodes run containerd and others do not; transient SSH failures mid-dump.
Related errors
- error listing systemd services: %v
- error reading /var/log: %v
- error listing %q: %v
- error listing systemd units: %v
- connecting: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/cb3742c05f17dd90.
Report an issue: GitHub.