Skip to content

Mount node-local storage with `hostPath`

Use kix.mount.hostPath when a workload must read or write a directory on the Kubernetes node itself. Common uses include node agents, local development, and caches that can be rebuilt.

hostPath ties the pod to node-local state. A replacement pod scheduled on a different node sees that node’s directory, and replacing the node removes the data. Use a PVC when the data must follow the workload or survive node replacement.

Add the mount to the parts returned by your package:

how-to/platform/hostpath-app.nix (L28–L33)
cacheMount = kix.mount.hostPath {
name = "cache";
hostPath = "/var/lib/example-cache";
mountPath = "/var/cache/app";
type = "DirectoryOrCreate";
};

View source on GitHub ↗

This maps /var/lib/example-cache on the node to /var/cache/app in the container. DirectoryOrCreate asks Kubernetes to create the node directory when it does not exist.

Set readOnly = true when the workload only needs to read the directory. Keep the host path as narrow as possible so the container cannot access unrelated node files.

Pass the mount to kix.withMounts before sealing the Deployment with scope.mkDeployment:

how-to/platform/hostpath-app.nix (L37–L57)
deployment =
{
name = scope.instanceName;
spec = {
replicas = 1;
selector.matchLabels = scope.selectorLabels;
template.spec.containers = [
{
name = "worker";
image = "docker.io/library/busybox:1.37";
command = [
"sh"
"-c"
"sleep infinity"
];
}
];
};
}
|> kix.withMounts [ self.cacheMount ]
|> scope.mkDeployment;

View source on GitHub ↗

kix.withMounts adds both the pod volume and the matching container volumeMount. For a multi-container workload, use kix.withMountsOn to name the container that should receive it.

Add the package to a cluster whose flavor permits privileged workloads:

how-to/platform/hostpath-cluster.nix (L19–L21)
instances.hostpath-example.worker = {
package = hostPathApp;
};

View source on GitHub ↗

Kix checks hostPath against cluster.capabilities.privilegedContainers. If the capability is false, evaluation fails. If it is true, the check passes. An undeclared capability is unknown; Kix emits a trace warning but continues. Declare the capability explicitly instead of treating the absence of an error as confirmation that the target supports hostPath.

Also pin the workload to the node that holds the data. The Deployment above has one replica and no scheduling constraint. If Kubernetes reschedules the Pod onto another node, it mounts that node’s directory, which may be empty. Add a nodeSelector or node affinity for the correct node.

Evaluate the cluster:

Run in kix-examples/
❱ kix check how-to-platform-hostpath
 TOOL         RESULT  DETAILS                                                       
 eval         pass    8 manifests evaluated                                         
 kubeconform  pass    skipped (this validation tool is not yet integrated with Kix) 
 pluto        pass    skipped (this validation tool is not yet integrated with Kix) 
 kyverno      pass    skipped (this validation tool is not yet integrated with Kix) 
 scorecard    pass    0 errors, 9 warnings, 1 info

Inspect the generated volume and mount:

Run in kix-examples/ Output excerpt
❱ kix build how-to-platform-hostpath --output json
{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "worker",
    "namespace": "hostpath-example"
  },
  "podSpec": {
    "containers": [
      {
        "name": "worker",
        "volumeMounts": [
          {
            "mountPath": "/var/cache/app",
            "name": "cache"
          }
        ]
      }
    ],
    "volumes": [
      {
        "hostPath": {
          "path": "/var/lib/example-cache",
          "type": "DirectoryOrCreate"
        },
        "name": "cache"
      }
    ]
  }
}

The Deployment contains a hostPath volume named cache and mounts that same volume at /var/cache/app in the worker container.