- 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.
444 lines
16 KiB
Markdown
444 lines
16 KiB
Markdown
# 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?;
|
|
```
|