seon
26061a474b
chore: ai image b0ff118 (external responder), harness ed3d41d (26 min diagnose for external-*)
...
external-* 모델 참고 측정용. ai-agent 는 EXTERNAL_ADDR=:8090 리스너를 켜되 호스트의
127.0.0.1:8090 에만 매핑해 IAP SSH 터널로만 닿게 한다(응답이 곧 진단이므로 VPC 노출 금지).
ai.env 에 진단·턴 대기 시간(1500/1200초)을 명시. 하네스는 external- 모델의 /diagnose 를
26분 기다린다. VM 반영(make ai-sync / harness-sync)은 진행 중인 m1·Fable 배치가 끝난 뒤.
2026-10-16 09:10:07 +09:00
seon
dcb4ea1da2
chore(harness): image 85d9932 (atomic auto-approval claim, rejected_at)
2026-10-15 23:42:09 +09:00
seon
b73ecadf10
chore(harness): image ca933a6 (per-run auto-approval for model measurement)
...
측정 모드(auto_approve_after_s)를 지원하는 하네스 이미지로 올린다.
2026-10-15 23:39:41 +09:00
seon
69a70711ea
chore(ai-env): ai image f671e24 (Claude thinking blocks replayed verbatim)
...
Claude Sonnet 5.5 의 thinking 블록을 그대로 재전송하도록 고친 이미지로 올린다.
2026-10-15 22:20:10 +09:00
seon
ac2afea4d0
chore(ai-env): Claude WIF rule/service-account ids and ai image 684e70b
...
Claude Console 에서 만든 Workload Identity Federation 리소스의 ID(규칙 gcp-selfheal-ai-vm,
서비스 계정 selfheal-ai-vm, Default 워크스페이스)를 ai.env 에 넣고, 페더레이션을 지원하는
ai 이미지 684e70b 로 올린다. ID 는 비밀이 아니다.
2026-10-15 20:42:19 +09:00
seon
7967f7a320
chore(ai-env): add the Claude Workload Identity Federation id settings (empty until the Console rule exists)
...
ai.env 에 ANTHROPIC_FEDERATION_RULE_ID 등 4개 설정 키를 추가한다. 값은 Console 위자드로
규칙을 만든 뒤 채운다. 비어 있는 동안 에이전트는 기존 키 파일 경로로 동작한다.
2026-10-15 11:48:36 +09:00
seon
d7ecd59b4c
chore: ai/harness images 53ff243 (per-run model, usage, Claude provider) and the Anthropic key file
...
ai-env·harness 이미지를 53ff243 로 올린다. apply.sh 가 Secret Manager 의
selfheal-anthropic-api-key 를 받아 /run/secrets/anthropic-api-key 로 두고 compose 가
ANTHROPIC_KEY_FILE 로 넘긴다. 값이 없으면 기존처럼 저하 모드로 기동한다.
2026-10-14 23:21:50 +09:00
seon
d390b6a5d4
chore(ai-env): ai images fa9c08c (hitl re-reads the full row before mirroring API approvals)
2026-10-09 10:19:33 +09:00
seon
602c53d5e6
chore: harness and ai images f8e0aa9 (alert dedupe, proposal state API, HITL API-approval sync, Jev recovered_now)
2026-10-09 08:41:15 +09:00
seon
fd08c32501
feat(ai-env,alerting): reference queries per alert in slo.md, rule expression as alert annotation
...
第 4 回 V-G1 で LLM が route フィルタのない 5 分窓の p95(0.017 秒)を根拠に
「遅延なし」と結論した。slo.md にアラートごとの基準クエリ(規則と同じ式、
legacy のインスタンス別遅延と要求率を含む)を書き、確かめ直すときは同じ式を
使わせる。各規則の annotations.condition に式をそのまま入れ、AI 側が
「アラート条件が解消したか」を計算できるようにする(Jev の recovering 再定義)。
2026-10-09 08:33:22 +09:00
seon
bfd5a710f7
chore(harness): image 8836b37 (alerts_ok ignores layer-1 signature alerts)
2026-10-08 21:33:17 +09:00
seon
3f686c1aea
fix(alerting): ApiLatencyHigh on the 1-minute p95, ApiMemoryPressure for 1m, C-G2 at 225MB
...
第 3 回キャンペーンの実測を反映する。V-G1 では ILB が 1 分以内に api の接続を
遅いインスタンスから逃がすため 5 分窓の p95 が 0.5 秒を越えず、ApiLatencyHigh が
発火しなかった(1 分窓の p95 は 3 分半 2.3 秒)。式を 1 分窓にし 2 分継続に変える。
C-G2 は 200MB で working set が limit の 0.797〜0.803 を行き来して閾値 0.8 を
保てなかったため 225MB にし、ApiMemoryPressure の継続を 1 分にする。
2026-10-08 21:27:24 +09:00
seon
a4f4b3a53a
chore(harness): bump image to cd8fbdd (alerts_ok in the judge, legacy:busy)
...
judge の alerts_ok 条件と legacy:busy 解決を含む harness イメージへ更新する。
2026-10-08 19:25:52 +09:00
seon
e64e24bdb1
feat(ai-env): switch the Jev review gate to enforce
...
shadow での 2 回のキャンペーンで review ゲートが LLM と食い違う判定を出さなかった
ことを確認したうえで、JEV_MODE を enforce にする。best_action が確信度 0.9 以上で
提案と異なる場合と target_valid が 0.5 未満の場合に、提案を escalate に格下げする。
2026-10-08 19:22:06 +09:00
seon
1e0e17b33c
fix(alerting): evaluate the replay-paused branch of DbReplicationLag, add ApiMemoryPressure; retarget grey-zone scenarios
...
DbReplicationLag の式は PromQL の or が左辺のサンプル(常に 0)を残すため
pg_is_wal_replay_paused の分岐が評価されず、第 1・2 回とも発火しなかった。2 つの
bool を加算して clamp する式に直す。api コンテナのメモリが limit の 80% を超えて
2 分続いたときの ApiMemoryPressure(第 2 層)を追加する。C-G2 の StressChaos は
size "80%"(ノード基準)で即 OOM になっていたため 200MB に、V-G1 の対象は
トラフィックを受けているインスタンス legacy:busy に変更する。slo.md に新ルールを追記。
2026-10-08 19:20:50 +09:00
seon
b2e10cf300
chore: bump harness and ai images to 13797e5 (1-minute p95 in the judge, Jev triage state v2, enforce mode)
...
ハーネスは復旧判定に 1 分窓の p95 を加えた版、ai-agent は Jev triage の state を
作り直し JEV_MODE=enforce を実装した版へ更新する。JEV_MODE は shadow のまま。
2026-10-08 17:53:08 +09:00
seon
bbb2817854
chore(ai-env): bump ai images to 91cdd9a (Jev shadow gates)
...
Jev shadow ゲートを含む ai-agent / ai-hitl のイメージへ更新する。
2026-10-08 15:18:08 +09:00
seon
d050c6d54b
feat(ai-env): wire the TypeSafe key and enable Jev shadow gates
...
AI VM の apply.sh が Secret Manager の selfheal-typesafe-api-key を取得し、
agent コンテナに JEV_KEY_FILE として渡す。ai.env で JEV_MODE=shadow、
JEV_MODEL=jev-1.13.0 を設定し、鍵が未登録でも agent は通常どおり動く
(ゲートは鍵未登録を記録するだけ)。
2026-10-08 15:10:25 +09:00
seon
73ac63f989
chore(ai-env): bump ai images to af1cb4f (hitl i18n)
...
Discord の文言を HITL_LANG で切り替えられる ai-agent / ai-hitl のイメージへ更新する。
2026-10-08 14:41:07 +09:00
seon
364654bb2c
feat(ai-env): write runbooks and prompt context in Japanese, set HITL_LANG=ja
...
ランブック 11 本と prompts/topology.md・slo.md を日本語で書き直し、
system.md に「根拠と判断理由は日本語で書く」指示を追加した。
Discord ボットの文言も HITL_LANG=ja で日本語になる。
識別子(action id、ラベル、メトリクス名、オブジェクト名)は英語のまま。
2026-10-08 14:34:10 +09:00
seon
027e896f30
chore(ai-env): gpt-6.1-sol for the comparison run (C-G1, C-I1, V-I1)
...
luna 캠페인에서 2층 진단이 발생한 3건을 sol로 재실행해 라벨·조치·비용·소요를 비교한다(설계서 11.1).
2026-10-08 14:00:30 +09:00
seon
d3c7f32a20
chore(ai-env): image 8b403c5
...
usage 누적 기록 수정이 든 이미지로 올린다.
2026-10-08 11:00:25 +09:00
seon
4886c97f9e
chore(ai-env): run the first live checks on gpt-6-luna
...
잔고 한도(약 $8) 안에서 WP-12 라이브 판정과 캠페인 1회차를 돌리기 위해 기본 모델을
gpt-6-luna(입력 $0.10/출력 $0.50 per 1M, 공식 가격 페이지 2026-10-08)로 둔다.
정확도 비교가 필요한 시나리오는 뒤에 gpt-6.1-sol로 재실행한다(설계서 11.1).
2026-10-08 10:33:41 +09:00
seon
11a60796a5
chore(ai-env): image 9bc3a3b
...
hitl_messages diagnosis 컬럼 멱등 ALTER가 든 이미지로 올린다.
2026-10-08 02:42:13 +09:00
seon
f7289be972
fix(alloy): keep the cadvisor up series
...
cadvisor_keep의 두 번째 keep 규칙이 namespace 없는 up을 떨어뜨려 스크랩 성공 여부를 볼 수 없었다.
up은 통과시키고 container_* 만 네임스페이스로 거른다.
2026-10-08 02:12:41 +09:00
seon
aa99da8a81
fix(alloy): scrape cadvisor from the kubelet port instead of the API server proxy
...
Alloy Helm 차트의 ClusterRole에는 nodes/metrics는 있지만 nodes/proxy가 없어(실측 2026-10-08)
/api/v1/nodes/<n>/proxy/metrics/cadvisor 경로가 거부되고 container_* 지표가 비었다. kubelet
10250을 직접 스크랩한다(자체 서명 인증서라 insecure_skip_verify). up도 남겨 스크랩 성공 여부를
볼 수 있게 하고, container_* 는 demo·ingress-nginx·argocd 네임스페이스만 유지한다.
2026-10-08 02:03:56 +09:00
seon
bc8a8fbc97
fix(postgres): compute replication lag without the idle-primary artifact
...
upstream replication 컬렉터는 수신 LSN != 재생 LSN이면 now()-마지막 트랜잭션 재생 시각을 지연으로
보고한다. replica 재시작 직후에는 수신 LSN이 세그먼트 시작점(재생 LSN보다 작음)에 머물러 유휴
프라이머리에서 지연이 무한히 커진다(실측 116초→281초, 트랜잭션 1건 뒤 0). DbReplicationLag가
pending으로 올라갔다. 수신 LSN <= 재생 LSN이면 0으로 보는 custom query로 교체하고 upstream
replication 컬렉터를 끈다. pg_replication_is_replica도 같은 쿼리에서 낸다.
2026-10-08 02:01:56 +09:00
seon
4f3188b491
fix: short host name for the instance label; AI VM images 683a2de
...
GCE의 hostname은 FQDN이라 Mimir의 instance 라벨이 legacy-2n1c.asia-northeast1-b.c....internal로
들어왔다(실측). hostname -s로 VM 이름만 쓴다. vm/ai-env/image.tag를 683a2de(hitl 진단 보존 수정)로.
2026-10-08 01:57:04 +09:00
seon
a500c3d40c
fix: Alloy block syntax, dpkg lock wait, hitl local bind, ai-reader nodes RBAC, harness image f30af2a
...
- Alloy 설정 3종: rule 블록을 한 줄 쉼표 나열에서 줄바꿈 속성으로 수정(실측: k8s DaemonSet
CrashLoopBackOff, db-replica alloy.service "expected TERMINATOR, got ,"). alloy fmt로 3종 파싱 확인.
- vm/postgres-common/alloy.sh: apt에 DPkg::Lock::Timeout=600(db-primary에서 unattended-upgrades 잠금으로 100 종료).
- vm/ai-env/compose.yaml: hitl 8081을 127.0.0.1에만 바인딩(agent는 compose 네트워크로 접근).
- workloads/rbac/ai-reader.yaml: nodes get/list/watch ClusterRole 추가(agent get_k8s(nodes) selfcheck 거부 해소).
- vm/harness/image.tag: f30af2a(POST /proposals/{token}/approve·reject 포함 러너).
2026-10-08 01:53:06 +09:00
seon
7ce2dc68fe
feat: AI VM stack (WP-12) and Alloy telemetry on k8s, legacy and DB VMs (WP-15)
...
WP-12(실험 설계서 6장) vm/ai-env: apply.sh(시크릿 4종을 Secret Manager에서 파일로, 미등록이면
성능 저하 모드로 기동), compose(agent 8080·hitl 8081·rag-db pgvector 0.8.7-pg16), ai.env(Discord
서버 Selfheal Lab 1557424985793101824, approvals 1557425140302872698, escalation 1557425282363691048,
OPENAI_MODEL gpt-6.1-sol 후보), 프롬프트 3종, 러너북 11종(조치별·토폴로지·3층 절차).
WP-15(실험 설계서 4.1·4.3): apps/alloy.yaml(Alloy Helm 1.13.0 DaemonSet, 클러스터링으로 KSM·Argo CD·
cadvisor 스크랩 분산, demo 등 파드 로그 → Loki), apps/kube-state-metrics.yaml(Helm 8.6.0).
legacy-api compose에 Alloy 사이드카(up{job="legacy-api"}, 컨테이너 로그). DB VM은
vm/postgres-common/alloy.sh로 apt 설치 + prometheus.exporter.postgres(pg_replication_lag_seconds)
+ custom query pg_is_wal_replay_paused + PostgreSQL 로그.
vm/harness/apply.sh: 준비 대기 루프의 curl에 || true(러너 재기동 순간 curl 56으로 중단되던 문제,
2026-10-08 harness-sync 실측).
2026-10-08 01:47:38 +09:00
seon
59995f3601
fix(harness): the legacy MIG is named selfheal-legacy-mig (mig.recreate_instance / mig.resize targets)
2026-09-24 02:55:36 +09:00
seon
b5119054be
fix(observability): LegacyUnhealthy must not fire while up{job=legacy-api} is absent (WP-15 supplies it)
2026-09-24 02:30:00 +09:00
seon
af37d19e2a
feat: harness VM stack (runner, measure-db, blackbox, Alloy, k6) and the 12 scenarios
...
Experiment design 5 and 7 for the harness VM (10.20.0.11): vm/harness/apply.sh pulls the secrets from Secret Manager,
compose runs runner:de076a7, measure-db, blackbox, Alloy (probe_success -> Mimir) and k6 under the campaign profile.
Scenario files C-K1..X-M2 are loaded by the runner. Harness ClusterRole gains replicasets get/list for rollout undo.
2026-09-24 02:27:41 +09:00
seon
de52d4a1ec
fix: run ingress-nginx admission jobs as Argo CD sync hooks; fix front links
...
- ingress-nginx admission Job 2개는 ttlSecondsAfterFinished: 0으로 완료 즉시 사라져
Argo CD가 영구 OutOfSync로 보고 selfHeal 때마다 다시 실행했다(2026-09-24 실측).
Sync 훅(HookSucceeded 삭제)으로 돌린다.
- front 정적 페이지의 /api/readyz 링크(404)를 제거한다(api의 /readyz는 /api 아래가 아님).
2026-09-24 01:46:17 +09:00
seon
8f41b3567b
fix(observability): recreate Grafana on apply so provisioning changes load
...
Grafana는 프로비저닝 파일을 기동 시에만 읽으므로 apply.sh가 grafana만 재생성한다
(상태는 볼륨에 유지).
2026-09-24 01:44:42 +09:00
seon
1db68b643f
feat: add ingress-nginx, demo-app, Chaos Mesh apps and Grafana alert rules
...
WP-14(Terraform 설계서 7.3, 실험·앱 설계서 3.1·4.3).
- apps/ingress-nginx: baremetal 매니페스트(controller-v1.15.1)를 kustomize로 가져와
NodePort 30080/30443 고정(ALB TG와 일치).
- apps/demo-app + workloads/demo-app: front(nginx-unprivileged 1.31.6, 정적 페이지 +
/api/ 프록시) 2, api(demo-api:8f5378b) 3 + PDB minAvailable 2, Service, Ingress(/ front,
/api api). DB_DSN은 Secret demo-db(make k8s-secrets로 생성, git 밖).
- apps/chaos-mesh: Helm chart 2.8.4(containerd 소켓, dashboard 없음).
- vm/observability/grafana/provisioning/alerting: contact point harness-webhook
(10.20.0.11:8080/hooks/alert), 루트 정책, 규칙 8건(ProbeDown·ApiLatencyHigh·
ApiErrorRateHigh·PodCrashLooping·LegacyUnhealthy·DbReplicationLag·DbPrimaryDown·
GitOpsDrift, 라벨 layer/signature).
2026-09-24 01:35:45 +09:00
seon
907056f4f6
fix(observability): drop unsupported compactor block from tempo.yaml
...
Tempo 3.0.3이 "field compactor not found in type app.Config"로 기동을 거부했다
(2026-09-24 실측). 보존 기간은 기본값으로 둔다.
2026-09-24 01:20:03 +09:00
seon
d2c7ddf242
feat: add LGTM compose for the observability VM
...
WP-10(Terraform 설계서 6.10, 실험·앱 설계서 4.1). Mimir 3.2.1(monolithic, GCS
prefix blocks/ruler/alertmanager), Loki 3.7.8(tsdb v13, GCS), Tempo 3.0.3(OTLP
4317/4318, GCS), Grafana 13.2.2(데이터소스 Mimir·Loki·Tempo 프로비저닝). 오브젝트
스토리지는 VM SA의 ADC로 인증(키 파일 없음). Grafana 관리자 비밀번호는 Secret Manager
selfheal-grafana-admin에서 실행 시 취득. 알림 규칙 8건은 WP-14에서 추가.
2026-09-24 01:18:33 +09:00
seon
1128adc1be
fix: pass the env file to compose ps as well
...
두 번째 compose 호출에 --env-file이 없어 "DB_DSN variable is not set" 경고가 났다(동작 무관).
2026-09-24 00:44:22 +09:00
seon
bd74aead51
feat: add PostgreSQL primary/replica apply scripts for the DB VMs
...
WP-09(Terraform 설계서 6.10, 실험·앱 설계서 3.3).
- postgres-primary: PostgreSQL 16, conf.d 오버라이드(listen *, ssl on, scram, wal_level
replica, slot 10, wal_keep_size 256MB), pg_hba는 hostssl+scram만(app: AWS·GCP 대역,
harness: GCP 대역, replicator: 10.20.0.21). 역할 app/replicator/harness(비밀번호는
Secret Manager selfheal-db-password), DB app + 스키마 app.price·app.orders + 시드.
harness에 pg_wal_replay_pause/resume·pg_promote EXECUTE와 pg_read_all_stats 부여
(카탈로그 db.replay_resume·db.promote).
- postgres-replica: 첫 실행에 pg_basebackup -R -C -S replica1(TLS 필수)로 standby 구성,
이후 실행은 재시작만.
2026-09-24 00:39:13 +09:00
seon
31334fac72
fix: write the join command before Argo CD and do not block on its rollout
...
CP는 NoSchedule taint를 유지하므로 워커가 join하기 전에는 Argo CD 파드가 Pending이다.
롤아웃 대기를 빼고 join 명령 저장을 앞으로 옮긴다.
2026-09-24 00:09:56 +09:00
seon
8ddf12c588
feat: add kubeadm bootstrap, Argo CD root app and lab RBAC
...
Terraform 설계서 7.2·7.3의 WP-07 내용.
- bootstrap/kubeadm/init-cp.sh: kubeadm init(사설 IP advertise, EIP cert SAN,
pod CIDR 10.244.0.0/16) → flannel v0.28.9 → Argo CD v3.5.3(server-side apply)
→ root-app 적용 → 워커 join 명령을 /opt/selfheal/join.sh(0600)에 저장. 재실행 안전.
- bootstrap/kubeadm/join-worker.sh: join 명령을 stdin으로 받아 실행(토큰이 터미널·로그에
남지 않음). 이미 join된 노드는 0으로 종료.
- argocd/root-app.yaml: apps/ 재귀 app-of-apps(공개 저장소, 자격증명 불요).
- apps/rbac.yaml + workloads/rbac: 네임스페이스 chaos-mesh·demo, SA harness(ClusterRole
selfheal-harness: chaos-mesh.org/*, deployments·scale, pods, nodes patch, pods/eviction),
SA ai-reader(ClusterRole view).
2026-09-24 00:09:24 +09:00
seon
390a903dbb
fix: require TLS for the legacy-api DB connection
...
보안 리뷰 재지적(prefer는 평문 허용). DB 서버는 WP-09에서 TLS를 켠 상태로
구축하므로 처음부터 sslmode=require로 둔다(서버 인증서 검증은 WP-09에서 확정).
2026-09-24 00:05:54 +09:00
seon
de771a5f1f
fix: prefer TLS for the legacy-api DB connection
...
보안 리뷰 지적(sslmode=disable). 사설 서브넷 안의 통신이지만 서버가 TLS를
제공하면 사용하도록 sslmode=prefer로 바꾼다(pgx 지원). 서버 인증서를 갖추는
WP-09에서 require로 올린다.
2026-09-24 00:02:00 +09:00
seon
b101e92584
feat: add legacy-api compose and apply script for MIG instances
...
MIG 인스턴스 startup script가 실행하는 vm/legacy-api/apply.sh를 추가한다.
VM SA의 메타데이터 토큰으로 Secret Manager(selfheal-db-password)에서 DB 비밀번호를
받아 env 파일(0600)에 DSN을 쓰고, 고정 태그 이미지(legacy-api:7186ef0)로 compose up.
Alloy는 WP-15에서 추가한다.
2026-09-23 23:48:04 +09:00
seon
2fc6305e1b
chore: scaffold gitops repository layout
...
Terraform 설계서 2장의 디렉터리 구조대로 뼈대만 만든다. 각 디렉터리의 내용은
해당 WP(07·08~12·14·15)에서 채운다. VM 디렉터리 이름은 Terraform이 VM
메타데이터로 넘기는 role 값(postgres-primary/-replica 포함)과 일치시킨다.
저장소는 공개이며 시크릿은 두지 않는다(값은 Secret Manager).
2026-09-23 20:38:25 +09:00