Alright, fellow developers! You’re looking to deploy your awesome Laravel application in Kubernetes? Let’s break it down step-by-step to make it as painless as possible.
Here’s a common approach and the key things you’ll need:
Core Concepts We’ll Touch On:
- Dockerizing Your Laravel App: Packaging your application and its dependencies.
- Kubernetes Manifests: YAML files defining your application’s deployment, services, etc.
- Deployments: Managing the desired state of your application replicas.
- Services: Exposing your application within the Kubernetes cluster.
- Ingress (Optional but Recommended): Exposing your application to the outside world.
- Secrets: Managing sensitive information like database credentials.
- ConfigMaps: Managing non-sensitive configuration.
Here’s a Basic Workflow and Key Manifest Examples:
1. Dockerize Your Laravel Application:
First, you need a Dockerfile in the root of your Laravel project. Here’s a basic example:
Dockerfile
FROM php:8.3-fpm-alpine
WORKDIR /var/www/html
# Install system dependencies
RUN apk update && apk add --no-cache --virtual .build-deps \
git \
curl \
libzip-dev \
unzip
# Install PHP extensions
RUN docker-php-ext-install pdo_mysql zip
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
# Copy application files
COPY . .
# Install PHP dependencies
RUN composer install --no-dev --optimize-autoloader
# Create storage link
RUN php artisan storage:link
# Set file permissions
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
RUN chmod -R 755 /var/www/html/bootstrap/cache /var/www/html/storage
# Expose port 80 (or your preferred port)
EXPOSE 80
# Set user for artisan commands
USER www-data
# Start PHP-FPM
CMD ["php-fpm"]
You’ll also likely need a .dockerignore file to exclude unnecessary files (like vendor, node_modules, etc.) from your Docker image.
Build your Docker image:
Bash
docker build -t your-registry/your-app-name:latest .
docker push your-registry/your-app-name:latest
Replace your-registry/your-app-name with your Docker registry details (e.g., Docker Hub, AWS ECR, etc.).
2. Kubernetes Deployment Manifest (deployment.yaml):
This defines how your Laravel application will be deployed and managed in Kubernetes.
YAML
apiVersion: apps/v1
kind: Deployment
metadata:
name: laravel-app-deployment
spec:
replicas: 3 # Adjust as needed
selector:
matchLabels:
app: laravel-app
template:
metadata:
labels:
app: laravel-app
spec:
containers:
- name: laravel-app-container
image: your-registry/your-app-name:latest
ports:
- containerPort: 80
env:
- name: APP_KEY
valueFrom:
secretKeyRef:
name: laravel-secrets
key: app-key
- name: DB_HOST
valueFrom:
secretKeyRef:
name: laravel-secrets
key: db-host
- name: DB_DATABASE
valueFrom:
secretKeyRef:
name: laravel-secrets
key: db-database
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: laravel-secrets
key: db-username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: laravel-secrets
key: db-password
# Add other environment variables as needed
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 15
periodSeconds: 5
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 30
periodSeconds: 10
Key points in the deployment.yaml:
- replicas: The number of instances (Pods) of your application you want running.
- selector: How Kubernetes identifies the Pods managed by this Deployment.
- template: Defines the Pod specification, including the container.
- image: The Docker image you built and pushed.
- ports: The port your container exposes.
- env: Environment variables passed to your Laravel application. Crucially, sensitive information is loaded from a Kubernetes Secret.
- readinessProbe: Kubernetes checks if the Pod is ready to serve traffic.
- livenessProbe: Kubernetes checks if the Pod is still running correctly and restarts it if necessary.
3. Kubernetes Service Manifest (service.yaml):
This exposes your Laravel application within the Kubernetes cluster.
YAML
apiVersion: v1
kind: Service
metadata:
name: laravel-app-service
spec:
selector:
app: laravel-app
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP # Only accessible within the cluster
Key points in the service.yaml:
selector: Matches the labels of your application’s Pods.
ports: Maps the service’s port to the container’s port.
type: ClusterIP: Creates an internal IP address for the service, accessible only within the Kubernetes cluster.
4. Kubernetes Secrets Manifest (secrets.yaml):
Store sensitive information securely.
YAML
apiVersion: v1
kind: Secret
metadata:
name: laravel-secrets
type: Opaque
data:
app-key: $(echo "your-app-key-in-base64" | base64)
db-host: $(echo "your-db-host-in-base64" | base64)
db-database: $(echo "your-db-name-in-base64" | base64)
db-username: $(echo "your-db-user-in-base64" | base64)
db-password: $(echo "your-db-password-in-base64" | base64)
Important: Replace the placeholder values with your actual sensitive data encoded in Base64. You can use the echo “your-secret” | base64 command in your terminal to encode them.
5. Kubernetes ConfigMap Manifest (configmap.yaml - Optional but useful):
Store non-sensitive configuration.
YAML
apiVersion: v1
kind: ConfigMap
metadata:
name: laravel-config
data:
APP_ENV: production
CACHE_DRIVER: redis
QUEUE_CONNECTION: redis
# Add other non-sensitive configuration here
You can then mount this ConfigMap as environment variables or volumes in your Deployment.
6. (Optional but Recommended) Kubernetes Ingress Manifest (ingress.yaml):
Expose your application to the outside world. You’ll need an Ingress controller running in your cluster (e.g., Nginx Ingress Controller).
YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: laravel-app-ingress
annotations:
kubernetes.io/ingress.class: nginx # Or your Ingress controller
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: your-domain.com # Replace with your actual domain
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: laravel-app-service
port:
number: 80
Applying Your Manifests:
Use kubectl apply -f .yaml to apply each of your manifest files to your Kubernetes cluster:
Bash
kubectl apply -f secrets.yaml
kubectl apply -f configmap.yaml # If you created one
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml # If you set up Ingress
Key Considerations and Next Steps:
Database: You’ll need a separate database service accessible by your Laravel application within the Kubernetes cluster (e.g., a managed database service or a PostgreSQL/MySQL deployment in Kubernetes).
Storage: For persistent storage (e.g., for user uploads), you’ll need to configure Persistent Volumes and Persistent Volume Claims.
Caching and Queues: If you’re using Redis or other caching/queueing systems, you’ll need to deploy and configure them in your Kubernetes cluster as well.
Environment Variables: Carefully manage your environment variables using Secrets for sensitive data and ConfigMaps for non-sensitive configuration.
Health Checks (Readiness and Liveness Probes): Ensure your probes are correctly configured to allow Kubernetes to manage the health of your application instances.
Logging and Monitoring: Set up proper logging and monitoring solutions for your Laravel application running in Kubernetes.
CI/CD Pipeline: Automate the process of building, pushing, and deploying your Laravel application updates to Kubernetes.
Troubleshooting Tips:
Check Pod Status: kubectl get pods
View Pod Logs: kubectl logs -c
Describe Pods/Deployments/Services: kubectl describe
Check Service Endpoints: kubectl get endpoints
Ingress Controller Logs: Check the logs of your Ingress controller if you’re having trouble accessing your application externally.
Also, this article on deploying your Laravel application in Kubernetes ll give you a solid starting point. Don’t hesitate to ask more specific questions as you progress! Good luck!