Files
obsidian/services/gitea.md
kappa 2356b86d36 obsidian: 정본 문서에서 히스토리/인시던트 분리 완료
15개 정본 문서에서 날짜별 변경이력, 인시던트 기록, 폐기된 구현 상세를
history/ 디렉토리로 분리. 정본은 현재 상태만 기술하는 백서 형태로 정리.
각 정본에 history 위키링크 추가.

분리된 history 파일 12건:
- apisix git push 500, k3s postgresql migration, apisix→traefik 전환
- netbis DDoS 공격, gitea 이전/분리, usb 2.5g hang + NFS hard mount
- supabase→patroni, apisix etcd 통합/분리, anomaly-detect 재설계
- patroni failover incident, zlambda nixos migration, ops-agents setup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 12:09:21 +09:00

4.4 KiB

title, updated
title updated
Gitea 서버 및 CI/CD 2026-03-28

서버

K3s 클러스터에서 Helm 차트(gitea/gitea 12.5.0)로 운영. 네임스페이스: gitea.

  • Gitea 1.25.4 + PostgreSQL 16 + Valkey
  • 도메인: gitea.inouter.com
  • 트래픽: BunnyCDN(iron-git, BlockNoneReferrer: false) → HAProxy → Traefik → gitea svc:3000
  • SSH 활성화, 외부 포트 2202 (relay4wd APISIX stream_route 경유: ssh -p 2202 git@git.inouter.com), MetalLB 192.168.9.54:22, SSH_DOMAIN: git.inouter.com
  • 스토리지: Git 저장소 Longhorn PVC 5Gi, 그 외 전부 R2 (패키지/LFS/첨부파일/아바타/아카이브/Actions)
  • R2 버킷: gitea-storage (APAC), Vault secret/cloud/r2-gitea, K8s Secret gitea-r2
  • 시크릿: Vault secret/apps/gitea
  • Deployment strategy: Recreate (RWO PVC 충돌 방지)
  • 메일: Mailgun SMTP (gitea@inouter.com, 도메인 inouter.com), FROM: noreply@inouter.com

Helm 관리

# values 파일
~/k8s/gitea/values.yaml

# 업그레이드
helm upgrade gitea gitea/gitea -n gitea -f ~/k8s/gitea/values.yaml

이미지 레지스트리

모든 컨테이너 이미지는 gitea.inouter.com/kaffa/ 경로. R2 gitea-storage 버킷에 저장.

R2 스토리지 설정

항목
STORAGE_TYPE minio (S3 호환)
엔드포인트 d8e5997eb4040f8b489f09095c0f623c.r2.cloudflarestorage.com
버킷 gitea-storage
API 키 Vault secret/cloud/r2-gitea (access_key_id, secret_access_key)
K8s Secret gitea-r2 (gitea 네임스페이스)

R2에 저장되는 데이터: packages, lfs, attachments, avatars, repo-avatars, repo-archive, actions_log, actions_artifacts

컨테이너 레지스트리

Gitea에 내장된 OCI 컨테이너 레지스트리. URL: gitea.inouter.com. K3s에서 이미지를 pull하려면 각 네임스페이스에 gitea-registry imagePullSecret이 필요.

# 네임스페이스에 gitea-registry secret 복사 (mcp 네임스페이스에서)
kubectl get secret gitea-registry -n mcp -o yaml | \
  sed 's/namespace: mcp/namespace: <대상-ns>/' | \
  kubectl apply -f -

⚠️ 흔한 사고: 새 네임스페이스에서 gitea.inouter.com/... 이미지로 Deployment를 만들면 imagePullSecrets: [gitea-registry]만 명시해도 secret이 그 네임스페이스에 없으면 ImagePullBackOff가 발생. K8s는 namespace 경계를 넘어 secret을 공유하지 않음. 매번 secret을 복사해야 함.

자동 배포 대안: cert-manager reflector annotation 또는 Kyverno generate 정책으로 자동 동기화 가능 (현재는 수동).

기존에 gitea-registry secret이 배포된 네임스페이스: mcp, tools, api, default (2026-04-08 추가).

Act Runner

Gitea Act Runner는 infra-hosts의 gitea-runner 컨테이너에서 실행 (act_runner daemon, systemd 서비스).

  • 라벨: ubuntu-latest, ubuntu-22.04, ubuntu-20.04
  • 설정: /root/.runner (address: https://gitea.inouter.com)
  • Docker config: /root/.docker/config.json (레지스트리 인증)
  • /etc/hosts: 192.168.9.53 gitea.inouter.com (직접 접근)

CI/CD 배포

ArgoCD로 배포 관리. CI workflow는 Docker 이미지 빌드+푸시만 수행하고, ArgoCD가 k8s/ 매니페스트 변경을 감지하여 자동 배포.

repo ArgoCD 앱 workflow 비고
namecheap-api namecheap-api docker.yaml build+push
vultr-api vultr-api build.yaml + ci.yml build+push
bunnycdn-mcp bunnycdn-mcp ci.yml build+push
cf-bouncer-manager cf-bouncer-manager build.yaml build+push

CI workflow 공통 패턴

env:
  REGISTRY: gitea.inouter.com
  IMAGE_NAME: ${{ gitea.repository }}
# secrets.REGISTRY_TOKEN 사용 (각 repo Actions secrets에 설정)

백업

K8s CronJob gitea-backup (매일 03:00 UTC):

  • gitea dump/backup/gitea-dump-*.tar.gz
  • 7일 보존, Longhorn PVC 10Gi
  • 매니페스트: ~/k8s/gitea/backup-cronjob.yaml

이전/분리/도메인 변경 이력: ../history/2026-03-various-gitea-changes

트러블슈팅

웹 로그인 안 될 때 비밀번호 리셋

curl -s -X PATCH "https://gitea.inouter.com/api/v1/admin/users/kaffa" \
  -H "Authorization: token <API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"password":"<PASSWORD>","must_change_password":false,"login_name":"kaffa","source_id":0}'
  • API 토큰, 비밀번호: Vault secret/apps/gitea