tutorial

How to Monitor cdk8s Applications with Vigilmon

cdk8s (Cloud Development Kit for Kubernetes) lets you define Kubernetes applications and reusable abstractions using TypeScript, Python, Java, or Go — genera...

cdk8s (Cloud Development Kit for Kubernetes) lets you define Kubernetes applications and reusable abstractions using TypeScript, Python, Java, or Go — generating standard Kubernetes YAML manifests from code. Instead of maintaining YAML by hand, you define infrastructure as typed classes, compose them into stacks, and synthesize manifests at build time.

cdk8s changes how Kubernetes resources are authored, not how they're deployed. Once your manifests are applied to a cluster, they face the same failure modes as any Kubernetes workload. But cdk8s introduces additional risks: synthesized manifests can contain subtle bugs that a type-checker won't catch — a wrong port number, a missing label selector, a health probe pointing at the wrong path.

This tutorial shows you how to monitor cdk8s-deployed applications with Vigilmon — free tier, no credit card required.


Why cdk8s deployments need external monitoring

cdk8s generates YAML from code. The code can compile successfully while producing manifests that result in broken deployments:

  • Health probe path mismatch — your cdk8s stack sets livenessProbe.httpGet.path to /health, but the container's actual health route is /healthz; pods restart-loop forever while load balancer routes traffic to unhealthy instances
  • Port misconfiguration — a refactor changes the container port in code but the Service targetPort isn't updated; traffic silently drops
  • Label selector mismatch — a Deployment's selector.matchLabels and pod template labels diverge in a cdk8s abstraction refactor; new pods are created but the Service routes to nothing
  • Resource limit too low — a shared cdk8s construct sets a default memory limit that's too low for one app; pods OOMKill under load
  • Ingress rule bug in a generated manifest — a cdk8s helper miscalculates path prefix rules; some routes 404 while others work fine

Kubernetes internal probes don't catch the routing and DNS failures that users actually experience. External monitoring from Vigilmon probes your endpoints from outside the cluster, exactly as users do.


What you'll need

  • A cdk8s app that synthesizes Kubernetes manifests and deploys them to a cluster
  • At least one HTTP service exposed externally
  • A free Vigilmon account

Step 1: Ensure your cdk8s app exposes a health endpoint

A common cdk8s pattern defines a reusable WebService construct. Make sure it includes a health endpoint and a correct probe:

// TypeScript example: a cdk8s construct for a web service
import { Construct } from 'constructs';
import { App, Chart } from 'cdk8s';
import { Deployment, Service, IntOrString } from 'cdk8s-plus-32';

export class WebService extends Chart {
  constructor(scope: Construct, id: string, props: { image: string; port: number }) {
    super(scope, id);

    const label = { app: id };

    const deployment = new Deployment(this, 'Deployment', {
      metadata: { labels: label },
      selector: { matchLabels: label },
    });

    const container = deployment.addContainer({
      image: props.image,
      portNumber: props.port,
      liveness: {
        httpGet: {
          path: '/health',
          port: IntOrString.fromNumber(props.port),
        },
      },
      readiness: {
        httpGet: {
          path: '/health',
          port: IntOrString.fromNumber(props.port),
        },
      },
    });

    new Service(this, 'Service', {
      metadata: { labels: label },
      selector: label,
      ports: [{ port: 80, targetPort: IntOrString.fromNumber(props.port) }],
      type: ServiceType.LOAD_BALANCER,
    });
  }
}

Synthesize and apply:

cdk8s synth
kubectl apply -f dist/

Verify the service is up:

kubectl get svc -l app=my-web-service
# NAME             TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)
# my-web-service   LoadBalancer   10.100.0.50    203.0.113.50    80:31080/TCP

curl http://203.0.113.50/health
# {"status":"ok","version":"2.3.1"}

Step 2: Add HTTP monitoring in Vigilmon

  1. Sign in at vigilmon.online and go to Monitors → New Monitor
  2. Select HTTP / HTTPS
  3. Enter your service URL: https://my-service.example.com/health (or the LoadBalancer IP)
  4. Set interval to 1 minute
  5. Under Expected response, configure:
    • Status code: 200
    • (Optional) Body contains: "status":"ok"
  6. Save the monitor

Vigilmon now probes your cdk8s-deployed application from multiple geographic regions. If a cdk8s refactor introduces a misconfiguration that breaks the service, Vigilmon catches it within minutes — even before your users notice.

