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