How I used js to dynamically create and delete pods in kubernetes
Tags: kubernetes, node, javascript, azure
Published: 2024-07-06 11:47:17

# First of all: Why?

Imagine you have a system where your user needs to execute something private on your server quickly and securely, like deploying bots or what Next.js does. This article is perfect for such cases.

# But, how do I do it on localhost?

To develop this code, we will use two approaches: production and development. We will use Minikube for the development environment and Azure for the production environment.

# How can we start?

We need to define a development path to avoid getting lost. We will need a way to communicate with Kubernetes, as well as to create and delete pods.

# Development

We will use the libraries `@kubernetes/client-node` and `@azure`.

## First

We start by creating the Kubernetes API. To do this, we define a function `getKubernetesApi`, and in it, we initiate the Kubernetes configuration, something like:

```javascript
import { ContainerServiceClient } from "@azure/arm-containerservice";
import { DefaultAzureCredential } from "@azure/identity";
import k8s from "kubernetes-client";

async function getKubernetesClient() {
    const kc = new k8s.KubeConfig();
}
```

Then we define a try catch block, where we test if the environment is production to configure Kubernetes with Azure, or load the default configuration in the development environment. We create and return the client, something like:

```js
async function getKubernetesClient() {
    const kc = new k8s.KubeConfig();
    try {
        if (process.env.NODE_ENV === "production") {
            const credentials = new DefaultAzureCredential();
            const containerServiceClient = new ContainerServiceClient(credentials);
            const response = await containerServiceClient.managedClusters.listClusterAdminCredentials();
            kc.loadFromString(response.kubeconfigs[0].value);
        } else {
            kc.loadFromDefault();
        }
        const k8sApi = kc.makeApiClient(k8s.CoreV1Api);
        return k8sApi;
    } catch (error) {
        console.error("Error while getting Kubernetes API", error);
        return;
    }
}
```

## Second
Next, we define the functions to create and delete pods using the obtained client. For this, we receive data such as the pod name, pod namespace, and metadata for the pod, something like:

```js
async function createPod(metadata, namespace) {
    try {
        const k8sApi = await getKubernetesClient();
        return await k8sApi.createNamespacedPod(namespace, metadata);
    } catch (error) {
        console.error("Error while creating pod", error);
        return;
    }
}

async function deletePod(name, namespace) {
    try {
        const k8sApi = await getKubernetesClient();
        return await k8sApi.deleteNamespacedPod(name, namespace);
    } catch (error) {
        console.error("Error while deleting pod", error);
        return;
    }
}
```

## Third, but not less important
Finally, we export the useful functions to be used in the code and ensure that they cannot be altered during execution. This can be done as:

```js
export default Object.freeze({
    createPod,
    deletePod,
    getKubernetesClient
});
```

## Final Result

```js
import { ContainerServiceClient } from "@azure/arm-containerservice";
import { DefaultAzureCredential } from "@azure/identity";
import k8s from "kubernetes-client";

async function getKubernetesClient() {
    const kc = new k8s.KubeConfig();
    try {
        if (process.env.NODE_ENV === "production") {
            const credentials = new DefaultAzureCredential();
            const containerServiceClient = new ContainerServiceClient(credentials);
            const response = await containerServiceClient.managedClusters.listClusterAdminCredentials();
            kc.loadFromString(response.kubeconfigs[0].value);
        } else {
            kc.loadFromDefault();
        }
        const k8sApi = kc.makeApiClient(k8s.CoreV1Api);
        return k8sApi;
    } catch (error) {
        console.error("Error while getting Kubernetes API", error);
        return;
    }
}

async function createPod(metadata, namespace) {
    try {
        const k8sApi = await getKubernetesClient();
        return await k8sApi.createNamespacedPod(namespace, metadata);
    } catch (error) {
        console.error("Error while creating pod", error);
        return;
    }
}

async function deletePod(name, namespace) {
    try {
        const k8sApi = await getKubernetesClient();
        return await k8sApi.deleteNamespacedPod(name, namespace);
    } catch (error) {
        console.error("Error while deleting pod", error);
        return;
    }
}

export default Object.freeze({
    createPod,
    deletePod,
    getKubernetesClient
});
```