Catching cdk8s synthesis bugs in staging first

Use separate Vigilmon monitors for staging and production environments:

  • https://staging.my-service.example.com/health — catches cdk8s manifest bugs before production
  • https://my-service.example.com/health — production uptime

When you push a cdk8s change, Vigilmon's staging monitor will alert you if the synthesized manifests break the service before you promote to production.


Step 3: Verify your cdk8s Service selector after synthesis

A common cdk8s bug is a mismatch between the Deployment's pod labels and the Service selector. This happens when you update labels in a shared construct without updating all the selectors. Add this check to your CI pipeline:

# After applying, verify endpoints are populated
kubectl get endpoints my-web-service
# NAME             ENDPOINTS           AGE
# my-web-service   10.244.0.15:3000    5m

# If ENDPOINTS shows <none>, the selector doesn't match any pods

If endpoints are empty, your cdk8s service selector is mismatched. Vigilmon will also detect this — the service will return 503 because the load balancer has no healthy backends.


Step 4: Add TCP monitoring for non-HTTP services

If your cdk8s app includes non-HTTP services — a gRPC server, a WebSocket endpoint, a database — add TCP monitors in Vigilmon:

  1. Go to Monitors → New Monitor → TCP Port
  2. Enter the host and port of your TCP service
  3. Set interval to 1 minute
  4. Save

Example TCP monitors for a cdk8s-defined application stack:

| Service | Host | Port | Protocol | |---------|------|------|----------| | API server | api.example.com | 443 | TCP (HTTPS) | | gRPC service | grpc.example.com | 50051 | TCP | | Redis cache | redis.internal.example.com | 6379 | TCP |


Step 5: Use response body checks to validate synthesis output

Include the app version — which your cdk8s stack encodes as a container image tag — in your health response:

{
  "status": "ok",
  "version": "2.3.1",
  "environment": "production"
}

In Vigilmon's Response body contains field, assert the expected version string. After a cdk8s synth + kubectl apply cycle, this assertion verifies the new image tag is actually running.

This is particularly useful when cdk8s constructs parameterize the image version — a synthesis bug that hardcodes the old version will be caught immediately.


Step 6: Configure alerts and correlate with cdk8s synth changes

Set up alert channels in Vigilmon:

  1. Go to Alert Channels → Add Channel
  2. Choose Webhook for Slack/PagerDuty or Email for direct notification
  3. Assign the channel to your monitors

When Vigilmon fires an alert after a cdk8s deployment:

# Check what was recently applied
kubectl rollout history deployment/my-web-service

# Look at the synthesized manifest diff
git diff HEAD~1 dist/my-chart.k8s.yaml

# Check pod events for the new deployment
kubectl describe deployment my-web-service
kubectl get events --sort-by='.lastTimestamp' | tail -20

# Roll back if needed
kubectl rollout undo deployment/my-web-service

The manifest diff is invaluable — it shows exactly what changed in the synthesized output between the last working version and the broken one.


Step 7: Build a service health status page

  1. In Vigilmon, go to Status Pages → New Status Page
  2. Name it after your cdk8s application stack or team
  3. Add all monitors: HTTP endpoints, TCP services, staging and production
  4. Group monitors by cdk8s chart or application layer
  5. Publish the page

Share the status page URL with your team. During cdk8s rollouts, team members can watch the status page instead of querying kubectl to verify services come back up after each kubectl apply.


Monitoring summary

| Monitor | Type | Purpose | |---------|------|---------| | https://my-service.example.com/health | HTTP | End-to-end service health | | Staging HTTP endpoint | HTTP | Catch cdk8s bugs pre-production | | TCP monitors for non-HTTP services | TCP | Port-level reachability | | Response body version assertion | HTTP | Correct image deployed |


What's next

  • Multi-environment monitors — mirror your cdk8s environment structure (dev, staging, prod) with corresponding Vigilmon monitors; use Vigilmon's status page grouping to organize them
  • SSL certificate monitoring — Vigilmon tracks TLS cert expiry for your cdk8s-managed services; critical when cert-manager TLS resources are synthesized as part of your cdk8s stack
  • Latency tracking — Vigilmon's response time history helps you detect performance regressions introduced by cdk8s manifest changes, such as reduced resource limits or changed probe timings

Start monitoring your cdk8s applications today at vigilmon.online — free tier, no credit card required.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →