Files
obsidian/history/2026-07-11-n8n-upgrade-2.29.10-helm-native.md

5.9 KiB

title, updated, tags
title updated tags
n8n 2.18.3 → 2.29.10 업그레이드 + Helm 드리프트 해소 2026-07-11
history
n8n
upgrade
helm
oidc

배경

2026-07-11-n8n-oidc-secret-not-wired 직후 사용자가 버전 업그레이드를 요청. n8n은 Helm 릴리스(n8n-2.0.1)이지만 OIDC 관련 설정이 Helm values 밖에서 kubectl apply/patch로 수동 추가되어 있어(../services/n8n#배포-구조-—-helm--수동-패치-혼재-주의), 그냥 helm upgrade를 돌리면 그 수동 설정이 통째로 날아갈 위험이 있었음.

사전 검증

프로덕션 건드리지 않고 n8nio/n8n:2.29.10 이미지로 임시 디버그 파드를 띄워, 커스텀 OIDC 훅(hooks.js)이 의존하는 비공식 내부 API가 신버전에도 살아있는지 확인:

  • @n8n/diContainer.get — 존재
  • dist/services/jwt.service.jsJwtService — 존재
  • n8n.ready 훅 시그니처 [server, config], frontend.settings 훅 시그니처 [frontendSettings]external-hooks.js/abstract-server.js 소스 직접 확인, 동일
  • AbstractServer.app — 여전히 Express 인스턴스로 노출

업그레이드 전 안전장치로 Patroni postgres-1(hp2)에서 pg_dump -Fc로 n8n DB 수동 백업 (226KB, 로컬 scratchpad에 보관 — NAS/R2 자동 백업 파이프라인에는 n8n DB가 없음, TODO 참조).

helm upgrade dry-run으로 드리프트 실제 확인

helm upgrade --dry-run으로 렌더링해보니 예상대로:

  • envFromn8n-oidc-secret 없음
  • oidc-hooks ConfigMap 볼륨/마운트 자체가 없음 (EXTERNAL_HOOK_FILES=/opt/n8n-oidc/hooks.js가 가리키는 파일이 사라짐 → n8n 기동 시 require() 실패로 크래시 가능성)

→ 그대로 helm upgrade 실행하지 않고, 먼저 kubectl set image로만 이미지 태그 단독 패치 시도 → JavaScript heap out of memory로 crash-loop (기존 limits.memory: 512Mi가 2.29.10엔 부족).

근본 해결 — OIDC 설정을 Helm values로 완전 편입

사용자 요청("helm 업그레이드가 가능하게 패치할 수 없어?")에 따라, 차트가 지원하는 확장 포인트를 활용해 수동 패치를 전부 제거:

  • main.config: 임의 키가 재귀적으로 대문자 스네이크케이스 env var로 변환됨(toEnvVars helper) → external_hook_files, external_frontend_hooks_urls, n8n_additional_non_ui_routes, n8n_push_backend, oidc_issuer_url, oidc_redirect_uri, oidc_scopes, diagnostics_enabled: false 추가
  • main.extraEnv: OIDC_CLIENT_ID/OIDC_CLIENT_SECRETvalueFrom.secretKeyRef로 기존 n8n-oidc-secret 참조 (차트가 env: 각 항목에 raw toYaml을 적용해서 valueFrom 구조 그대로 지원)
  • main.extraVolumes / main.extraVolumeMounts: n8n-oidc-hooks ConfigMap → /opt/n8n-oidc/hooks.js 마운트
  • main.resources.limits.memory: 512Mi → 1Gi (2.29.10 OOM 대응), requests.memory 256Mi → 512Mi
  • image.tag: 2.18.3 → 2.29.10

values 파일: ~/helm-charts/values/n8n.yaml에 이미 자리가 있었으나 2.16.1 시절 스냅샷이라 라이브 상태와 괴리되어 있었음 — 이번에 최신화해서 커밋 (kaffa/helm-charts repo, commit 975eae9). n8n은 OCI 차트(oci://8gears.container-registry.com/library/n8n --version 2.0.1)를 직접 참조하며 이 repo는 values 스냅샷만 관리.

재현 명령:

helm upgrade n8n oci://8gears.container-registry.com/library/n8n --version 2.0.1 -n n8n -f values/n8n.yaml

dry-run으로 렌더링 결과가 기존 수동 설정과 100% 동일함을 확인 후 실제 적용. helm upgrade 정상 완료(REVISION 9), 재기동 로그에 Recorded version change: 2.18.3 -> 2.29.10, [OIDC Hook] Initializing OIDC authentication..., OIDC 라우트 3개 정상 등록 확인.

부작용 — 텔레메트리 재시도 폭주로 자체 IP 차단

업그레이드 직후 브라우저에서 빈 화면 재현. 콘솔에 /rest/telemetry/proxy/v1/track 호출들이 429로 실패. BunnyCDN Shield rate limit 규칙(IPBurst200per10s, shieldZoneId 101015, pullZoneId 5555227)이 "10초간 200회 요청 시 60초 IP 차단"으로 확인 — WAF 로그(bunny_waf_logs)에서 실제 차단 IP가 테스트 중이던 내 브라우저 IP였고 URL이 전부 telemetry proxy였음을 확인.

원인: n8n 2.18.3은 "release가 6주 이상 지나면 error tracking 비활성화" 가드로 우연히 텔레메트리가 꺼져 있었으나, 2.29.10(신규 릴리스)은 가드가 적용 안 돼 텔레메트리가 켜짐 → 이 환경에서 텔레메트리 업스트림(posthog 등)으로 아웃바운드가 안 되니 클라이언트가 백오프 없이 초당 수십~수백 회 재시도 → BunnyCDN 자체 방어 규칙에 걸려 정상 사용자 IP까지 막힘.

조치: main.config.diagnostics_enabled: false 추가 (N8N_DIAGNOSTICS_ENABLED=false) → 재배포 후 재현 안 됨, 정상 렌더링 확인.

검증 완료

  • Overview 페이지 정상 렌더링, 기존 워크플로 outline-to-discord (heimdall) 그대로 보임 (DB 마이그레이션/데이터 무결성 OK)
  • 콘솔 에러 없음
  • 메모리 사용량 246Mi (1Gi 한도 내 안정)
  • OIDC SSO 버튼/라우트 정상

TODO

  • n8n Helm values.yaml을 git에 커밋 — 2026-07-11 완료 (kaffa/helm-charts commit 975eae9)
  • n8n DB 자동 백업 파이프라인 없음 — ../infra/data/backup에 n8n용 pg_dump 스케줄 추가 검토
  • Gitea OIDC 로그인 end-to-end 플로우 테스트 (2.29.10에서도 미검증 — 이번엔 로컬 세션으로 접속됨)
  • BunnyCDN IPBurst200per10s 룰이 n8n 텔레메트리 같은 내부 재시도 폭주에 취약함을 인지 — 다른 서비스에서도 유사 패턴(아웃바운드 차단된 상태에서 백오프 없는 재시도) 있는지 점검

관련