DevOps ve Ölçeklendirme

Geniş Ölçekte CAPTCHA Çözümü için Kubernetes İş Kuyrukları

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.

Bu makale için yorumlar devre dışı bırakılmıştır.