[Infrastructure as Code (IaC)] Use Pulumi kubernetes (K8S) Helm Chart to deploy nfs-client-provisioner

nfs-client-provisioner

nfs-client-provisioner chart will deploy the Kubernetes nfs provisioner. This provisioner is intended for connecting to a pre-existing NFS server, and not includes a built in NFS server. If you want a built in NFS Server, please consider using the nfs-client-provisioner - https://github.com/helm/charts/tree/master/stable/nfs-client-provisioner instead.

Pulumi - Modern Infrastructure as Code - https://www.pulumi.com/ is a Modern Infrastructure as Code (IaC) to create, deploy, and manage infrastructure on any cloud using familiar programming languages and tools.

This article is about how to use Pulumi, kubernetes (K8S) provider, Helm Chart and TypeScript SDK to deploy nfs-client-provisioner within Kubernetes (K8S).

The NFS client provisioner - https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client is an automatic provisioner for Kubernetes that uses your already configured NFS server, automatically creating Persistent Volumes.

Pulumi’s Cloud Native SDK makes it easy to target any Kubernetes environment to provision a cluster, configure and deploy applications, and update them as required.

Helm Chart is a component representing a collection of resources described by an arbitrary Helm Chart.

The Chart can be fetched from any source that is accessible to the helm command line. Values in the values.yml file can be overridden using ChartOpts.values (equivalent to --set or having multiple values.yml files). Objects can be transformed arbitrarily by supplying callbacks to ChartOpts.transformations.


As of Nov 13, 2020, charts in this repo will no longer be updated. For more information, see the Helm Charts Deprecation and Archive Notice, and Update.


You can use Azure Helm mirror - http://mirror.azure.cn/kubernetes/charts/ to replace https://kubernetes-charts.storage.googleapis.com

Prerequisites

Usage

Pulumi New

Create the workspace directory.

1
2
3
$ mkdir -p col-example-pulumi-typescript-nfs-client-provisioner

$ cd col-example-pulumi-typescript-nfs-client-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
15
16
17
# values.yaml

# charts/values.yaml at master · helm/charts · GitHub
# https://github.com/helm/charts/blob/master/stable/nfs-client-provisioner/values.yaml

nfs:
server: {{ Values.nfs.server }}
path: /ifs/kubernetes
mountOptions:
- vers=4
- minorversion=0
- rsize=1048576
- wsize=1048576
- hard
- timeo=600
- retrans=2
- noresvport

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
32
33
34
35
36
37
38
39
// main.ts

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

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

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

const nameNfsClientProvisioner = "nfs-client-provisioner"

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

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

// charts/stable/nfs-client-provisioner at master · helm/charts · GitHub
// https://github.com/helm/charts/tree/master/stable/nfs-client-provisioner
const charNameNfsClientProvisioner = "nfs-client-provisioner"

// kubernetes.helm/v3.Chart | Pulumi
// https://www.pulumi.com/docs/reference/pkg/kubernetes/helm/v3/chart/
const charNfsClientProvisioner = new k8s.helm.v3.Chart(charNameNfsClientProvisioner, {
chart: charNameNfsClientProvisioner,
version: "1.2.9",
fetchOpts:{
// Index of /kubernetes/charts/
// http://mirror.azure.cn/kubernetes/charts/
repo: "http://mirror.azure.cn/kubernetes/charts/",
},
namespace: namespaceNfsClientProvisioner.metadata.name,
values: values,
});

Pulumi Up

Run pulumi up to create the namespace and pods.

1
$ pulumi up

See pods about nfs-client-provisioner.

1
2
3
$ kubectl get pods -n nfs-client-provisioner
NAMESPACE NAME READY STATUS RESTARTS AGE
nfs-client-provisioner app-dep-rx8h9grh-f89759699-2hn27 1/1 Running 0 14s

check the StorageClass status.

1
2
3
$ kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-client cluster.local/nfs-client-provisioner Delete Immediate true 11h

Pulumi Destroy

Destroy all resources created by Pulumi.

1
$ pulumi destroy

FAQs

bad option; for several filesystems (e.g. nfs, cifs) you might need a /sbin/mount. helper program

1
MountVolume.SetUp failed for volume "pvc-c10001c32-f2dd-4f8c-8d19-bd8c2e01b5cf" : mount failed: exit status 32 Mounting command: mount Mounting arguments: -t nfs -o nolock,tcp,noresvport,vers=4.1 bad option; for several filesystems (e.g. nfs, cifs) you might need a /sbin/mount.<type> helper program.

Install nfs packages to solve that issue.

1
2
3
4
5
# Debian, Ubuntu
$ apt-get install nfs-common

# CentOS
$ yum install nfs-utils

Unable to attach or mount volumes: unmounted volumes=[config storage xxxxxx-volume], unattached volumes=[config storage xxxxxx-volume]: timed out waiting for the condition

Modify mountOptions to vers=4.1 and nolock,tcp,noresvport to fix that issue.

1
2
3
4
5
6
7
# values.yaml

nfs:

mountOptions:
- vers=4.1
- nolock,tcp,noresvport

References

[1] kubernetes.helm/v3.Chart | Pulumi - https://www.pulumi.com/docs/reference/pkg/kubernetes/helm/v3/chart/

[2] [charts/stable/nfs-client-provisioner at master · helm/charts · GitHub - https://github.com/helm/charts/tree/master/stable/nfs-client-provisioner]

[3] Azure Helm mirror - http://mirror.azure.cn/kubernetes/charts/

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

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

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

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

[8] Helm - https://helm.sh/