All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 14m36s
問題 1 — ArgoCD "All connection attempts failed": - ARGOCD_URL 指向 192.168.0.120:30443,但 node 120 kube-proxy 對 30443 有路由 bug(ArgoCD pod 在 121) - 修復: ARGOCD_URL → 192.168.0.121:30443 - NetworkPolicy: 補白名單 192.168.0.121/32:30443 - NetworkPolicy: 補白名單 192.168.0.125/32:30443 (keepalived VIP) 問題 2 — drift-scanner Error x5 / 系統沉默 9.4h: - CronJob pod template 缺少 system=awoooi label - default-deny-all 封鎖所有 egress,allow-required-egress 僅對 system=awoooi pods 生效 - 修復: drift-cronjob pod template 新增 system: awoooi Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
79 lines
3.3 KiB
YAML
79 lines
3.3 KiB
YAML
# Config Drift Detection CronJob - Phase 25 P2
|
||
# 每小時掃描 awoooi-prod namespace 的配置漂移
|
||
#
|
||
# 建立時間: 2026-04-04 (台北時區)
|
||
# 建立者: Claude Code (Phase 25 P2)
|
||
# 關聯設計: docs/superpowers/specs/2026-04-04-nemotron-active-defense-design.md 方向三
|
||
# 關聯 ADR: 待起草 ADR-057
|
||
#
|
||
# 部署: kubectl apply -f k8s/drift-cronjob.yaml -n awoooi-prod
|
||
# 手動觸發: kubectl create job --from=cronjob/drift-scanner drift-scan-manual -n awoooi-prod
|
||
# 查看 log: kubectl logs -l job-name=drift-scanner -n awoooi-prod
|
||
|
||
apiVersion: batch/v1
|
||
kind: CronJob
|
||
metadata:
|
||
name: drift-scanner
|
||
namespace: awoooi-prod
|
||
labels:
|
||
app: awoooi
|
||
component: drift-scanner
|
||
phase: "25"
|
||
annotations:
|
||
# 2026-04-04 ogt: Phase 25 P2 — Config Drift Detection
|
||
description: "每小時掃描 K8s 配置漂移,由 Nemotron 做意圖分析"
|
||
spec:
|
||
# 每小時整點執行(台北時間 = UTC+8,schedule 用 UTC)
|
||
schedule: "0 * * * *"
|
||
concurrencyPolicy: Forbid # 禁止並發:上次未完成則跳過
|
||
successfulJobsHistoryLimit: 3
|
||
failedJobsHistoryLimit: 5
|
||
startingDeadlineSeconds: 60 # 錯過時間窗口超過 60s 則跳過
|
||
jobTemplate:
|
||
spec:
|
||
backoffLimit: 0 # 失敗不重試(漂移掃描冪等,下次 cron 自動補掃)
|
||
activeDeadlineSeconds: 300 # 最長 5 分鐘
|
||
template:
|
||
metadata:
|
||
labels:
|
||
app: awoooi
|
||
component: drift-scanner
|
||
# 2026-04-14 Claude Sonnet 4.6: 補 system=awoooi — allow-required-egress 以此篩選
|
||
# 缺此 label 導致 default-deny-all 封鎖所有 egress(系統沉默 9.4h 根因)
|
||
system: awoooi
|
||
spec:
|
||
restartPolicy: Never
|
||
# 2026-04-09 Claude Sonnet 4.6: awoooi-api SA 不存在,改用 default(只需呼叫內部 API,不需 K8s 權限)
|
||
serviceAccountName: default
|
||
containers:
|
||
- name: drift-scanner
|
||
# 使用 awoooi-api 鏡像(含 kubectl + Python 環境)
|
||
# 2026-04-09 Claude Sonnet 4.6: 改用內網 registry + 固定 SHA tag (禁止 latest)
|
||
image: 192.168.0.110:5000/awoooi/api:21567a7a6dbee7db2c0f59c265f80713ff5e6fe4
|
||
imagePullPolicy: Always
|
||
command:
|
||
- python
|
||
- -c
|
||
- |
|
||
import asyncio, httpx, os
|
||
API_URL = os.environ.get("INTERNAL_API_URL", "http://awoooi-api:8000")
|
||
async def run():
|
||
async with httpx.AsyncClient(timeout=240) as c:
|
||
r = await c.post(f"{API_URL}/api/v1/drift/internal/scan")
|
||
print(f"status={r.status_code} body={r.text[:200]}")
|
||
asyncio.run(run())
|
||
env:
|
||
# 2026-04-09 Claude Sonnet 4.6: ClusterIP 和 DNS 在 Job Pod 均不可達
|
||
# 改用 NodePort 直連 K3s worker node(同 K8s_API_SERVER_URL 解法)
|
||
- name: INTERNAL_API_URL
|
||
value: "http://192.168.0.121:32334"
|
||
- name: DRIFT_SCAN_NAMESPACES
|
||
value: "awoooi-prod"
|
||
resources:
|
||
requests:
|
||
cpu: "50m"
|
||
memory: "64Mi"
|
||
limits:
|
||
cpu: "200m"
|
||
memory: "256Mi"
|