Skip to main content

Pod Execution

The Kubernetes adapter provides powerful pod execution capabilities, supporting direct pod targeting, label-based selection, multi-container scenarios, and flexible execution options. This guide covers comprehensive pod command execution patterns and best practices.

Basic Pod Execution​

Direct Pod Execution​

Execute commands in specific pods by name:

import { $ } from '@xec-sh/core';

// Execute in named pod
const result = await $({
adapterOptions: {
type: 'kubernetes',
pod: 'web-server-deployment-abc123',
namespace: 'production'
}
})`hostname && whoami`;

console.log('Pod info:', result.stdout);

// Execute with specific container
await $({
adapterOptions: {
type: 'kubernetes',
pod: 'api-server-xyz789',
container: 'app',
namespace: 'production'
}
})`cat /app/config.json`;

Template Literal Execution​

Use template literals for dynamic command construction:

const serviceName = 'user-service';
const logLevel = 'debug';

// Dynamic command construction
const result = await $({
adapterOptions: {
type: 'kubernetes',
pod: `${serviceName}-pod`,
namespace: 'production'
}
})`curl -s http://localhost:8080/${serviceName}/health?level=${logLevel}`;

// Environment variable substitution
const environment = 'production';
await $({
env: { ENVIRONMENT: environment },
adapterOptions: {
type: 'kubernetes',
pod: 'config-pod'
}
})`echo "Running in $ENVIRONMENT environment"`;

Pod Selection Strategies​

Label-Based Selection​

Select pods using Kubernetes label selectors:

// Simple label selector
await $({
adapterOptions: {
type: 'kubernetes',
pod: '-l app=web-server',
namespace: 'production'
}
})`ps aux | grep nginx`;

// Multiple label selection
await $({
adapterOptions: {
type: 'kubernetes',
pod: '-l app=api,version=v2,tier=backend',
namespace: 'production'
}
})`curl -s http://localhost:8080/metrics`;

// Advanced label expressions
await $({
adapterOptions: {
type: 'kubernetes',
pod: '-l environment in (staging,production),app!=legacy',
namespace: 'production'
}
})`cat /proc/version`;

Dynamic Pod Selection​

Select pods dynamically based on runtime conditions:

import { KubernetesAdapter } from '@xec-sh/core';

const k8s = new KubernetesAdapter();

// Get the most recent pod from a deployment
async function getLatestPod(appLabel, namespace) {
const pods = await k8s.executeKubectl([
'get', 'pods',
'-l', `app=${appLabel}`,
'-n', namespace,
'--sort-by=.metadata.creationTimestamp',
'-o', 'jsonpath={.items[-1:].metadata.name}'
]);

return pods.stdout.trim();
}

// Execute in the latest pod
const latestPod = await getLatestPod('web-server', 'production');
await $({
adapterOptions: {
type: 'kubernetes',
pod: latestPod,
namespace: 'production'
}
})`echo "Executing in latest pod: $(hostname)"`;

Conditional Pod Selection​

Implement conditional pod selection logic:

// Select pod based on conditions
async function selectHealthyPod(selector, namespace) {
const k8s = new KubernetesAdapter();

// Get all pods matching selector
const podList = await k8s.executeKubectl([
'get', 'pods',
'-l', selector,
'-n', namespace,
'-o', 'jsonpath={.items[*].metadata.name}'
]);

const pods = podList.stdout.trim().split(' ').filter(Boolean);

// Check each pod's readiness
for (const pod of pods) {
if (await k8s.isPodReady(pod, namespace)) {
return pod;
}
}

throw new Error(`No healthy pods found for selector: ${selector}`);
}

// Use conditional selection
try {
const healthyPod = await selectHealthyPod('app=database', 'production');

const result = await $({
adapterOptions: {
type: 'kubernetes',
pod: healthyPod,
namespace: 'production'
}
})`mysql -e "SELECT 1" --silent`;

console.log('Database is responsive');
} catch (error) {
console.error('No healthy database pods available:', error.message);
}

