xiaohongshu
xiaohongshu
cdk8s-apps
CDK8s for type-safe Kubernetes manifests using Python. Use when building complex K8s applications programmatically, generating manifests from code, creating reusable infrastructure patterns, or managing multi-environment deployments.
Full skill instructions
Define Kubernetes applications using Python instead of YAML. cdk8s (Cloud Development Kit for Kubernetes) is a CNCF Sandbox project that provides type-safe, programmable infrastructure for Kubernetes.
What is cdk8s?
Key Benefits:
When to Use cdk8s:
# Install cdk8s CLI (requires Node.js 18+)
npm install -g cdk8s-cli
# Initialize Python project
cdk8s init python-app
cd my-cdk8s-app
# Install dependencies
pip install -r requirements.txt
#!/usr/bin/env python3
from constructs import Construct
from cdk8s import App, Chart
from cdk8s_plus_27 import Deployment, ContainerProps
class WebApp(Chart):
def __init__(self, scope: Construct, id: str):
super().__init__(scope, id)
# Create deployment with 3 replicas
deployment = Deployment(
self, "web",
replicas=3,
containers=[
ContainerProps(
image="nginx:1.21",
port=80
)
]
)
# Expose as LoadBalancer service
deployment.expose_via_service(port=80)
# Synthesize to YAML
app = App()
WebApp(app, "my-app")
app.synth()
# Generate Kubernetes manifests
cdk8s synth
# Review generated YAML
cat dist/my-app.k8s.yaml
# Deploy to cluster
kubectl apply -f dist/
cdk8s uses three levels of constructs:
L1 Constructs (Low-Level)
from imports import k8s
k8s.KubeDeployment(
self, "deployment",
spec=k8s.DeploymentSpec(
replicas=3,
selector=k8s.LabelSelector(match_labels={"app": "web"}),
template=k8s.PodTemplateSpec(...)
)
)
L2 Constructs (High-Level - cdk8s-plus)
from cdk8s_plus_27 import Deployment, ContainerProps
Deployment(
self, "deployment",
replicas=3,
containers=[ContainerProps(image="nginx", port=80)]
)
L3 Constructs (Custom Abstractions)
class WebService(Construct):
def __init__(self, scope, id, image, replicas=3):
super().__init__(scope, id)
# Compose deployment + service + ingress
App: Root container for all charts Chart: Represents a single Kubernetes manifest file
app = App()
# Each chart → separate YAML file
dev_chart = MyChart(app, "dev", namespace="development")
prod_chart = MyChart(app, "prod", namespace="production")
app.synth() # Generates dist/dev.k8s.yaml and dist/prod.k8s.yaml
Import CRDs, Helm charts, and external definitions:
# Import Kubernetes API
cdk8s import k8s
# Import CRD from URL
cdk8s import https://raw.githubusercontent.com/aws-controllers-k8s/s3-controller/main/helm/crds/s3.services.k8s.aws_buckets.yaml
# Import Helm chart
cdk8s import helm:https://charts.bitnami.com/bitnami/[email protected]
# Import from GitHub
cdk8s import github:crossplane/[email protected]
from cdk8s import App, Chart
from cdk8s_plus_27 import Deployment, ConfigMap, EnvValue, ContainerProps
class WebApp(Chart):
def __init__(self, scope, id):
super().__init__(scope, id)
# Configuration
config = ConfigMap(
self, "config",
data={
"DATABASE_HOST": "postgres.default.svc",
"LOG_LEVEL": "info"
}
)
# Deployment
deployment = Deployment(
self, "web",
replicas=3,
containers=[
ContainerProps(
image="myapp:v1.0",
port=8080,
env_variables={
"DATABASE_HOST": EnvValue.from_config_map(
config, "DATABASE_HOST"
)
}
)
]
)
# Expose as service
deployment.expose_via_service(port=80, target_port=8080)
app = App()
WebApp(app, "web-app")
app.synth()
from cdk8s import App, Chart
from cdk8s_plus_27 import Deployment, ContainerProps
class MyApp(Chart):
def __init__(self, scope, id, env, replicas, image_tag):
super().__init__(scope, id, namespace=env)
Deployment(
self, "app",
replicas=replicas,
containers=[
ContainerProps(
image=f"myapp:{image_tag}",
port=8080
)
]
)
app = App()
# Development
MyApp(app, "dev", env="development", replicas=1, image_tag="dev")
# Staging
MyApp(app, "staging", env="staging", replicas=2, image_tag="v1.2.3-rc")
# Production
MyApp(app, "prod", env="production", replicas=5, image_tag="v1.2.3")
app.synth()
from constructs import Construct
from cdk8s_plus_27 import (
Deployment, Service, ConfigMap, Secret,
ContainerProps, EnvValue, ServiceType
)
class MicroserviceApp(Construct):
"""Reusable microservice with deployment, service, and config."""
def __init__(
self,
scope: Construct,
id: str,
image: str,
replicas: int = 3,
port: int = 8080,
config: dict = None,
secrets: dict = None
):
super().__init__(scope, id)
# ConfigMap
if config:
cfg = ConfigMap(self, "config", data=config)
# Secret
if secrets:
sec = Secret(self, "secret", string_data=secrets)
# Build env vars
env_vars = {}
if config:
for key in config.keys():
env_vars[key] = EnvValue.from_config_map(cfg, key)
if secrets:
for key in secrets.keys():
env_vars[key] = EnvValue.from_secret_value(key, sec)
# Deployment
self.deployment = Deployment(
self, "deployment",
replicas=replicas,
containers=[
ContainerProps(
image=image,
port=port,
env_variables=env_vars
)
]
)
# Service
self.service = self.deployment.expose_via_service(
service_type=ServiceType.CLUSTER_IP,
port=port
)
# Usage
from cdk8s import App, Chart
class MyChart(Chart):
def __init__(self, scope, id):
super().__init__(scope, id)
# Deploy 3 microservices with one construct
MicroserviceApp(
self, "frontend",
image="myapp/frontend:v1",
replicas=5,
config={"API_URL": "http://api:8080"}
)
MicroserviceApp(
self, "api",
image="myapp/api:v1",
replicas=3,
secrets={"DATABASE_PASSWORD": "supersecret"}
)
MicroserviceApp(
self, "worker",
image="myapp/worker:v1",
replicas=2
)
app = App()
MyChart(app, "microservices")
app.synth()
# tests/test_chart.py
import pytest
from cdk8s import Testing
from app import MyChart
def test_deployment_has_correct_replicas():
chart = Testing.chart()
MyChart(chart)
manifests = Testing.synth(chart)
deployment = [m for m in manifests if m["kind"] == "Deployment"][0]
assert deployment["spec"]["replicas"] == 3
def test_service_exposes_correct_port():
chart = Testing.chart()
MyChart(chart)
manifests = Testing.synth(chart)
service = [m for m in manifests if m["kind"] == "Service"][0]
assert service["spec"]["ports"][0]["port"] == 80
def test_no_latest_tags():
"""Enforce no :latest image tags"""
chart = Testing.chart()
MyChart(chart)
manifests = Testing.synth(chart)
for manifest in manifests:
if manifest["kind"] == "Deployment":
containers = manifest["spec"]["template"]["spec"]["containers"]
for container in containers:
assert not container["image"].endswith(":latest")
def test_all_containers_have_resource_limits():
"""Enforce resource limits"""
chart = Testing.chart()
MyChart(chart)
manifests = Testing.synth(chart)
for manifest in manifests:
if manifest["kind"] == "Deployment":
containers = manifest["spec"]["template"]["spec"]["containers"]
for container in containers:
assert "resources" in container
assert "limits" in container["resources"]
# .github/workflows/deploy.yml
name: Deploy to Kubernetes
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install dependencies
run: |
npm install -g cdk8s-cli
pip install -r requirements.txt
- name: Synthesize manifests
run: cdk8s synth
- name: Deploy to EKS
run: kubectl apply -f dist/
Deploy cdk8s apps directly to EKS clusters:
from aws_cdk import Stack, aws_eks as eks
from constructs import Construct
import cdk8s
from my_k8s_app import MyK8sChart
class EksStack(Stack):
def __init__(self, scope: Construct, id: str):
super().__init__(scope, id)
# Create EKS cluster with AWS CDK
cluster = eks.Cluster(
self, "Cluster",
version=eks.KubernetesVersion.V1_28
)
# Define K8s app with cdk8s
cdk8s_app = cdk8s.App()
k8s_chart = MyK8sChart(cdk8s_app, "app")
# Bridge: Deploy cdk8s chart to EKS
cluster.add_cdk8s_chart("my-app", k8s_chart)
# requirements.txt
cdk8s==2.70.26
cdk8s-plus-27==2.7.84 # Match your K8s version
constructs>=10.0.0
# ❌ Dangerous: Renaming ID recreates resource
Deployment(self, "app-v2", ...)
# ✅ Safe: Use explicit name metadata
from imports import k8s
Deployment(
self, "app-v2",
metadata=k8s.ObjectMeta(name="app") # Stable name
)
class ProdChart(Chart):
def __init__(self, scope, id):
super().__init__(
scope, id,
namespace="production",
labels={"env": "prod"}
)
# Dry-run validation
kubectl apply --dry-run=client -f dist/
# Run unit tests
pytest tests/
# GitOps review
git diff dist/
# Initialize project
cdk8s init python-app
# Import K8s API
cdk8s import k8s
# Import CRD
cdk8s import https://example.com/crd.yaml
# Import Helm chart
cdk8s import helm:https://charts.example.com/[email protected]
# Synthesize manifests
cdk8s synth
# Watch mode (auto-synth)
cdk8s synth --watch
# Deploy
kubectl apply -f dist/
# Validate
kubectl apply --dry-run=client -f dist/
| cdk8s-plus | Kubernetes | Python | Node.js |
|---|---|---|---|
| cdk8s-plus-27 | 1.27+ | 3.7+ | 18+ |
| cdk8s-plus-28 | 1.28+ | 3.7+ | 18+ |
| cdk8s-plus-29 | 1.29+ | 3.7+ | 18+ |
Use cdk8s when:
Use Helm when:
Use Kustomize when:
Use Raw YAML when:
Workloads: Deployment, StatefulSet, DaemonSet, Job, CronJob, Pod
Services: Service, Ingress
Config: ConfigMap, Secret, EnvValue
Storage: Volume, PersistentVolume, PersistentVolumeClaim
RBAC: ServiceAccount, Role, ClusterRole, RoleBinding, ClusterRoleBinding
Scaling: HorizontalPodAutoscaler
Networking: NetworkPolicy
For in-depth information, see:
Official Documentation:
AWS Resources:
Community:
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience