Life becomes just a little bit easier if you can invoke the Kubernetes API directly. That's why GoDaddy decided to make kubernetes-client, an easy to use Node.js client for Kubernetes.
It is listed as the officially supported Kubernetes client library for JavaScript. This is significant as it is has the backing of Kubernetes SIG API Machinery, which means it is kept up to date with changes to the Kubernetes API specification. It also means that your support requests and issues are much more likely to get a timely response.
Installing
Install with npm:
npm install kubernetes-client --save
Configuring
kubernetes-client generates a Kubernetes API client at runtime based on a Swagger/OpenAPI definition.
kubernetes-client will configure itself automatically by first trying to load configuration from the KUBECONFIG
environment variable, then in ~/.kube/config
. If it hasn't found anything yet it will then try to use an in-cluster service account, and eventually settle on a default proxy configuration as a last resort.
A simple configuration:
const { Client, KubeConfig } = require('kubernetes-client');
const Request = require('kubernetes-client/backends/request');
async function initKubeClient() {
const kubeconfig = new KubeConfig();
if (process.env.NODE_ENV === 'production') {
kubeconfig.loadFromCluster();
} else {
kubeconfig.loadFromDefault();
}
const backend = new Request({ kubeconfig });
const kubeclient = new Client({ backend });
await kubeclient.loadSpec();
return kubeclient;
}
Using
kubernetes-client maps path item objects to object chains ending in HTTP methods. So for example, api/v1/namespaces/myproject/configmaps
maps to to .api.v1.namespaces('myproject').configmaps
. This mapping logic can be used for all resources types.
You can refer to the Kubernetes API documentation to find the API endpoint for a particular resource.
Deployments
Let's learn how to interact with Deployments. I picked Deployments as an example as they are commonly used, and the same logic can be applied to all other resources.
Creating a deployment
You can create a deployment by making a POST
request to the Kubernetes API.
const deploymentManifest = require('./nginx-deployment.json');
const createdDeployment = await kubeclient.apis.apps.v1.namespaces(namespace).deployments.post({ body: deploymentManifest });
console.log('NGINX Deployment created:', createdDeployment);
You can also verify that the deployment was created using kubectl
.
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 1 1 1 0 1m
Modifying a deployment
To modify part of a resource you can send a PATCH
request.
const labels = {
metadata: {
labels: {
environment: 'DEVELOPMENT'
}
}
};
const modified = await kubeclient.apis.apps.v1.namespaces(namespace).deployments(deploymentManifest.metadata.name).patch({ body: labels });
console.log('Deployment modified:', modified.body.metadata);
Updating a deployment
By making a PUT
request you can replace the entire resource.
const updated = await kubeclient.apis.apps.v1.namespaces(namespace).deployments(deploymentManifest.metadata.name).put({ body: deploymentManifest });
console.log('Deployment updated:', updated);
Fetching deployment(s)
Getting all deployments in a namespace.
const deployment = await kubeclient.apis.apps.v1.namespaces(namespace).deployments(deploymentManifest.metadata.name).get();
console.log('Deployment:', deployment);
Fetching a single deployment by in a namespace.
const deployments = await kubeclient.apis.apps.v1.namespaces(namespace).deployments.get();
console.log('Deployments:', deployments);
Getting all deployments in all namespaces.
const deployments = await kubeclient.apis.apps.v1.deployments.get();
console.log('Deployments (all namespaces):', deployments);
You can optionally specify a query string object qs
to GET requests. For example, to filter on label selector.
const deployments = await kubeclient.apis.apps.v1.namespaces(namespace).deployments.get({ qs: { labelSelector: 'app=nginx'}});
console.log(deployments);
You can use the Kubernetes API documentation to see what other query parameters are available for a resource.
Deleting a deployment
Deployments can be deleted with DELETE
.
const removed = await kubeclient.apis.apps.v1.namespaces(namespace).deployments(deploymentManifest.metadata.name).delete();
console.log('Deployment deleted:', removed);
Custom Resources
With kubernetes-client it is possible to extend the Kubernetes API with a CustomResourceDefinition.
In this example, I am creating a CustomResourceDefinition for GitHub accounts.
githubaccount-crd.json
{
"kind": "CustomResourceDefinition",
"spec": {
"scope": "Namespaced",
"version": "v1",
"versions": [{
"name": "v1",
"served": true,
"storage": true
}],
"group": "craicoverflow.github.io",
"names": {
"shortNames": [
"ga"
],
"kind": "GitHubAccount",
"plural": "githubaccounts",
"singular": "githubaccount"
}
},
"apiVersion": "apiextensions.k8s.io/v1beta1",
"metadata": {
"name": "githubaccounts.craicoverflow.github.io"
}
}
Creating a CustomResourceDefinition
const crd = require('./githubaccount-crd.json');
const createCRD = await kubeclient.apis['apiextensions.k8s.io'].v1beta1.customresourcedefinitions.post({ body: crd });
console.log('CustomResourceDefinition created:', createCRD);
You then need to add the endpoints for the new CustomResourceDefinition to kubeclient
.
kubeclient.addCustomResourceDefinition(crd);
Creating a custom resource
Now that we have created the GitHubAccount
CRD, we will be able to create a GitHubAccount
custom resource.
githubaccount-cr.json
{
"apiVersion": "craicoverflow.github.io/v1",
"kind": "GitHubAccount",
"metadata": {
"name": "craicoverflow"
},
"spec": {
"login": "craicoverflow",
"blog": "https://endaphelan.me",
"bio": "// TODO: Add a bio",
"type": "User",
"public_repos": "52"
}
}
const customResource = require('./githubaccount-crd.json');
const createdAccount = await kubeclient.apis[crd.spec.group].v1.namespaces(namespace).githubaccounts.post({ body: customResource });
console.log('Created GitHubAccount:', createdAccount);
Fetching custom resource(s)
Fetching a GitHubAccount custom resource.
const githubAccount = await kubeclient.apis[crd.spec.group].v1.namespaces(namespace).githubaccounts(customResource.metadata.name).get();
console.log('GitHubAccount:', githubAccount);
Fetching all GitHubAccount custom resources in a namespace.
const allAccounts = await kubeclient.apis[crd.spec.group].v1.namespaces(namespace).githubaccounts.get();
console.log('GitHubAccountList:', allAccounts);
Deleting a custom resource
const deleteAccounts = await kubeclient.apis[crd.spec.group].v1.namespaces(namespace).githubaccounts(customResource.metadata.name).delete();
console.log('Deleted GitHubAccount:', deleteAccounts);
Deleting a CustomResourceDefinition
const deletedCRD = await kubeclient.apis['apiextensions.k8s.io'].v1beta1.customresourcedefinitions(crd.metadata.name).delete();
console.log('GitHubAccount CRD deleted:', deletedCRD);
Error handling
kubernetes-client outputs a HTTP error when a request fails. The following example emulates kubectl apply
, by handling a 409 Conflict
error when creating a deployment, and replacing the resource instead.
try {
const createdDeployment = await kubeclient.apis.apps.v1.namespaces(namespace).deployments.post({ body: deploymentManifest });
console.log('Deployment created:', createdDeployment);
} catch (err) {
if (err.statusCode === 409) {
const updatedDeployment = await kubeclient.apis.apps.v1.namespaces(namespace).deployments(deploymentManifest.metadata.name).put({ body: deploymentManifest });
console.log('Updated updated:', updatedDeployment);
}
}
Watching resources
You can use watch endpoints to stream events from resources. Common event types are ADDED
, MODIFIED
, DELETED
, which signal a new or changed resource at that endpoint.
Watching deployments
const deploymentStream = await kubeclient.apis.apps.v1.watch.namespaces(namespace).deployments.getObjectStream();
deploymentStream.on('data', event => {
if (event.type === 'ADDED') {
console.log('Deployment created:', event.body);
}
});
Watching custom resources
const githubAccountStream = await kubeclient.apis[crd.spec.group].v1.watch.namespaces(namespace).githubaccounts.getObjectStream();
githubAccountStream.on('data', event => {
if (event.type === 'CLOSED') {
console.log('GitHub account deleted:', event);
}
});
To see the watch
in action, create or update a GitHubAccount custom resource from your terminal and you will see the event stream output a new event in your Node.js application.
cat <<EOF | kubectl apply -n myproject -f -
apiVersion: craicoverflow.github.io/v1
kind: GitHubAccount
metadata:
name: testuser
spec:
bio: ''
blog: https://example.com
login: testuser
public_repos: "100"
type: User
EOF
Additional Resources
- godaddy/kubernetes-client - the documentation for this library is brilliant. On top of that, there are lots of great examples.
- craicoverflow/kubernetes-client-nodejs-example - a sample project containing all of the code from this guide.
- Kubernetes Documentation - the official documentation for Kubernetes.
Top comments (0)