Execution Options​

TTY and Interactive Mode​

Configure TTY and interactive execution:

// Interactive TTY mode
await $({
stdin: 'SELECT * FROM users LIMIT 10;\n\\q\n',
adapterOptions: {
type: 'kubernetes',
pod: 'postgres-primary',
container: 'postgresql',
tty: true
}
})`psql -U admin -d myapp`;

// Non-interactive mode for scripting
await $({
adapterOptions: {
type: 'kubernetes',
pod: 'batch-processor',
tty: false
}
})`
for i in {1..100}; do
echo "Processing batch $i"
./process-batch.sh $i
done
`;

Working Directory Configuration​

Set working directories for command execution:

// Execute in specific directory
await $({
adapterOptions: {
type: 'kubernetes',
pod: 'build-runner',
workdir: '/workspace/project'
}
})`
pwd
ls -la
make build
`;

// Override container's default working directory
await $({
adapterOptions: {
type: 'kubernetes',
pod: 'web-app',
container: 'app',
execFlags: ['--workdir=/app/scripts']
}
})`./deploy.sh production`;

Environment Variables​

Pass environment variables to pod commands:

// Set environment variables for execution
await $({
env: {
DATABASE_URL: 'postgresql://user:pass@db:5432/app',
LOG_LEVEL: 'debug',
FEATURE_FLAGS: 'feature1,feature2'
},
adapterOptions: {
type: 'kubernetes',
pod: 'migration-runner',
namespace: 'production'
}
})`
echo "Database URL: $DATABASE_URL"
echo "Log Level: $LOG_LEVEL"
./run-migrations.sh
`;

// Use environment variables in pod selection
const environment = process.env.NODE_ENV || 'development';
await $({
adapterOptions: {
type: 'kubernetes',
pod: `-l app=api,environment=${environment}`,
namespace: environment
}
})`echo "Running in ${environment} environment"`;

Advanced Execution Patterns​

Command Chaining​

Chain multiple commands within pods:

// Sequential command execution
await $({
adapterOptions: {
type: 'kubernetes',
pod: 'worker-pod',
namespace: 'production'
}
})`
echo "Starting backup process..."
pg_dump -h database -U admin myapp > /tmp/backup.sql
gzip /tmp/backup.sql
aws s3 cp /tmp/backup.sql.gz s3://backups/$(date +%Y%m%d_%H%M%S).sql.gz
rm /tmp/backup.sql.gz
echo "Backup completed successfully"
`;

// Conditional command execution
await $({
adapterOptions: {
type: 'kubernetes',
pod: 'health-checker',
namespace: 'monitoring'
}
})`
if curl -f http://api:8080/health; then
echo "Service is healthy"
kubectl scale deployment api --replicas=3
else
echo "Service is unhealthy"
kubectl scale deployment api --replicas=5
fi
`;

Parallel Execution​

Execute commands in multiple pods simultaneously:

// Execute health checks across multiple services
const services = ['api', 'worker', 'scheduler'];

const healthChecks = services.map(service =>
$({
adapterOptions: {
type: 'kubernetes',
pod: `-l app=${service}`,
namespace: 'production'
}
})`curl -f http://localhost:8080/health`
);

try {
const results = await Promise.all(healthChecks);
results.forEach((result, index) => {
console.log(`${services[index]} health:`, result.exitCode === 0 ? 'OK' : 'FAIL');
});
} catch (error) {
console.error('Health check failed:', error.message);
}

Stream Processing​

Process streaming output from pod commands:

// Stream log processing
const logStream = $({
stdout: 'pipe',
adapterOptions: {
type: 'kubernetes',
pod: 'log-aggregator',
namespace: 'logging'
}
})`tail -f /var/log/application.log`;

