diff --git a/.gitea/workflows/cd.yaml b/.gitea/workflows/cd.yaml index 90f010e2..d0d5bff9 100644 --- a/.gitea/workflows/cd.yaml +++ b/.gitea/workflows/cd.yaml @@ -42,10 +42,10 @@ env: OTEL_SERVICE_NAME: awoooi-cd OTEL_RESOURCE_ATTRIBUTES: service.version=${{ github.sha }},deployment.environment=production CI_IMAGE: 192.168.0.110:5000/awoooi/ci-runner:act-22.04 - # CD SSH still lands on 121 because that host has the deploy sudo path. - # Its kubeconfig points to 127.0.0.1, so the deploy scripts rewrite a temp - # kubeconfig to the 120 control-plane API server before running kubectl. - K8S_SSH_HOST: 192.168.0.121 + # 2026-05-06 Codex: deploy through the 120 control-plane node. After dirty + # reboots, 121 host-key prompts can block the non-interactive host runner. + # Both nodes support the sudo kubectl path, but 120 removes the extra hop. + K8S_SSH_HOST: 192.168.0.120 K8S_API_SERVER: https://192.168.0.120:6443 # 2026-05-05 Codex: health/smoke probes use the keepalived VIP instead of a # fixed node. Kubectl still tunnels through K8S_SSH_HOST with --server=120. @@ -446,8 +446,9 @@ jobs: mkdir -p ~/.ssh echo "$SSH_PRIVATE_KEY" > ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key - ssh-keyscan "${{ env.K8S_SSH_HOST }}" >> ~/.ssh/known_hosts 2>/dev/null - ssh -i ~/.ssh/deploy_key "wooo@${{ env.K8S_SSH_HOST }}" << SECRETS + ssh-keyscan -T 5 "${{ env.K8S_SSH_HOST }}" > ~/.ssh/known_hosts 2>/dev/null + SSH_OPTS="-i ~/.ssh/deploy_key -o BatchMode=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=${HOME}/.ssh/known_hosts -o ConnectTimeout=10" + ssh $SSH_OPTS "wooo@${{ env.K8S_SSH_HOST }}" << SECRETS set -e K8S_API_SERVER="${{ env.K8S_API_SERVER }}" KUBECTL="sudo kubectl --kubeconfig=/etc/rancher/k3s/k3s.yaml --server=\${K8S_API_SERVER}" @@ -676,19 +677,20 @@ jobs: mkdir -p ~/.ssh echo "$SSH_PRIVATE_KEY" > ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key - ssh-keyscan "${{ env.K8S_SSH_HOST }}" >> ~/.ssh/known_hosts 2>/dev/null + ssh-keyscan -T 5 "${{ env.K8S_SSH_HOST }}" > ~/.ssh/known_hosts 2>/dev/null + SSH_OPTS="-i ~/.ssh/deploy_key -o BatchMode=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=${HOME}/.ssh/known_hosts -o ConnectTimeout=10" IMAGE_TAG="${{ github.sha }}" HARBOR=192.168.0.110:5000 # ─── Step 1: Apply ConfigMap + ServiceRegistry (ArgoCD 管的是 Deployment,ConfigMap 仍直接 apply) ─── cat k8s/awoooi-prod/04-configmap.yaml | \ - ssh -i ~/.ssh/deploy_key "wooo@${{ env.K8S_SSH_HOST }}" \ + ssh $SSH_OPTS "wooo@${{ env.K8S_SSH_HOST }}" \ "KUBECTL='sudo kubectl --kubeconfig=/etc/rancher/k3s/k3s.yaml --server=${{ env.K8S_API_SERVER }}'; \$KUBECTL apply -f -" echo "✅ ConfigMap 已更新" cat k8s/awoooi-prod/15-service-registry-configmap.yaml | \ - ssh -i ~/.ssh/deploy_key "wooo@${{ env.K8S_SSH_HOST }}" \ + ssh $SSH_OPTS "wooo@${{ env.K8S_SSH_HOST }}" \ "KUBECTL='sudo kubectl --kubeconfig=/etc/rancher/k3s/k3s.yaml --server=${{ env.K8S_API_SERVER }}'; \$KUBECTL apply -f -" echo "✅ Service Registry ConfigMap 已更新" @@ -730,7 +732,7 @@ jobs: } # ─── Step 4: 等待 ArgoCD sync + rollout ─── - ssh -i ~/.ssh/deploy_key "wooo@${{ env.K8S_SSH_HOST }}" \ + ssh $SSH_OPTS "wooo@${{ env.K8S_SSH_HOST }}" \ "EXPECTED_REVISION='${DEPLOY_REVISION}' bash -s" << 'ARGOCD_WAIT' set -e K8S_API_SERVER="${{ env.K8S_API_SERVER }}" diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 4a3c5b12..6eea00e7 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,15 @@ +## 2026-05-06 | CD host-key prompt unblock for AwoooP Ollama rollout + +**背景**:`09256be6` 已推到 Gitea main,但 CD `build-and-deploy` 卡在 SSH 到 `192.168.0.121` 的 host-key authenticity prompt,runner 無互動輸入,導致新 image tag 尚未注入 `kustomization.yaml`。 + +**本次修補**: +- `.gitea/workflows/cd.yaml` 的 K8s deploy SSH 目標改為已驗證可用的 `192.168.0.120` 控制面。 +- `Inject K8s Secrets` 與 `Deploy to K8s` 兩段 SSH 加上 `BatchMode=yes`、`StrictHostKeyChecking=yes`、固定 `UserKnownHostsFile` 與 `ConnectTimeout=10`。 +- 目的:重開機或 known_hosts 清空時,CD 要明確成功或失敗,不能再卡住整條部署鏈。 + +**驗證**: +- 本機已驗證 `wooo@192.168.0.120` 可用 `sudo -n kubectl --server=https://192.168.0.120:6443` 查詢 `awoooi-prod` namespace。 + # LOGBOOK - AWOOOI 進度軌跡 > **用途**: AI 代理進度追蹤,防止 Session 斷層