Kubernetes for Laravel Getting Started

Khimananda Oli 7 min read CI/CD and Automation
Kubernetes for Laravel Getting Started

By Khimananda Oli | Last reviewed: August 2026

Moving a PHP application from a traditional VPS to an orchestrated container platform introduces new complexities around state, caching, and background processing. This Kubernetes for Laravel getting started guide bridges that gap by translating standard Laravel deployment patterns into cloud-native primitives without over-engineering. Before applying any manifests, ensure you have mastered local containerization with Docker for beginners, as your production cluster will only be as reliable as your base image.

Laravel on Kubernetes ArchitectureIngress ControllerPHP-FPM Pods(Web Requests)Queue Worker Pods(Background Jobs)Redis / CachePostgreSQL / MySQL
High-level Kubernetes for Laravel getting started topology separating web traffic from background processing

How do you containerize Laravel for Kubernetes?

The foundation of any successful Kubernetes for Laravel getting started workflow is a production-grade Dockerfile. Never use the official php:apache image for Kubernetes; it lacks the process isolation and performance characteristics required for orchestrated environments. Instead, build a multi-stage image using PHP-FPM that separates build dependencies from the final runtime artifact.

Multi-stage Dockerfile for PHP-FPM

This Dockerfile optimizes layer caching and produces a lean image under 150MB. It installs system dependencies, compiles required PHP extensions, and copies application code in discrete steps to maximize build cache efficiency.

# Build stage
FROM composer:2 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist

