PHP / Magento Dev Blog

  • Publikacje
  • O autorze
  • Kontakt

Kubernetes dla PHP developera – kubectl debugging, Deployment YAML, HPA, troubleshooting

by Henryk Tews / piątek, 21 marca 2025 / Opublikowano w Środowiska

Kubernetes pojawia się w coraz większej liczbie projektów e-commerce na poziomie infrastruktury. Jako PHP developer nie musisz pisać Helm chartów ani konfigurować RBAC – od tego są DevOps. Ale gdy deploy się wysypuje, pody crashują albo request timeout nie działa tak jak powinien – rozumienie co się dzieje wewnątrz klastra Kubernetes jest niezbędne do diagnozowania problemów. Pokazuję minimalny zestaw wiedzy który naprawdę pomaga.

Podstawowe pojęcia – bez których nie da się debugować

Pojęcie Analogia Docker Compose Co robi
Pod docker-compose service instance Jeden lub więcej kontenerów razem na tym samym hoście
Deployment docker-compose service config Deklaracja ile podów ma działać i jak
Service nginx upstream + DNS Stały endpoint do grupy podów (load balancing)
ConfigMap .env plik Konfiguracja jako dane (nie sekrety)
Secret Docker secrets Hasła, tokeny – base64 encoded w etcd
Ingress nginx reverse proxy config Routing HTTP/HTTPS do serwisów
Namespace docker-compose project Izolacja zasobów (staging, production)
PersistentVolumeClaim docker volume Persistentne storage dla bazy, plików

kubectl – komendy które faktycznie używam

# Kontekst - który klaster i namespace
kubectl config get-contexts
kubectl config use-context production-cluster
kubectl config set-context --current --namespace=magento-prod

# Status podów - pierwsze co sprawdzam
kubectl get pods
kubectl get pods -o wide  # pokaż też IP i node

# Szczegóły poda - gdy status nie jest Running
kubectl describe pod php-deployment-7d9b8c-xk2p4

# Logi - jak docker logs
kubectl logs php-deployment-7d9b8c-xk2p4
kubectl logs -f php-deployment-7d9b8c-xk2p4  # follow
kubectl logs php-deployment-7d9b8c-xk2p4 --previous  # poprzedni pod (po crashu)
kubectl logs -l app=php-fpm --tail=100  # wszystkie pody z labelkiem

# Wejście do kontenera - jak docker exec
kubectl exec -it php-deployment-7d9b8c-xk2p4 -- bash
kubectl exec -it php-deployment-7d9b8c-xk2p4 -- php bin/magento cache:flush

# Restart deploymentu (bez zmiany konfiguracji)
kubectl rollout restart deployment/php-deployment

# Status rollout - czy nowe pody się uruchomiły
kubectl rollout status deployment/php-deployment

# Cofnij deploy
kubectl rollout undo deployment/php-deployment

# Historia deploymentów
kubectl rollout history deployment/php-deployment

Manifest Deployment dla PHP-FPM

# php-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-deployment
  namespace: magento-prod
  labels:
    app: php-fpm
spec:
  replicas: 3          # 3 instancje PHP-FPM
  selector:
    matchLabels:
      app: php-fpm
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1        # max 1 dodatkowy pod podczas update
      maxUnavailable: 0  # zero downtime - zawsze min 3 pody
  template:
    metadata:
      labels:
        app: php-fpm
    spec:
      containers:
      - name: php-fpm
        image: registry.example.com/magento:2.4.8-8.4
        ports:
        - containerPort: 9000

        # Zasoby - krytyczne żeby Kubernetes mógł planować
        resources:
          requests:
            memory: "512Mi"  # minimalne potrzebne
            cpu: "250m"      # 0.25 CPU
          limits:
            memory: "2Gi"    # maksymalne
            cpu: "1000m"     # 1 CPU

        # Zmienne środowiskowe z ConfigMap i Secrets
        env:
        - name: MAGE_MODE
          value: "production"
        - name: DB_HOST
          valueFrom:
            configMapKeyRef:
              name: magento-config
              key: db_host
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: magento-secrets
              key: db_password

        # Liveness probe - czy PHP-FPM żyje?
        livenessProbe:
          exec:
            command: ["php-fpm", "-t"]
          initialDelaySeconds: 30
          periodSeconds: 30
          failureThreshold: 3

        # Readiness probe - czy PHP-FPM jest gotowy na traffic?
        readinessProbe:
          tcpSocket:
            port: 9000
          initialDelaySeconds: 10
          periodSeconds: 5
          failureThreshold: 3

        volumeMounts:
        - name: magento-code
          mountPath: /var/www/magento
          readOnly: true

      volumes:
      - name: magento-code
        persistentVolumeClaim:
          claimName: magento-code-pvc

Debugowanie problemów – typowe scenariusze

# Scenariusz 1: Pod w stanie CrashLoopBackOff
kubectl get pods
# NAME                           READY   STATUS             RESTARTS
# php-deployment-7d9b8c-xk2p4   0/1     CrashLoopBackOff   5

# Sprawdź logi (poprzedniego crashu)
kubectl logs php-deployment-7d9b8c-xk2p4 --previous

# Sprawdź zdarzenia
kubectl describe pod php-deployment-7d9b8c-xk2p4
# Sekcja Events pokaże co się stało

