Laravel na k3s — Część 1 · Część 2 · Część 3 · Część 4
Usługi wspierające kuszą, bo każda obiecuje brakujący element dojrzałości produkcyjnej. Tracking błędów daje stack trace, object storage przechowuje uploady, kontrola uptime'u zapewnia widok z zewnątrz, a dashboard czyni Kubernetes mniej nieprzejrzystym. Każda z tych usług ma jednak własną bazę danych albo volume, poświadczenia, ścieżkę aktualizacji, alerty i przyszłe odtworzenie. Celem nie jest zmieścić na jednym VPS każdego użytecznego narzędzia. Chodzi o dodanie najmniejszej usługi, która odpowiada na nazwaną potrzebę operacyjną i ma właściciela.
Najpierw granica, potem chart albo kontener
Zapisz decyzję w jednym zdaniu. „Potrzebujemy zewnętrznego sprawdzenia publicznego checkoutu co pięć minut” uzasadnia monitor uptime. „Może kiedyś przyda się monitoring” nie uzasadnia niczego. Dla małej instalacji Laravel zarządzany tracking błędów, zarządzany object storage i monitoring uptime od dostawcy są zwykle bezpieczniejszymi alternatywami niż samodzielne utrzymywanie trzech systemów stanowych. Przenoszą na dostawcę odpowiedzialność za łatki, replikację storage i część procesu odtworzenia.
Self-hostuj tylko wtedy, gdy wymogi dotyczące rezydencji danych, koszt, integracja albo istniejące kompetencje operacyjne przeważają nad tym kosztem. Nie dodawaj usługi wyłącznie dlatego, że istnieje dla niej chart Helm. Klaster z jednym węzłem nie staje się odporny tylko dlatego, że uruchamia więcej Podów; staje się większą pojedynczą domeną awarii.
Oddziel opcjonalne narzędzie od namespace aplikacji. Własność, RBAC i budżet zasobów są wtedy widoczne, a zbyt szeroki selector Service nie skieruje przypadkiem ruchu do administracyjnego Poda.
apiVersion: v1
kind: Namespace
metadata:
name: observability
labels:
owner: platform
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: observability-budget
namespace: observability
spec:
hard:
requests.cpu: "500m"
requests.memory: 1Gi
limits.cpu: "1500m"
limits.memory: 3Gi
persistentvolumeclaims: "2"
Quota jest barierką ochronną, nie planowaniem pojemności. Najpierw zmierz dostępne CPU, pamięć i dysk węzła. Jeśli error tracker konkuruje o pamięć z MySQL albo workerem kolejki, workload klienta wygrywa; przeniesienie obserwowalności do zarządzanego produktu bywa bardziej użyteczne niż strojenie zachowania mechanizmu eviction.
Prywatna ścieżka administracyjna
Wewnętrzne narzędzie nie może stać się nieuwierzytelnioną publiczną stroną tylko dlatego, że Ingress pozwala do niego dotrzeć. Wybierz VPN, sieć prywatną, proxy świadome tożsamości albo przynajmniej allowlistę sieci administracyjnej w połączeniu z uwierzytelnianiem aplikacji i TLS. Sama allowlista IP jest słaba dla zespołów pracujących z różnych miejsc i nie zastępuje zarządzania cyklem życia kont.
Poniższy Ingress nadaje monitorowi odrębny hostname. Celowo nie udaje, że zapewnia uwierzytelnianie: skonfiguruj je na wybranej warstwie proxy albo usługi i przetestuj, czy anonimowe żądania są odrzucane.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: uptime-admin
namespace: observability
spec:
ingressClassName: traefik
rules:
- host: status-admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: uptime-kuma
port:
number: 3001
Nigdy nie zapisuj w manifeście commitowanym do Gita hasła dashboardu, klucza S3 ani DSN error trackera. Odwołaj się do chronionego źródła Secret, przyznaj service accountowi tylko niezbędne uprawnienia i rotuj poświadczenia w tej samej kontrolowanej procedurze restartu, której używasz dla Laravel. Base64 w Kubernetes to kodowanie, nie vault.
Mały monitor uptime z jasnym limitem
Użytecznym zadaniem monitora uptime jest sprawdzanie publicznej ścieżki spoza
procesu aplikacji. Powinien osobno kontrolować stabilny endpoint zdrowia i
krytyczną podróż klienta. Żądanie do /up potwierdza routing oraz dostępność
procesu, ale nie dowodzi, że checkout potrafi zapisać zamówienie.
apiVersion: apps/v1
kind: Deployment
metadata:
name: uptime-kuma
namespace: observability
spec:
replicas: 1
selector:
matchLabels: { app: uptime-kuma }
template:
metadata:
labels: { app: uptime-kuma }
spec:
containers:
- name: uptime-kuma
image: louislam/uptime-kuma:1.23.16
ports: [{ name: http, containerPort: 3001 }]
resources:
requests: { cpu: 50m, memory: 128Mi }
limits: { cpu: 250m, memory: 512Mi }
volumeMounts: [{ name: data, mountPath: /app/data }]
volumes:
- name: data
persistentVolumeClaim:
claimName: uptime-kuma-data
---
apiVersion: v1
kind: Service
metadata: { name: uptime-kuma, namespace: observability }
spec:
selector: { app: uptime-kuma }
ports: [{ name: http, port: 3001, targetPort: http }]
Przypnij sprawdzoną wersję obrazu lub digest; nie kopiuj niezweryfikowanego
przykładu z latest. PVC utwórz dopiero po wybraniu klasy storage i
zrozumieniu, czy jej volume przetrwa utratę węzła. Monitor może alarmować o
aplikacji, ale na jednym VPS nie zaalarmuje wiarygodnie o awarii tego samego
VPS, jego sieci albo dysku. Dla tego trybu awarii użyj niezależnego monitora
zewnętrznego.
Object storage jest kontraktem aplikacji
Uploady Laravel powinny korzystać z nazwanego dysku i polityki bucketu prywatnego domyślnie. Niezależnie od tego, czy endpointem jest MinIO, dostawca zgodny z S3 czy usługa chmurowa, aplikacja potrzebuje jednego stabilnego endpointu, poświadczeń ograniczonych do jednego bucketu oraz planu odtworzenia zarówno obiektów, jak i rekordów bazy danych. Nie wystawiaj konsoli ani API MinIO z szerokimi publicznymi poświadczeniami tylko po to, aby ułatwić lokalne testy.
// config/filesystems.php
'disks' => [
'uploads' => [
'driver' => 's3',
'key' => env('UPLOADS_ACCESS_KEY_ID'),
'secret' => env('UPLOADS_SECRET_ACCESS_KEY'),
'region' => env('UPLOADS_REGION', 'us-east-1'),
'bucket' => env('UPLOADS_BUCKET'),
'endpoint' => env('UPLOADS_ENDPOINT'),
'use_path_style_endpoint' => env('UPLOADS_PATH_STYLE', false),
'visibility' => 'private',
],
],
Używaj podpisanych tymczasowych URL-i albo kontrolera pobierania z uwierzytelnieniem zamiast zamieniać prywatny bucket dokumentów w publiczny. Twórz backup obiektów w niezależnej lokalizacji i testuj odtworzenie wraz z odpowiadającymi im referencjami w bazie. Backup bucketu bez metadanych może uniemożliwić aplikacji odnalezienie obiektów, a backup bazy bez obiektów pozostawia uszkodzone linki. Automatyczne usuwanie według lifecycle nie jest polityką backupu.
Tracking błędów wymaga minimalizacji danych
GlitchTip albo inna usługa zgodna z Sentry jest cenna, kiedy grupuje wyjątki i łączy je z release'ami, ale zdarzenia błędów mogą zawierać PII, nagłówki autoryzacji, parametry query albo body żądania. Skonfiguruj filtrowanie serwerowego i klienckiego SDK przed wysłaniem ruchu produkcyjnego, ustaw okres retencji i ogranicz krąg osób, które mogą przeglądać zdarzenia. Próbkuj błędy o dużym wolumenie; nie pozwól, aby awaria zamieniła się w zdarzenie wyczerpania storage.
Na granicy Laravel trzymaj DSN poza Gitem i wysyłaj identyfikator release'u zgodny z wdrożonym obrazem. Zweryfikuj integrację przez celowo nieszkodliwy wyjątek na stagingu, a następnie go usuń. Nie testuj monitoringu produkcyjnego, wprowadzając do wyjątku dane prawdziwego klienta.
kubectl -n storefront set env deployment/web RELEASE_SHA=3f18d7c
kubectl -n storefront rollout status deployment/web --timeout=180s
kubectl -n storefront logs deployment/web --tail=100
Odtworzenie, usunięcie i sytuacje, gdy nie dodawać usługi
Przed uruchomieniem dowolnej usługi wspierającej na produkcji przećwicz jej odtworzenie: odtwórz PVC albo backup do izolowanego namespace, zaloguj się nowo wydanym kontem administratora i potwierdź, że usługa odczytuje odtworzone dane. Zapisz, kto odbiera jej alerty i kto aktualizuje obraz. Alert bez właściciela nie jest obserwowalnością; jest przyszłym szumem.
Usunięcie powinno być równie jednoznaczne. Wyeksportuj konfigurację i dane,
najpierw usuń Ingress, upewnij się, że żaden Secret aplikacji ani rekord DNS
nie wskazuje usługi, a następnie usuń workload i volume zgodnie z polityką
retencji. Nigdy nie kasuj PVC tylko po to, by kubectl get wyglądało
porządnie, bez potwierdzenia istnienia przetestowanego backupu.
Nie uruchamiaj MinIO w tym klastrze, jeśli zarządzany object store zapewnia
wymaganą trwałość. Nie utrzymuj samodzielnie trackera błędów, jeśli zespół nie
potrafi aktualizować i backupować jego bazy. Nie wdrażaj dashboardu, jeżeli
kubectl wraz z runbookiem wystarcza, a nikt nie będzie właścicielem kont
użytkowników. Trwała architektura nadal pozostaje nudna: Pody aplikacji mają
probe'y i ograniczenia zasobów, systemy stanowe mają przetestowane odtworzenie,
endpointy administracyjne są prywatne, a każda dodana usługa ma powód istnienia.
GlitchTip, MinIO, Uptime Kuma i dashboardy klastra mogą być użyteczne, lecz każdy dodaje storage, aktualizacje, poświadczenia i własność alertów. Dodawaj usługę tylko wtedy, gdy odpowiada na konkretną potrzebę operacyjną. Umieść ją we własnym namespace'ie albo za jasną granicą, ustaw requesty i limity CPU/pamięci, backupuj jej dane i unikaj publicznego wystawiania UI administracyjnych.
Trwała architektura jest nudna: workloady aplikacji mają probe'y, usługi stanowe mają przetestowane odtwarzanie, logi i alerty wskazują właściciela, a każdy deployment da się wycofać do znanego obrazu.