01.14.21

CDK8S for Kubernetes: How to interact with Kubernetes without KubeCTL

By Mauricio Ashimine

Introduction

Kubernetes has become the most popular DevOps tools in the industry. From startups to enterprises, everyone is leveraging the power of containerization by running their application in containers inside the Kubernetes cluster.

To work with Kubernetes, you need to create YAML files which contain all the cluster resources, services, deployments detail. YAML is human-readable and easy to learn, but if it becomes very difficult to work with YAML files when the cluster becomes complex. Adding or removing resources from a big YAML file is not an easy task.

What if we told you there is a solution to this issue? And moreover, that if you’re a developer, you are going to love this solution. The answer lies in CDK8s.

What is CDK8s?

CDK8s is an open-source cloud development kit for managing the Kubernetes clusters. In CDK8s, instead of using YAML files for managing the resources and applications in Kubernetes, you write codes for it using familiar programming languages (JavaScript, TypeScript, Python, etc.), which you would already know. Hence, it is developer-friendly.

You get all of the advantages of using a programming language that you are familiar with, like your ide, type hinting, auto-completion, less context switching, loops and iteration, shareable modules and classes. Testing all of this can help boost your productivity and prevent you from writing a ton of YAML lines. CDK8s will then take that code you write and generate the corresponding YAML for you, at which point you can then use your standard Kubernetes tools to create those resources inside your Kubernetes cluster.

CDK8s runs locally, but it can generate YAML, which can be deployed anywhere on a Kubernetes cluster. So, it maintains standardization across on-premises and any cloud provider. CDK8s was introduced by AWS, but it can be used by anybody with resources outside AWS also.

CDK8s Building Blocks

There are three main components of CDK8s – the core framework, the construct library and the command-line interface.

With the core framework, you can create and structure apps that contain one or multiple stacks. Stacks are logical units of infrastructure that contains multiple resources and mapped one-to-one to cloud formation stacks.

The construct library is a set of components crafted to create resources for a specific service. It can be a Kubernetes resource such as pod, or it can be a complete application also. This helps to decouple libraries and use only the dependencies that you need in your project. It is also built with best practices and security considerations to provide a good developer experience, ease of use and fast iteration cycles.

The CDK CLI helps to interact with the core framework to initialize project structure, inspect differences between deployments.

CDK8s Demo Example

Before we discuss how CDK8s works, here are some prerequisites that you need first. The prerequisite to run CDK8s is that you need to have nodejs and npm installed on your system. And then you can install CDK8s by a single command:

npm install -g cdk8s-cli

Now to initialize a project in CDK8s, you need to use cdk8s init command with a project template, for example, python-app or typescript-app. To show an example of CDK8s, we will create a directory and initialize a CDK8s application in it. We are using a typescript application in this example.

[centos@centos7 ~]$ mkdir cdk8s-example
[centos@centos7 ~]$ cd cdk8s-example/
[centos@centos7 cdk8s-example]$ cdk8s init typescript-app

Initializing a project from the typescript-app template

npm notice created a lockfile as package-lock.json. You should commit this file.
+ cdk8s-plus-17@1.0.0-beta.5
+ constructs@3.2.74
+ cdk8s@1.0.0-beta.5
added 12 packages from 10 contributors and audited 12 packages in 2.446s
+ @types/jest@26.0.19
+ cdk8s-cli@1.0.0-beta.5
+ jest@26.6.3
+ @types/node@14.14.14
+ typescript@4.1.3
+ ts-jest@26.4.4
added 629 packages from 437 contributors and audited 643 packages in 73.113s

PASS  ./main.test.ts (7.258 s)
Placeholder
   ✓ Empty (12 ms)
› 1 snapshot written.
Snapshot Summary
› 1 snapshot written from 1 test suite.
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   1 written, 1 total
Time:        16.272 s
Ran all test suites.
> cdk8s-example@1.0.0 synth /home/centos/cdk8s-example
> cdk8s synth
dist/cdk8s-example.k8s.yaml
Your cdk8s typescript project is ready!

The YAML file created at dist/cdk8s-example.k8s.yaml will be empty at this moment.

Now that the project is initialized, you can see many files have been imported to this directory depending on the project type we mentioned in the init command.

[centos@centos7 cdk8s-example]$ ls -l
total 288
-rw-rw-r--.   1 centos centos     56 Dec 18 12:40 cdk8s.yaml
drwxrwxr-x.   2 centos centos     36 Dec 18 12:42 dist
-rw-rw-r--.   1 centos centos    916 Dec 18 12:40 help
drwxrwxr-x.   2 centos centos     50 Dec 18 12:42 imports
-rw-rw-r--.   1 centos centos    156 Dec 18 12:40 jest.config.js
-rw-rw-r--.   1 centos centos    197 Dec 18 12:42 main.d.ts
-rw-rw-r--.   1 centos centos   1454 Dec 18 12:42 main.js
-rw-rw-r--.   1 centos centos     11 Dec 18 12:42 main.test.d.ts
-rw-rw-r--.   1 centos centos   1502 Dec 18 12:42 main.test.js
-rw-rw-r--.   1 centos centos    291 Dec 18 12:40 main.test.ts
-rw-rw-r--.   1 centos centos    335 Dec 18 12:40 main.ts
drwxrwxr-x. 460 centos centos  16384 Dec 18 12:41 node_modules
-rw-rw-r--.   1 centos centos    779 Dec 18 12:41 package.json
-rw-rw-r--.   1 centos centos 226992 Dec 18 12:41 package-lock.json
drwxrwxr-x.   2 centos centos     31 Dec 18 12:42 __snapshots__
-rw-rw-r--.   1 centos centos    717 Dec 18 12:40 tsconfig.json