// Process streaming output
logStream.stdout.on('data', (chunk) => {
const lines = chunk.toString().split('\n').filter(Boolean);
lines.forEach(line => {
if (line.includes('ERROR')) {
console.error('Error detected:', line);
} else if (line.includes('WARN')) {
console.warn('Warning detected:', line);
}
});
});

// Stop streaming after 30 seconds
setTimeout(() => {
logStream.kill();
}, 30000);

Shell and Command Modes​

Shell Command Execution​

Execute commands through shell:

// Execute through default shell
await $({
shell: true,
adapterOptions: {
type: 'kubernetes',
pod: 'script-runner',
namespace: 'automation'
}
})`
export PATH=$PATH:/usr/local/bin
source /app/config/environment.sh
./complex-script.sh arg1 arg2
`;

// Execute through specific shell
await $({
shell: '/bin/bash',
adapterOptions: {
type: 'kubernetes',
pod: 'bash-runner',
namespace: 'scripts'
}
})`
set -euo pipefail
echo "Starting complex bash script..."
for file in /data/*.json; do
echo "Processing $file"
jq '.status' "$file" >> /tmp/statuses.log
done
`;

Direct Command Execution​

Execute commands directly without shell:

// Direct binary execution (no shell)
await $({
adapterOptions: {
type: 'kubernetes',
pod: 'utility-pod',
namespace: 'tools'
}
})`cat /proc/meminfo`;

// Execute with arguments array
const k8s = new KubernetesAdapter();
await k8s.execute({
command: 'kubectl',
args: ['get', 'pods', '--all-namespaces'],
adapterOptions: {
type: 'kubernetes',
pod: 'kubectl-pod'
}
});

Error Handling and Recovery​

Execution Error Handling​

Handle pod execution errors gracefully:

import { ExecutionError } from '@xec-sh/core';

try {
await $({
throwOnNonZeroExit: true,
adapterOptions: {
type: 'kubernetes',
pod: 'database-pod',
namespace: 'production'
}
})`mysql -e "INVALID SQL COMMAND"`;
} catch (error) {
if (error instanceof ExecutionError) {
console.error('SQL execution failed:');
console.error('Exit code:', error.result?.exitCode);
console.error('Stderr:', error.result?.stderr);

// Attempt recovery
console.log('Attempting database recovery...');
await $({
adapterOptions: {
type: 'kubernetes',
pod: 'database-pod',
namespace: 'production'
}
})`mysql -e "SELECT 1"`; // Simple connectivity test
}
}

Pod Availability Recovery​

Handle pod unavailability scenarios:

async function executeWithRetry(podSelector, command, maxRetries = 3) {
const k8s = new KubernetesAdapter();

for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
// Try to find healthy pod
const pod = await k8s.getPodFromSelector(podSelector, 'production');
if (!pod) {
throw new Error('No pods found');
}

if (!(await k8s.isPodReady(pod, 'production'))) {
throw new Error('Pod not ready');
}

// Execute command
return await $({
adapterOptions: {
type: 'kubernetes',
pod,
namespace: 'production'
}
})`${command}`;

} catch (error) {
console.log(`Attempt ${attempt} failed:`, error.message);

if (attempt === maxRetries) {
throw error;
}

// Wait before retry
await new Promise(resolve => setTimeout(resolve, 2000 * attempt));
}
}
}

// Usage with retry logic
try {
const result = await executeWithRetry('app=api', 'curl http://localhost:8080/status');
console.log('API status:', result.stdout);
} catch (error) {
console.error('All retry attempts failed:', error.message);
}

Performance Optimization​

Efficient Pod Selection​

Optimize pod selection for better performance:

// Cache pod selection results
const podCache = new Map();

async function getCachedPod(selector, namespace, ttl = 60000) {
const cacheKey = `${selector}:${namespace}`;
const cached = podCache.get(cacheKey);

if (cached && Date.now() - cached.timestamp < ttl) {
return cached.pod;
}

const k8s = new KubernetesAdapter();
const pod = await k8s.getPodFromSelector(selector, namespace);

if (pod) {
podCache.set(cacheKey, {
pod,
timestamp: Date.now()
});
}

return pod;
}

