blob: cc80544eeaa05770df3aa1c112a0da4704f6e688 [file] [log] [blame]
# local-path-provisioner v0.0.37, based on upstream deploy/local-path-storage.yaml
# with these local changes:
# - PVs live under /var/k8s; setup.sh/teardown.sh create and unmount one
# ZFS dataset per PV (rpool/var/k8s/<pv>) in the host mount namespace.
# - The helper pod needs hostPID and privileged for nsenter.
# - The namespace (PSA enforce=privileged) is not managed here.
# setup and teardown below must stay in sync with setup.sh and teardown.sh.
# The provisioner reads helperPod.yaml only at startup; restart it after
# changing that.
apiVersion: apps/v1
kind: Deployment
metadata:
name: local-path-provisioner
namespace: local-path-storage
labels:
app: local-path-provisioner
spec:
replicas: 1
selector:
matchLabels:
app: local-path-provisioner
template:
metadata:
labels:
app: local-path-provisioner
spec:
serviceAccountName: local-path-provisioner-service-account
containers:
- name: local-path-provisioner
image: docker.io/rancher/local-path-provisioner:v0.0.37
imagePullPolicy: IfNotPresent
command:
- local-path-provisioner
- --debug
- start
- --config
- /etc/config/config.json
# The helper pod needs hostPID for nsenter (see setup.sh).
- --allow-unsafe-helper-pod-template
ports:
- name: health
containerPort: 8080
protocol: TCP
startupProbe:
httpGet:
path: /health
port: health
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 12
livenessProbe:
httpGet:
path: /health
port: health
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: health
initialDelaySeconds: 5
periodSeconds: 5
volumeMounts:
- name: config-volume
mountPath: /etc/config/
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: CONFIG_MOUNT_PATH
value: /etc/config/
- name: HEALTH_PORT
value: "8080"
volumes:
- name: config-volume
configMap:
name: local-path-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: local-path-config
namespace: local-path-storage
data:
config.json: |-
{
"nodePathMap":[
{
"node":"DEFAULT_PATH_FOR_NON_LISTED_NODES",
"paths":["/var/k8s"]
}
]
}
setup: |
#!/bin/sh
# Creates a ZFS dataset per PV. The helper pod runs with hostPID, and all
# ZFS and filesystem operations are performed in the host's mount namespace
# (nsenter -t 1 -m). Running zfs directly inside the helper container would
# mount the dataset only inside the container's own mount namespace; the
# workload would then write into the parent dataset, and the child dataset
# would shadow that data after the next host reboot.
#
# The provisioner passes the volume path as $VOL_DIR (v0.0.2x and later);
# older versions passed it as -p.
set -eu
absolutePath=${VOL_DIR:-}
while getopts "m:s:p:" opt
do
case $opt in
p)
absolutePath=$OPTARG
;;
s)
sizeInBytes=$OPTARG
;;
m)
volMode=$OPTARG
;;
esac
done
[ -n "$absolutePath" ] || { echo "setup: no volume path given" >&2; exit 1; }
host() { nsenter -t 1 -m -- "$@"; }
host zfs create "rpool${absolutePath}"
host zfs mount "rpool${absolutePath}" 2>/dev/null || :
host findmnt -n -o SOURCE "${absolutePath}" | grep -qx "rpool${absolutePath}"
host chmod 0777 "${absolutePath}"
teardown: |
#!/bin/sh
# Unmounts (but keeps) the PV's ZFS dataset. Runs in the host's mount
# namespace; see setup.sh.
set -eu
absolutePath=${VOL_DIR:-}
while getopts "m:s:p:" opt
do
case $opt in
p)
absolutePath=$OPTARG
;;
s)
sizeInBytes=$OPTARG
;;
m)
volMode=$OPTARG
;;
esac
done
[ -n "$absolutePath" ] || { echo "teardown: no volume path given" >&2; exit 1; }
nsenter -t 1 -m -- zfs set mountpoint=none "rpool${absolutePath}"
helperPod.yaml: |
apiVersion: v1
kind: Pod
metadata:
name: helper-pod
spec:
priorityClassName: system-node-critical
tolerations:
- key: node.kubernetes.io/disk-pressure
operator: Exists
effect: NoSchedule
hostPID: true
containers:
- name: helper-pod
image: alpine:3.20
imagePullPolicy: IfNotPresent
securityContext:
privileged: true
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: local-path-provisioner-service-account
namespace: local-path-storage
---
# Since v0.0.24 helper pods run in the provisioner's namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: local-path-provisioner-role
namespace: local-path-storage
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch", "create", "patch", "update", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: local-path-provisioner-bind
namespace: local-path-storage
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: local-path-provisioner-role
subjects:
- kind: ServiceAccount
name: local-path-provisioner-service-account
namespace: local-path-storage
---
# Leftover from PodSecurityPolicy times (psp:default no longer grants anything).
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: local-path-provisioner:psp:default
namespace: local-path-storage
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: psp:default
subjects:
- kind: ServiceAccount
name: local-path-provisioner-service-account
namespace: local-path-storage
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: local-path-provisioner-role
rules:
- apiGroups: [""]
resources: ["nodes", "persistentvolumeclaims", "configmaps", "pods", "pods/log"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "patch", "update", "delete"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "patch"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: local-path-provisioner-bind
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: local-path-provisioner-role
subjects:
- kind: ServiceAccount
name: local-path-provisioner-service-account
namespace: local-path-storage
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-path
provisioner: rancher.io/local-path
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete