CloudPloy

Kubernetes for PHP and WordPress - What You Need to Know

Kubernetes is the industry standard for container orchestration at scale. It handles scheduling containers across a cluster of machines, self-healing, service discovery, rolling updates, and dozens of other production concerns. For teams with the expertise to run it, Kubernetes is genuinely powerful. But for most PHP, Laravel, and WordPress applications, Kubernetes introduces more complexity than the workload justifies. This page explains the tradeoffs honestly and maps Kubernetes concepts to what CloudPloy provides.

What Kubernetes Actually Does

Kubernetes is a cluster management system. Its core job is answering the question: "I have N machines and M containers - which container runs on which machine, and what happens if a machine fails?" It also handles routing traffic to those containers, scaling them based on load, and rolling out new versions without downtime.

The main abstractions in Kubernetes:

K8s Concept What It Does CloudPloy Equivalent
Pod One or more containers sharing a network namespace App container (Docker container)
Deployment Declares desired state: run N replicas of this container App deployment with replica count
Service Stable DNS name and IP for a set of pods Internal service discovery (automatic)
Ingress HTTP routing rules - which domain/path goes to which service App > Settings > Domains + Nginx config
ConfigMap Non-secret configuration mounted into containers Environment variables in App > Settings
Secret Sensitive configuration (passwords, API keys) Environment variables (stored encrypted)
PersistentVolumeClaim Persistent storage that survives pod restarts Volumes in App > Settings > Volumes
Liveness Probe Restart container if health check fails Health check endpoint (auto-restart on failure)
Readiness Probe Don't route traffic until container is ready Health check before traffic switch on deploy
HorizontalPodAutoscaler Scale replica count based on CPU/memory Auto-scaling rules
CronJob Run a container on a schedule Server > Cron Jobs
Job Run a container once and verify it completes One-off commands via App > Terminal
Node Physical or virtual machine in the cluster Server (single dedicated server per CloudPloy account)

The Real Cost of Running Kubernetes

Kubernetes is not free to operate. Before evaluating it for your PHP application, understand what it actually costs:

Infrastructure Cost

A minimal production-grade Kubernetes cluster requires at minimum three control plane nodes (for etcd quorum) plus worker nodes. On AWS, three t3.medium control plane nodes alone cost ~$120/month before you run a single container. Managed Kubernetes (EKS, GKE, AKS) reduces operational burden but still requires worker node instances at $50-200+/month per node depending on size.

Operational Complexity

Someone on your team needs to understand:

  • Kubernetes networking (CNI plugins, pod CIDR, service CIDR)
  • RBAC (Role-Based Access Control) for multiple teams
  • Certificate management (cert-manager, Kubernetes TLS secrets)
  • Storage classes and persistent volume provisioning
  • Ingress controllers (nginx-ingress, Traefik, AWS ALB)
  • Monitoring (Prometheus, Grafana, alerting rules)
  • Cluster upgrades (Kubernetes versions, node OS patches)
  • etcd backups and restoration procedures

YAML Management

A basic Laravel application on Kubernetes requires approximately 200-400 lines of YAML: Deployment, Service, Ingress, HorizontalPodAutoscaler, PodDisruptionBudget, ConfigMap, multiple Secrets, PersistentVolumeClaim, CronJob (for scheduler), and multiple Deployment specs for workers. Every configuration change requires updating YAML, committing, and applying.

When Kubernetes Makes Sense for PHP Apps

Despite the overhead, there are legitimate reasons to run PHP applications on Kubernetes:

  • Multi-region active/active: You need your app running in 5+ geographic regions simultaneously with automatic failover between them
  • Thousands of concurrent deployments: A platform deploying many independent customer applications per minute benefits from Kubernetes scheduling
  • Mixed workload types: Your team also runs Go services, Python ML jobs, and Rust microservices - standardizing everything on Kubernetes reduces cognitive overhead
  • Regulatory isolation requirements: Each customer's data must run in a completely separate namespace with network policies enforcing zero lateral movement
  • Existing K8s investment: Your team already runs Kubernetes for other systems and has the expertise

When CloudPloy Makes More Sense

For the majority of PHP and WordPress applications - including high-traffic sites, WooCommerce stores, and SaaS Laravel applications - a well-configured dedicated server with proper container orchestration provides better performance-per-dollar than a Kubernetes cluster:

  • Single-server applications: Most PHP apps fit on one well-sized server. A 16GB RAM dedicated server handles 100-200 concurrent PHP-FPM workers, more than enough for millions of monthly visitors.
  • Simpler mental model: One server, one app. No cluster networking to debug when something breaks.
  • Faster deployments: Building and pushing a new Docker container to a running server takes 30-90 seconds. Kubernetes rolling updates for a Deployment take 2-5 minutes waiting for pod readiness checks.
  • Better cache locality: Redis, MySQL, and your PHP-FPM workers all communicate over localhost rather than crossing pod network boundaries.
  • Lower operational cost: No etcd cluster, no ingress controller, no cert-manager, no cluster upgrade windows.

CloudPloy's Container Orchestration Features

CloudPloy implements the features that matter for PHP applications without requiring Kubernetes knowledge.

Zero-Downtime Deployments

