Skip to main content
Docs navigation

Kubernetes

To operate the nodes themselves, run one runner per node as a DaemonSet. The runner can only act on what the pod spec grants — which makes the manifest your blast-radius dial. This page is the worked manifest; the two mechanics it relies on (a service-less binary and a persistent state volume) are on Containers.

The DaemonSet#

The manifest below is the observation-heavy variant: one runner per node that can watch anything running on it, from processes to ports to journals. It reuses a reusable enrollment key (via a Secret) and a per-node /var/lib/emisar state volume so each node's runner keeps a stable identity across pod restarts — see the shared mechanics.

yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: emisar-runner
spec:
  selector:
    matchLabels:
      app: emisar-runner
  template:
    metadata:
      labels:
        app: emisar-runner
    spec:
      hostPID: true      # see every process on the node
      hostNetwork: true  # see the node's real interfaces and ports
      containers:
        - name: runner
          image: your-registry/emisar-runner
          env:
            - name: EMISAR_URL
              value: "https://emisar.dev"
            - name: EMISAR_ENROLLMENT_KEY
              valueFrom:
                secretKeyRef:
                  name: emisar-runner
                  key: enrollment-key
          volumeMounts:
            - name: state
              mountPath: /var/lib/emisar
            - name: host-root      # node filesystem, read-only, for file inspection
              mountPath: /host
              readOnly: true
            - name: journal        # journald logs on systemd nodes
              mountPath: /var/log/journal
              readOnly: true
            - name: systemd-run    # systemd state, for unit status reads
              mountPath: /run/systemd
              readOnly: true
      volumes:
        - name: state
          hostPath:
            path: /var/lib/emisar
            type: DirectoryOrCreate
        - name: host-root
          hostPath:
            path: /
        - name: journal
          hostPath:
            path: /var/log/journal
        - name: systemd-run
          hostPath:
            path: /run/systemd

What the pod spec grants#

With the manifest above, process packs see every node process (hostPID), network packs see the node's real ports (hostNetwork), journal reads work against the mounted journal, and file-inspection actions reach node paths under /host. Two limits: pack binaries run from the container's image, so put the tools your packs call into it; and the mounts above are read-only on purpose. You own the image, built from the release tarball, and every grant in it — narrow the mounts and drop hostPID/hostNetwork for a tighter runner that only inspects what you allow.

Letting a node action mutate#

A verb that mutates the node — restarting a unit, say — needs the systemd/dbus socket writable, a grant you make deliberately rather than by default: mount /run/systemd and /run/dbus writable and give the runner the privileges that action calls for (see the runner's user and the sudoers pattern on the host-install page ). Keep those grants scoped to the exact actions you intend the node runner to perform.