[Infrastructure as Code (IaC) Pulumi] Use Pulumi kubernetes (K8S) Helm Chart to deploy Rancher Local Path Provisioner to provide dynamic provisioning the volume using hostPath

Rancher Local Path Provisioner

Local Path Provisioner provides a way for the Kubernetes users to utilize the local storage in each node. Based on the user configuration, the Local Path Provisioner will create hostPath based persistent volume on the node automatically. It utilizes the features introduced by Kubernetes Local Persistent Volume feature, but make it a simpler solution than the built-in local volume feature in Kubernetes.

This article is about how to use Pulumi, kubernetes (K8S) provider, Helm Chart and TypeScript SDK to deploy Rancher Local Path Provisioner within Kubernetes (K8S).

Prerequisites

Usage

Pulumi New

Create the workspace directory.

1
2
3
$ mkdir -p col-example-pulumi-typescript-local-path-provisioner

$ cd col-example-pulumi-typescript-local-path-provisioner

Pulumi login into local file system.

1
2
3
$ pulumi login file://.
Logged in to cloudolife as cloudolife (file://.)
or visit https://pulumi.com/docs/reference/install/ for manual instructions and release notes.

Pulumi new a project with kubernetes-typescript SDK.

1
$ pulumi new kubernetes-typescript

The above command will create some files within the current directory.

1
2
3
4
5
6
7
8
tree . -L 1
.
├── node_modules/
├── package.json
├── package.json.lock
├── Pulumi.dev.yaml
├── Pulumi.yaml
└── main.ts

Install js-yaml package to load and parse yaml file.

1
$ npm i js-yaml

Pulumi Configuration

Configure Kubernetes

By default, Pulumi will look for a kubeconfig file in the following locations, just like kubectl:

  • The environment variable: $KUBECONFIG,

  • Or in current user’s default kubeconfig directory: ~/.kube/config

If the kubeconfig file is not in either of these locations, Pulumi will not find it, and it will fail to authenticate against the cluster. Set one of these locations to a valid kubeconfig file, if you have not done so already.

Configure Values.yaml

Edit values.yaml and replace content within {{ }}.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# values.yaml

# local-path-provisioner/values.yaml at master · rancher/local-path-provisioner
# https://github.com/rancher/local-path-provisioner/blob/master/deploy/chart/values.yaml

## For creating the StorageClass automatically:
storageClass:

## Set a StorageClass name
## Ignored if storageClass.create is false
name: local-path

nodeSelector:
kubernetes.io/hostname: {{ .Values.hostname }}

Download Helm Chart code.

1
2
3
$ git clone [email protected]:rancher/local-path-provisioner.git

$ ln -fs ./deploy/chart local-path-provisioner

See and modify main.ts file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// main.ts

import * as pulumi from "@pulumi/pulumi";

import * as k8s from "@pulumi/kubernetes";

const yaml = require('js-yaml');
const fs = require('fs');

const namelocalPathProvisioner = "local-path-provisioner"

// kubernetes.core/v1.Namespace | Pulumi
// https://www.pulumi.com/docs/reference/pkg/kubernetes/core/v1/namespace/
const namespacelocalPathProvisioner = new k8s.core.v1.Namespace(namelocalPathProvisioner, {
metadata: {
name: namelocalPathProvisioner,
},
})

const values = yaml.safeLoad(fs.readFileSync("./values.yaml", 'utf8'))

const charNamelocalPathProvisioner = "local-path-provisioner"

// rancher/local-path-provisioner: Dynamically provisioning persistent local storage with Kubernetes
// https://github.com/rancher/local-path-provisioner
const charIngressNginx = new k8s.helm.v3.Chart(charNameIngressNginx, {
chart: charNameIngressNginx,
path: ".", // Will find ./local-path-provisioner directory
namespace: namespaceIngressNginx.metadata.name,
values: values,
});

Pulumi Up

Run pulumi up to create the namespace and pods.

1
$ pulumi up

See pods about local-path-provisioner.

1
2
3
$ kubectl get pods -n local-path-provisioner
NAME READY STATUS RESTARTS AGE
local-path-provisioner-7454875dcb-c94hn 1/1 Running 2 (8m58s ago) 27m

See Storage Class about local-path-provisioner.

1
2
3
$ kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
local-path cluster.local/local-path-provisioner Delete WaitForFirstConsumer true 12d

Test Local Path Provisioner Storage Class

Create or edit a pvc.yaml manifest file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-local-path
labels:
app: test
spec:
storageClassName: local-path
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi

Run command to run and check.

1
2
3
4
5
$ kubectl apply -f pvc.yaml

$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
test-local-path Bound pvc-ce500448-7ce8-42a4-b9aa-f96bd005fd5b 1Gi RWO local-path 19

Pulumi Destroy

Destroy all resources created by Pulumi.

1
$ pulumi destroy

References

[1] rancher/local-path-provisioner: Dynamically provisioning persistent local storage with Kubernetes - https://github.com/rancher/local-path-provisioner

[2] Local Persistent Volumes for Kubernetes Goes Beta | Kubernetes - https://kubernetes.io/blog/2018/04/13/local-persistent-volumes-beta/

[3] Kubernetes Getting Started | Pulumi - https://www.pulumi.com/docs/get-started/kubernetes/

[4] Pulumi - Modern Infrastructure as Code - https://www.pulumi.com/

[5] Kubernetes - https://kubernetes.io/

[6] TypeScript: Typed JavaScript at Any Scale. - https://www.typescriptlang.org/