- Add Kubernetes examples demonstrating deployment of various applications (PostgreSQL, Redis, generic). This improves the documentation and provides practical usage examples. - Add `tokio` dependency for async examples. This enables the use of asynchronous operations in the examples. - Add `once_cell` dependency for improved resource management in Kubernetes module. This allows efficient management of singletons and other resources.
16 KiB
SAL Kubernetes (sal-kubernetes
)
Kubernetes cluster management and operations for the System Abstraction Layer (SAL).
Installation
Add this to your Cargo.toml
:
[dependencies]
sal-kubernetes = "0.1.0"
⚠️ IMPORTANT SECURITY NOTICE
This package includes destructive operations that can permanently delete Kubernetes resources!
- The
delete(pattern)
function uses PCRE regex patterns to bulk delete resources - Always test patterns in a safe environment first
- Use specific patterns to avoid accidental deletion of critical resources
- Consider the impact on dependent resources before deletion
- No confirmation prompts - deletions are immediate and irreversible
Overview
This package provides a high-level interface for managing Kubernetes clusters using the kube-rs
SDK. It focuses on namespace-scoped operations through the KubernetesManager
factory pattern.
Production Safety Features
- Configurable Timeouts: All operations have configurable timeouts to prevent hanging
- Exponential Backoff Retry: Automatic retry logic for transient failures
- Rate Limiting: Built-in rate limiting to prevent API overload
- Comprehensive Error Handling: Detailed error types and proper error propagation
- Structured Logging: Production-ready logging for monitoring and debugging
Features
- Application Deployment: Deploy complete applications with a single method call
- Environment Variables & Labels: Configure containers with environment variables and Kubernetes labels
- Resource Lifecycle Management: Automatic cleanup and replacement of existing resources
- Namespace-scoped Management: Each
KubernetesManager
instance operates on a single namespace - Pod Management: List, create, and manage pods
- Pattern-based Deletion: Delete resources using PCRE pattern matching
- Namespace Operations: Create and manage namespaces (idempotent operations)
- Resource Management: Support for pods, services, deployments, configmaps, secrets, and more
- Rhai Integration: Full scripting support through Rhai wrappers with environment variables
Core Concepts
Labels vs Environment Variables
Understanding the difference between labels and environment variables is crucial for effective Kubernetes deployments:
Labels (Kubernetes Metadata)
- Purpose: Organize, select, and manage Kubernetes resources
- Scope: Kubernetes cluster management and resource organization
- Visibility: Used by Kubernetes controllers, selectors, and monitoring systems
- Examples:
app=my-app
,tier=backend
,environment=production
,version=v1.2.3
- Use Cases: Resource grouping, service discovery, monitoring labels, deployment strategies
Environment Variables (Container Configuration)
- Purpose: Configure application runtime behavior and settings
- Scope: Inside container processes - available to your application code
- Visibility: Accessible via
process.env
,os.environ
, etc. in your application - Examples:
NODE_ENV=production
,DATABASE_URL=postgres://...
,API_KEY=secret
- Use Cases: Database connections, API keys, feature flags, runtime configuration
Example: Complete Application Configuration
// Labels: For Kubernetes resource management
let mut labels = HashMap::new();
labels.insert("app".to_string(), "web-api".to_string()); // Service discovery
labels.insert("tier".to_string(), "backend".to_string()); // Architecture layer
labels.insert("environment".to_string(), "production".to_string()); // Deployment stage
labels.insert("version".to_string(), "v2.1.0".to_string()); // Release version
// Environment Variables: For application configuration
let mut env_vars = HashMap::new();
env_vars.insert("NODE_ENV".to_string(), "production".to_string()); // Runtime mode
env_vars.insert("DATABASE_URL".to_string(), "postgres://db:5432/app".to_string()); // DB connection
env_vars.insert("REDIS_URL".to_string(), "redis://cache:6379".to_string()); // Cache connection
env_vars.insert("LOG_LEVEL".to_string(), "info".to_string()); // Logging config
Usage
Application Deployment (Recommended)
Deploy complete applications with labels and environment variables:
use sal_kubernetes::KubernetesManager;
use std::collections::HashMap;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let km = KubernetesManager::new("default").await?;
// Configure labels for Kubernetes resource organization
let mut labels = HashMap::new();
labels.insert("app".to_string(), "my-app".to_string());
labels.insert("tier".to_string(), "backend".to_string());
// Configure environment variables for the container
let mut env_vars = HashMap::new();
env_vars.insert("NODE_ENV".to_string(), "production".to_string());
env_vars.insert("DATABASE_URL".to_string(), "postgres://db:5432/myapp".to_string());
env_vars.insert("API_KEY".to_string(), "secret-api-key".to_string());
// Deploy application with deployment + service
km.deploy_application(
"my-app", // name
"node:18-alpine", // image
3, // replicas
3000, // port
Some(labels), // Kubernetes labels
Some(env_vars), // container environment variables
).await?;
println!("✅ Application deployed successfully!");
Ok(())
}
Basic Operations
use sal_kubernetes::KubernetesManager;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a manager for the "default" namespace
let km = KubernetesManager::new("default").await?;
// List all pods in the namespace
let pods = km.pods_list().await?;
println!("Found {} pods", pods.len());
// Create a namespace (no error if it already exists)
km.namespace_create("my-namespace").await?;
// Delete resources matching a pattern
km.delete("test-.*").await?;
Ok(())
}
Rhai Scripting
// Create Kubernetes manager for namespace
let km = kubernetes_manager_new("default");
// Deploy application with labels and environment variables
deploy_application(km, "my-app", "node:18-alpine", 3, 3000, #{
"app": "my-app",
"tier": "backend",
"environment": "production"
}, #{
"NODE_ENV": "production",
"DATABASE_URL": "postgres://db:5432/myapp",
"API_KEY": "secret-api-key"
});
print("✅ Application deployed!");
// Basic operations
let pods = pods_list(km);
print("Found " + pods.len() + " pods");
namespace_create(km, "my-namespace");
delete(km, "test-.*");
Dependencies
kube
: Kubernetes client libraryk8s-openapi
: Kubernetes API typestokio
: Async runtimeregex
: Pattern matching for resource deletionrhai
: Scripting integration (optional)
Configuration
Kubernetes Authentication
The package uses the standard Kubernetes configuration methods:
- In-cluster configuration (when running in a pod)
- Kubeconfig file (
~/.kube/config
orKUBECONFIG
environment variable) - Service account tokens
Production Safety Configuration
use sal_kubernetes::{KubernetesManager, KubernetesConfig};
use std::time::Duration;
// Create with custom configuration
let config = KubernetesConfig::new()
.with_timeout(Duration::from_secs(60))
.with_retries(5, Duration::from_secs(1), Duration::from_secs(30))
.with_rate_limit(20, 50);
let km = KubernetesManager::with_config("my-namespace", config).await?;
Pre-configured Profiles
// High-throughput environment
let config = KubernetesConfig::high_throughput();
// Low-latency environment
let config = KubernetesConfig::low_latency();
// Development/testing
let config = KubernetesConfig::development();
Error Handling
All operations return Result<T, KubernetesError>
with comprehensive error types for different failure scenarios including API errors, configuration issues, and permission problems.
API Reference
KubernetesManager
The main interface for Kubernetes operations. Each instance is scoped to a single namespace.
Constructor
KubernetesManager::new(namespace)
- Create a manager for the specified namespace
Application Deployment
deploy_application(name, image, replicas, port, labels, env_vars)
- Deploy complete application with deployment and servicedeployment_create(name, image, replicas, labels, env_vars)
- Create deployment with environment variables and labels
Resource Creation
pod_create(name, image, labels, env_vars)
- Create pod with environment variables and labelsservice_create(name, selector, port, target_port)
- Create service with port mappingconfigmap_create(name, data)
- Create configmap with datasecret_create(name, data, secret_type)
- Create secret with data and optional type
Resource Listing
pods_list()
- List all pods in the namespaceservices_list()
- List all services in the namespacedeployments_list()
- List all deployments in the namespaceconfigmaps_list()
- List all configmaps in the namespacesecrets_list()
- List all secrets in the namespace
Resource Management
pod_get(name)
- Get a specific pod by nameservice_get(name)
- Get a specific service by namedeployment_get(name)
- Get a specific deployment by namepod_delete(name)
- Delete a specific pod by nameservice_delete(name)
- Delete a specific service by namedeployment_delete(name)
- Delete a specific deployment by nameconfigmap_delete(name)
- Delete a specific configmap by namesecret_delete(name)
- Delete a specific secret by name
Pattern-based Operations
delete(pattern)
- Delete all resources matching a PCRE pattern
Namespace Operations
namespace_create(name)
- Create a namespace (idempotent)namespace_exists(name)
- Check if a namespace existsnamespaces_list()
- List all namespaces (cluster-wide)
Utility Functions
resource_counts()
- Get counts of all resource types in the namespacenamespace()
- Get the namespace this manager operates on
Rhai Functions
When using the Rhai integration, the following functions are available:
Manager Creation & Application Deployment:
kubernetes_manager_new(namespace)
- Create a KubernetesManagerdeploy_application(km, name, image, replicas, port, labels, env_vars)
- Deploy application with environment variables
Resource Listing:
pods_list(km)
- List podsservices_list(km)
- List servicesdeployments_list(km)
- List deploymentsconfigmaps_list(km)
- List configmapssecrets_list(km)
- List secretsnamespaces_list(km)
- List all namespacesresource_counts(km)
- Get resource counts
Resource Operations:
delete(km, pattern)
- Delete resources matching patternpod_delete(km, name)
- Delete specific podservice_delete(km, name)
- Delete specific servicedeployment_delete(km, name)
- Delete specific deploymentconfigmap_delete(km, name)
- Delete specific configmapsecret_delete(km, name)
- Delete specific secret
Namespace Functions:
namespace_create(km, name)
- Create namespacenamespace_exists(km, name)
- Check namespace existencenamespace_delete(km, name)
- Delete namespacenamespace(km)
- Get manager's namespace
Examples
The examples/kubernetes/clusters/
directory contains comprehensive examples:
Rust Examples
Run with: cargo run --example <name> --features kubernetes
postgres
- PostgreSQL database deployment with environment variablesredis
- Redis cache deployment with configurationgeneric
- Multiple application deployments (nginx, node.js, mongodb)
Rhai Examples
Run with: ./target/debug/herodo examples/kubernetes/clusters/<script>.rhai
postgres.rhai
- PostgreSQL cluster deployment scriptredis.rhai
- Redis cluster deployment script
Real-World Examples
PostgreSQL Database
let mut env_vars = HashMap::new();
env_vars.insert("POSTGRES_DB".to_string(), "myapp".to_string());
env_vars.insert("POSTGRES_USER".to_string(), "postgres".to_string());
env_vars.insert("POSTGRES_PASSWORD".to_string(), "secretpassword".to_string());
km.deploy_application("postgres", "postgres:15", 1, 5432, Some(labels), Some(env_vars)).await?;
Redis Cache
let mut env_vars = HashMap::new();
env_vars.insert("REDIS_PASSWORD".to_string(), "redispassword".to_string());
env_vars.insert("REDIS_MAXMEMORY".to_string(), "256mb".to_string());
km.deploy_application("redis", "redis:7-alpine", 3, 6379, None, Some(env_vars)).await?;
Testing
Test Coverage
The module includes comprehensive test coverage:
- Unit Tests: Core functionality without cluster dependency
- Integration Tests: Real Kubernetes cluster operations
- Environment Variables Tests: Complete env var functionality testing
- Edge Cases Tests: Error handling and boundary conditions
- Rhai Integration Tests: Scripting environment testing
- Production Readiness Tests: Concurrent operations and error handling
Running Tests
# Unit tests (no cluster required)
cargo test --package sal-kubernetes
# Integration tests (requires cluster)
KUBERNETES_TEST_ENABLED=1 cargo test --package sal-kubernetes
# Rhai integration tests
KUBERNETES_TEST_ENABLED=1 cargo test --package sal-kubernetes --features rhai
# Run specific test suites
cargo test --package sal-kubernetes deployment_env_vars_test
cargo test --package sal-kubernetes edge_cases_test
# Rhai environment variables test
KUBERNETES_TEST_ENABLED=1 ./target/debug/herodo kubernetes/tests/rhai/env_vars_test.rhai
Test Requirements
- Kubernetes Cluster: Integration tests require a running Kubernetes cluster
- Environment Variable: Set
KUBERNETES_TEST_ENABLED=1
to enable integration tests - Permissions: Tests require permissions to create/delete resources in the
default
namespace
Production Considerations
Security
- Always use specific PCRE patterns to avoid accidental deletion of important resources
- Test deletion patterns in a safe environment first
- Ensure proper RBAC permissions are configured
- Be cautious with cluster-wide operations like namespace listing
- Use Kubernetes secrets for sensitive environment variables instead of plain text
Performance & Scalability
- Consider adding resource limits (CPU/memory) for production deployments
- Use persistent volumes for stateful applications
- Configure readiness and liveness probes for health checks
- Implement proper monitoring and logging labels
Environment Variables Best Practices
- Use Kubernetes secrets for sensitive data (passwords, API keys)
- Validate environment variable values before deployment
- Use consistent naming conventions (e.g.,
DATABASE_URL
,API_KEY
) - Document required vs optional environment variables
Example: Production-Ready Deployment
// Production labels for monitoring and management
let mut labels = HashMap::new();
labels.insert("app".to_string(), "web-api".to_string());
labels.insert("version".to_string(), "v1.2.3".to_string());
labels.insert("environment".to_string(), "production".to_string());
labels.insert("team".to_string(), "backend".to_string());
// Non-sensitive environment variables
let mut env_vars = HashMap::new();
env_vars.insert("NODE_ENV".to_string(), "production".to_string());
env_vars.insert("LOG_LEVEL".to_string(), "info".to_string());
env_vars.insert("PORT".to_string(), "3000".to_string());
// Note: Use Kubernetes secrets for DATABASE_URL, API_KEY, etc.
km.deploy_application("web-api", "myapp:v1.2.3", 3, 3000, Some(labels), Some(env_vars)).await?;