In the k8s environment, we often use the local path as persistent storage. In the k8s official document, there are two ways to use local storage, one is hostPath, the other is local volume, neither of which supports dynamic expansion, and the program porting changes are relatively large, and local-path-provisioner is very good made up for this shortcoming.
Steps to use local-path-provisioner:
1. Create a local-path path
[root@node1 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sr0 11:0 1 470K 0 rom vda 253:0 0 100G 0 disk └─vda1 253:1 0 100G 0 part / vdb 253:16 0 500G 0 disk └─nfs-lvol0 252:0 0 495G 0 lvm /data vdc 253:32 0 400G 0 disk ###Add a disk [root@node1 ~]# mkdir /local ####Create directory [root@node1 ~]# pvcreate /dev/vdc ####Create pv WARNING: xfs signature detected on /dev/vdc at offset 0. Wipe it? [y/n]: y Wiping xfs signature on /dev/vdc. Physical volume "/dev/vdc" successfully created. [root@node1 ~]# vgcreate local-path /dev/vdc ####Create vg Volume group "local-path" successfully created [root@node1~]# [root@node1 ~]# vgs VG #PV #LV #SN Attr VSize VFree local-path 1 0 0 wz--n- <400.00g <400.00g nfs 1 1 0 wz--n- <500.00g <5.00g [root@node1~]# [root@node1 ~]# lvcreate --size 300G local-path ####create lvm Logical volume "lvol0" created. [root@node1~]# [root@node1 ~]# mkfs.xfs /dev/local-path/lvol0 meta-data=/dev/local-path/lvol0 isize=512 agcount=4, agsize=19660800 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=0, sparse=0 data = bsize=4096 blocks=78643200, imaxpct=25 = sunit=0 width=0 blks naming=version 2 bsize=4096 ascii-ci=0 ftype=1 log=internal log bsize=4096 blocks=38400, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime=none extsz=4096 blocks=0, rtextents=0 [root@node1~]# [root@node1 ~]# mount /dev/local-path/lvol0 /local/ ####mount lvm to local [root@node1~]# [root@node1 ~]# cat /etc/fstab LABEL=img-rootfs / xfs defaults 0 1 /dev/nfs/lvol0 /data xfs defaults 0 1 /dev/local-path/lvol0 /local xfs defaults 0 1 ####Write into fstab, it can be automatically mounted when booting [root@node1~]#
2. Start local-path-provisioner
1: Edit the local-path-storage.yaml file as follows: --- apiVersion: v1 kind:Namespace metadata: name: local-path-storage --- apiVersion: v1 kind: ServiceAccount metadata: 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", "persistent volume claims", "configmaps" ] verbs: [ "get", "list", "watch" ] - apiGroups: [ "" ] resources: [ "endpoints", "persistent volumes", "pods" ] verbs: [ "*" ] - 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: apps/v1 kind: Deployment metadata: name: local-path-provisioner namespace: local-path-storage 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.22 imagePullPolicy: IfNotPresent command: -local-path-provisioner - --debug - start - --config - /etc/config/config.json volumeMounts: - name: config-volume mountPath: /etc/config/ env: - name: PROVISIONER_NAME value: rancher.io/local-path - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace volumes: - name: config-volume configMap: name: local-path-config --- apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: local-path provisioner: rancher.io/local-path volumeBindingMode: WaitForFirstConsumer reclaimPolicy: Delete --- kind: ConfigMap apiVersion: v1 metadata: name: local-path-config namespace: local-path-storage data: config.json: |- { "nodePathMap":[ { "node":"DEFAULT_PATH_FOR_NON_LISTED_NODES", "paths":["/local"] ##### replace the actual path } ] } setup: |- #!/bin/sh set-eu mkdir -m 0777 -p "$VOL_DIR" teardown: |- #!/bin/sh set-eu rm -rf "$VOL_DIR" helperPod.yaml: |- apiVersion: v1 kind: Pod metadata: name: helper-pod spec: containers: - name: helper-pod image: busybox imagePullPolicy: IfNotPresent [root@node1 local]# [root@node1 local]# kubectl apply -f local-path-storage.yaml ####Check if the pod starts normally [root@node1 ~]# kubectl get po -n local-path-storage NAME READY STATUS RESTARTS AGE local-path-provisioner-c755757b6-5gcr6 1/1 Running 0 23d [root@node1~]# ####View the log, the local path has been identified [root@node1 ~]# kubectl logs local-path-provisioner-c755757b6-5gcr6 -n local-path-storage time="2023-04-28T07:28:26Z" level=debug msg="Applied config: {"nodePathMap":[{"node":\ "DEFAULT_PATH_FOR_NON_LISTED_NODES","paths":["/local"]}]}" time="2023-04-28T07:28:26Z" level=debug msg="Provisioner started" I0428 07:28:26.478078 1 controller.go:773] Starting provisioner controller rancher.io/local-path_local-path-provisioner-c755757b6-5gcr6_d00cd9cb-89e8-4911-b9c3-f7ed5a89a368! I0428 07:28:26.578610 1 controller.go:822] Started provisioner controller rancher.io/local-path_local-path-provisioner-c755757b6-5gcr6_d00cd9cb-89e8-4911-b9c3-f7ed5a89a368 2: Create a storage class, as follows: --- apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: local-path provisioner: rancher.io/local-path ####The provisioner name defined above volumeBindingMode: WaitForFirstConsumer reclaimPolicy: Delete Execute sc.yaml as follows: [root@node1 local]# kubectl apply -f sc.yaml [root@node1 ~]# kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUME BINDING MODE ALLOW VOLUME EXPANSION AGE local-path rancher.io/local-path Delete WaitForFirstConsumer false 23d [root@node1~]# 3: The use of local-path In the yaml file, directly use the sc name to dynamically create pvc. The local-path is suitable for a stand-alone environment. If there are multiple nodes, you must ensure that each node has a local-path to ensure that the pod can be scheduled successfully.