# Scenariusz 2: Pod w stanie Pending
kubectl describe pod php-deployment-7d9b8c-abc123
# Często przyczyna: niewystarczające zasoby na nodach
# Events: "0/3 nodes are available: 3 Insufficient memory"

# Sprawdź zasoby nodów
kubectl describe nodes | grep -A5 "Allocated resources"

# Scenariusz 3: Pody się uruchamiają ale ruch nie dochodzi
# Sprawdź endpoints serwisu
kubectl get endpoints magento-php-service

# Sprawdź czy labele poda zgadzają się z selectorem serwisu
kubectl get pod php-deployment-7d9b8c-xk2p4 --show-labels
kubectl get service magento-php-service -o yaml | grep selector

# Scenariusz 4: Magento timeout przy komendy
# Port-forward - bezpośredni dostęp do poda bez serwisu
kubectl port-forward pod/php-deployment-7d9b8c-xk2p4 9000:9000

# Uruchom komendę z większym timeoutem
kubectl exec -it php-deployment-7d9b8c-xk2p4 -- \
    timeout 300 php bin/magento indexer:reindex

ConfigMap i Secrets – konfiguracja Magento

# Utwórz Secret z pliku env.php
kubectl create secret generic magento-env \
    --from-file=env.php=./app/etc/env.php \
    --namespace=magento-prod

# Lub z wartości
kubectl create secret generic magento-secrets \
    --from-literal=db_password='tajne_haslo_bazy' \
    --from-literal=redis_password='tajne_haslo_redis' \
    --namespace=magento-prod

# Sprawdź sekrety (bez dekodowania wartości)
kubectl get secrets
kubectl describe secret magento-secrets

# Dekoduj jeśli potrzebujesz sprawdzić
kubectl get secret magento-secrets -o jsonpath='{.data.db_password}' | base64 -d

# ConfigMap dla konfiguracji niepoufnej
kubectl create configmap magento-config \
    --from-literal=db_host=mariadb-service \
    --from-literal=es_host=opensearch-service \
    --from-literal=redis_host=redis-cache-service

HorizontalPodAutoscaler – skalowanie przy ruchu

# hpa.yaml - automatyczne skalowanie na podstawie CPU
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-hpa
  namespace: magento-prod
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-deployment
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70  # skaluj gdy CPU > 70%
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
# Zastosuj HPA
kubectl apply -f hpa.yaml

# Sprawdź status autoskalowania
kubectl get hpa
# NAME      REFERENCE                TARGETS         MINPODS   MAXPODS   REPLICAS
# php-hpa   Deployment/php-deployment   45%/70%   3         10        3

Podsumowanie

Kubernetes nie wymaga od PHP developera pełnej wiedzy DevOps – ale kilkanaście komend kubectl i rozumienie Pod/Deployment/Service/Ingress robi dużą różnicę przy diagnozowaniu problemów w środowiskach produkcyjnych. CrashLoopBackOff ma powód w logach, Pending pod ma powód w zasobach nodów, niedziałający ruch ma powód w labelkach i selectorach. Te wzorce debugowania są powtarzalne i warto je znać zanim zadzwonisz do DevOps o pomoc.

About Henryk Tews

Co możesz przeczytać następne

Blackfire – instalacja w DDEV, profilowanie HTTP i CLI, asercje w CI/CD
Varnish – VCL, cache tagging, ESI, invalidacja, DDEV setup
DDEV zaawansowany – mutagen, własne serwisy, hooks, współdzielona konfiguracja w teamie
  • Publikacje
  • O autorze
  • Kontakt

© 2026 Created by

GÓRA
Zarządzaj zgodą
Aby zapewnić jak najlepsze wrażenia, korzystamy z technologii, takich jak pliki cookie, do przechowywania i/lub uzyskiwania dostępu do informacji o urządzeniu. Zgoda na te technologie pozwoli nam przetwarzać dane, takie jak zachowanie podczas przeglądania lub unikalne identyfikatory na tej stronie. Brak wyrażenia zgody lub wycofanie zgody może niekorzystnie wpłynąć na niektóre cechy i funkcje.
Funkcjonalne Zawsze aktywne
Przechowywanie lub dostęp do danych technicznych jest ściśle konieczny do uzasadnionego celu umożliwienia korzystania z konkretnej usługi wyraźnie żądanej przez subskrybenta lub użytkownika, lub wyłącznie w celu przeprowadzenia transmisji komunikatu przez sieć łączności elektronicznej.
Preferencje
Przechowywanie lub dostęp techniczny jest niezbędny do uzasadnionego celu przechowywania preferencji, o które nie prosi subskrybent lub użytkownik.
Statystyka
Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do celów statystycznych. Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do anonimowych celów statystycznych. Bez wezwania do sądu, dobrowolnego podporządkowania się dostawcy usług internetowych lub dodatkowych zapisów od strony trzeciej, informacje przechowywane lub pobierane wyłącznie w tym celu zwykle nie mogą być wykorzystywane do identyfikacji użytkownika.
Marketing
Przechowywanie lub dostęp techniczny jest wymagany do tworzenia profili użytkowników w celu wysyłania reklam lub śledzenia użytkownika na stronie internetowej lub na kilku stronach internetowych w podobnych celach marketingowych.
  • Zarządzaj opcjami
  • Zarządzaj serwisami
  • Zarządzaj {vendor_count} dostawcami
  • Przeczytaj więcej o tych celach
Zobacz preferencje
  • {title}
  • {title}
  • {title}