kubernetix / k8x

Deploy and manage reusable k8s apps with ts/js
0 stars 0 forks source link
cli cmd docker docker-compose go golang k8s kubernetes npm terminal typescript

Kubernetix (K8x)

Deploy and manage reusable apps with typescript and javascript

Most basic chart definition

This example shows the most basic, non configurable version of a chart. It closly follows the example yaml definition of a kubernetes deployment

touch chart.js

// https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#creating-a-deployment
const deployment = {
  apiVersion: 'apps/v1',
  kind: 'Deployment',
  metadata: { 
    name: "hello-world-deployment",
    labels: { app: "hello-world" }
  },
  spec: {
    replicas: 1,
    selector: {
      matchLabels: { app: "hello-world" }
    },
    template: {
      metadata: { labels: { app: "hello-world" } },
      spec: {
        containers: [
          { name: 'nginx', image: "nginx:1.14.2", ports: [{ containerPort: 80 }] }
        ]
      }
    }
  }
}

export default () => ({
  name: "hello-world",
  namespace: "default",
  components: [pod],
});

Deploy it with:

k8x install chart.js

Most basic chart definition with types

You can use typescript with proper type definitions.

npm install -D @kubernetix/types && mv chart.js chart.ts

+/// <reference types="@kubernetix/types" />

// https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#creating-a-deployment
- const deployment = {
+ const deployment: k8x.Deployment = {
  apiVersion: 'apps/v1',
  kind: 'Deployment',
  metadata: { 
    name: "hello-world-deployment",
    labels: { app: "hello-world" }
  },
  spec: {
    replicas: 1,
    selector: {
      matchLabels: { app: "hello-world" }
    },
    template: {
      metadata: { labels: { app: "hello-world" } },
      spec: {
        containers: [
          { name: 'nginx', image: "nginx:1.14.2", ports: [{ containerPort: 80 }] }
        ]
      }
    }
  }
}

- export default () => ({
+ export default (): k8x.Chart => ({
  name: "hello-world",
  namespace: "default",
  components: [pod],
});

Deploy it with:

k8x install chart.ts

Most basic chart definition with types and env integration

Every environment variable prefixed with K8X_ is availabe for the chart to use

/// <reference types="@kubernetix/types" />

// https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#creating-a-deployment
const deployment: k8x.Deployment = {
  apiVersion: 'apps/v1',
  kind: 'Deployment',
  metadata: { 
    name: "hello-world-deployment",
    labels: { app: "hello-world" }
  },
  spec: {
    replicas: 1,
    selector: {
      matchLabels: { app: "hello-world" }
    },
    template: {
      metadata: { labels: { app: "hello-world" } },
      spec: {
        containers: [
          { name: 'nginx', image: "nginx:1.14.2", ports: [{ containerPort: 80 }] }
        ]
      }
    }
  }
}

export default (): k8x.Chart => ({
  name: "hello-world",
-  namespace: "default",
+  namespace: k8x.$env["NAMESPACE"] ?? "default",
  components: [pod],
});

Deploy it with:

K8X_NAMESPACE=backend-staging k8x install chart.ts

Most basic chart definition with types and env integration and imported ingress component

You can use leverage js imports to reuse components or variables

/// <reference types="@kubernetix/types" />

+import ingress from "./components/ingress"

// https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#creating-a-deployment
const deployment: k8x.Deployment = {
  apiVersion: 'apps/v1',
  kind: 'Deployment',
  metadata: { 
    name: "hello-world-deployment",
    labels: { app: "hello-world" }
  },
  spec: {
    replicas: 1,
    selector: {
      matchLabels: { app: "hello-world" }
    },
    template: {
      metadata: { labels: { app: "hello-world" } },
      spec: {
        containers: [
          { name: 'nginx', image: "nginx:1.14.2", ports: [{ containerPort: 80 }] }
        ]
      }
    }
  }
}

export default (): k8x.Chart => ({
  name: "hello-world",
  namespace: k8x.$env["NAMESPACE"] ?? "default",
-  components: [pod],
+  components: [pod, ingress],
});

That's it, deploy your apps with typescript or javascript. Happy deploying!

Medium complicated chart definition

/// <reference types="@kubernetix/types" />

import MyIngress, { MyIngressProps } from "./components/ingress"

const values: MyIngressProps = {
  name: k8x.$env["INGRESS_NAME"] ?? "my-ingress",
  appRoot: k8x.$env["INGRESS_NAME"] ?? "/var/www/html",
  additionalPaths:
    Object.keys(k8x.$env)
      .filter((key) => key.startsWith("INGRESS_PATH"))
      .map((key) => k8x.$env[key]) ?? [],
}

export default (): k8x.Chart => ({
  name: "default",
  namespace: "default",
  components: [MyIngress(values)],
})

Features:

Usage

k8x install <file>
k8x update <file>
k8x inspect <file>
k8x ls
k8x rm

Goals

Reuse existing infrastructure and code features for enhanced developer experience

Non Goals

Helm differentiation

I feel like helm was built by the ops side of devops people. k8x is built by the dev side of devops people.

In general k8x is pretty similar to helm. It also took a lot of inspiration from it. But where helm is reinventing the wheel, k8x just falls back to already used mechanisms and infrastructure. (npm/typescript/configuration)

Topic helm k8x
Packaging custom npm
Templating gotmpl js/ts
Configuration --set servers.foo.port=80 .env
Scripting custom js/ts
Code sharing custom js/ts

By custom I mean either a custom implementation, or a existing template language with limited or changed features.

Terminology

Component

A piece of reusable/configurable code, that is typically a kubernetes object, for example ingress, pod, service