[Infrastructure as Code (IaC) Pulumi] Use Pulumi kubernetes (K8S) Helm Chart to deploy ingress-nginx

ingress-nginx

ingress-nginx is an Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer.

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

Prerequisites

Usage

Pulumi New

Create the workspace directory.

1
2
3
$ mkdir -p col-example-pulumi-typescript-ingress-nginx

$ cd col-example-pulumi-typescript-ingress-nginx

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

ingress-nginx expose Ingress with LoadBalance mode by default.

Edit values.yaml to expose Ingress with hostNetwork mode.

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
# values.yaml

# ingress-nginx/values.yaml at master · kubernetes/ingress-nginx
# https://github.com/kubernetes/ingress-nginx/blob/master/charts/ingress-nginx/values.yaml

controller:

# Required for use with CNI based kubernetes installations (such as ones set up by kubeadm),
# since CNI and hostport don't mix yet. Can be deprecated once https://github.com/kubernetes/kubernetes/issues/23920
# is merged
hostNetwork: true

# DaemonSet or Deployment
#
kind: DaemonSet

service:

type: "ClusterIP"

dnsPolicy: "ClusterFirstWithHostNet"

# Node labels for default backend pod assignment
# Ref: https://kubernetes.io/docs/user-guide/node-selection/
#
nodeSelector:
# Select node labeled `kubernetes.io/hostname: node1`
kubernetes.io/hostname: node1

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
// main.ts

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

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

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

const nameIngressNginx = "ingress-nginx"

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

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

const charNameIngressNginx = "ingress-nginx"

// ingress-nginx 4.0.1 · kubernetes/ingress-nginx
// https://artifacthub.io/packages/helm/ingress-nginx/ingress-nginx
const charIngressNginx = new k8s.helm.v3.Chart(charNameIngressNginx, {
chart: charNameIngressNginx,
version: "4.0.1",
fetchOpts:{
repo: "https://kubernetes.github.io/ingress-nginx",
},
namespace: namespaceIngressNginx.metadata.name,
values: values,
});

Pulumi Up

Run pulumi up to create the namespace and pods.

1
$ pulumi up

See pods about ingress-nginx.

1
2
3
4
5
6
$ kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-gq264 0/1 Completed 0 2d1h
ingress-nginx-admission-patch-ztbxh 0/1 Completed 2 2d1h
ingress-nginx-controller-9q6qg 1/1 Running 0 40h
ingress-nginx-controller-ngxkh 1/1 Running 0 40h

To use, add the kubernetes.io/ingress.class: nginx annotation to your Ingress resources annonations.

Pulumi Destroy

Destroy all resources created by Pulumi.

1
$ pulumi destroy

FAQs

chart requires kubeVersion: >=1.19.0-0 which is incompatible with Kubernetes v1.18.0 on Kuberneters (K8S) 1.22+

1
error: Error: invocation of kubernetes:helm:template returned an error: failed to generate YAML for specified Helm chart: failed to create chart from template: chart requires kubeVersion: >=1.19.0-0 which is incompatible with Kubernetes v1.18.0

Download ingress-nginx chart.

1
2
3
$ helm pull ingress-nginx/ingress-nginx

$ tar -xvf ingress-nginx.x.x.x.tgz

Edit Chart.yaml to commment kubeVersion content.

1
2
3
# Chart.yaml

# kubeVersion: '>=1.19.0-0'

Install from local ./ingress-nginx directory.

1
2
3
4
5
6
7
8
9
10
11
12
13
// ingress-nginx 4.0.1 · kubernetes/ingress-nginx
// https://artifacthub.io/packages/helm/ingress-nginx/ingress-nginx
const charIngressNginx = new k8s.helm.v3.Chart(charNameIngressNginx, {
chart: charNameIngressNginx,
// version: "4.0.1",
// fetchOpts:{
// repo: "https://kubernetes.github.io/ingress-nginx",
// },

path: ".", // Will find ./ingress-nginx directory
namespace: namespaceIngressNginx.metadata.name,
values: values,
});

References

[1] kubernetes/ingress-nginx: NGINX Ingress Controller for Kubernetes - https://github.com/kubernetes/ingress-nginx

[2] ingress-nginx/charts/ingress-nginx at main · kubernetes/ingress-nginx - https://github.com/kubernetes/ingress-nginx/tree/main/charts/ingress-nginx

[3] Welcome - NGINX Ingress Controller - https://kubernetes.github.io/ingress-nginx/

[4] [ingress-nginx/values.yaml at master · kubernetes/ingress-nginx - https://github.com/kubernetes/ingress-nginx/blob/master/charts/ingress-nginx/values.yaml]

[5] Ingress | Kubernetes - https://kubernetes.io/docs/concepts/services-networking/ingress/

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

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

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

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

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