If we open the typescript application file main.ts, you can see a basic typescript code with no Kubernetes resource defined in it.

Modify the main.ts file and add Kubernetes resources to it. Using Constructs in CDK8s, you can add the resources using the typescript code mentioned below.

This is how the updated main.ts will look like:

import { Construct } from 'constructs';
import { App, Chart, ChartProps } from 'cdk8s';

// imported constructs
import { KubeDeployment, KubeService, IntOrString } from './imports/k8s';

export class MyChart extends Chart {
 constructor(scope: Construct, id: string, props: ChartProps = { }) {
   super(scope, id, props);
   const label = { app: 'cdk8s-example' };

   new KubeService(this, 'service', {
     spec: {
       type: 'LoadBalancer',
       ports: [ { port: 80, targetPort: IntOrString.fromNumber(8080) } ],
       selector: label
     }
   });

   new KubeDeployment(this, 'deployment', {
     spec: {
       replicas: 3,
       selector: {
         matchLabels: label
       },
       template: {
         metadata: { labels: label },
         spec: {
           containers: [
             {
               name: 'hello-kubernetes',
               image: '*******/hello-kubernetes:1.7',
               ports: [ { containerPort: 8080 } ]
             }
           ]
         }
       }
     }
   });
 }
}

const app = new App();
new MyChart(app, 'cdk8s-example');
app.synth();

Here you are creating a load balancer service and the deployment will have 3 replicas on the Kubernetes cluster.

Now that we have changed the code in the main.ts file, we need to compile it again.

[centos@centos7 cdk8s-example]$ npm run compile
> cdk8s-example@1.0.0 compile /home/centos/cdk8s-example
> tsc


After compiling it, we will run cdk8s synth command. Synth will create the Kubernetes YAML file from the code you have written.

[centos@centos7 cdk8s-example]$ cdk8s synth
dist/cdk8s-example.k8s.yaml

Now, if we go back and check the YAML file inside the dist directory, it won’t be empty. A proper Kubernetes YAML file has been created with resources defined in it.

Let’s apply this to the Kubernetes cluster. We will run the kubectl apply command, which will create both service and deployment defined in the YAML file through the typescript code.

[centos@centos7 cdk8s-example]$ kubectl apply -f dist/cdk8s-example.k8s.yaml
service/cdk8s-example-service-c8ca0070 created
deployment.apps/cdk8s-example-deployment-c8635417 created

Run the command below to check if the service got created. We can see our service cdk8s-example-service-c8ca0070 has just now started.

[centos@centos7 cdk8s-example]$ kubectl get services
NAME                             TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
cdk8s-example-service-c8ca0070   LoadBalancer   10.105.40.213   <none>     80:30923/TCP    2m5s
dashboard                        ClusterIP      10.104.61.127   <none>        443/TCP        40d
loki-grafana                     ClusterIP      10.110.135.3    <none>        80/TCP         40d

Run the command below to check the deployment of the service. Since we had mentioned 3 replicas, you can see the service is running on 3 pods on the cluster.

[centos@centos7 cdk8s-example]$ kubectl get pods
NAME                                                 READY   STATUS             RESTARTS   AGE
cdk8s-example-deployment-c8635417-5d89c89d48-b7pz9   1/1     Running            0          2m9s
cdk8s-example-deployment-c8635417-5d89c89d48-dv8sn   1/1     Running            0          2m9s
cdk8s-example-deployment-c8635417-5d89c89d48-mg4m7   1/1     Running            0          2m9s
dashboard-864cf78fb-2p7k9                            0/1     CrashLoopBackOff   297        40d
loki-grafana-57ddbf496b-845dg                        1/1     Running            0          40d

Congratulations, you have successfully executed a CDK8s example!

Conclusion

CDK8s is a very promising tool to work with complex Kubernetes clusters. It is very easy for devs to work with this tool as you can easily write programs in the programming languages you know to create Kubernetes YAML files. But in case you have a small Kubernetes cluster, which is not a production cluster, you do not necessarily need to use CDK8s, you can simply work with YAML.


Caylent provides a critical DevOps-as-a-Service function to high growth companies looking for expert support with Kubernetes, cloud security, cloud infrastructure, and CI/CD pipelines. Our managed and consulting services are a more cost-effective option than hiring in-house, and we scale as your team and company grow. Check out some of the use cases, learn how we work with clients, and read more about our DevOps-as-a-Service offering.