...
This commit is contained in:
443
packages/system/kubernetes/README.md
Normal file
443
packages/system/kubernetes/README.md
Normal file
@@ -0,0 +1,443 @@
|
||||
# SAL Kubernetes (`sal-kubernetes`)
|
||||
|
||||
Kubernetes cluster management and operations for the System Abstraction Layer (SAL).
|
||||
|
||||
## Installation
|
||||
|
||||
Add this to your `Cargo.toml`:
|
||||
|
||||
```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**
|
||||
|
||||
```rust
|
||||
// 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:
|
||||
|
||||
```rust
|
||||
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
|
||||
|
||||
```rust
|
||||
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
|
||||
|
||||
```javascript
|
||||
// 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 library
|
||||
- `k8s-openapi`: Kubernetes API types
|
||||
- `tokio`: Async runtime
|
||||
- `regex`: Pattern matching for resource deletion
|
||||
- `rhai`: 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` or `KUBECONFIG` environment variable)
|
||||
- Service account tokens
|
||||
|
||||
### Production Safety Configuration
|
||||
|
||||
```rust
|
||||
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
|
||||
|
||||
```rust
|
||||
// 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 service
|
||||
- `deployment_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 labels
|
||||
- `service_create(name, selector, port, target_port)` - Create service with port mapping
|
||||
- `configmap_create(name, data)` - Create configmap with data
|
||||
- `secret_create(name, data, secret_type)` - Create secret with data and optional type
|
||||
|
||||
#### Resource Listing
|
||||
|
||||
- `pods_list()` - List all pods in the namespace
|
||||
- `services_list()` - List all services in the namespace
|
||||
- `deployments_list()` - List all deployments in the namespace
|
||||
- `configmaps_list()` - List all configmaps in the namespace
|
||||
- `secrets_list()` - List all secrets in the namespace
|
||||
|
||||
#### Resource Management
|
||||
|
||||
- `pod_get(name)` - Get a specific pod by name
|
||||
- `service_get(name)` - Get a specific service by name
|
||||
- `deployment_get(name)` - Get a specific deployment by name
|
||||
- `pod_delete(name)` - Delete a specific pod by name
|
||||
- `service_delete(name)` - Delete a specific service by name
|
||||
- `deployment_delete(name)` - Delete a specific deployment by name
|
||||
- `configmap_delete(name)` - Delete a specific configmap by name
|
||||
- `secret_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 exists
|
||||
- `namespaces_list()` - List all namespaces (cluster-wide)
|
||||
|
||||
#### Utility Functions
|
||||
|
||||
- `resource_counts()` - Get counts of all resource types in the namespace
|
||||
- `namespace()` - 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 KubernetesManager
|
||||
- `deploy_application(km, name, image, replicas, port, labels, env_vars)` - Deploy application with environment variables
|
||||
|
||||
**Resource Listing:**
|
||||
|
||||
- `pods_list(km)` - List pods
|
||||
- `services_list(km)` - List services
|
||||
- `deployments_list(km)` - List deployments
|
||||
- `configmaps_list(km)` - List configmaps
|
||||
- `secrets_list(km)` - List secrets
|
||||
- `namespaces_list(km)` - List all namespaces
|
||||
- `resource_counts(km)` - Get resource counts
|
||||
|
||||
**Resource Operations:**
|
||||
|
||||
- `delete(km, pattern)` - Delete resources matching pattern
|
||||
- `pod_delete(km, name)` - Delete specific pod
|
||||
- `service_delete(km, name)` - Delete specific service
|
||||
- `deployment_delete(km, name)` - Delete specific deployment
|
||||
- `configmap_delete(km, name)` - Delete specific configmap
|
||||
- `secret_delete(km, name)` - Delete specific secret
|
||||
|
||||
**Namespace Functions:**
|
||||
|
||||
- `namespace_create(km, name)` - Create namespace
|
||||
- `namespace_exists(km, name)` - Check namespace existence
|
||||
- `namespace_delete(km, name)` - Delete namespace
|
||||
- `namespace(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 variables
|
||||
- `redis` - Redis cache deployment with configuration
|
||||
- `generic` - Multiple application deployments (nginx, node.js, mongodb)
|
||||
|
||||
### Rhai Examples
|
||||
|
||||
Run with: `./target/debug/herodo examples/kubernetes/clusters/<script>.rhai`
|
||||
|
||||
- `postgres.rhai` - PostgreSQL cluster deployment script
|
||||
- `redis.rhai` - Redis cluster deployment script
|
||||
|
||||
### Real-World Examples
|
||||
|
||||
#### PostgreSQL Database
|
||||
|
||||
```rust
|
||||
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
|
||||
|
||||
```rust
|
||||
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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```rust
|
||||
// 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?;
|
||||
```
|
Reference in New Issue
Block a user