Деплой PHP на Kubernetes: базовое руководство для разработчиков

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Деплой PHP на Kubernetes: базовое руководство

Современная веб-разработка всё чаще требует масштабируемых и отказоустойчивых решений. Kubernetes (K8s) стал стандартом де-факто для оркестрации контейнеров. Если вы PHP-разработчик и хотите освоить деплой своих приложений в Kubernetes — это руководство для вас. Мы пройдём путь от создания Docker-образа до развёртывания полноценного PHP-сервиса в кластере.

Зачем деплоить PHP на Kubernetes?

Kubernetes предоставляет ряд преимуществ для PHP-приложений:

  • Автоматическое масштабирование: K8s может увеличивать количество подов при росте нагрузки и уменьшать при её спаде.
  • Самоисцеление: Если контейнер упадёт, Kubernetes автоматически перезапустит его.
  • Управление конфигурацией: Переменные окружения и конфигурационные файлы легко централизовать через ConfigMap и Secrets.
  • Простота обновлений: Rolling updates позволяют обновлять приложение без даунтайма.

Для PHP это особенно актуально, так как многие legacy-проекты сложно масштабировать традиционными методами.

Шаг 1: Контейнеризация PHP-приложения

Прежде чем деплоить приложение в Kubernetes, его нужно упаковать в Docker-образ. Рассмотрим пример простого PHP-приложения с использованием Nginx и PHP-FPM.

Создаём структуру проекта

my-php-app/
├── src/
│   └── index.php
├── docker/
│   ├── nginx/
│   │   └── default.conf
│   └── php/
│       └── Dockerfile
└── docker-compose.yml

Пример src/index.php

<?php
echo "Hello from PHP on Kubernetes!";
phpinfo();
?>

Dockerfile для PHP-FPM

FROM php:8.2-fpm-alpine

RUN docker-php-ext-install pdo pdo_mysql

COPY src/ /var/www/html/

EXPOSE 9000
CMD ["php-fpm"]

Конфигурация Nginx (docker/nginx/default.conf)

server {
    listen 80;
    server_name localhost;
    root /var/www/html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

Сборка образа

docker build -t my-php-app:latest -f docker/php/Dockerfile .

Шаг 2: Написание манифестов Kubernetes

Теперь, когда образ готов, создадим манифесты для развёртывания в кластере.

Deployment для PHP-FPM

apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-app
  labels:
    app: php-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: php-app
  template:
    metadata:
      labels:
        app: php-app
    spec:
      containers:
      - name: php-fpm
        image: my-php-app:latest
        ports:
        - containerPort: 9000
        env:
        - name: DB_HOST
          value: "mysql-service"
        - name: DB_NAME
          value: "mydb"
        resources:
          requests:
            memory: "128Mi"
            cpu: "250m"
          limits:
            memory: "256Mi"
            cpu: "500m"

Deployment для Nginx

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80
        volumeMounts:
        - name: nginx-config
          mountPath: /etc/nginx/conf.d
      volumes:
      - name: nginx-config
        configMap:
          name: nginx-config

ConfigMap для конфигурации Nginx

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  default.conf: |
    server {
        listen 80;
        server_name _;
        root /var/www/html;

        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }

        location ~ \.php$ {
            fastcgi_pass php-service:9000;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
    }

Service для доступа к приложению

apiVersion: v1
kind: Service
metadata:
  name: php-service
spec:
  selector:
    app: php-app
  ports:
    - protocol: TCP
      port: 9000
      targetPort: 9000
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: LoadBalancer
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

Шаг 3: Развёртывание в кластере

Теперь применим все манифесты:

kubectl apply -f deployment-php.yaml
kubectl apply -f deployment-nginx.yaml
kubectl apply -f configmap-nginx.yaml
kubectl apply -f services.yaml

Проверим статус подов:

kubectl get pods

Вы должны увидеть что-то вроде:

NAME                        READY   STATUS    RESTARTS   AGE
php-app-7d4b9f6b8c-abc12   1/1     Running   0          2m
php-app-7d4b9f6b8c-def34   1/1     Running   0          2m
php-app-7d4b9f6b8c-ghi56   1/1     Running   0          2m
nginx-5c8d7f9b78-jkl78     1/1     Running   0          2m
nginx-5c8d7f9b78-mno90     1/1     Running   0          2m

Доступ к приложению

Если вы используете Minikube, выполните:

minikube service nginx-service

В облачном кластере (GKE, EKS, AKS)

Блоги

Рекомендаций по книгам