[G1-Sync] Manual knowledge update

This commit is contained in:
Antigravity Agent
2026-05-10 22:08:15 +09:00
parent 21ac3ed255
commit 504fd5fb42
3011 changed files with 380280 additions and 206977 deletions
@@ -0,0 +1,395 @@
---
id: devops-external-secrets-atlantis
title: External Secrets / Atlantis / GitHub Actions deep
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [devops, secrets, gitops, vibe-coding]
tech_stack: { language: "YAML", applicable_to: ["DevOps"] }
applied_in: []
aliases: [external secrets operator, Atlantis, Terraform PR, GitHub Actions, OIDC, reusable workflow]
---
# External Secrets / Atlantis / GHA
> K8s + Vault + Terraform + CI 의 modern integration. **External Secrets Operator (vault → K8s), Atlantis (Terraform PR), GHA (advanced)**.
## 📖 핵심 개념
- ESO: 외부 secret store → K8s Secret 자동 sync.
- Atlantis: Terraform 의 GitOps.
- GHA OIDC: cloud auth 가 token 없이.
- Reusable workflow / matrix.
## 💻 코드 패턴
### External Secrets Operator
```yaml
# SecretStore (Vault 연결)
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-store
spec:
provider:
vault:
server: https://vault.example.com
path: secret
auth:
kubernetes:
mountPath: kubernetes
role: my-role
```
```yaml
# ExternalSecret (sync)
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
spec:
refreshInterval: 1m
secretStoreRef:
name: vault-store
kind: SecretStore
target:
name: db-secret # → K8s Secret
data:
- secretKey: password
remoteRef:
key: secret/myapp/db
property: password
```
→ App 가 K8s Secret 만 read. Vault 가 source.
### AWS Secrets Manager 도
```yaml
spec:
provider:
aws:
service: SecretsManager
region: us-east-1
auth:
jwt:
serviceAccountRef:
name: external-secrets-sa
```
→ AWS IRSA (IAM Role for SA).
### Auto rotation
```yaml
# AWS Secrets Manager 가 매 30 days rotate
# ESO 가 매 1 min check + sync
# K8s pod 가 secret mount = 자동 update (eventually)
```
### Pod restart
```yaml
# Stakater Reloader 가 secret 변경 시 pod restart
metadata:
annotations:
secret.reloader.stakater.com/reload: 'db-secret'
```
→ Secret 변경 → pod restart → 새 credential.
### Atlantis (Terraform 의 GitOps)
```yaml
# atlantis.yaml
version: 3
projects:
- name: prod-vpc
dir: terraform/prod/vpc
autoplan:
when_modified: ['*.tf', '*.tfvars']
apply_requirements: [approved]
```
### Workflow
```
1. Engineer 가 PR 가 terraform 변경.
2. Atlantis 가 자동 `terraform plan` → PR comment 에 결과.
3. Reviewer 가 plan 검토.
4. Approved → engineer 가 `atlantis apply`.
5. Atlantis 가 `terraform apply`.
6. PR merge.
```
→ "Apply 후 merge" — drift 안.
### Atlantis 의 lock
```
매 project 가 1 PR 만 apply 가능.
- A 가 apply 중 → B 가 wait.
- "Apply" PR comment 가 lock 가져.
- 종료 시 release.
```
→ Concurrent apply 가 conflict 방지.
### terraform plan output
```diff
$ atlantis plan
+ aws_instance.web
ami = "ami-12345"
instance_type = "t3.micro"
- aws_security_group.old
~ aws_db_instance.main
~ instance_class: "db.t3.micro" -> "db.t3.small"
```
→ PR 의 visual plan.
### Atlantis 의 alternative
```
- Spacelift (managed, 더 강력)
- Terraform Cloud / HCP Terraform (HashiCorp)
- env0 (managed)
- Terragrunt + custom CI
```
→ Atlantis 가 OSS + 자체 host.
### GitHub Actions OIDC (cloud auth)
```yaml
# .github/workflows/deploy.yml
permissions:
id-token: write # OIDC token
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789:role/GHA-Deploy
aws-region: us-east-1
- run: aws s3 sync ./build s3://my-bucket
```
→ Long-lived AWS key X. OIDC token 가 short-lived.
→ AWS / GCP / Azure 가 OIDC trust 설정.
### Reusable workflow
```yaml
# .github/workflows/test.yml (reusable)
on:
workflow_call:
inputs:
node-version:
type: string
default: '20'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: ${{ inputs.node-version }} }
- run: npm ci && npm test
```
```yaml
# Caller
jobs:
test:
uses: ./.github/workflows/test.yml
with:
node-version: '22'
```
### Matrix
```yaml
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node: [18, 20, 22]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/setup-node@v4
with: { node-version: ${{ matrix.node }} }
```
→ 9 jobs 가 parallel.
### Conditional matrix
```yaml
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
include:
- os: macos-latest
special: true
exclude:
- os: windows-latest
node: 18
```
### Environment + secrets
```yaml
jobs:
deploy:
environment: production # → manual approval gate
steps:
- run: ./deploy.sh
env:
API_KEY: ${{ secrets.API_KEY }} # environment-scoped
```
→ Prod environment 가 별 secrets + manual approval.
### Composite action
```yaml
# .github/actions/setup/action.yml
name: 'Setup'
runs:
using: 'composite'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20' }
- shell: bash
run: npm ci
```
```yaml
# Use
- uses: ./.github/actions/setup
```
→ Reusable inline.
### Concurrency
```yaml
concurrency:
group: ${{ github.ref }}
cancel-in-progress: true
```
→ 같은 branch 의 새 push = 옛 cancel.
### Cache
```yaml
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
```
→ Build 빠름.
### Dependabot
```yaml
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'weekly'
```
→ Action 도 자동 update.
### Self-hosted runner
```yaml
runs-on: self-hosted
# 자체 server 가 runner.
```
→ Cost ↓ (큰 traffic). Setup overhead.
### Action security
```
- Pin to SHA (version 가 mutable).
- uses: actions/checkout@v4.1.0
- uses: actions/checkout@b32f140b0c872d58512e0a66172253c302617b90 # SHA
→ Supply chain 안전.
```
### GitHub Actions 의 secret 주의
```
Secret value 가 log mask (자동).
하지만:
- 부분 echo 가 가능.
- Forked PR 가 secret access X.
- 외부 action 가 secret access (악성 가능).
→ Pin SHA. Secret 최소화.
```
### Workflow_dispatch (manual)
```yaml
on:
workflow_dispatch:
inputs:
env:
description: 'Deploy environment'
required: true
type: choice
options: [dev, staging, prod]
```
→ UI 에서 click 가 trigger.
### Schedule
```yaml
on:
schedule:
- cron: '0 9 * * 1-5' # 평일 9 AM UTC
```
→ Cron 가 GHA 안.
### Workflow run 의 cost
```
Public repo: 무료.
Private repo:
- 2000 min / month free.
- $0.008 / minute (Linux).
- $0.04 / minute (Windows / macOS).
→ Optimization (cache, matrix exclude) 가 매 cost.
```
## 🤔 의사결정 기준
| 작업 | 추천 |
|---|---|
| K8s + Vault | External Secrets Operator |
| Terraform GitOps | Atlantis |
| Cloud auth | GHA OIDC |
| 반복 logic | Reusable workflow / composite action |
| Multi-env | Environment + protection |
| Cost-sensitive | Self-hosted runner |
| Security | Pin SHA |
## ❌ 안티패턴
- **K8s Secret 직접 commit (encrypted SealedSecret 도)**: rotation 어려움.
- **Long-lived AWS key**: OIDC.
- **모든 거 inline workflow**: reuse 안 됨.
- **Secret echo**: leak.
- **No environment**: prod 가 dev 와 같은 gate.
- **No concurrency**: 중복 deploy.
- **Action @main**: supply chain.
## 🤖 LLM 활용 힌트
- ESO 가 K8s + 외부 secret store 의 답.
- Atlantis 가 Terraform 의 GitOps.
- GHA OIDC 가 modern cloud auth.
- Reusable workflow 가 DRY.
## 🔗 관련 문서
- [[DevOps_Vault_Secrets]]
- [[DevOps_Terraform_Patterns]]
- [[DevOps_CI_CD_Pipeline_Patterns]]