# Standalone worker deployment with claudebox sidecar. # Workers poll rdev-api for tasks and execute them via HTTP calls to the local sidecar. apiVersion: apps/v1 kind: Deployment metadata: name: rdev-worker namespace: rdev labels: app.kubernetes.io/name: rdev-worker app.kubernetes.io/part-of: rdev spec: replicas: 1 # RollingUpdate enabled by RWX (ReadWriteMany) PVC for claude-config # See: deployments/k8s/base/pvc.yaml and storageclass-rwx.yaml strategy: type: RollingUpdate rollingUpdate: maxSurge: 2 maxUnavailable: 0 selector: matchLabels: app: rdev-worker template: metadata: labels: app: rdev-worker app.kubernetes.io/name: rdev-worker app.kubernetes.io/part-of: rdev rdev.orchard9.ai/role: worker spec: containers: # Main worker container - polls for tasks and orchestrates execution - name: worker image: registry.threesix.ai/rdev/worker:latest imagePullPolicy: Always env: - name: RDEV_API_URL value: "http://rdev-api.rdev.svc.cluster.local:8080" - name: CLAUDEBOX_URL value: "http://localhost:8080" - name: RDEV_API_KEY valueFrom: secretKeyRef: name: rdev-worker-credentials key: api-key - name: WORKER_ID valueFrom: fieldRef: fieldPath: metadata.name - name: WORKER_POLL_INTERVAL value: "5s" - name: WORKER_HEARTBEAT_INTERVAL value: "30s" - name: WORKER_TASK_TIMEOUT value: "15m" - name: WORKER_CAPABILITIES value: "build,sdlc" resources: requests: cpu: "100m" memory: "128Mi" limits: cpu: "500m" memory: "256Mi" livenessProbe: exec: command: - test - -f - /usr/local/bin/rdev-worker initialDelaySeconds: 5 periodSeconds: 60 # Claudebox sidecar - provides Claude Code execution via HTTP - name: claudebox image: registry.threesix.ai/rdev/claudebox:latest imagePullPolicy: Always env: - name: PORT value: "8080" - name: WORKSPACE_DIR value: "/workspace" - name: GITEA_TOKEN valueFrom: secretKeyRef: name: rdev-worker-credentials key: gitea-token optional: true - name: GIT_USER value: "rdev-worker" - name: GIT_EMAIL value: "worker@threesix.ai" # Claude Code Telemetry - exports to OTEL collector - name: CLAUDE_CODE_ENABLE_TELEMETRY value: "1" - name: OTEL_METRICS_EXPORTER value: "otlp" - name: OTEL_LOGS_EXPORTER value: "otlp" - name: OTEL_EXPORTER_OTLP_PROTOCOL value: "grpc" - name: OTEL_EXPORTER_OTLP_ENDPOINT value: "otel-collector.observability.svc.cluster.local:4317" - name: OTEL_SERVICE_NAME value: "claudebox-worker" - name: OTEL_METRIC_EXPORT_INTERVAL value: "10000" - name: OTEL_LOGS_EXPORT_INTERVAL value: "5000" ports: - name: http containerPort: 8080 resources: requests: cpu: "500m" memory: "1Gi" limits: cpu: "2" memory: "4Gi" volumeMounts: - name: workspace mountPath: /workspace - name: claude-config mountPath: /root/.claude livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 10 periodSeconds: 30 readinessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 5 periodSeconds: 10 volumes: # EmptyDir for workspace - ephemeral per-pod - name: workspace emptyDir: sizeLimit: 10Gi # Shared Claude config volume for authentication # Uses the same PVC as the claudebox statefulset - name: claude-config persistentVolumeClaim: claimName: claudebox-claude-config --- # Secret for worker credentials apiVersion: v1 kind: Secret metadata: name: rdev-worker-credentials namespace: rdev labels: app.kubernetes.io/name: rdev-worker app.kubernetes.io/part-of: rdev type: Opaque stringData: # API key for workers to authenticate with rdev-api # Create with: kubectl create secret generic rdev-worker-credentials --from-literal=api-key= --from-literal=gitea-token= api-key: "placeholder-replace-me" gitea-token: "placeholder-replace-me" --- # Service for accessing worker metrics (optional) apiVersion: v1 kind: Service metadata: name: rdev-worker namespace: rdev labels: app.kubernetes.io/name: rdev-worker app.kubernetes.io/part-of: rdev spec: selector: app: rdev-worker ports: - port: 8080 name: claudebox targetPort: 8080