k8s-mechanic
이름 변경: 이 프로젝트는 이전에는 k8s-mendabot으로 알려져 있었습니다. 이제 k8s-mechanic으로 이름이 변경되었습니다. CRD API 그룹은 remediation.mendabot.io에서 remediation.mechanic.io로 변경되었습니다. 기존 설치 환경은 마이그레이션이 필요합니다.
k8s-mechanic은 클러스터의 실패를 감지하고, 이를 자동으로 조사하며, 제안된 수정 사항을 포함하여 GitOps 저장소에 풀 리퀘스트(pull requests)를 여는 Kubernetes 컨트롤러입니다. 이 모든 과정이 클러스터를 벗어나지 않고 이루어집니다.
Pod가 crash-looping 상태이거나, Deployment가 degraded 상태이거나, Node가 NotReady 상태가 될 때, mechanic은 인클러스터 OpenCode 에이전트를 생성하여 실시간 클러스터를 검사하고, GitOps 저장소에서 관련 매니페스트를 찾으며, 근본 원인을 파악한 후 PR을 엽니다. 사용자가 이를 검토하고 병합합니다. 외부 오퍼레이터나 외부 데이터베이스, 또는 클러스터 외부에 영구적인 서비스는 없습니다.
기능 설명 (What it does)
- 실패 감지 — Kubernetes API를 통해 Pod, Deployment, StatefulSet, PVC, Node, Job을 네이티브하게 모니터링합니다.
- 부모 기준으로 중복 제거 — 동일한 Deployment에서 반복되는 Pod 재시작은 개별 재시작마다 조사하는 것이 아니라 하나의 조사로 처리됩니다.
- 조치 전 안정화 — 설정 가능한 시간 창(기본값: 120초)이 일시적인 오류를 필터링한 후에 조사를 시작합니다.
- 인클러스터 조사 — 읽기 전용 RBAC을 가진 에이전트 Job이 실행되어 GitOps 저장소를 클론하고 실시간 클러스터를 검사합니다.
- PR 열기 — 요약, 증거(evidence), 근본 원인, 제안된 수정 사항, 신뢰도 수준 등의 구조화된 본문과 함께 PR을 엽니다.
호출당 가능한 세 가지 결과:
| 결과 | 언제 | 조치 |
|---|
| Fix PR | 근본 원인 식별됨, 신뢰도 보통 또는 높음 | 목표 매니페스트 변경 사항이 포함된 PR을 엽니다. |
| ... | | |
에이전트 프롬프트에는 다음과 같은 엄격한 제약 조건이 적용됩니다: main 브랜치에 직접 커밋하지 않기; GitOps 저장소의 Kubernetes Secret은 건드리지 않기; 호출당 정확히 하나의 결과만 도출하기.
기능 (Features)
OpenCode 에이전트 워크플로우 — 조사는 클러스터 내부에서 실행되는 OpenCode에 의해 구동됩니다. 모든 OpenAI와 호환 가능한 LLM 엔드포인트와 작동합니다. 추가 에이전트 백엔드가 계획 중입니다.
감지(Detection) — Pods, Deployments, StatefulSets, PVCs, Nodes, Jobs를 네이티브하게 감시합니다. CrashLoopBackOff, ImagePullBackOff, OOMKilled 상태, 성능 저하된 Deployment, 스케줄링 불가능한 Pods, 실패한 Jobs, PVC 프로비저닝 실패, 그리고 비정상적인 노드(Nodes)를 다룹니다.
중복 제거(Deduplication) — 발견된 사항은 부모 리소스 지문(sha256(namespace + kind + parentObject + sorted errors))을 통해 중복 제거됩니다. 동일한 Deployment에서 반복되는 Pod 재시작은 하나의 조사만 생성합니다. 상태는 RemediationJob CRD 객체에 저장되어 감시자(watcher) 재시작에도 유지되며 외부 저장소가 필요하지 않습니다.
심각도 계층(Severity tiers) — 모든 발견 사항은 감지된 조건에 따라 critical, high, medium, 또는 low로 분류됩니다 (예: CrashLoopBackOff 5회 초과 재시작 → critical; OOMKilled → high; 성능 저하되었으나 사용 가능한 Deployment → medium). 감시자(watcher) Deployment의 MIN_SEVERITY 환경 변수는 설정된 임계값보다 낮은 발견 사항을 억제합니다. 에이전트는 런타임에 심각도를 받아 그에 맞춰 조사 깊이를 조정하며, critical 상황에서는 최대의 철저함을, low 상황에서는 보수적인 최소 변경 제안을 합니다.
안정화 기간(Stabilisation window) — 구성 가능한 대기 기간(기본값: 120초)을 통해 조사가 전송되기 전에 일시적인 변동 사항(transient blips)이 억제됩니다.
동시성 제한(Concurrency throttling) — maxConcurrentJobs (기본값: 3)가 동시에 실행되는 에이전트 Job의 수를 제한합니다. 초과된 발견 사항(findings)은 Pending 상태로 대기열에 추가되며, 슬롯이 사용 가능해지면 배포됩니다.
사용자 지정 가능한 에이전트 프롬프트(Customisable agent prompt) — 조사용 프롬프트는 ConfigMap에서 마운트되며, values.yaml 내의 prompt.coreOverride / prompt.agentOverride를 통해 완전히 재정의할 수 있습니다.
Prometheus 메트릭(Prometheus metrics) — 감시자(watcher)의 상태 관찰 가능성(observability)을 위한 선택적 메트릭 서비스와 Prometheus Operator ServiceMonitor를 제공합니다.
해결된 발견 사항 자동 닫기(Auto-close resolved findings) — Kubernetes에서 발견 사항이 해소될 때 (Deployment 복구, PVC 프로비저닝, Node가 Ready 상태로 돌아올 때), 감시자는 에이전트가 열었던 GitHub PR을 자동으로 닫습니다. 이는 진행 중인 작업(in-flight jobs) (Pending/Dispatched/Running)과 클러스터가 자체적으로 복구된 후 PR이 오래된(stale) 작업을 모두 처리합니다. REST API를 통해 GitHub App 설치 토큰을 직접 사용하므로, 감시자 내에서 gh CLI가 필요하지 않습니다. watcher.prAutoClose: false로 비활성화할 수 있습니다.
PR 병합 인식 중복 제거(PR-merge-aware deduplication) — mechanic에 의해 열린 PR이 병합되면, RemediationJob은 기본 7일 TTL 대신 짧은 TTL (1시간)로 무효화(tombstoned)됩니다. 이는 GitOps reconciler가 수정 사항을 적용하고 클러스터가 안정화되는 동안 동일한 발견 사항이 병합 직후 재조사되는 것을 방지합니다.
드라이 런 모드(Dry-run mode) — watcher.dryRun: true를 설정하여 PR을 열지 않고 전체 조사 파이프라인을 실행할 수 있습니다. 대신 에이전트는 mechanic-dryrun-<fingerprint> ConfigMap에 기록된 조사 보고서를 생성합니다. 이는 스테이징 환경에서 mechanic의 동작을 검증하거나, 프로덕션에서 활성화하기 전에 새로운 LLM 모델을 검증하는 데 유용합니다.
GitHub App 토큰 만료 방지 — 메인 에이전트 컨테이너는 작업을 진행하기 전에 설치 토큰의 만료 여부를 확인합니다. 토큰이 만료되었거나 만료까지 60초 이내일 경우, 조사 과정 깊은 곳에서 조용히 실패하는 대신 명확한 오류와 함께 빠르게 실패(fails fast)합니다.
필수 매니페스트 검증 — GitOps 레포에 변경 사항을 커밋하기 전에 에이전트는 수정된 모든 매니페스트에 대해 kubeconform (오버레이 변경의 경우 kustomize build)를 실행합니다. 검증에 실패하면, 스키마가 유효하지 않은 매니페스트를 커밋하는 대신 전체 오류 출력을 포함한 validation-failed 레이블의 플레이스홀더 PR을 엽니다.
보안 (Security)
비밀 정보 마스킹(Secret redaction) — 클러스터 상태에서 추출된 오류 텍스트(파드 Waiting.Message, 노드 조건 메시지 등)는 RemediationJob에 저장되거나 에이전트에 주입되기 전에 마스킹 필터를 거칩니다. 패턴에는 URL 자격 증명, base64로 인코딩된 값 (≥ 40자), 그리고 일반적인 비밀 키 접두사(password=, token=, api-key= 등)가 포함됩니다.
프롬프트 주입 탐지(Prompt injection detection) — Finding.Errors는 필드당 500자로 제한되며 프롬프트 내에서 명시적인 신뢰할 수 없는 데이터(untrusted-data) 엔벨로프로 감싸집니다. 주입 휴리스틱(ignore.*previous.*instructions)이 탐지 및 기록되며, 해당 발견을 완전히 억제하도록 구성 가능합니다 (INJECTION_DETECTION_ACTION=suppress).
에이전트 네트워크 정책(Agent network policy) — 선택적 NetworkPolicy는 에이전트 Job의 외부 통신(egress)을 클러스터 API 서버, GitHub, 그리고 LLM 엔드포인트로 제한합니다. 이는 values.yaml에서 networkPolicy.enabled: true를 통해 활성화됩니다. NetworkPolicy를 강제하는 CNI(Cilium, Calico 등)가 필요합니다.
읽기 전용 에이전트 RBAC — 해당 에이전트는 클러스터 전체 범위에서 get/list/watch 동사(verbs)만 보유합니다.
어떤 Kubernetes 리소스도 생성, 수정 또는 삭제할 수 없습니다. 모든 클러스터 변경 사항은 Git을 통해 이루어지며, 사용자의 GitOps 재조정기(reconciler)를 거칩니다.
네임스페이스 범위 에이전트 RBAC — AGENT_RBAC_SCOPE=namespace를 사용하면 에이전트가 클러스터 전체 범위의 ClusterRole에서 네임스페이스 범위의 Role로 전환되며, 에이전트가 읽을 수 있는 범위를 지정된 네임스페이스로 제한합니다.
구조화된 감사 로그 — 모든 억제 및 디스패치 결정은 audit: true를 포함하는 구조화된 로그 라인을 방출하며, 사후 사고 포렌식(post-incident forensics)을 위해 모든 로그 집계 시스템(Loki, Elasticsearch, Datadog)에서 검색할 수 있습니다.
Trivy CVE 스캐닝 — mechanic-watcher와 mechanic-agent 이미지는 모든 릴리스 시 Trivy를 사용하여 스캔됩니다 (CRITICAL 및 HIGH, 수정 불가 무시(ignore-unfixed)). 수정 가능한 취약점이 감지되면 빌드가 실패합니다. 상위 버전의 사전 구축된 바이너리(아직 필요한 Go 버전을 사용해 출시되지 않은 도구)에 있는 수정 불가능한 CVE는 .trivyignore에 추적되며 재평가를 위한 필수 만료일이 지정됩니다.
단기 GitHub 자격 증명 — 에이전트는 장기간 유효한 PAT(Personal Access Token)를 절대 보유하지 않습니다. GitHub App 설치 토큰(1시간 TTL)은 초기화 컨테이너(init container)에서 교환되며 메인 에이전트 컨테이너에 노출되지 않습니다.
강화 모드 (Hardened mode)
강화 모드(values.yaml의 agent.hardenKubectl: true, 기본값 비활성화)는 아래 항상 활성화되는 기본 설정 위에 추가적인 읽기 제한을 추가합니다.
항상 활성화됨 (강화 모드와 무관)
| 제어 기능 | 작동 방식 |
|---|
| kubectl write 차단 | apply, create, delete, edit, patch, replace, scale, label, annotate, taint, drain, cordon, uncordon, rollout restart/undo — 모두 종료 코드 1을 반환합니다. 모든 클러스터 변경 사항은 Git을 거쳐 사용자의 GitOps 재조정기(reconciler)를 통해 이루어져야 합니다. |
| ... | |
| 강화 모드 전용 (Hardened mode only) | |
| 제어 기능 | 추가되는 보안 조치 |
|---|
| kubectl secret 차단 | get secret(s), describe secret(s), 그리고 get all이 차단됩니다. Kubernetes Secret은 kubectl을 통해 LLM 컨텍스트에 절대 도달할 수 없습니다. |
| kubectl exec / port-forward 차단 | exec와 port-forward가 차단됩니다. 에이전트는 클러스터 워크로드로의 대화형 세션 열기나 포트 전달(forward)을 할 수 없습니다. |
정보 유출 테스트 (Exfiltration testing)
보안 제어 기능은 정기적인 적대적 팀(red-team) 실행에서 검증됩니다. 결과와 전체 정보 유출 누수 레지스트리(exfiltration leak registry)는 다음 위치에 있습니다:
docs/SECURITY/EXFIL_LEAK_REGISTRY.md.
빠른 시작 (Quick Start)
필수 조건 (Prerequisites)
- Kubernetes >= 1.28
- Helm >= 3.14
- GitOps 저장소에 설치된 GitHub App: Contents(쓰기), Pull Requests(쓰기), Issues(쓰기) 권한 필요
- OpenAI와 호환되는 LLM API 키
GitHub App 권한
| 권한 | 레벨 | 목적 |
|---|
| Contents | 쓰기 | 저장소 클론, 브랜치 생성, 변경 사항 푸시 |
| ... | | |
1. 필요한 Secret 생성
kubectl create namespace mechanic
github-app
github-app Secret에는 세 가지 키가 포함되어야 합니다:
apiVersion: v1
kind: Secret
metadata:
...
App ID는 GitHub App의 설정 페이지(https://github.com/settings/apps/<your-app-name>)에서 확인할 수 있습니다. 각 사용자가 자신의 GitHub App을 생성하며, 프로젝트 작성자는 귀하의 자격 증명(credentials), 토큰 또는 저장소에 대한 가시성을 갖지 못합니다.
설치 ID(Installation ID)는 앱의 설치를 볼 때 URL에 포함된 숫자 접미사입니다:
https://github.com/organizations/<org>/settings/installations/<id>
(개인 계정의 경우: https://github.com/settings/installations/<id>).
이 ID는 또한 App JWT로 인증된 GET https://api.github.com/app/installations 요청을 통해서도 반환됩니다.
프라이빗 키(private key)는 단지 에이전트 Job의 init 컨테이너에서만 사용되며, 단기 설치 토큰(1시간 TTL) 교환에 이용됩니다. 이는 메인 에이전트 컨테이너 내부로 주입되는 일은 절대 없습니다.
llm-credentials-opencode
llm-credentials-opencode 시크릿에는 전체 OpenCode config가 provider-config 키 값으로 저장됩니다. 올바른 스키마는 model을 최상위 레벨(top-level) 키로 가져야 하며 (형식: "<provider-id>/<model-id>"); options는 루트에 속하는 것이 아니라 provider.<name> 내부에 위치해야 합니다.
Opencode가 현재 사용 가능한 유일한 에이전트형 제공자(agentic provider)이며, 더 많은 옵션은 추후 추가될 예정입니다.
네이티브 OpenAI (api.openai.com)
apiVersion: v1
kind: Secret
metadata:
...
커스텀 OpenAI 호환 엔드포인트 (셀프 호스팅, Ollama, Azure 등)
api.openai.com이 아니거나 내장된 OpenAI 제공자에서 등록되지 않은 모델 이름을 사용하는 모든 엔드포인트의 경우, `