diff --git a/.env.example b/.env.example index 7eaaab0..4cdd80a 100644 --- a/.env.example +++ b/.env.example @@ -39,6 +39,16 @@ PLATFORM_DOMAIN=sarex.local # основной домен платфо ADMIN_DOMAIN=admin.sarex.local # RabbitMQ management UI MINIO_DOMAIN=minio.sarex.local # MinIO: S3 API (/) + консоль (/console/) +# --- Docker-образы инфраструктуры (тег/реестр можно переопределить) --- +K3S_IMAGE=rancher/k3s:v1.36.2-k3s1 +GITEA_IMAGE=gitea/gitea:1.22 +POSTGRES_IMAGE=postgres:12-alpine +NGINX_IMAGE=nginx:1.27-alpine +SAREX_REDIS_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/redis:7.0.10 +SAREX_RABBITMQ_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/rabbimtq:3.11.23 +SAREX_MINIO_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/minio:250724 +SAREX_MC_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/mc:250724 + # Образы приложения (приватный реестр cr.yandex — нужен docker login) SAREX_BACKEND_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/sarex-backend-dev:latest SAREX_FRONTEND_IMAGE=cr.yandex/crp3ccidau046kdj8g9q/sarex-frontend-dev:latest diff --git a/aero/roles/sarex_stack/tasks/main.yml b/aero/roles/sarex_stack/tasks/main.yml index 2001183..f4e33f8 100644 --- a/aero/roles/sarex_stack/tasks/main.yml +++ b/aero/roles/sarex_stack/tasks/main.yml @@ -23,6 +23,13 @@ dest: "{{ deploy_dir }}/nginx/templates/" mode: "0644" +# backend монтирует ./backend/uwsgi.ini (http-socket + 4 воркера) +- name: Скопировать конфиг uwsgi для backend + ansible.builtin.copy: + src: "{{ deploy_src_root }}/backend/uwsgi.ini" + dest: "{{ deploy_dir }}/backend/uwsgi.ini" + mode: "0644" + # --- Секреты: генерация с персистом на control-node (идемпотентно) -------- - name: Сгенерировать/загрузить пароли (persist в secrets_store, gitignored) ansible.builtin.set_fact: diff --git a/backend/uwsgi.ini b/backend/uwsgi.ini new file mode 100644 index 0000000..fde4cbb --- /dev/null +++ b/backend/uwsgi.ini @@ -0,0 +1,24 @@ +[uwsgi] +log-format = {"time": "%(time)", "method": "%(method)", "uri": "%(uri)", "status": "%(status)", "size": "%(size)", "addr": "%(addr)", "user": "%(user)", "proto": "%(proto)", "user_agent": "%(uagent)", "referer": "%(referer)", "trace_id": "%(trace_id)", "span_id": "%(span_id)"} +module = config.wsgi:application +DJANGO_SETTINGS_MODULE = config.settings.production +# HTTP-протокол вместо uwsgi (nginx проксирует через proxy_pass, доступен напрямую) +http-socket = 0.0.0.0:8000 +processes = 4 +master = true +vacuum = true +die-on-term = true +enable-threads = true +buffer-size = 65535 +stats = :3031 +stats-http = true +memory-report = true +lazy-apps = true +listen = 1024 +disable-write-exception= 0 +harakiri = 300 +socket-timeout = 300 +chunked-input-timeout = 300 +http-timeout = 300 +worker-reload-mercy = 240 +mule-reload-mercy = 240 diff --git a/docker-compose.yaml b/docker-compose.yaml index c7a4684..041c1d9 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,6 +1,6 @@ services: k3s-server: - image: rancher/k3s:v1.36.2-k3s1 + image: ${K3S_IMAGE:-rancher/k3s:v1.36.2-k3s1} container_name: k3s-server command: - server @@ -38,7 +38,7 @@ services: start_period: 30s k3s-worker: - image: rancher/k3s:v1.36.2-k3s1 + image: ${K3S_IMAGE:-rancher/k3s:v1.36.2-k3s1} container_name: k3s-worker command: - agent @@ -63,7 +63,7 @@ services: hard: 65535 gitea: - image: gitea/gitea:1.22 + image: ${GITEA_IMAGE:-gitea/gitea:1.22} container_name: gitea restart: unless-stopped environment: @@ -89,7 +89,7 @@ services: # Креды/версии взяты из sarex-backend/docker-compose.yaml и apps/django/.env.example. # --------------------------------------------------------------------------- postgres: - image: postgres:12-alpine + image: ${POSTGRES_IMAGE:-postgres:12-alpine} container_name: postgres restart: unless-stopped environment: @@ -116,7 +116,7 @@ services: # Одноразовый init: на каждое приложение заводит роль (LOGIN+пароль) и базу # данных с этим владельцем. Идемпотентно (по образцу minio-init). postgres-init: - image: postgres:12-alpine + image: ${POSTGRES_IMAGE:-postgres:12-alpine} depends_on: postgres: condition: service_healthy @@ -170,7 +170,7 @@ services: restart: "no" redis: - image: cr.yandex/crp3ccidau046kdj8g9q/redis:7.0.10 + image: ${SAREX_REDIS_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/redis:7.0.10} container_name: redis restart: unless-stopped command: ["redis-server", "--save", "60", "1", "--loglevel", "warning"] @@ -184,7 +184,7 @@ services: start_period: 5s rabbitmq: - image: cr.yandex/crp3ccidau046kdj8g9q/rabbimtq:3.11.23 + image: ${SAREX_RABBITMQ_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/rabbimtq:3.11.23} container_name: rabbitmq restart: unless-stopped environment: @@ -202,7 +202,7 @@ services: start_period: 30s minio: - image: cr.yandex/crp3ccidau046kdj8g9q/minio:250724 + image: ${SAREX_MINIO_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/minio:250724} container_name: minio restart: unless-stopped command: ["server", "/data", "--console-address", ":9001"] @@ -217,7 +217,7 @@ services: # Одноразовый init: ждёт MinIO и на каждое приложение заводит бакет + # отдельного пользователя со scoped-политикой (доступ только к своему бакету). minio-init: - image: cr.yandex/crp3ccidau046kdj8g9q/mc:250724 + image: ${SAREX_MC_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/mc:250724} depends_on: - minio entrypoint: @@ -271,11 +271,12 @@ services: DJANGO_POSTGRES_DATABASE: ${SAREX_POSTGRES_DB:-sarex_db} DJANGO_POSTGRES_USER: ${SAREX_DJANGO_DB_USER:-django} DJANGO_POSTGRES_PASSWORD: ${SAREX_DJANGO_DB_PASSWORD:-django-secret} - DJANGO_REDIS_HOST: redis - DJANGO_RABBIT_HOSTNAME: rabbitmq - DJANGO_RABBIT_USER: ${SAREX_RABBITMQ_USER:-rabbit} - DJANGO_RABBIT_PASS: ${SAREX_RABBITMQ_PASSWORD:-rabbit} - DJANGO_RABBIT_VHOST: ${SAREX_RABBITMQ_VHOST:-api} + # celery: брокер rabbitmq + result backend redis (pydantic env_prefix CELERY_*) + CELERY_RABBITMQ_HOST: rabbitmq + CELERY_RABBITMQ_USER: ${SAREX_RABBITMQ_USER:-rabbit} + CELERY_RABBITMQ_PASSWORD: ${SAREX_RABBITMQ_PASSWORD:-rabbit} + CELERY_RABBITMQ_VHOST: ${SAREX_RABBITMQ_VHOST:-api} + CELERY_REDIS_HOST: redis # S3 / объектное хранилище → MinIO (сервис minio) S3_HOST: http://minio:9000 AWS_S3_ENDPOINT_URL: http://minio:9000 @@ -287,7 +288,10 @@ services: MEASUREMENTS_HOST: ${SAREX_MEASUREMENTS_HOST:-http://measurements:8000/} tty: true ports: - - "8000:8000" # HTTP API (uWSGI), migrate выполняется в entrypoint + - "8000:8000" # HTTP API (uWSGI http-socket), migrate выполняется в entrypoint + volumes: + # свой uwsgi.ini поверх образного: http-socket + 4 воркера (:z — SELinux/RedOS) + - ./backend/uwsgi.ini:/opt/sarex/uwsgi.ini:ro,z depends_on: postgres: condition: service_healthy @@ -391,7 +395,7 @@ services: # Верхний reverse-proxy: 3 домена → платформа / rabbitmq (admin) / minio nginx: - image: nginx:1.27-alpine + image: ${NGINX_IMAGE:-nginx:1.27-alpine} container_name: sarex-nginx restart: unless-stopped ports: @@ -413,7 +417,7 @@ services: # - processing-api # processing пока не поднимаем (закомментирован в шаблоне nginx) # - processing-frontend healthcheck: - test: ["CMD", "wget", "-qO-", "http://localhost/healthz"] + test: ["CMD", "wget", "-qO-", "http://127.0.0.1/healthz"] interval: 10s timeout: 5s retries: 6 diff --git a/nginx/templates/default.conf.template b/nginx/templates/default.conf.template index 7798b3a..04f3d62 100644 --- a/nginx/templates/default.conf.template +++ b/nginx/templates/default.conf.template @@ -26,8 +26,8 @@ map $http_upgrade $connection_upgrade { '' close; } -# upstream backend { server backend:8000; } # TODO: в работе -# upstream frontend { server frontend:80; } # TODO: в работе +upstream backend { server backend:8000; } +# upstream frontend { server frontend:80; } # frontend пока не поднят upstream minio_s3 { server minio:9000; } upstream minio_console { server minio:9001; } upstream rabbitmq_mgmt { server rabbitmq:15672; } @@ -55,9 +55,9 @@ server { return 200 "ok\n"; } - # Django backend: REST API + админка (TODO: в работе) - # location /api/ { proxy_pass http://backend; } - # location /admin/ { proxy_pass http://backend; } + # Django backend: REST API + админка + location /api/ { proxy_pass http://backend; } + location /admin/ { proxy_pass http://backend; } # --- processing (workflows) под /workflows --- (пока не поднимаем) # Префикс /workflows срезаем: api ждёт пути /api/v1/..., фронт — от корня.