From ac8101869508b56696a4381f5c687ced27abb434 Mon Sep 17 00:00:00 2001 From: Heimdall Date: Wed, 8 Apr 2026 08:34:07 +0000 Subject: [PATCH] =?UTF-8?q?infra:=20APISIX=20ingress=20controller=20?= =?UTF-8?q?=EB=B3=B5=EA=B5=AC=20=EB=B0=8F=20PostgreSQL=20HA=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=AA=85=ED=99=95=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - apisix.md: ingress controller 2026-04-08 복구, GatewayProxy + ApisixRoute CRD 호환 검증, 옛 helm values 문제 정정, ApisixRoute 예시 추가 - apisix.md: 외부 통합 etcd 클러스터 사용 명시 (K3s 내부 StatefulSet 아님), global_rules는 chaitin-waf 미포함 (라우트별 적용) - postgresql-ha.md: pgcat가 HAProxy 단일 백엔드 경유로 변경 (2026-04-08 사고 기록), Patroni 노드 IP 직접 박지 말 것 경고 - gitea.md: 컨테이너 레지스트리 섹션 추가, gitea-registry secret 네임스페이스별 수동 복사 필요 명시 --- infra/apisix.md | 65 ++++++++++++++++++++++++++++++++++++++---- infra/postgresql-ha.md | 28 ++++++++++++++++++ services/gitea.md | 17 +++++++++++ 3 files changed, 104 insertions(+), 6 deletions(-) diff --git a/infra/apisix.md b/infra/apisix.md index 28c9cfb..6d98905 100644 --- a/infra/apisix.md +++ b/infra/apisix.md @@ -52,13 +52,13 @@ BunnyCDN(inouter, ID 5316471) → apisix-osaka(172.233.93.180) → 백엔드 - 배포: K3s apisix 네임스페이스, **Deployment replica 2** (2026-04-04 HA 업그레이드) - APISIX: 3.15.0-ubuntu - SafeLine WAF 연동: `plugin_attr.chaitin-waf` → `safeline-detector:8000` (10.43.253.244) -- global_rules: `chaitin-waf` (mode: block) + `limit-req` (rate 20, burst 10) +- global_rules (id=1): `http-logger` (CrowdSec 로그 전송) + `limit-req` (rate 20, burst 10). **`chaitin-waf`는 global_rules에 없음** — 라우트별 적용 (2026-03-15 git push 500 사건 이후) - 서비스: apisix-gateway LoadBalancer 192.168.9.50 (80→9080, 443→9443) -- etcd: apisix-etcd StatefulSet **3 replicas** (K3s 내부, 2026-04-04 HA 업그레이드) -- Admin API: `apisix-admin` ClusterIP :9180 (라우트/upstream/SSL 수동 관리) +- etcd: **외부 통합 etcd 클러스터** (192.168.9.100, 10.100.2.214, 10.253.101.233), prefix `/apisix/seoul`. K3s 내부 apisix-etcd StatefulSet은 통합 이전 시 삭제됨 (2026-04-06). 자세한 내용은 [[postgresql-ha#etcd-클러스터-patroni-dcs|postgresql-ha]] 참고 +- Admin API: `apisix-admin` ClusterIP :9180 (`adminKey: edd1c9f034335f136f87ad84b625c8f1`) - HAProxy: OpenWrt에서 :9080→192.168.9.50:80, :9443→192.168.9.50:443 (MetalLB) - 2026-03-25 메인 라우팅 역할을 Traefik으로 이전, APISIX는 SafeLine WAF 전용으로 축소 -- Ingress Controller + Gateway API CRD 제거됨 (GatewayProxy 모드에서 ApisixRoute CRD 미지원, HTTPRoute에 플러그인 개별 적용 불가 문제) +- 2026-04-08 ApisixRoute CRD 사용을 위해 ingress controller 복구 #### plugin_metadata (etcd 직접 등록) @@ -79,11 +79,64 @@ etcdctl put /apisix/plugin_metadata/chaitin-waf '{"id":"chaitin-waf","nodes":[{" `real_ip_header: X-Forwarded-For`, `real_ip_from: 0.0.0.0/0` (BunnyCDN 경유이므로 전체 허용). Helm values로는 반영 안 되어 ConfigMap 직접 패치. #### 이전 사유 (2026-03-25) -- Ingress Controller 2.0 GatewayProxy 모드가 ApisixRoute CRD를 sync하지 않음 -- Gateway API HTTPRoute에 플러그인 개별 적용 방법이 없음 +- Ingress Controller 2.0 초기 시도에서 GatewayProxy 모드 + ApisixRoute CRD 연동 실패 (당시 helm values에 v1.x 형식의 `config.apisix.serviceName` 사용 → 차트 1.x 스키마와 불일치) +- Gateway API HTTPRoute에 플러그인 개별 적용 방법이 없음 → ApisixRoute CRD 필요 - global_rules를 Ingress Controller가 덮어쓰려는 충돌 발생 - → Traefik으로 메인 라우팅 교체, APISIX는 SafeLine WAF 연동 전용으로 유지 +#### Ingress Controller 복구 (2026-04-08) + +`apisix-ingress-controller` Helm release는 살아있었으나 Deployment가 수동 삭제된 상태였음. helm values를 chart 1.1.2 (controller v2.0.1) 스키마에 맞게 재작성 후 `helm upgrade`로 복구. + +값 수정 핵심: +```yaml +gatewayProxy: + createDefault: true # GatewayProxy CR 자동 생성 + provider: + type: ControlPlane + controlPlane: + service: + name: apisix-admin + port: 9180 + auth: + type: AdminKey + adminKey: + value: "edd1c9f034335f136f87ad84b625c8f1" +config: + disableGatewayAPI: false # Gateway API + ApisixRoute 양쪽 다 지원 + kubernetes: + ingressClass: apisix +``` + +검증 결과: GatewayProxy 모드에서도 ApisixRoute CRD(v2)는 정상 동작함. 옛 메모의 "GatewayProxy 모드에서 ApisixRoute CRD 미지원"은 틀렸음 — 잘못된 helm values 때문이었음. ApisixRoute에 `ingressClassName: apisix`만 명시하면 controller가 자동으로 admin API에 push. + +ApisixRoute 예시 (라우트별 chaitin-waf): +```yaml +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: + namespace: +spec: + ingressClassName: apisix + http: + - name: rule1 + match: + hosts: [] + paths: ["/*"] + backends: + - serviceName: + servicePort: + plugins: + - name: chaitin-waf + enable: true + config: + mode: block + append_waf_resp_header: true +``` + +WAF가 문제 시 `plugins` 항목만 빼면 즉시 비활성화됨. + ### BunnyCDN Pull Zone 매핑 | Zone | ID | Origin | 방향 | 주요 Hostnames | diff --git a/infra/postgresql-ha.md b/infra/postgresql-ha.md index f92a774..2d84b02 100644 --- a/infra/postgresql-ha.md +++ b/infra/postgresql-ha.md @@ -112,6 +112,34 @@ backend bk_postgres_primary - Patroni failover 시 HAProxy가 자동으로 새 Leader를 감지 (~3초) - K3s config 변경 없이 Leader 전환 대응 +## 애플리케이션 접속 경로 + +NocoDB, n8n 등 K3s 내부 애플리케이션은 **pgcat**(연결 풀링)을 통해 PostgreSQL에 접속. + +``` +nocodb/n8n → pgcat (db.svc.cluster.local:6432) → HAProxy 192.168.9.1:5432 → Patroni Leader +``` + +`db/pgcat-config` ConfigMap의 각 풀의 `shards.0.servers`는 **HAProxy 단일 백엔드만 가리켜야 함** (2026-04-08 변경): + +```toml +[pools.nocodb.shards.0] +database = "nocodb" +servers = [["192.168.9.1", 5432, "primary"]] + +[pools.n8n.shards.0] +database = "n8n" +servers = [["192.168.9.1", 5432, "primary"]] +``` + +⚠️ **하지 말 것**: pgcat에 Patroni 노드 IP(10.100.2.5/3.185/1.83)를 직접 박지 말 것. Patroni failover가 발생하면 pgcat는 옛 primary를 계속 가리키게 되어 nocodb/n8n이 read-only 에러 발생. + +pgcat는 풀링 전용으로만 쓰고, leader 탐지는 OpenWrt HAProxy에 위임. `query_parser_enabled = false` 설정 (read/write splitting 비활성). + +### 2026-04-08 사고 기록 + +Patroni failover 발생 → pgcat가 옛 primary IP(`10.100.2.5`)를 hardcoded 참조 → nocodb 마이그레이션 시 `cannot execute UPDATE in a read-only transaction` 에러로 4시간 가량 CrashLoopBackOff. n8n은 마이그레이션이 없어서 표면화되지는 않았으나 동일한 잠재 문제 존재. 위의 단일 백엔드 구조로 변경하여 항구 해결. + ## APISIX etcd 통합 (2026-04-06) 기존 각 사이트별 독립 etcd를 통합 etcd 클러스터로 이전. diff --git a/services/gitea.md b/services/gitea.md index 2c7014c..0f990e9 100644 --- a/services/gitea.md +++ b/services/gitea.md @@ -51,6 +51,23 @@ R2에 저장되는 데이터: packages, lfs, attachments, avatars, repo-avatars, Gitea는 iron-kr에서 **iron-git** (ID 5584382)으로 분리. 이유: iron-kr의 `BlockNoneReferrer: true`가 git 클라이언트(Referrer 없음)를 차단하여 git push/pull 403 에러 발생. iron-git은 `BlockNoneReferrer: false`로 설정. +## 컨테이너 레지스트리 + +Gitea에 내장된 OCI 컨테이너 레지스트리. URL: `gitea.inouter.com`. K3s에서 이미지를 pull하려면 각 네임스페이스에 `gitea-registry` imagePullSecret이 필요. + +```bash +# 네임스페이스에 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|incus-jp1]]의 gitea-runner 컨테이너에서 실행 (act_runner daemon, systemd 서비스).