# FluxCD v2 Monorepooo

Репозиторий Infrastructure as Code, управляемый [FluxCD v2](https://fluxcd.io/) с использованием Kustomize-оверлеев и Helm-релизов.

## Карта инфраструктуры и межсервисных маршрутов

Диаграмма ниже показывает инфраструктурные компоненты кластера, их зависимости и типовые маршруты вызовов между бизнес-сервисами.

```mermaid
flowchart LR
    %% ===== Внешний контур =====
    User([👤 Пользователь<br/>Web / Mobile]):::ext
    Admin([🛡 Администратор<br/>kubectl / flux]):::ext
    LE([🔐 Let's Encrypt<br/>ACME v2]):::ext
    GitRepo([📦 Git Repository<br/>FluxCD source]):::ext
    OCI([🐳 OCI Registry<br/>cr.yandex]):::ext

    %% ===== GitOps =====
    subgraph GITOPS["⚙️ GitOps Control Plane"]
        direction TB
        FluxSource[source-controller]:::flux
        FluxKust[kustomize-controller]:::flux
        FluxHelm[helm-controller]:::flux
        FluxNotif[notification-controller]:::flux
        FluxSource --> FluxKust
        FluxSource --> FluxHelm
        FluxKust --> FluxNotif
        FluxHelm --> FluxNotif
    end

    %% ===== Edge / Service Mesh =====
    subgraph EDGE["🌐 Edge & Service Mesh — istio-system"]
        direction TB
        Gateway["Istio Gateway<br/>:443 / :80<br/>LoadBalancer"]:::mesh
        Pilot["istiod / Pilot<br/>xDS :15010/:15012"]:::mesh
        Base[Istio Base<br/>CRDs + RBAC]:::mesh
        Cert["cert-manager<br/>v1.x"]:::mesh
        IssuerProd[ClusterIssuer<br/>letsencrypt-prod]:::mesh
        IssuerIstio[ClusterIssuer<br/>letsencrypt-istio]:::mesh
        Pilot -->|sidecar inject| Gateway
        Base --> Pilot
        Cert --> IssuerProd
        Cert --> IssuerIstio
        IssuerIstio -. TLS cert .-> Gateway
    end

    %% ===== Платформа =====
    subgraph PLATFORM["🛠 Платформа"]
        direction TB
        Dashboard["K8s Dashboard<br/>UI :8443"]:::platform
        LPP["local-path-provisioner<br/>StorageClass: local-path"]:::platform
        Vault["HashiCorp Vault<br/>:8200 KV/Transit"]:::platform
        S3Proxy["S3 Proxy<br/>S3 API gateway"]:::platform
    end

    %% ===== Identity =====
    subgraph IDENTITY["🪪 Identity & SSO"]
        direction TB
        Zitadel["Zitadel<br/>OIDC :8080"]:::identity
        Keycloak["Keycloak<br/>OIDC/SAML :8080"]:::identity
        OpenLDAP["OpenLDAP<br/>:389 / :636"]:::identity
        Keycloak -- "LDAP federation" --> OpenLDAP
    end

    %% ===== Данные =====
    subgraph DATA["🗄 Хранилища данных"]
        direction TB
        PG[("PostgreSQL<br/>:5432<br/>HA primary/replica")]:::data
        Redis[("Redis<br/>:6379<br/>cache + pub/sub")]:::data
        MinIO[("MinIO<br/>S3 :9000<br/>console :9001")]:::data
    end

    %% ===== Messaging =====
    subgraph MSG["📨 Messaging"]
        direction TB
        Kafka[["Kafka<br/>:9092 / :9093 SASL<br/>3 brokers"]]:::msg
        ZK[["ZooKeeper / KRaft<br/>:2181"]]:::msg
        RMQ[["RabbitMQ<br/>:5672 / mgmt :15672"]]:::msg
        Kafka --- ZK
    end

    %% ===== BPM =====
    subgraph BPM["🔧 BPM"]
        direction TB
        Camunda["Camunda Platform<br/>REST :8080 / Tasklist"]:::app
        Operate["Camunda Operate<br/>UI :8081"]:::app
    end

    %% ===== Бизнес-сервисы (каждый в своём namespace) =====
    subgraph APPS["💼 Бизнес-сервисы — namespaces"]
        direction LR
        CI["ns: control-interface"]:::app
        Django["ns: django"]:::app
        EAV["ns: eav"]:::app
        Workspaces["ns: workspaces"]:::app
        Projects["ns: projects"]:::app
        PM["ns: pm"]:::app
        Contracts["ns: contracts"]:::app
        Resources["ns: resources"]:::app
        Subs["ns: subscriptions"]:::app
        SysLog["ns: system-log"]:::app
        MsgHub["ns: message-hub"]:::app
        FaaS["ns: faas"]:::app
        Flows["ns: flows"]:::app
        Docs["ns: documentations"]:::app
        DocLink["ns: document-link"]:::app
        Attach["ns: attachments"]:::app
        Transmittal["ns: transmittal"]:::app
        CDE["ns: cde"]:::app
        Drawings["ns: drawings"]:::app
        BIM["ns: bim"]:::app
        Stamp["ns: stamp-verification"]:::app
        Inspect["ns: inspections"]:::app
        Checklists["ns: checklists"]:::app
        Remarks["ns: remarks"]:::app
        Issues["ns: issues"]:::app
        RFI["ns: rfi"]:::app
        Reviews["ns: reviews"]:::app
        Prescr["ns: prescriptions"]:::app
        Compare["ns: comparisons"]:::app
        Measure["ns: measurements"]:::app
        Mapper["ns: mapper"]:::app
        XSection["ns: cross-section"]:::app
        Process["ns: processing"]:::app
        Notes["ns: notes"]:::app
    end

    %% ===== GitOps потоки =====
    Admin ==>|git push| GitRepo
    GitRepo ==>|pull/poll| FluxSource
    OCI ==>|OCI charts| FluxSource
    FluxKust ==>|apply manifests| EDGE
    FluxKust ==>|apply manifests| PLATFORM
    FluxKust ==>|apply manifests| IDENTITY
    FluxHelm ==>|HelmRelease| DATA
    FluxHelm ==>|HelmRelease| MSG
    FluxHelm ==>|HelmRelease| BPM
    FluxHelm ==>|HelmRelease| APPS

    %% ===== Внешний трафик =====
    User ==>|HTTPS 443| Gateway
    LE -. ACME HTTP-01 .-> Cert
    Gateway ==>|VirtualService<br/>mTLS| CI
    Gateway ==>|/api| Django
    Gateway ==>|/bim| BIM
    Gateway ==>|/cde| CDE
    Gateway ==>|/docs| Docs
    Gateway ==>|/pm| PM
    Gateway ==>|VirtualService| Camunda
    Gateway ==>|VirtualService| Operate
    Gateway ==>|/auth| Keycloak
    Gateway ==>|/oauth| Zitadel
    Gateway ==>|/dashboard| Dashboard
    Gateway ==>|/minio| MinIO
    Admin -.->|kubectl| Dashboard

    %% ===== Frontend → backend (через control-interface) =====
    CI -- "API gateway" --> Django
    CI -- "API gateway" --> PM
    CI -- "API gateway" --> Projects
    CI -- "API gateway" --> Workspaces

    %% ===== Подключения к данным =====
    Django -- "JDBC/ORM" --> PG
    EAV -- "JDBC" --> PG
    PM -- "JDBC" --> PG
    Contracts -- "JDBC" --> PG
    Resources -- "JDBC" --> PG
    Projects -- "JDBC" --> PG
    Workspaces -- "JDBC" --> PG
    Subs -- "JDBC" --> PG
    SysLog -- "JDBC" --> PG
    Docs -- "JDBC" --> PG
    DocLink -- "JDBC" --> PG
    CDE -- "JDBC" --> PG
    BIM -- "JDBC" --> PG
    Drawings -- "JDBC" --> PG
    Inspect -- "JDBC" --> PG
    Checklists -- "JDBC" --> PG
    Issues -- "JDBC" --> PG
    Remarks -- "JDBC" --> PG
    RFI -- "JDBC" --> PG
    Reviews -- "JDBC" --> PG
    Prescr -- "JDBC" --> PG
    Compare -- "JDBC" --> PG
    Measure -- "JDBC" --> PG
    Mapper -- "JDBC" --> PG
    XSection -- "JDBC" --> PG
    Notes -- "JDBC" --> PG
    Stamp -- "JDBC" --> PG
    Transmittal -- "JDBC" --> PG
    Camunda -- "JDBC" --> PG
    Operate -- "JDBC" --> PG
    Zitadel -- "JDBC" --> PG
    Keycloak -- "JDBC" --> PG

    %% ===== Redis (общий кэш / sessions) =====
    Django -- "session/cache" --> Redis
    CI -- "session" --> Redis
    PM -- "cache" --> Redis
    Workspaces -- "cache" --> Redis
    Subs -- "pub/sub realtime" --> Redis
    MsgHub -- "pub/sub" --> Redis
    Flows -- "state" --> Redis
    FaaS -- "queue" --> Redis
    Camunda -- "cache" --> Redis
    Keycloak -- "session" --> Redis

    %% ===== S3 / объектное хранилище =====
    Attach -- "PUT/GET" --> S3Proxy
    Docs -- "filestream" --> S3Proxy
    BIM -- "IFC/RVT" --> S3Proxy
    Drawings -- "DWG/PDF" --> S3Proxy
    CDE -- "files" --> S3Proxy
    Compare -- "rendered diff" --> S3Proxy
    Stamp -- "signed PDF" --> S3Proxy
    Transmittal -- "bundles" --> S3Proxy
    Process -- "raw + результаты" --> S3Proxy
    Mapper -- "tiles" --> S3Proxy
    Measure -- "snapshots" --> S3Proxy
    XSection -- "профили" --> S3Proxy
    S3Proxy -- "S3 API" --> MinIO

    %% ===== Vault (secrets) =====
    Django -. "kv" .-> Vault
    Camunda -. "approle" .-> Vault
    Keycloak -. "kv" .-> Vault
    Zitadel -. "kv" .-> Vault
    FaaS -. "approle" .-> Vault
    Flows -. "approle" .-> Vault

    %% ===== Storage / PVC =====
    PG -.->|PVC| LPP
    Redis -.->|PVC| LPP
    Kafka -.->|PVC| LPP
    ZK -.->|PVC| LPP
    RMQ -.->|PVC| LPP
    MinIO -.->|PVC| LPP
    Vault -.->|PVC| LPP

    %% ===== Kafka (event bus) =====
    SysLog -- "consume audit.*" --> Kafka
    MsgHub -- "produce notify.*" --> Kafka
    Subs -- "consume notify.*" --> Kafka
    Flows -- "produce/consume flows.*" --> Kafka
    Camunda -- "produce bpm.events" --> Kafka
    Operate -- "consume zeebe-records" --> Kafka
    BIM -- "produce bim.processed" --> Kafka
    Drawings -- "produce drawings.uploaded" --> Kafka
    Process -- "consume processing.jobs" --> Kafka
    Compare -- "consume drawings.uploaded" --> Kafka
    Inspect -- "produce inspect.events" --> Kafka
    Issues -- "consume inspect.events" --> Kafka
    Remarks -- "produce remarks.events" --> Kafka
    Reviews -- "consume remarks.events" --> Kafka

    %% ===== RabbitMQ (work queues) =====
    FaaS -- "consume tasks.*" --> RMQ
    Flows -- "publish tasks.*" --> RMQ
    Process -- "publish jobs" --> RMQ
    Mapper -- "consume tile.jobs" --> RMQ
    XSection -- "consume xs.jobs" --> RMQ
    Stamp -- "consume sign.jobs" --> RMQ
    Camunda -- "consume bpm.tasks" --> RMQ

    %% ===== Межсервисные REST маршруты =====
    PM -- "REST" --> Projects
    PM -- "REST" --> Contracts
    PM -- "REST" --> Resources
    Projects -- "REST" --> Workspaces
    Contracts -- "REST" --> Resources
    Inspect -- "REST" --> Checklists
    Inspect -- "REST" --> Issues
    Issues -- "REST" --> Remarks
    Reviews -- "REST" --> RFI
    Reviews -- "REST" --> Prescr
    RFI -- "REST" --> DocLink
    DocLink --> Docs
    DocLink --> CDE
    CDE -- "REST" --> Docs
    CDE -- "REST" --> Drawings
    CDE -- "REST" --> BIM
    Transmittal -- "REST" --> CDE
    Transmittal -- "REST" --> Docs
    Drawings -- "REST" --> Compare
    Drawings -- "REST" --> Stamp
    Measure -- "REST" --> Mapper
    Mapper -- "REST" --> XSection
    XSection --> Process
    BIM -- "REST" --> Process
    Notes -- "REST" --> DocLink
    Flows -- "trigger" --> FaaS
    Flows -- "start" --> Camunda
    Camunda -- "callback" --> Flows
    EAV -- "schemas" --> Django
    MsgHub -- "deliver email/push" --> Subs

    %% ===== AuthN / AuthZ =====
    Django -. "OIDC validate" .-> Keycloak
    CI -. "OIDC login" .-> Keycloak
    PM -. "JWT" .-> Keycloak
    Camunda -. "JWT" .-> Zitadel
    Operate -. "OIDC" .-> Zitadel
    Dashboard -. "OIDC" .-> Keycloak
    BIM -. "JWT" .-> Keycloak
    CDE -. "JWT" .-> Keycloak
    Docs -. "JWT" .-> Keycloak

    %% ===== Service mesh sidecar metrics =====
    CI -. "envoy" .-> Pilot
    Django -. "envoy" .-> Pilot
    Camunda -. "envoy" .-> Pilot
    BIM -. "envoy" .-> Pilot
    Flows -. "envoy" .-> Pilot


    %% ===== Стили =====
    classDef ext fill:#1f2937,stroke:#9ca3af,stroke-width:2px,color:#f9fafb
    classDef flux fill:#6366f1,stroke:#3730a3,stroke-width:2px,color:#fff
    classDef mesh fill:#7c3aed,stroke:#4c1d95,stroke-width:2px,color:#fff
    classDef platform fill:#0ea5e9,stroke:#075985,stroke-width:2px,color:#fff
    classDef identity fill:#f59e0b,stroke:#92400e,stroke-width:2px,color:#fff
    classDef data fill:#10b981,stroke:#065f46,stroke-width:2px,color:#fff
    classDef msg fill:#ef4444,stroke:#991b1b,stroke-width:2px,color:#fff
    classDef app fill:#ec4899,stroke:#9d174d,stroke-width:2px,color:#fff

    style GITOPS fill:#e0e7ff,stroke:#6366f1,stroke-width:2px
    style EDGE fill:#ede9fe,stroke:#7c3aed,stroke-width:2px
    style PLATFORM fill:#e0f2fe,stroke:#0ea5e9,stroke-width:2px
    style IDENTITY fill:#fef3c7,stroke:#f59e0b,stroke-width:2px
    style DATA fill:#d1fae5,stroke:#10b981,stroke-width:2px
    style MSG fill:#fee2e2,stroke:#ef4444,stroke-width:2px
    style BPM fill:#fce7f3,stroke:#ec4899,stroke-width:2px
    style APPS fill:#fce7f3,stroke:#ec4899,stroke-width:2px
```

📂 **Подробные диаграммы по каждому бизнес-сервису:** [`docs/apps/`](./docs/apps/README.md)

**Легенда:**
- 🟪 **Edge / Mesh** — терминация TLS, маршрутизация и mTLS между сервисами (Istio + cert-manager)
- 🟦 **Платформа** — служебные компоненты (storage, secrets, S3 proxy, dashboard)
- 🟧 **Identity** — единый вход и федерация пользователей (Zitadel, Keycloak, OpenLDAP)
- 🟩 **Данные** — постоянные хранилища (PostgreSQL, Redis, MinIO)
- 🟥 **Messaging** — асинхронный обмен (Kafka, RabbitMQ)
- 🟪 **Бизнес-сервисы** — прикладная логика (Camunda, бизнес-приложения)

## Структура репозитория

```
├── clusters/                       # Точка входа для каждого кластера (Flux читает отсюда)
│   └── contour/                    # Кластер contour
│       ├── flux-system/            # Автогенерируется через `flux bootstrap` (не редактировать)
│       ├── helm-repositories.yaml  # Определения HelmRepository
│       ├── infrastructure.yaml     # Flux Kustomization → ./infrastructure
│       └── apps.yaml               # Flux Kustomization → ./apps
│
├── infrastructure/                 # Инфраструктурные компоненты
│   ├── kustomization.yaml          # Список всех инфра-сервисов
│   └── example-infra/              # Пример инфра-компонента
│       ├── kustomization.yaml      # Собирает base + patches
│       ├── base/                   # Базовые манифесты (namespace, HelmRelease)
│       └── patches/                # Патчи поверх base
│
├── apps/                           # Прикладные сервисы
│   ├── kustomization.yaml          # Список всех приложений
│   └── example-app/                # Пример приложения
│       ├── kustomization.yaml      # Собирает base + patches
│       ├── base/                   # Базовые манифесты (Deployment, Service, ConfigMap)
│       └── patches/                # Патчи поверх base
```

## Как это работает

Flux отслеживает директорию `clusters/<имя-кластера>/`. Каждый кластер содержит два Flux Kustomization CRD верхнего уровня:

1. **infrastructure.yaml** — реконсилирует `./infrastructure`. Содержит HelmReleases и вспомогательные ресурсы.
2. **apps.yaml** — реконсилирует `./apps`. Содержит Deployments, Services и другие ресурсы приложений.

`apps` зависит от `infrastructure`, что гарантирует готовность инфраструктуры до деплоя приложений.

Каждый сервис (в `infrastructure/` или `apps/`) имеет собственную структуру:
- **base/** — базовые манифесты, общие для всех окружений
- **patches/** — патчи, применяемые поверх base
- **kustomization.yaml** — на уровне сервиса, собирает base + patches через Kustomize

## Начало работы

### Бутстрап Flux

```bash
flux bootstrap git \
  --url=<URL_ВАШЕГО_РЕПОЗИТОРИЯ> \
  --branch=master \
  --path=clusters/contour
```

### Проверка реконсиляции

```bash
flux get kustomizations
flux get helmreleases -A
flux events --watch
```

## Добавление нового инфраструктурного компонента

1. Создайте директорию с base и patches:
   ```
   infrastructure/my-component/
   ├── kustomization.yaml      # resources: [./base], patches: [patches/...]
   ├── base/
   │   ├── kustomization.yaml
   │   ├── namespace.yaml
   │   └── helmrelease.yaml
   └── patches/
       └── values.yaml
   ```

2. Зарегистрируйте в `infrastructure/kustomization.yaml`:
   ```yaml
   resources:
     - example-infra
     - my-component    # Добавьте эту строку
   ```

3. Если нужен новый HelmRepository, добавьте его в `clusters/<кластер>/helm-repositories.yaml`.

## Добавление нового приложения

1. Создайте директорию с base и patches:
   ```
   apps/my-app/
   ├── kustomization.yaml      # resources: [./base], patches: [patches/...]
   ├── base/
   │   ├── kustomization.yaml
   │   ├── namespace.yaml
   │   ├── deployment.yaml
   │   └── service.yaml
   └── patches/
       └── replicas.yaml
   ```

2. Зарегистрируйте в `apps/kustomization.yaml`:
   ```yaml
   resources:
     - example-app
     - my-app          # Добавьте эту строку
   ```

## Добавление нового кластера

1. Создайте точку входа `clusters/<имя>/` с `infrastructure.yaml`, `apps.yaml` и `helm-repositories.yaml`
2. Выполните бутстрап Flux с `--path=clusters/<имя>`

## Справочник API-версий

| Ресурс           | apiVersion                              |
|------------------|-----------------------------------------|
| Kustomization    | `kustomize.toolkit.fluxcd.io/v1`        |
| GitRepository    | `source.toolkit.fluxcd.io/v1`           |
| HelmRepository   | `source.toolkit.fluxcd.io/v1`           |
| HelmRelease      | `helm.toolkit.fluxcd.io/v2`             |
