Kubernetes, yüksek hacimli CAPTCHA çözümü için otomatik ölçeklendirme, kendi kendini iyileştirme altyapısı sağlar. Bu kılavuz, görevleri Redis kuyruğundan alan ve talebe göre ölçeklendiren çalışan bölmelerini dağıtır.
Mimarlık
Producer → Redis Queue → Worker Pods (auto-scaled) → CaptchaAI API
↓
Results Store (Redis)
İşçi Dağıtımı
# k8s/worker-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: captcha-worker
labels:
app: captcha-worker
spec:
replicas: 3
selector:
matchLabels:
app: captcha-worker
template:
metadata:
labels:
app: captcha-worker
spec:
containers:
- name: worker
image: your-registry/captcha-worker:latest
env:
- name: CAPTCHAAI_KEY
valueFrom:
secretKeyRef:
name: captchaai-secret
key: api-key
- name: REDIS_URL
value: "redis://redis-service:6379"
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "250m"
Kubernetes'in Sırrı
kubectl create secret generic captchaai-secret \
--from-literal=api-key=YOUR_API_KEY
Redis Dağıtımı
# k8s/redis.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
resources:
requests:
memory: "128Mi"
cpu: "100m"
---
apiVersion: v1
kind: Service
metadata:
name: redis-service
spec:
selector:
app: redis
ports:
- port: 6379
İşçi Kodu
# worker.py
import os
import json
import time
import redis
import requests
class CaptchaWorker:
"""Kubernetes worker that processes CAPTCHA tasks from Redis."""
def __init__(self):
self.api_key = os.environ["CAPTCHAAI_KEY"]
self.redis = redis.from_url(
os.environ.get("REDIS_URL", "redis://localhost:6379"),
)
self.base = "https://ocr.captchaai.com"
def run(self):
"""Main worker loop."""
hostname = os.environ.get("HOSTNAME", "unknown")
print(f"Worker {hostname} started")
while True:
result = self.redis.blpop("captcha:queue", timeout=30)
if result is None:
continue
_, raw = result
task = json.loads(raw)
task_id = task.get("id", "unknown")
print(f"[{hostname}] Processing {task_id}")
start = time.time()
try:
token = self._solve(task["method"], task["params"])
duration = time.time() - start
self.redis.hset("captcha:results", task_id, json.dumps({
"status": "success",
"token": token,
"duration": f"{duration:.1f}s",
"worker": hostname,
}))
print(f"[{hostname}] {task_id} solved in {duration:.1f}s")
except Exception as e:
self.redis.hset("captcha:results", task_id, json.dumps({
"status": "error",
"error": str(e),
"worker": hostname,
}))
print(f"[{hostname}] {task_id} failed: {e}")
# Update queue length metric
queue_len = self.redis.llen("captcha:queue")
self.redis.set("captcha:queue_length", queue_len)
def _solve(self, method, params, timeout=120):
resp = requests.post(f"{self.base}/in.php", data={
"key": self.api_key,
"method": method,
"json": 1,
**params,
}, timeout=30)
result = resp.json()
if result.get("status") != 1:
raise RuntimeError(result.get("request"))
captcha_id = result["request"]
start = time.time()
while time.time() - start < timeout:
time.sleep(5)
resp = requests.get(f"{self.base}/res.php", params={
"key": self.api_key,
"action": "get",
"id": captcha_id,
"json": 1,
}, timeout=15)
data = resp.json()
if data["request"] != "CAPCHA_NOT_READY":
if data.get("status") == 1:
return data["request"]
raise RuntimeError(data["request"])
raise TimeoutError("Solve timeout")
if __name__ == "__main__":
CaptchaWorker().run()
Yatay Kapsül Otomatik Ölçekleyici
Çalışanları kuyruk derinliğine göre ölçeklendirin:
# k8s/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: captcha-worker-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: captcha-worker
minReplicas: 2
maxReplicas: 20
metrics:
- type: External
external:
metric:
name: redis_queue_length
selector:
matchLabels:
queue: captcha
target:
type: AverageValue
averageValue: "10"
Görev Yapımcısı
import json
import uuid
import redis
def submit_tasks(redis_url, tasks):
"""Submit CAPTCHA tasks to the queue."""
r = redis.from_url(redis_url)
task_ids = []
for task in tasks:
task_id = str(uuid.uuid4())[:8]
task["id"] = task_id
r.rpush("captcha:queue", json.dumps(task))
task_ids.append(task_id)
return task_ids
def get_results(redis_url, task_ids, timeout=180):
"""Wait for and collect results."""
r = redis.from_url(redis_url)
results = {}
deadline = time.time() + timeout
while len(results) < len(task_ids) and time.time() < deadline:
for tid in task_ids:
if tid in results:
continue
raw = r.hget("captcha:results", tid)
if raw:
results[tid] = json.loads(raw)
time.sleep(1)
return results
Sorun giderme
| Sorun | Sebep | Düzeltme |
|---|---|---|
| İşçiler başlamıyor | Gizli bilgi oluşturulmadı | kubectl create secret komutunu çalıştırın |
| CrashLoopBackOff'taki bölmeler | Env değişkenleri veya Redis eksik | Günlükleri kubectl logs ile kontrol edin |
| HPA ölçeklenmiyor | Özel metrikler yapılandırılmadı | Metrik adaptörünü (KEDA) yükleyin |
| Kuyruk büyüyor ancak işlem yapılmıyor | Boşta kalan işçiler/crashed | Pod sağlığını kontrol edin ve yeniden başlatın |
SSS
Kaç tane işçi kapsülüyle başlamalıyım?
3 kopyayla başlayın ve HPA'nın kuyruk derinliğine göre ölçeklendirilmesine izin verin. Her bölme, CAPTCHA türüne bağlı olarak ~5-10 eşzamanlı çözümü yönetir.
Jobs'u mu yoksa Dağıtımları mı kullanmalıyım?
Paylaşılan bir kuyruğu işleyen sürekli çalışanlar için Dağıtımları kullanın. Sabit sayıda görev içeren toplu iş yükleri için İşler'i kullanın.
HPA yerine KEDA'yı kullanabilir miyim?
Evet. KEDA (Kubernetes Olay Odaklı Otomatik Ölçeklendirme), bir ölçeklendirme tetikleyicisi olarak Redis kuyruk uzunluğunu yerel olarak destekler ve yapılandırılması özel ölçümlere göre daha kolaydır.
İlgili Kılavuzlar
Binlere ölçeklendirin —CaptchaAI'yi edininKubernetes için.