Every CloudPloy deployment uses blue-green switching: build new container, verify health check passes, switch traffic atomically, drain old container over 30 seconds. This is equivalent to a Kubernetes rolling update strategy with maxUnavailable: 0. Users never see downtime during a normal deployment.

Self-Healing Containers

CloudPloy polls your health check endpoint every 30 seconds (like a Kubernetes liveness probe). Three consecutive failures trigger an automatic container restart. The restart uses the current running image - it does not trigger a new deployment. Typical restart time is under 10 seconds.

Worker Processes

Configure multiple worker processes in App > Workers - equivalent to Kubernetes Deployments with a separate container spec. Each worker runs independently, with its own restart policy, and can be scaled to multiple replicas. Common workers for Laravel:

# Queue worker (App > Workers > Add Worker)
php artisan queue:work redis --sleep=3 --tries=3 --max-time=3600

# Horizon (replaces multiple queue:work workers)
php artisan horizon

Scheduled Tasks (CronJobs)

Configure cron jobs in Server > Cron Jobs - equivalent to Kubernetes CronJob resources. For Laravel's task scheduler, add:

* * * * * cd /var/www/html && php artisan schedule:run

Resource Limits

Set CPU and memory limits per application in App > Settings > Resources. These map to Docker's --memory and --cpus flags, equivalent to Kubernetes resources.limits in a pod spec. If a container exceeds its memory limit, it is OOM-killed and automatically restarted.

Health Check Configuration

Configure the health check endpoint in App > Settings > Health Check. CloudPloy supports both HTTP path checks (equivalent to Kubernetes httpGet probe) and TCP port checks. Implement a meaningful health endpoint in Laravel:

// routes/web.php
Route::get('/health', function () {
    $checks = [];

    // Database check
    try {
        DB::select('SELECT 1');
        $checks['database'] = 'ok';
    } catch (\Exception $e) {
        $checks['database'] = 'error: ' . $e->getMessage();
    }

    // Redis check
    try {
        Cache::store('redis')->put('health', 1, 5);
        $checks['redis'] = 'ok';
    } catch (\Exception $e) {
        $checks['redis'] = 'error: ' . $e->getMessage();
    }

    $healthy = !in_array(false, array_map(
        fn($v) => $v === 'ok', $checks
    ));

    return response()->json($checks, $healthy ? 200 : 503);
});

Environment Variables and Secrets

CloudPloy's environment variable store is equivalent to Kubernetes Secrets with envFrom: secretRef. Variables are encrypted at rest, injected at container startup, and never visible in build logs or image layers. Unlike Kubernetes, there is no YAML to write - add variables in the dashboard or via the CloudPloy CLI.

Migrating from Kubernetes to CloudPloy

If you have a PHP application running on Kubernetes and want to simplify:

  1. Extract your Dockerfile: Your existing Kubernetes Deployment spec references a container image. Find the Dockerfile that builds it and add it to your repository root (if not already there).
  2. Map environment variables: Export your Kubernetes Secrets to environment variables in CloudPloy: kubectl get secret mysecret -o jsonpath='{.data}' | base64 -d
  3. Map volumes: For each PersistentVolumeClaim, create a corresponding volume mount in CloudPloy at the same path.
  4. Map workers: For each Kubernetes Deployment or StatefulSet running a worker process (queue workers, schedulers), create a corresponding Worker in CloudPloy.
  5. Map cron jobs: For each Kubernetes CronJob, create a corresponding Cron Job in CloudPloy.
  6. Test on staging: Deploy to a CloudPloy staging environment and run smoke tests before switching production DNS.

Kubernetes Concepts You Don't Need on CloudPloy

K8s Concept Why You Don't Need It
Namespaces Each CloudPloy app is already isolated by default - separate containers, networks, env vars
RBAC CloudPloy uses team roles (owner, developer, viewer) instead of Kubernetes RBAC
NetworkPolicy Containers communicate via internal hostnames; no pod-to-pod traffic without explicit configuration
PodDisruptionBudget Blue-green deployments guarantee zero disruption without PDB configuration
Ingress Controller Nginx is pre-configured and managed; just add domains
cert-manager Let's Encrypt certificates are provisioned and renewed automatically
etcd backup No cluster state to back up - configuration lives in CloudPloy's database
kubectl CloudPloy dashboard and CLI replace all kubectl operations

When You Genuinely Need Kubernetes

Be honest with yourself about your requirements. If your application needs any of the following, evaluate Kubernetes seriously:

  • Running 50+ distinct microservices that need independent scaling and deployment
  • Burst workloads that scale from 0 to thousands of containers in seconds (Kubernetes KEDA for event-driven scaling)
  • Multi-tenant SaaS where each customer gets their own isolated namespace with resource quotas
  • Stateful distributed systems (Apache Kafka, Cassandra, distributed databases) that require Kubernetes Operators
  • Compliance requirements that mandate specific audit logs, network policies, or workload isolation that only K8s can provide

For everything else - including most SaaS products, agencies, and high-traffic WordPress/WooCommerce sites - the operational simplicity of CloudPloy's managed container hosting lets your team ship features instead of managing cluster infrastructure.


Questions about whether CloudPloy fits your application's architecture? Read the Docker container guide for details on the container runtime, or talk to the CloudPloy team about your specific requirements.