// Use cached pod selection
const pod = await getCachedPod('app=web-server', 'production');
await $({
adapterOptions: {
type: 'kubernetes',
pod,
namespace: 'production'
}
})`echo "Using cached pod selection"`;

Batch Operations​

Optimize batch operations in pods:

// Batch multiple commands in single execution
await $({
adapterOptions: {
type: 'kubernetes',
pod: 'batch-processor',
namespace: 'production'
}
})`
echo "Starting batch operations..."

# Process multiple files in parallel
for file in /data/input/*.json; do
(
echo "Processing $file"
jq '.transform' "$file" > "/data/output/$(basename "$file")"
) &
done

# Wait for all background processes
wait

echo "Batch operations completed"
ls -la /data/output/
`;

// Parallel execution across multiple pods
const batchTasks = Array.from({ length: 5 }, (_, i) =>
$({
adapterOptions: {
type: 'kubernetes',
pod: `-l app=worker`,
namespace: 'production'
}
})`echo "Processing batch ${i + 1}" && sleep 2`
);

await Promise.all(batchTasks);
console.log('All batch tasks completed');

Best Practices​

Security Best Practices​

  • Use specific pod selectors to limit execution scope
  • Validate pod existence and readiness before execution
  • Avoid passing secrets in command arguments
  • Use least-privilege container configurations
  • Monitor and log all pod executions

Performance Best Practices​

  • Cache pod selection results when appropriate
  • Use label selectors efficiently
  • Batch multiple operations when possible
  • Configure appropriate timeouts
  • Monitor resource usage during execution

Reliability Best Practices​

  • Implement retry logic for transient failures
  • Check pod health before command execution
  • Handle pod restarts and migrations gracefully
  • Use health checks and readiness probes
  • Plan for network partitions and cluster issues
// Example of comprehensive pod execution
import { KubernetesAdapter, ExecutionError } from '@xec-sh/core';

class RobustPodExecutor {
constructor(namespace = 'default') {
this.k8s = new KubernetesAdapter({ namespace });
this.namespace = namespace;
}

async execute(selector, command, options = {}) {
const {
maxRetries = 3,
retryDelay = 2000,
timeout = 30000
} = options;

for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
// Validate cluster connectivity
if (!(await this.k8s.isAvailable())) {
throw new Error('Kubernetes cluster not available');
}

// Select healthy pod
const pod = await this.selectHealthyPod(selector);

// Execute with timeout
const result = await Promise.race([
$({
adapterOptions: {
type: 'kubernetes',
pod,
namespace: this.namespace
}
})`${command}`,
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Execution timeout')), timeout)
)
]);

return result;

} catch (error) {
console.log(`Execution attempt ${attempt} failed:`, error.message);

if (attempt === maxRetries) {
throw new ExecutionError(
`Pod execution failed after ${maxRetries} attempts: ${error.message}`,
'KUBERNETES_ERROR'
);
}

await new Promise(resolve => setTimeout(resolve, retryDelay * attempt));
}
}
}

async selectHealthyPod(selector) {
const pod = await this.k8s.getPodFromSelector(selector, this.namespace);
if (!pod) {
throw new Error(`No pods found for selector: ${selector}`);
}

if (!(await this.k8s.isPodReady(pod, this.namespace))) {
throw new Error(`Pod ${pod} is not ready`);
}

return pod;
}

async dispose() {
await this.k8s.dispose();
}
}

// Usage
const executor = new RobustPodExecutor('production');
try {
const result = await executor.execute(
'app=api',
'curl -f http://localhost:8080/health',
{ maxRetries: 5, timeout: 10000 }
);
console.log('Health check passed:', result.stdout);
} finally {
await executor.dispose();
}