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

MetalLB

MetalLB is a load-balancer implementation for bare metal Kubernetes clusters, using standard routing protocols.

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

Prerequisites

Usage

Pulumi New

Create the workspace directory.

1
2
3
$ mkdir -p col-example-pulumi-typescript-metallb

$ cd col-example-pulumi-typescript-metallb

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
18
19
20
21
22
23
24
25
26
27
28
# values.yaml

# charts/values.yaml at master · bitnami/charts
# https://github.com/bitnami/charts/blob/master/bitnami/metallb/values.yaml

## To configure MetalLB, you must specify ONE of the following two
## options.
#
## existingConfigMap specifies the name of an externally-defined
## ConfigMap to use as the configuration. Helm will not manage the
## contents of this ConfigMap, it is your responsibility to create it.
#
# existingConfigMap: metallb-config
#
## configInline specifies MetalLB's configuration directly, in yaml
## format. When configInline is used, Helm manages MetalLB's
## configuration ConfigMap as part of the release, and
## existingConfigMap is ignored.
## Refer to https://metallb.universe.tf/configuration/ for
## available options.
#
configInline:
# https://metallb.universe.tf/configuration/#layer-2-configuration
address-pools:
- name: default
protocol: layer2
addresses:
- {{ .Values.addresses }}

main.ts

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

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

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

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

const nameMetalLB = "metallb"

// kubernetes.core/v1.Namespace | Pulumi
// https://www.pulumi.com/docs/reference/pkg/kubernetes/core/v1/namespace/
const namespaceMetalLB = new k8s.core.v1.Namespace(nameMetalLB, {
metadata: {
// MetalLB must be installed into `metallb-system` namespaces.
name: "metallb-system",
},
})

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

const charNameMetalLB = "metallb"

const charMetalLB = new k8s.helm.v3.Chart(charNameMetalLB, {
chart: charNameMetalLB,
version: "0.11.0",
fetchOpts:{
repo: "https://metallb.github.io/metallb",
},
namespace: namespaceMetalLB.metadata.name,
values: values,
})

Pulumi Up

Run pulumi up to create the namespace and pods.

1
$ pulumi up

See pods about metallb.

1
2
3
4
5
6
$ kubectl get pods -n metallb-system
NAME READY STATUS RESTARTS AGE
metallb-controller-7cb7dd579d-27lzq 1/1 Running 0 20d
metallb-speaker-7dg97 1/1 Running 1 (4d22h ago) 20d
metallb-speaker-mmf6l 1/1 Running 4 (3d9h ago) 20d
metallb-speaker-xbp4k 1/1 Running 0 20d

Example

Create Deployment and Service(LoadBalancer) for Nginx.

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
# https://raw.githubusercontent.com/metallb/metallb/main/manifests/tutorial-2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1
ports:
- name: http
containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
type: LoadBalancer

Apply manifest file.

1
$ kubectl apply -f tutorial-2.yaml

Then, check svc or Service.

1
2
3
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx LoadBalancer 10.105.4.74 <Your addresse> 80:32159/TCP 31d

Pulumi Destroy

Destroy all resources created by Pulumi.

1
$ pulumi destroy

References

[1] MetalLB, bare metal load-balancer for Kubernetes - https://metallb.universe.tf/

[2] metallb/metallb: A network load-balancer implementation for Kubernetes using standard routing protocols - https://github.com/metallb/metallb

[3] metallb 0.11.0 · metallb/metallb - https://artifacthub.io/packages/helm/metallb/metallb

[4] charts/bitnami/metallb at master · bitnami/charts - https://github.com/bitnami/charts/tree/master/bitnami/metallb

[5] MetalLB, bare metal load-balancer for Kubernetes - https://metallb.universe.tf/installation/

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

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

[8] Important Notes | MetalLB | Documentation - https://metallb.io/docs/1.2.0/deploy/important-notes/

[9] Deprecated API Migration Guide | Kubernetes - https://kubernetes.io/docs/reference/using-api/deprecation-guide/

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

[10] Basic Authentication - NGINX Ingress Controller - https://kubernetes.github.io/ingress-nginx/examples/auth/basic/