Skip to main content

Cloud Development Kit for Kubernetes

Project description

cdk8s

Cloud Development Kit for Kubernetes

cdk8s is a software development framework for defining Kubernetes applications using rich object-oriented APIs. It allows developers to leverage the full power of software in order to define abstract components called "constructs" which compose Kubernetes resources or other constructs into higher-level abstractions.

This library is the foundation of cdk8s. It includes base types that are used to define cdk8s applications.

Chart

The Chart is a container that synthesizes a single Kubernetes manifest.

# Example automatically generated without compilation. See https://github.com/aws/jsii/issues/826
class MyChart(Chart):
    def __init__(self, scope, ns):
        super().__init__(scope, ns)

During synthesis, charts collect all the ApiObject nodes (recursively) and emit a single YAML manifest that includes all these objects.

ApiObject

An ApiObject is a construct that represents an entry in a Kubernetes manifest. In most cases, you won't use ApiObject directly but rather use classes that are generated by the cdk8s CLI and extend this base class.

Include

The Include construct can be used to include an existing manifest in a chart.

The following example will include the Kubernetes Dashboard in MyChart:

# Example automatically generated without compilation. See https://github.com/aws/jsii/issues/826
from cdk8s import Include

class MyChart(Chart):
    def __init__(self, scope, id):
        super().__init__(scope, id)

        dashboard = Include(self, "dashboard", {
            "url": "https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml",
            # or
            "url": "dashboard.yaml"
        })

All API objects defined in the included manifest will be added as children ApiObjects under the Include construct's scope. This implies that you can use Node.of(include).children to inspect them.

The following example queries for all the Deployment resources in the dashboard:

# Example automatically generated without compilation. See https://github.com/aws/jsii/issues/826
deps = Node.of(dashboard).children.filter((c: ApiObject) => c.kind === 'Deployment')

NOTE: names of included objects (metadata.name) are preserved. This means that if you try to include the same manifest twice into the same chart, your manifest will have duplicate definitions of the same objects.

Dependencies

You can declare dependencies between various cdk8s constructs by using the built-in support of the underlying constructs model.

ApiObjects

For example, you can force kubernetes to first apply a Namespace before applying the Service in the scope of that namespace:

# Example automatically generated without compilation. See https://github.com/aws/jsii/issues/826
namespace = k8s.Namespace(chart, "backend")
service = k8s.Service(chart, "Service", metadata={"namespace": namespace.name})

# declare the dependency. this is just a syntactic sugar for Node.of(service).addDependency(namespace)
service.add_dependency(namespace)

cdk8s will ensure that the Namespace object is placed before the Service object in the resulting manifest:

apiVersion: v1
kind: Namespace
metadata:
  name: chart-backend-a59d2e47
---
apiVersion: v1
kind: Service
metadata:
  name: chart-service-93d02be7
  namespace: chart-backend-a59d2e47

Charts

You can also specify dependencies between charts, in exactly the same manner. For example, if we have a chart that provisions our namespace, we need that chart to be applied first:

# Example automatically generated without compilation. See https://github.com/aws/jsii/issues/826
namespace_chart = NamespaceChart(app, "namespace")
application_chart = ApplicationChart(app, "application")

# declare the dependency. this is just a syntactic sugar for Node.of(applicationChart).addDependency(namespaceChart)
application_chart.add_dependency(namespace_chart)

Running cdk8s synth will produce the following dist directory:

> cdk8s synth

dist/0000-namespace.k8s.yaml
dist/0001-application.k8s.yaml

Notice that the namespace chart appears first with the 0000 prefix. This will ensure that a subsequent execution of kubectl apply -f dist/ will apply the namespace first, and the application second.

Custom Constructs

The behavior above applies in the same way to custom constructs that you create or use.

# Example automatically generated without compilation. See https://github.com/aws/jsii/issues/826
class Database(Construct):
    def __init__(self, scope, name):
        super().__init__(scope, name)

        k8s.StatefulSet(self, "StatefulSet")
        k8s.ConfigMap(self, "ConfigMap")

app = App()

chart = Chart(app, "Chart")

service = k8s.Service(chart, "Service")
database = Database(chart, "Database")

service.add_dependency(database)

Declaring such a dependency will cause each ApiObject in the source construct, to depend on every ApiObject in the target construct.

Note that in the example above, the source construct is actually an ApiObject, which is also ok since it is essentially a construct with a single ApiObject.

Note that if the source of your dependency is a custom construct, it won't have the addDependency syntactic sugar by default, so you'll have to use Node.of().

The resulting manifest will be:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: chart-database-statefulset-4627f8e2
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: chart-database-configmap-676f8640
---
apiVersion: v1
kind: Service
metadata:
  name: chart-service-93d02be7

You can see that all ApiObjects of the Database construct, appear before the Service object.

Things just got cool

If you simply declare a dependency between two ApiObjects (or Constructs), that belong to two different Charts, cdk8s will create the chart dependency automatically for you.

# Example automatically generated without compilation. See https://github.com/aws/jsii/issues/826
namespace_chart = NamespaceChart(app, "namespace")
application_chart = ApplicationChart(app, "application")

namespace = k8s.Namespace(namespace_chart, "namespace")
deployment = k8s.Deployment(application_chart, "Deployment")

# dependency between ApiObjects, not Charts!
deployment.add_dependency(namespace)

Running cdk8s synth will produce the same result as if explicit chart dependencies were declared:

> cdk8s synth

dist/0000-namespace.k8s.yaml
dist/0001-application.k8s.yaml

This means you need not be bothered with managing chart dependencies, simply work with the ApiObjects you create, and let cdk8s infer the chart dependencies.

Testing

cdk8s bundles a set of test utilities under the Testing class:

  • Testing.app() returns an App object bound to a temporary output directory.
  • Testing.synth(chart) returns the Kubernetes manifest synthesized from a chart.

License

This project is distributed under the Apache License, Version 2.0.

This module is part of the cdk8s project.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cdk8s-0.27.0.tar.gz (207.2 kB view hashes)

Uploaded Source

Built Distribution

cdk8s-0.27.0-py3-none-any.whl (205.0 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page