Kubernetes, Helm ve yüksek erişilebilirlik
QueryProxy'yi Helm chart'ıyla Kubernetes'te çalıştırın; SQLite'ta tek pod'luk denemeden PostgreSQL, S3 ve ayrı web, worker, scheduler pod'larıyla HA kuruluma.
Güncelleme:
QueryProxy, depoda bir Helm chart ile gelir:
deploy/helm/queryproxy.
Yayımlanan tek imajı çalıştırır. Harici bir uygulama veritabanıyla bu imajı,
birbirinden bağımsız ölçeklenen ayrı web, worker ve scheduler
Deployment’ları olarak başlatır. Bu sayfa bir özettir; tüm değer listesi ve
ayrıntılar chart’ın
README
dosyasındadır. Chart Kubernetes 1.27 ya da daha yenisini ister. 0.4.1’den
itibaren chart bir registry’ye de yayımlanır (bkz.
OCI registry’den kurun); aksi hâlde çalıştırmak
istediğiniz sürüm etiketindeki bir checkout’un chart dizininden kurun.
İki mod
database.connection |
Chart’ın ürettiği | Replika |
|---|---|---|
sqlite (varsayılan) |
Web, worker ve scheduler’ı çalıştıran tek bir Deployment | Tam 1, Recreate, storage/app üzerinde bir volume |
pgsql, mysql, mariadb |
web, worker ve scheduler Deployment’ları, ek olarak bir migration Job’ı |
web ve worker ayarladığınız kadar, scheduler her zaman 1 |
SQLite tek pod demektir. SQLite dosyası tek bir volume’de yaşar ve pod’lar arasında paylaşılamaz; bu yüzden SQLite ile chart, docker-compose’daki gibi tek bir hepsi bir arada Deployment kurar. Birden fazla web replikasıyla, worker otomatik ölçeklemesiyle ya da kalıcı volume olmadan üretmeyi reddeder. Bu modu QueryProxy’yi denemek ya da küçük bir ekip için kullanın; ölçeklemek için önce harici bir veritabanına geçin.
Rol ayrımı yalnızca harici uygulama veritabanıyla geçerlidir. Orada roller
QUERYPROXY_RUN_WORKER ve QUERYPROXY_RUN_SCHEDULER ile ayrılır: web Deployment’ı
ikisini de çalıştırmaz, worker Deployment’ı yalnızca kuyruk işçisini, scheduler
Deployment’ı yalnızca zamanlayıcıyı çalıştırır. Bir worker’daki çökme döngüsü ya da
pahalı bir sorgu artık arayüzü de düşürmez. docker-compose değişmez; her şeyi hâlâ
tek konteynerde çalıştırır.
OCI registry’den kurun
Her sürüm etiketi chart’ı GitHub Container Registry’ye
oci://ghcr.io/queryproxy/charts/queryproxy olarak yayımlar. Chart sürümü,
v olmadan sürüm numarasıdır. Aşağıdaki örneklerde yerel yol yerine bu komutları
kullanın:
helm upgrade --install queryproxy oci://ghcr.io/queryproxy/charts/queryproxy --version 0.4.1 \
--namespace queryproxy --create-namespace \
--set admin.email=admin@example.com --set secrets.adminPassword="$(openssl rand -hex 16)"
# Ya da önce indirin, örneğin values-ha.yaml'ı okumak için:
helm pull oci://ghcr.io/queryproxy/charts/queryproxy --version 0.4.1 --untar
Sürüm iş akışı chart’ı cosign ile anahtarsız (Sigstore, GitHub OIDC kimliği) imzalar, imajlarda yaptığı gibi, ve bitirmeden önce imzayı kendisi de doğrular. Kurmadan önce siz de cosign v3 ya da daha yenisiyle doğrulayın. Kimlik, bir sürüm etiketindeki QueryProxy deposunun sürüm iş akışı olmalı ve GitHub Actions tarafından verilmiş olmalıdır:
cosign verify \
--certificate-identity-regexp '^https://github\.com/QueryProxy/QueryProxy/\.github/workflows/release\.yml@refs/tags/v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/queryproxy/charts/queryproxy:0.4.1
0.4.1 yerine kurduğunuz sürümü yazın. Bir sürüm yalnızca etiket, chart’ın
Chart.yaml dosyasındaki version ve appVersion ile aynıysa yayımlanır; yani
çektiğiniz chart her zaman aynı numaralı imaja aittir.
SQLite ile deneyin
helm upgrade --install queryproxy deploy/helm/queryproxy \
--namespace queryproxy --create-namespace \
--set admin.email=admin@example.com \
--set secrets.adminPassword="$(openssl rand -hex 16)"
kubectl -n queryproxy port-forward svc/queryproxy 7432:80
Sonra http://localhost:7432 adresini açın. config.appUrl varsayılan olarak
budur. QueryProxy yalnızca APP_URL’nin host’una, chart’ın eklediği Service’in küme içi adlarına ve
config.trustedHosts’a yanıt verir; gerçek bir kurulumda config.appUrl’yi kullanıcıların yazdığı adrese, genelde
Ingress’in HTTPS adresine ayarlayın.
Yüksek erişilebilirlik
Referans profil values-ha.yaml’dır:
Ingress / LoadBalancer
|
Service (80 -> 7432)
|
+---------------------+----------------------+
| |
web x N (nginx + php-fpm) worker x M (queue:work) scheduler x 1
| | |
+--------------------+-----------------------+------------------+
|
harici PostgreSQL / MySQL (kullanıcılar, talepler, kuyruk, oturumlar, denetim zinciri)
|
S3 bucket (sonuç dosyaları) hedef veritabanları (worker'lar ulaşır)
Profil, sslMode: require ile harici bir PostgreSQL, S3 sonuç depolama, iki web ve iki worker pod’u (zamanlayıcının yapabildiği yerde
bölgelere yayılır: ScheduleAnyway), bir scheduler, TLS’li bir Ingress, web ve
worker için PodDisruptionBudget ve bir NetworkPolicy ayarlar. Şöyle kurun:
- PostgreSQL’i (yönetilen bir servis ya da operator) QueryProxy için bir veritabanı ve rolle, sonuç dosyaları için de özel bir S3 bucket’ıyla hazırlayın.
secrets.existingSecretiçinde adı geçen Secret’ı kurulumdan önce oluşturun; migration hook’u ona ihtiyaç duyar.values-ha.yamliçindeki herexampledeğerini değiştirin, sonra:
helm upgrade --install queryproxy deploy/helm/queryproxy \
-f deploy/helm/queryproxy/values-ha.yaml \
--namespace queryproxy --create-namespace
Kendiniz boyutlandıracaklarınız:
- PostgreSQL durum tutan (stateful) tek bağımlılıktır. Kuyruğu, oturumları ve yalnızca eklenen denetim zincirini tutar; bu yüzden çoğaltılmış, yedeklenen bir servis kullanın. Her pod kendi bağlantılarını açar; çok sayıda worker için önüne bir pooler koyun.
- Worker’lar onaylı sorguları çalıştırır. Paralellik
worker.replicasçarpıconfig.workerProcesses’tir. Durdurulan bir worker pod’u, çalışan sorguyu bitirmek içinconfig.executionTimeout + 30saniye alır. - Scheduler tek replikadır ve
Recreatestratejisini kullanır. İki scheduler, zamanlanmış her görevi (saklama süresi temizliği, hatırlatmalar, süreli tanımlamaların sona ermesi) iki kez çalıştırırdı.
Secret’lar
Tüm pod’lar aynı APP_KEY’e, ayrıca veritabanı parolasına ve kullanılıyorsa Redis
parolasına, metrik token’ına ve S3 anahtarlarına ihtiyaç duyar.
- Kendi Secret’ınız (üretim).
secrets.existingSecretayarlayın. Beklenen anahtarlarAPP_KEY,DB_PASSWORDve gerektiğindeREDIS_PASSWORD,QUERYPROXY_METRICS_TOKEN,QUERYPROXY_ADMIN_PASSWORD,AWS_ACCESS_KEY_IDveAWS_SECRET_ACCESS_KEY’dir. Secret External Secrets Operator’dan gelebilir; chart README’sinde bir örnek var. Döndürdükten sonra pod’ları kendiniz yeniden başlatın. - Chart’ın yönettiği Secret (deneme).
secrets.existingSecret’ı boş bırakın. ChartAPP_KEY’i ilk kurulumda üretir ve korur. Secret bilerekhelm uninstall’dan sağ çıkar; çünkü saklanan bağlantı kimlik bilgileri anahtar olmadan çözülemez: yedekleyin. - Dosya olarak secret’lar.
secrets.mountAsFiles=trueSecret’ı bağlar ve*_FILEdeğişkenlerini ayarlar; böylece değerler pod spesifikasyonunda görünmez. IRSA ya da Workload Identity ile S3 anahtarlarını dışarıda bırakabilirsiniz (results.s3.useSecretCredentials=false).
Bağlantı parolalarının QueryProxy’de durması da gerekmez.
Harici gizli bilgi referanslarıyla pod, bir
bağlantı açılırken parolayı Vault, AWS Secrets Manager ya da Azure Key Vault’tan
okur: AWS için IRSA, Azure için workload identity ve Vault’un Kubernetes girişi
saklanan kimlik bilgisi gerektirmez. QUERYPROXY_VAULT_*, QUERYPROXY_AWS_* ya da
QUERYPROXY_AZURE_* ayarlarından düz olanları (QUERYPROXY_VAULT_ADDR,
QUERYPROXY_VAULT_AUTH, QUERYPROXY_VAULT_K8S_ROLE, QUERYPROXY_AWS_REGION,
QUERYPROXY_AZURE_TENANT_ID gibi) config.extraEnv ile geçirin.
config.extraEnv değerleri bir ConfigMap’e ve pod spesifikasyonuna düz metin
olarak yazılır; bu yüzden QUERYPROXY_VAULT_TOKEN, QUERYPROXY_VAULT_SECRET_ID
ya da QUERYPROXY_AZURE_CLIENT_SECRET’ı oraya asla koymayın. Anahtar adları bu
adlar olan bir Kubernetes Secret’ta tutun ve config.extraEnvFrom ile başvurun:
config:
extraEnvFrom:
- secretRef:
name: queryproxy-secret-store
Tek oturum açma için QUERYPROXY_OIDC_* değişkenlerini config.extraEnv ile
geçirin, istemci secret’ını da config.extraEnvFrom ile başvurduğunuz bir
Secret’ta tutun. Bkz. Tek oturum açma.
Migration’lar ve yükseltmeler
Harici veritabanıyla bir pre-install,pre-upgrade Job’ı, yeni sürümün hiçbir pod’u
başlamadan önce php artisan migrate --force çalıştırır. Başarısız olursa sürüm
ilerlemez. ConfigMap, Secret ve ServiceAccount sıradan sürüm kaynaklarıdır; bu yüzden
helm rollback önceki yapılandırmayı geri getirir. Geri alma migration’ları geri
almaz; Yükseltme ve geri alma sayfasını izleyin ve
veritabanı yedeğini elinizde tutun.
Mevcut bir SQLite kurulumunu PostgreSQL’e taşımak için onu durdurun ve
php artisan queryproxy:migrate-appdb --to=<dsn> kullanın; sonra chart’ı yeni
database.* değerleriyle kurun.
Worker’ları otomatik ölçekleme
worker.autoscaling.enabled=true, queryproxy_queue_depth harici metriğine göre ölçekleyen bir
HorizontalPodAutoscaler üretir. Varsayılan olarak kapalıdır; çünkü şunları ister:
secrets.metricsTokenilemetrics.enabled=true.- Prometheus’un
/metrics’i Service adı üzerinden kazıması. QueryProxy yalnızca güvenilen host adlarına yanıt verir; bir pod IP’sini kazımak400döner. - Metriği sunan bir metrics adapter; chart’ın
values.yamldosyasında bir prometheus-adapter kuralı var.
Ölçek küçültme bilerek yavaştır; çünkü sorgu çalıştıran bir pod’u durdurmak onu bekler. Metrik için bkz. İzleme.
Ağ, erişilebilirlik ve sertleştirme
- Probe’lar
config.appUrl’nin host’uylaGET /upçağırır. - Web ve worker için
maxUnavailable: 1ile PodDisruptionBudget. Scheduler’ın yoktur: tek pod’dur ve boşaltma onu yeniden başlatır. - NetworkPolicy (
networkPolicy.enabled): yalnızcanetworkPolicy.ingressFromeşleri 7432 portuna ulaşır;ingressFromboşsa (varsayılan) her kaynak yine de ulaşabilir, diğer tüm portlar kapalıdır. NetworkPolicy, ağ eklentiniz onu uygularsa etkili olur (örneğin Calico ya da Cilium). Egress varsayılan olarak açıktır; çünkü worker’ların kaydettiğiniz her hedef veritabanına ulaşması gerekir.networkPolicy.egress.restrict=trueile DNS’i, uygulama veritabanını, S3’ü, hedef veritabanlarınızı ve sohbet ile SIEM uç noktalarınızınetworkPolicy.egress.rulesiçinde listeleyin. Ingress kuralı sürümün her pod’unu kapsar;/metrics’i kazıyan Prometheus’un namespace’iniingressFrom’a ekleyin. - Güvenlik bağlamı. Pod’lar root olmayan bir kullanıcıyla, tüm capability’ler düşürülmüş ve ayrıcalık yükseltmesi kapalı çalışır.
- Kök dosya sistemi hâlâ yazılabilir. İmajın entrypoint’i başlangıçta ona yazar;
bu yüzden
readOnlyRootFilesystemkapalıdır. Chart bugün bundan fazlasını vaat edemez.
S3 ve Redis
İmaj S3 adaptörünü ve predis Redis istemcisini taşır; ikisi de isteğe bağlıdır.
results.disk=s3 sonuç dosyalarını S3’te ya da S3 API’sini sunan bir uç noktada saklar; S3
olmadan web ve worker’ın paylaştığı bir ReadWriteMany volume kullanın.
redis.enabled cache’i, kuyruğu ve oturumları Redis’e taşır; her şey yalnızca
veritabanıyla da çalışır.
Sonraki adımlar
- Hâlâ geçerli kontrol listesi için Üretim güvenliği.
- Chart’ın geçirebildiği tüm ortam değişkenleri için Yapılandırma.
- Veritabanı ve
APP_KEYiçin Yedekleme ve geri yükleme.