diff --git a/Dockerfile.orchestrator b/Dockerfile.orchestrator index 931de0e..c10a509 100644 --- a/Dockerfile.orchestrator +++ b/Dockerfile.orchestrator @@ -1,5 +1,16 @@ FROM python:3.11-slim +# kubectl — the kubernetes launch backend (agent_swarm#16/#56) shells out to `kubectl apply/delete` +# to create/teardown agent Pods + per-swarm key Secrets. Without it the k8s backend fails (0 agents). +# Pinned to the cluster minor (AKS 1.34) per kubectl skew policy. (linux/amd64 — AKS default node arch.) +RUN apt-get update \ + && apt-get install -y --no-install-recommends curl ca-certificates \ + && KUBECTL_VERSION="$(curl -fsSL https://dl.k8s.io/release/stable-1.34.txt)" \ + && curl -fsSL "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl" -o /usr/local/bin/kubectl \ + && chmod +x /usr/local/bin/kubectl \ + && kubectl version --client=true 2>/dev/null \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + WORKDIR /app # Install dependencies diff --git a/k8s/orchestrator-deployment.yaml b/k8s/orchestrator-deployment.yaml index e6114ef..54df88b 100644 --- a/k8s/orchestrator-deployment.yaml +++ b/k8s/orchestrator-deployment.yaml @@ -30,11 +30,15 @@ spec: metadata: labels: app: orchestrator + # Required for the AKS workload-identity webhook to inject AZURE_FEDERATED_TOKEN_FILE etc. + # into the pod, so the orchestrator can read the per-user model key from heicode-vault via + # its UAMI (SA swarm-orchestrator is annotated with azure.workload.identity/client-id). #56 + azure.workload.identity/use: "true" spec: serviceAccountName: swarm-orchestrator containers: - name: orchestrator - image: swarm-orchestrator:latest + image: heicode.azurecr.io/swarm-orchestrator:latest # deploy pins the tag (e.g. :) imagePullPolicy: IfNotPresent ports: - containerPort: 8000 @@ -66,6 +70,26 @@ spec: # (also set REDIS_CLUSTER=1 for an OSSCluster endpoint). - name: LOG_LEVEL value: "INFO" + # ── Swarm agent launch (agent_swarm#16/#56): make the runtime actually spawn agents ── + # Without AGENT_LAUNCH_BACKEND the launcher is a no-op (0 agents → run hangs). + - name: AGENT_LAUNCH_BACKEND + value: "kubernetes" + - name: AGENT_POD_IMAGE + value: "heicode.azurecr.io/swarm-agent:latest" # build: az acr build -r heicode -t swarm-agent:latest -f Dockerfile.agent . + # Agent Pods + per-swarm key Secrets are created here — MUST match the RBAC Role's ns + # (k8s/rbac/orchestrator-role.yaml is in swarm-system). + - name: AGENT_POD_NAMESPACE + value: "swarm-system" + # In-cluster Service DNS the launched agents connect back to (Service: orchestrator-service). + - name: ORCHESTRATOR_PUBLIC_URL + value: "ws://orchestrator-service.swarm-system.svc.cluster.local:8000" + # HM model gateway (OpenAI-compatible). code.heicode.cc is the official address (#56). + - name: AGENT_OPENAI_API_BASE + value: "https://code.heicode.cc/v1" + # Resolve per-user model key from heicode-vault via the pod's workload identity (#56). + # (Redundant when AZURE_FEDERATED_TOKEN_FILE is injected, but explicit is clearer.) + - name: SECRET_RESOLVER + value: "azkv" resources: requests: memory: "256Mi" diff --git a/k8s/rbac/orchestrator-role.yaml b/k8s/rbac/orchestrator-role.yaml index fe69294..df303ab 100644 --- a/k8s/rbac/orchestrator-role.yaml +++ b/k8s/rbac/orchestrator-role.yaml @@ -6,12 +6,23 @@ metadata: labels: app: heicode-swarm component: orchestrator +# NOTE: a Role is namespaced — these permissions only apply in `swarm-system`. The k8s launch +# backend creates agent Pods + per-swarm key Secrets in AGENT_POD_NAMESPACE, so that env MUST equal +# this namespace (set AGENT_POD_NAMESPACE=swarm-system), or a matching Role+RoleBinding must exist in +# the agent-pod namespace. (agent_swarm#56) rules: # Pod management permissions - apiGroups: [""] resources: ["pods"] verbs: ["create", "delete", "list", "watch", "get"] + # Per-swarm model-key Secret: the launcher applies a Secret (build_secret_manifest) referenced by + # the agent Pod via secretKeyRef, and deletes it on teardown (`kubectl delete pod,secret`). + # Without `secrets` create/delete the key Secret can't be made → agents start keyless. (#56) + - apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "delete", "list", "get"] + # Pod log access - apiGroups: [""] resources: ["pods/log"]