Files
obsidian/infra/security/external-secrets.md

107 lines
3.7 KiB
Markdown

---
title: External Secrets Operator (ESO)
updated: 2026-04-13
tags: [infra, k3s, vault, eso, secrets]
---
## 개요
HashiCorp Vault의 시크릿을 K8s Secret으로 자동 동기화. Vault가 단일 진실 소스(Single Source of Truth).
## 구성 요소
| 항목 | 값 |
|------|-----|
| 설치 방식 | Helm (external-secrets/external-secrets) |
| 네임스페이스 | external-secrets |
| 버전 | v2.3.0 |
| ClusterSecretStore | `vault` |
| Vault 주소 | `http://10.253.101.58:8200` (K3s 내부 직접 접근) |
| Vault 인증 | Token (Secret `vault-token` in external-secrets ns) |
| KV 엔진 | v2 |
| refresh 주기 | 1시간 |
### Vault 접근 경로
ESO는 K3s Pod에서 Vault에 접근해야 하므로 CDN URL(`hcv.inouter.com`)이 아닌 **내부 IP 직접 접근** 사용.
- Vault 위치: incus-jp1 `vault` 컨테이너 (10.253.101.58)
- `hcv.inouter.com`은 BunnyCDN을 거치며 API 경로가 404 반환 → ESO 사용 불가
## ExternalSecret 목록
| ExternalSecret | 네임스페이스 | K8s Secret 이름 | Vault 경로 | 키 매핑 |
|---|---|---|---|---|
| smtp-relay-mailgun | mail | smtp-relay-mailgun | `messaging/mailgun/smtp` | username, password |
| bunnycdn-secrets | mcp | bunnycdn-secrets | `cloud/bunnycdn` | api_key → api-key |
| outline-secrets | outline | outline-secrets | `apps/outline` | dataFrom extract (전체 키) |
| openmemory-secrets | openmemory | openmemory-secrets | `ai/openai` | API_KEY → OPENAI_API_KEY |
| cfb-ssh-key | tools | cfb-ssh-key | `apps/cfb-manager` | ssh_key → id_rsa |
| namecheap-api-env | tools | namecheap-api-env | `domain/namecheap` | API_KEY, API_USER, CLIENT_IP, USERNAME, SANDBOX |
## ESO로 관리하지 않는 Secret
| Secret | 네임스페이스 | 이유 |
|--------|-------------|------|
| searxng-ca-bundle | searxng | 270KB CA 인증서, Vault 부적합. ArgoCD prune 제외 어노테이션 적용 |
| searxng-config | searxng | Helm 차트 values에서 생성 |
## Vault 시크릿 경로 정리
```
secret/
├── ai/
│ └── openai # OPENAI_API_KEY (openmemory 등)
├── apps/
│ ├── outline # DB URL, OIDC, SECRET_KEY 등 11개 키
│ ├── cfb-manager # ssh_key
│ ├── portainer # api_token, google_client_id/secret
│ └── gitea # api_token 등
├── cloud/
│ └── bunnycdn # api_key
├── domain/
│ └── namecheap # API_KEY, API_USER, CLIENT_IP, USERNAME, SANDBOX
├── messaging/
│ └── mailgun/smtp # username, password, host, port 등
└── infra/
└── ... # SSH 키, Tailscale 등
```
## 운영 가이드
### 새 시크릿 추가 절차
1. Vault에 시크릿 저장: `vault kv put -mount=secret <path> key=value`
2. ExternalSecret 매니페스트 작성 및 적용
3. `kubectl get externalsecret -A` 로 SecretSynced 확인
4. Pod에서 참조 확인
### Vault 토큰 갱신
ESO가 사용하는 토큰은 `external-secrets/vault-token` Secret에 저장.
토큰 만료 시:
```
vault token create -policy=default -ttl=768h
kubectl -n external-secrets create secret generic vault-token --from-literal=token=<new-token> --dry-run=client -o yaml | kubectl apply -f -
```
### 트러블슈팅
```bash
# ExternalSecret 상태 확인
kubectl get externalsecret -A
# 상세 에러 확인
kubectl get externalsecret <name> -n <ns> -o jsonpath='{.status.conditions}'
# 강제 재동기화
kubectl annotate externalsecret <name> -n <ns> force-sync=$(date +%s) --overwrite
# ClusterSecretStore 상태
kubectl get clustersecretstore vault
```
## 관련 문서
- [[helm-charts]] — Helm 차트 관리 체계
- [[k3s-ingress-architecture]] — 인그레스 구조