# Runtime stage
FROM php:8.3-fpm-alpine
RUN apk add --no-cache \
    nginx \
    postgresql-dev \
    libzip-dev \
    icu-dev \
    && docker-php-ext-install pdo_pgsql zip intl opcache \
    && rm -rf /var/cache/apk/*

COPY --from=vendor /app/vendor /var/www/html/vendor
COPY . /var/www/html
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache

COPY docker/nginx.conf /etc/nginx/http.d/default.conf
COPY docker/php.ini /usr/local/etc/php/conf.d/99-laravel.ini

EXPOSE 8080
CMD ["sh", "-c", "nginx && php-fpm"]

A common mistake during this Kubernetes for Laravel getting started phase is forgetting to set proper ownership on the storage and bootstrap/cache directories. Without this step, Laravel cannot write logs or cache files at runtime, resulting in immediate CrashLoopBackOff errors. Always verify permissions in your CI pipeline before pushing images to your registry.

What Kubernetes resources does Laravel need?

Laravel is not a single-process application. Treating it as one monolithic pod is the most frequent architectural error I see teams make. You need at minimum three distinct resource types: a Deployment for PHP-FPM handling HTTP requests, a separate Deployment for queue workers, and a CronJob for scheduled tasks. Each has different scaling characteristics, resource profiles, and failure modes.

Web DeploymentPHP-FPM + NginxReadiness Probe: /upHPA: CPU / MemoryQueue Deploymentphp artisan queue:workNo Readiness ProbeScale by Queue DepthCronJobphp artisan schedule:runconcurrencyPolicy: ForbidRuns Every Minute
Resource separation pattern for Kubernetes for Laravel getting started with distinct web, queue, and scheduler components

Web deployment manifest

Your web deployment handles synchronous HTTP traffic and must include readiness probes. Laravel 11+ ships with a built-in /up health endpoint that returns 200 when the application is bootstrapped and maintenance mode is disabled. Configure this as your readiness probe to prevent traffic from reaching pods that are still warming OPcache or connecting to databases.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: laravel-web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: laravel-web
  template:
    metadata:
      labels:
        app: laravel-web
    spec:
      containers:
      - name: php-fpm
        image: registry.example.com/laravel-app:v1.2.0
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            path: /up
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
        resources:
          requests:
            cpu: 250m
            memory: 256Mi
          limits:
            cpu: 500m
            memory: 512Mi
        envFrom:
        - configMapRef:
            name: laravel-config
        - secretRef:
            name: laravel-secrets

Queue worker deployment

Queue workers are fundamentally different from web pods. They do not serve HTTP traffic, so readiness probes based on HTTP endpoints are meaningless and will cause unnecessary restarts. Instead, use a liveness probe that checks if the queue:work process is running. Scale these pods based on queue depth metrics from Redis or SQS rather than CPU utilization. Refer to Laravel queues and jobs explained for tuning worker concurrency and timeout values appropriate for your workload.

How do you manage secrets and configuration in Kubernetes?

Laravel’s .env file does not exist in Kubernetes. You must decompose your environment variables into ConfigMaps for non-sensitive data and Secrets for credentials. This separation is critical for security compliance and operational clarity. Never store database passwords, API keys, or encryption tokens in ConfigMaps, even if they appear harmless.

ConfigMap and Secret strategy

  • ConfigMap: APP_NAME, APP_ENV, APP_URL, LOG_LEVEL, CACHE_DRIVER, QUEUE_CONNECTION, SESSION_DRIVER. These can be version-controlled in your GitOps repository.
  • Secret: DB_PASSWORD, REDIS_PASSWORD, MAIL_PASSWORD, AWS_SECRET_ACCESS_KEY, APP_KEY. These should be injected via external secret managers like AWS Secrets Manager or HashiCorp Vault, never committed to Git.

When configuring Kubernetes secrets management done right, remember that Laravel caches configuration aggressively. After updating a ConfigMap or Secret, you must roll out a new deployment to clear the cached config. Use kubectl rollout restart deployment/laravel-web rather than trying to exec into pods and run php artisan config:clear, which creates inconsistent state across replicas.

How do you handle storage and migrations?

Laravel expects a writable storage directory for logs, sessions, and uploaded files. In Kubernetes, ephemeral pod storage means all written data disappears on restart. You have two viable options: mount a PersistentVolumeClaim for shared storage, or externalize all stateful operations to managed services. For most production workloads, externalizing is superior.

ApproachProsConsBest For
PersistentVolume (NFS/EBS)Drop-in replacement for local storageSingle-writer bottleneck, backup complexityLegacy apps, small teams
S3/GCS for uploadsUnlimited scale, CDN integrationRequires code changes, latency on readsMedia-heavy applications
Redis for sessions/cacheFast, shared across pods, no disk I/OAdds infrastructure dependencyAll production deployments
Stdout for logsNative K8s log aggregationNo local file access for debuggingCloud-native observability stacks

Database migration strategy

Never run migrations inside your web or queue pod entrypoints. Migrations must be a discrete, idempotent job that runs exactly once per deployment before new pods serve traffic. Use a Kubernetes Job with restartPolicy: OnFailure and integrate it into your CI/CD pipeline as a pre-deployment step. This prevents race conditions where multiple pods attempt concurrent schema changes during rolling updates. For detailed guidance on safe schema evolution, review zero-downtime Laravel database migrations.

CI PipelineBuild & Push ImageMigration Jobartisan migrate --forceWeb RolloutRolling UpdateQueue RestartGraceful DrainOn FailureHalt PipelineReadiness Gate/up returns 200
Safe deployment sequence for Kubernetes for Laravel getting started ensuring migrations complete before traffic shifts

What monitoring and observability practices matter?

Running Laravel on Kubernetes without proper observability is operating blind. You need visibility into both application-level metrics and infrastructure health. Configure structured logging to stdout so your cluster’s log aggregator can parse and index entries. Implement OpenTelemetry tracing to follow requests across PHP-FPM, queue workers, and external services. Set up alerts for queue depth, job failure rates, and p99 latency rather than generic CPU thresholds. Understanding the four golden signals of monitoring will help you distinguish between noise and genuine incidents in a distributed PHP environment.

Next Steps for Your Laravel Kubernetes Journey

This Kubernetes for Laravel getting started guide establishes the foundational architecture, but production readiness requires iterative refinement. Begin by deploying to a staging cluster with identical resource constraints to production. Validate your backup and restore procedures for both databases and persistent volumes. Implement network policies to restrict pod-to-pod communication. Most importantly, treat your Kubernetes manifests as first-class code subject to review, testing, and version control. If your team needs hands-on support designing or auditing a Laravel Kubernetes deployment, reach out directly to discuss your specific architecture and compliance requirements.

Frequently Asked Questions

Yes, for simple apps. Use Laravel Forge or Ploi instead. Kubernetes adds significant operational complexity that rarely justifies the overhead for projects with fewer than five microservices or low traffic volumes in 2026.

Deploy workers as a separate Deployment from your web pods. Configure horizontal pod autoscaling based on Redis queue length metrics using KEDA. This ensures background jobs scale independently without affecting HTTP response latency during traffic spikes.

Store secrets in Kubernetes Secrets or external vaults like HashiCorp Vault. Mount them as environment variables or files. Never commit .env files to Git. Use sealed-secrets or SOPS to encrypt sensitive configuration data at rest within your repository.

No. Pods are ephemeral and stateless. Use an S3-compatible object storage service or configure a ReadWriteMany persistent volume claim. Local filesystem writes will be lost during pod restarts or scaling events, breaking user uploads and cached assets.

Sessions must be stored externally since requests route to different pods. Configure Redis or DynamoDB as the session driver in your .env file. File-based sessions fail immediately in multi-pod deployments because session data cannot share across container boundaries.

Start with 256Mi memory and 250m CPU requests. Set limits at 512Mi and 500m respectively. Monitor actual usage with Prometheus and adjust. PHP-FPM child processes consume memory individually, so calculate limits based on max_children settings to prevent OOM kills.

Execute migrations via a Kubernetes Job or init container before updating the main deployment. Never run migrate inside entrypoint scripts. This prevents race conditions where multiple pods attempt schema changes simultaneously during rolling updates, causing database locks or corruption.

Rarely. Managed Kubernetes control planes cost extra, and minimum node requirements often exceed single VPS pricing. Savings only materialize at significant scale where auto-scaling reduces idle resources compared to provisioned dedicated servers running below capacity.

Create a dedicated /up endpoint returning 200 OK. Configure liveness probes to check this path every ten seconds. Avoid hitting database-dependent routes for liveness checks, as transient DB failures would unnecessarily restart healthy application pods.

NGINX Ingress Controller is the standard choice for Laravel. It supports path-based routing, SSL termination, and custom annotations for PHP-specific configurations. Traefik is a valid alternative but requires more adaptation for traditional LEMP stack patterns common in Laravel deployments.

Use kubectl logs to check application output and kubectl describe pod for event history. Exec into running containers with kubectl exec to inspect runtime state. Check resource limits, configmap mounts, and secret availability as primary failure causes.

Use official PHP Docker images with multi-stage builds. Buildpacks lack fine-grained control over PHP extensions and system dependencies Laravel requires. Custom Dockerfiles ensure consistent opcache, gd, and bcmath extension availability across development and production environments in 2026.

Use Kubernetes CronJobs to trigger php artisan schedule:run every minute. Alternatively, deploy a dedicated scheduler pod running the command continuously. Never rely on host crontab since pods are ephemeral and rescheduled across nodes unpredictably.

Use managed databases like RDS or Cloud SQL instead of self-hosting PostgreSQL or MySQL in-cluster. Stateful database management in Kubernetes adds operational burden without benefit. External services provide automated backups, patching, and scaling independent of application deployments.

Pre-warm opcache during image build using opcache_compile_file. Minimize layer count and use Alpine-based PHP images. Startup latency directly impacts autoscaling responsiveness and rolling update duration, making fast boot times critical for production reliability.