Deploying a Simple NodeJS Microservice using CDK8s
Tags: kubernetes, typescript, cdk8s, devops
Published: 2021-02-22 13:13:00


Writing 200+ lines of YAML code just to deploy a Microservice on Kubernetes is a massive pain for a DevOps engineer.

CDK8s can be used to remove all that duplicate code, and make it easier to deploy your Microservice without having to write massive YAML manifests.

We also get the ability to write code using our favorite object-oriented languages.

We will be writing a sample CDK8s chart using TypeScript and opensource CDK8s constructs.

Constructs used :
```
@opencdk8s/cdk8s-redis-sts v0.0.7
cdk8s-plus-17 v1.0.0-beta.8
```
* Initialize CDK8s project
```
mkdir cdk8s-node-app && cd cdk8s-node-app
cdk8s init typescript-app
```
* Install construct libraries
```
npm install @opencdk8s/cdk8s-redis-sts 
```
* Edit main.ts to include our Redis db, and NodeJS app
```
import { Construct } from 'constructs';
import { App, Chart, ChartProps } from 'cdk8s';
import { MyRedis } from '@opencdk8s/cdk8s-redis-sts';
import { Deployment } from 'cdk8s-plus-17';

export class MyChart extends Chart {
  constructor(scope: Construct, id: string, props: ChartProps = { }) {
    super(scope, id, props);
const redis = new MyRedis(this, 'redis', {
      image: 'redis',
      namespace: 'default',
      volumeSize: '10Gi',
      replicas: 3,
      createStorageClass: false,
    });
new Deployment(this, "deployment", {
      metadata: {
        namespace: 'default',
      },
      containers: [{
        image: "hunterthompson/node-redis-counter:latest",
        name: "hello",
        env: {
          'REDIS_URI': {
            value: redis.name
          }
        }
      }]
    })
  }
}

const app = new App();
new MyChart(app, 'microservice');
app.synth();
```
* Run Compile and Synth
```
npm run compile && npm run synth
```
The end result of the npm run synth command is a YAML manifest that you can apply using kubectl

```
apiVersion: v1
data:
  master.conf: |-
    
    bind 0.0.0.0
    daemonize no
    port 6379
    tcp-backlog 511
    timeout 0
    tcp-keepalive 300
    supervised no
  slave.conf: |-
    
    slaveof redis 6379
kind: ConfigMap
metadata:
  name: redis-redis-conf
  namespace: default
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: redis
  name: redis
  namespace: default
spec:
  ports:
    - port: 6379
      targetPort: 6379
  selector:
    app: redis
  type: ClusterIP
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app: redis
  name: redis
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: redis
  serviceName: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - command:
            - bash
            - -c
            - |-
              [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
              ordinal=${BASH_REMATCH[1]}
              if [[ $ordinal -eq 0 ]]; then
              redis-server /mnt/redis/master.conf
              else
              redis-server /mnt/redis/slave.conf
              fi
          env: []
          image: redis
          name: redis
          ports:
            - containerPort: 6379
          resources:
            limits:
              cpu: 400m
              memory: 512Mi
            requests:
              cpu: 200m
              memory: 256Mi
          volumeMounts:
            - mountPath: /data
              name: redis
            - mountPath: /mnt/redis/
              name: redis-redis-conf
      terminationGracePeriodSeconds: 10
      volumes:
        - configMap:
            name: redis-redis-conf
          name: redis-redis-conf
  volumeClaimTemplates:
    - metadata:
        name: redis
        namespace: default
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 10Gi
        storageClassName: gp2
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: microservice-deployment-c89e8760
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      cdk8s.deployment: microservice-deployment-c87f6fea
  template:
    metadata:
      labels:
        cdk8s.deployment: microservice-deployment-c87f6fea
    spec:
      containers:
        - env:
            - name: REDIS_URI
              value: redis
          image: hunterthompson/node-redis-counter:latest
          imagePullPolicy: Always
          name: hello
          ports: []
          volumeMounts: []
      volumes: []
```
We just synthesized a 130 line YAML manifest by writing 33 lines of CDK8s code.