Direct Deployment
Direct deployment allows you to deploy TypeKro resource graphs directly to a Kubernetes cluster without requiring external orchestrators like KRO. This is perfect for development, testing, and scenarios where you need immediate feedback and simple deployment workflows.
Overview
Direct deployment provides:
- Immediate deployment to any Kubernetes cluster
- Real-time status feedback through live cluster querying
- Simple debugging with direct kubectl integration
- Rapid iteration for development workflows
- No additional dependencies beyond kubectl access
typescript
import { toResourceGraph, simpleDeployment, simpleService } from 'typekro';
const webApp = toResourceGraph(/* ... */);
// Deploy directly to cluster
const factory = await webApp.factory('direct', {
namespace: 'development'
});
await factory.deploy({
name: 'my-app',
image: 'nginx:latest',
replicas: 2
});
console.log('Deployed! 🚀');
Prerequisites
Required Tools
- kubectl configured with cluster access
- Node.js 18+ or Bun runtime
- TypeKro installed in your project
Cluster Requirements
- Valid kubeconfig for target cluster
- RBAC permissions for resource creation
- Network access to Kubernetes API server
Quick Setup Verification
bash
# Test cluster access
kubectl cluster-info
kubectl get nodes
# Verify permissions
kubectl auth can-i create deployments
kubectl auth can-i create services
kubectl auth can-i get pods
Bootstrap Runtime (Optional)
If you plan to use HelmRelease resources or want to set up a complete TypeKro runtime environment, you can use the bootstrap composition to install Flux CD and KRO:
typescript
// bootstrap-cluster.ts
import { typeKroRuntimeBootstrap } from 'typekro';
async function setupCluster() {
const bootstrap = typeKroRuntimeBootstrap({
namespace: 'flux-system',
fluxVersion: 'v2.4.0',
kroVersion: '0.3.0'
});
const factory = await bootstrap.factory('direct', {
namespace: 'flux-system',
waitForReady: true,
timeout: 300000
});
console.log('Setting up TypeKro runtime...');
await factory.deploy({ namespace: 'flux-system' });
console.log('Runtime ready!');
}
setupCluster().catch(console.error);
This setup enables:
- HelmRelease support for Helm chart deployments
- Advanced KRO features like runtime dependencies
- GitOps workflows with Flux CD integration
- Production-ready monitoring and management
Basic Direct Deployment
For complete examples, see:
- Basic WebApp Pattern - Simple app with deployment + service
- Database + Application - Full stack with database
Quick Direct Deployment
typescript
// 1. Create factory
const factory = await webapp.factory('direct', { namespace: 'dev' });
// 2. Deploy application
await factory.deploy({
name: 'my-app',
image: 'nginx:latest',
replicas: 2,
environment: 'development'
});
// 3. Check status
const status = await factory.getStatus();
console.log('App ready:', status.ready);
Deployment with Configuration
typescript
const factory = await simpleApp.factory('direct', {
namespace: 'development',
timeout: 300000, // 5 minute timeout
waitForReady: true, // Wait for resources to be ready
kubeconfig: '~/.kube/config', // Custom kubeconfig path
context: 'dev-cluster' // Specific kubectl context
});
Factory Configuration Options
Basic Options
typescript
interface DirectFactoryOptions {
namespace?: string; // Target namespace (default: 'default')
timeout?: number; // Deployment timeout in milliseconds
waitForReady?: boolean; // Wait for resources to be ready
kubeconfig?: string; // Path to kubeconfig file
context?: string; // Kubernetes context to use
}
Advanced Options
typescript
const factory = await graph.factory('direct', {
// Basic configuration
namespace: 'production',
timeout: 600000, // 10 minutes
// Resource management
waitForReady: true,
readinessTimeout: 300000, // 5 minutes for readiness
// Authentication
kubeconfig: '/path/to/kubeconfig',
context: 'production-cluster',
// Deployment behavior
replaceExisting: true, // Replace existing resources
dryRun: false, // Actually deploy (set true for validation)
// Monitoring
statusUpdateInterval: 10000, // Check status every 10 seconds
// Error handling
retryAttempts: 3,
retryBackoff: 'exponential'
});
Deployment Lifecycle
1. Resource Creation
typescript
const factory = await graph.factory('direct');
// Deploy resources
const deployment = await factory.deploy({
name: 'my-app',
image: 'app:v1.0.0',
replicas: 2
});
console.log('Resources created:', deployment.resources);
2. Status Monitoring
typescript
// Check deployment status
const status = await factory.getStatus();
console.log('Current status:', status);
// Wait for specific conditions
await factory.waitForCondition(
(status) => status.readyReplicas >= 2,
{ timeout: 300000 }
);
// Listen for status updates
factory.onStatusUpdate((newStatus) => {
console.log('Status changed:', newStatus);
});
3. Resource Management
typescript
// Update deployment
await factory.update({
name: 'my-app',
image: 'app:v1.1.0', // New image version
replicas: 5 // Scale up
});
// Restart deployment
await factory.restart();
// Scale specific resources
await factory.scale('deployment', 3);
// Delete deployment
await factory.delete();
Environment-Specific Deployments
Development Environment
typescript
const devFactory = await graph.factory('direct', {
namespace: 'development',
waitForReady: false, // Deploy quickly without waiting
timeout: 60000, // Short timeout for fast feedback
replaceExisting: true // Replace existing dev resources
});
await devFactory.deploy({
name: 'dev-app',
image: 'app:latest',
replicas: 1,
environment: 'development'
});
Staging Environment
typescript
const stagingFactory = await graph.factory('direct', {
namespace: 'staging',
waitForReady: true, // Ensure readiness
timeout: 300000, // Moderate timeout
context: 'staging-cluster'
});
await stagingFactory.deploy({
name: 'staging-app',
image: 'app:v1.2.0-rc1',
replicas: 2,
environment: 'staging'
});
Production Environment
typescript
const prodFactory = await graph.factory('direct', {
namespace: 'production',
waitForReady: true, // Must be ready
timeout: 600000, // Longer timeout
readinessTimeout: 300000, // Wait for full readiness
context: 'production-cluster',
retryAttempts: 5 // More retries
});
await prodFactory.deploy({
name: 'prod-app',
image: 'app:v1.2.0',
replicas: 5,
environment: 'production'
});
Multi-Resource Deployments
Database and Application Stack
typescript
const fullStack = toResourceGraph(
{ name: 'fullstack', schema: { spec: FullStackSpec } },
(schema) => ({
// Database
database: simpleDeployment({
name: Cel.expr(schema.spec.name, '-db'),
image: 'postgres:15',
env: {
POSTGRES_DB: schema.spec.database.name,
POSTGRES_USER: schema.spec.database.user,
POSTGRES_PASSWORD: schema.spec.database.password
},
ports: [{ containerPort: 5432 }]
}),
databaseService: simpleService({
name: Cel.expr(schema.spec.name, '-db-service'),
selector: { app: Cel.expr(schema.spec.name, '-db') },
ports: [{ port: 5432, targetPort: 5432 }]
}),
// Wait for database before starting app
app: simpleDeployment({
name: schema.spec.name,
image: schema.spec.image,
env: {
DATABASE_URL: Cel.template('postgresql://%s:%s@%s:5432/%s', schema.spec.database.user, schema.spec.database.password, databaseService.metadata.name, schema.spec.database.name)
},
ports: [{ containerPort: 3000 }]
}),
appService: simpleService({
name: Cel.expr(schema.spec.name, '-service'),
selector: { app: schema.spec.name },
ports: [{ port: 80, targetPort: 3000 }]
})
}),
(schema, resources) => ({
databaseReady: Cel.expr(resources.database.status.readyReplicas, '> 0'),
appReady: Cel.expr(resources.app.status.readyReplicas, '> 0'),
url: Cel.template('http://%s', resources.appService.spec.clusterIP),
fullyReady: Cel.expr(
resources.database.status.readyReplicas, '> 0 && ',
resources.app.status.readyReplicas, '> 0'
)
})
);
// Deploy with dependency ordering
const factory = await fullStack.factory('direct', {
namespace: 'default',
waitForReady: true
});
await factory.deploy({
name: 'my-fullstack',
image: 'myapp:latest',
database: {
name: 'myapp',
user: 'appuser',
password: 'secretpassword'
}
});
Microservices Deployment
typescript
const microservices = toResourceGraph(
{ name: 'microservices', schema: { spec: MicroservicesSpec } },
(schema) => {
const services = {};
// Create deployments for each service
schema.spec.services.forEach(service => {
services[service.name] = simpleDeployment({
name: service.name,
image: service.image,
replicas: service.replicas,
ports: [{ containerPort: service.port }],
env: service.env
});
services[Cel.expr(service.name, 'Service')] = simpleService({
name: Cel.expr(service.name, '-service'),
selector: { app: service.name },
ports: [{ port: service.port, targetPort: service.port }]
});
});
return services;
},
(schema, resources) => {
const serviceStatus = {};
schema.spec.services.forEach(service => {
serviceStatus[service.name] = {
ready: Cel.expr(resources[service.name].status.readyReplicas, '> 0'),
endpoint: Cel.template('http://%s:%d', resources[Cel.expr(service.name, 'Service')].spec.clusterIP, service.port)
};
});
return {
services: serviceStatus,
allReady: Cel.expr(
schema.spec.services.map(s =>
Cel.expr(resources[s.name].status.readyReplicas, ' > 0')
).join(' && ')
)
};
}
);
Deployment Patterns
Rolling Deployment
typescript
async function rollingDeployment() {
const factory = await graph.factory('direct');
// Deploy new version with zero downtime
await factory.update({
name: 'my-app',
image: 'app:v2.0.0',
replicas: 3,
strategy: 'RollingUpdate',
maxUnavailable: 1,
maxSurge: 1
});
// Wait for rollout to complete
await factory.waitForRollout();
console.log('Rolling deployment completed');
}
Blue-Green Deployment
typescript
async function blueGreenDeployment() {
const factory = await graph.factory('direct');
// Deploy green version alongside blue
const greenDeployment = await factory.deploy({
name: 'my-app-green',
image: 'app:v2.0.0',
replicas: 3
});
// Wait for green to be ready
await factory.waitForCondition(
(status) => status.readyReplicas >= 3
);
// Switch traffic to green
await factory.updateService('my-app-service', {
selector: { app: 'my-app-green' }
});
// Clean up blue version
await factory.deleteDeployment('my-app-blue');
}
Canary Deployment
typescript
async function canaryDeployment() {
const factory = await graph.factory('direct');
// Deploy canary with 10% traffic
await factory.deploy({
name: 'my-app-canary',
image: 'app:v2.0.0',
replicas: 1 // 10% of production traffic
});
// Monitor canary metrics
const canaryHealthy = await monitorCanaryHealth();
if (canaryHealthy) {
// Scale up canary and scale down main
await factory.scale('my-app-canary', 3);
await factory.scale('my-app', 0);
// Promote canary to main
await factory.promote('my-app-canary', 'my-app');
} else {
// Rollback canary
await factory.delete('my-app-canary');
}
}
Advanced Features
Health Checks and Readiness
typescript
const healthyApp = toResourceGraph(
{ name: 'healthy-app', schema: { spec: AppSpec } },
(schema) => ({
app: simpleDeployment({
name: schema.spec.name,
image: schema.spec.image,
ports: [{ containerPort: 3000 }],
// Health check configuration
livenessProbe: {
httpGet: { path: '/health', port: 3000 },
initialDelaySeconds: 30,
periodSeconds: 10,
timeoutSeconds: 5,
failureThreshold: 3
},
readinessProbe: {
httpGet: { path: '/ready', port: 3000 },
initialDelaySeconds: 5,
periodSeconds: 5,
timeoutSeconds: 3,
failureThreshold: 2
}
})
}),
(schema, resources) => ({
healthy: Cel.expr(
resources.app.status.readyReplicas,
'== ',
resources.app.spec.replicas
)
})
);
// Deploy with health monitoring
const factory = await healthyApp.factory('direct', {
waitForReady: true,
readinessTimeout: 120000 // 2 minutes for health checks
});
Resource Limits and Scaling
typescript
const scalableApp = toResourceGraph(
{ name: 'scalable-app', schema: { spec: ScalableAppSpec } },
(schema) => ({
app: simpleDeployment({
name: schema.spec.name,
image: schema.spec.image,
replicas: schema.spec.replicas,
// Resource constraints
resources: {
requests: {
cpu: schema.spec.resources.cpu.min,
memory: schema.spec.resources.memory.min
},
limits: {
cpu: schema.spec.resources.cpu.max,
memory: schema.spec.resources.memory.max
}
}
}),
// Horizontal Pod Autoscaler
hpa: simpleHpa({
name: Cel.expr(schema.spec.name, '-hpa'),
scaleTargetRef: {
apiVersion: 'apps/v1',
kind: 'Deployment',
name: schema.spec.name
},
minReplicas: schema.spec.scaling.min,
maxReplicas: schema.spec.scaling.max,
targetCPUUtilizationPercentage: 80
})
}),
(schema, resources) => ({
currentReplicas: resources.app.status.readyReplicas,
desiredReplicas: resources.app.spec.replicas,
autoscalingEnabled: true
})
);
Persistent Storage
typescript
const statefulApp = toResourceGraph(
{ name: 'stateful-app', schema: { spec: StatefulAppSpec } },
(schema) => ({
storage: simplePvc({
name: Cel.expr(schema.spec.name, '-storage'),
size: schema.spec.storage.size,
storageClass: schema.spec.storage.class,
accessModes: ['ReadWriteOnce']
}),
app: simpleDeployment({
name: schema.spec.name,
image: schema.spec.image,
volumeMounts: [{
name: 'data',
mountPath: '/data'
}],
volumes: [{
name: 'data',
persistentVolumeClaim: {
claimName: storage.metadata.name
}
}]
})
}),
(schema, resources) => ({
storageReady: resources.storage.status.phase === 'Bound',
storagePath: '/data',
storageSize: schema.spec.storage.size
})
);
Debugging and Troubleshooting
Enable Debug Logging
typescript
import { createLogger } from 'typekro';
const logger = createLogger({
level: 'debug',
pretty: true
});
const factory = await graph.factory('direct', {
logger,
namespace: 'development'
});
Deployment Inspection
typescript
// Get detailed deployment information
const deployment = await factory.getDeploymentDetails();
console.log('Deployment details:', deployment);
// Check resource events
const events = await factory.getResourceEvents();
console.log('Resource events:', events);
// Inspect resource YAML
const yaml = await factory.getResourceYaml('deployment', 'my-app');
console.log('Deployment YAML:', yaml);
Error Handling
typescript
try {
await factory.deploy(spec);
} catch (error) {
if (error instanceof ResourceDeploymentError) {
console.error('Deployment failed:', error.message);
console.error('Failed resources:', error.failedResources);
// Get detailed error information
for (const resource of error.failedResources) {
const events = await factory.getResourceEvents(resource.kind, resource.name);
console.error(Cel.template('Events for %s:', resource.name), events);
}
}
}
Dry Run Mode
typescript
// Test deployment without actually creating resources
const factory = await graph.factory('direct', {
dryRun: true,
namespace: 'development'
});
const dryRunResult = await factory.deploy(spec);
console.log('Dry run result:', dryRunResult);
console.log('Would create resources:', dryRunResult.resources);
Performance Optimization
Parallel Deployment
typescript
// Deploy multiple independent resources in parallel
const factory = await graph.factory('direct', {
parallelDeployment: true,
maxConcurrency: 5
});
Resource Caching
typescript
const factory = await graph.factory('direct', {
cacheResourceDefinitions: true,
cacheTTL: 300000 // 5 minutes
});
Batch Operations
typescript
// Deploy multiple applications in batch
const apps = ['app1', 'app2', 'app3'];
const deployments = await Promise.all(
apps.map(name => factory.deploy({
name,
image: Cel.template('%s:latest', name),
replicas: 2
}))
);
Integration with CI/CD
GitHub Actions Integration
typescript
// deploy.ts - deployment script for CI/CD
import { config } from './config.js';
import { webApp } from './webapp.js';
async function deploy() {
const environment = process.env.ENVIRONMENT || 'development';
const imageTag = process.env.IMAGE_TAG || 'latest';
const factory = await webApp.factory('direct', {
namespace: environment,
context: config[environment].cluster,
timeout: 600000
});
await factory.deploy({
name: Cel.template('myapp-%s', environment),
image: Cel.template('myregistry/myapp:%s', imageTag),
replicas: config[environment].replicas,
environment
});
console.log(Cel.template('✅ Deployed to %s', environment));
}
deploy().catch(process.exit(1));
GitLab CI Integration
yaml
# .gitlab-ci.yml
deploy:
stage: deploy
script:
- bun install
- bun run deploy
environment:
name: $CI_COMMIT_REF_SLUG
only:
- main
- develop
Best Practices
1. Environment Separation
typescript
// ✅ Use different namespaces for environments
const environments = {
dev: { namespace: 'development', replicas: 1 },
staging: { namespace: 'staging', replicas: 2 },
prod: { namespace: 'production', replicas: 5 }
};
const env = process.env.NODE_ENV || 'dev';
const config = environments[env];
const factory = await graph.factory('direct', config);
2. Resource Naming
typescript
// ✅ Use consistent, descriptive names
const factory = await graph.factory('direct');
await factory.deploy({
name: Cel.template('%s-%s', appName, environment),
image: Cel.template('%s/%s:%s', registry, appName, version),
replicas: config.replicas
});
3. Error Recovery
typescript
// ✅ Implement retry logic and rollback
async function deployWithRollback() {
const factory = await graph.factory('direct');
try {
await factory.deploy(newVersion);
} catch (error) {
console.error('Deployment failed, rolling back...');
await factory.rollback();
throw error;
}
}
4. Resource Cleanup
typescript
// ✅ Clean up temporary resources
process.on('SIGINT', async () => {
console.log('Cleaning up resources...');
await factory.delete();
process.exit(0);
});
Next Steps
- KRO Integration - Advanced orchestration with KRO
- GitOps Workflows - Deploy via GitOps with YAML generation
- Status Hydration - Monitor deployment status
- Troubleshooting - Debug deployment issues