From a9955a736b524fb4141b15dbbc35b73ba7424ebc Mon Sep 17 00:00:00 2001 From: migatu Date: Fri, 24 Jul 2026 19:22:11 +0200 Subject: [PATCH] =?UTF-8?q?feat(astrololo):=20usluga=20render=20=E2=80=94?= =?UTF-8?q?=20raport=20PDF=20(PRE-24)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nowy komponent skladajacy raport PDF. Osobny obraz, bo dzwiga TeX Live (setki MB) — ta sama zasada co przy izolacji swissepha (LOG-27): obraz produktu zostaje maly, TeX aktualizuje sie niezaleznie, a awaria renderu nie kladzie aplikacji, tylko przycisk „Pobierz PDF". - render.yaml — Deployment + Service. ClusterIP, BEZ NodePortu i Ingressu: nie ma powodu, zeby ktokolwiek siegal do tej uslugi z zewnatrz. Rozmawia wylacznie z prezentacja. - Szyfrowanie: wlasny, TRZECI klucz LINK_KEY_PRESENTATION_RENDER z sekretu astrololo-link. Osobny, bo tym laczem plynie CALY raport (dane urodzeniowe i opisy z baz) — przejecie go nie moze otwierac lacza do logiki ani danych. LINK_ENCRYPTION_REQUIRED=true, wiec bez klucza pod NIE wstaje. - readOnlyRootFilesystem + emptyDir na /tmp: kompilacja pisze tylko do katalogu tymczasowego, raport nie zostawia sladu w kontenerze. - Limity rozjechane celowo (100m/256Mi -> 1500m/1Gi): XeLaTeX na obszernym raporcie bierze duzo, ale na krotko. - presentation: RENDER_URL + trzeci klucz lacza. Sekret astrololo-link trzeba UZUPELNIC o trzeci klucz PRZED wdrozeniem, zachowujac dwa dotychczasowe — komenda w instrukcji. Sprawdzone: kubectl kustomize + apply --dry-run=server na zywym klastrze (service/render i deployment.apps/render created). Pelna instrukcja: docs/wdrozenie-render-pdf.md w repo astrololo. Co-Authored-By: Claude Opus 4.8 --- astrololo/kustomization.yaml | 3 ++ astrololo/presentation.yaml | 8 +++++ astrololo/render.yaml | 69 ++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 astrololo/render.yaml diff --git a/astrololo/kustomization.yaml b/astrololo/kustomization.yaml index fb2faf7..99f5435 100644 --- a/astrololo/kustomization.yaml +++ b/astrololo/kustomization.yaml @@ -5,6 +5,7 @@ resources: - data.yaml - logic.yaml - presentation.yaml + - render.yaml # składanie raportu PDF (PRE-24), osobny obraz z TeX Live - tls.yaml # certyfikat z własnego CA (wymaga cert-managera) - ingress.yaml # wejście po https + przekierowanie z http images: @@ -12,5 +13,7 @@ images: newTag: f34016a4 - name: gitea.czernobog.pl/gitea/astrololo-logic newTag: f34016a4 + - name: gitea.czernobog.pl/gitea/astrololo-render + newTag: latest - name: gitea.czernobog.pl/gitea/astrololo-presentation newTag: f34016a4 diff --git a/astrololo/presentation.yaml b/astrololo/presentation.yaml index 9a2cd4c..ad8cc51 100644 --- a/astrololo/presentation.yaml +++ b/astrololo/presentation.yaml @@ -46,6 +46,14 @@ spec: # Bez klucza usługa ma NIE wstać, a klient ma nie wysłać niczego. # Sam serwer broni się fail-closed, ale to za mało: klient bez klucza # zdążyłby wypuścić zapytanie jawnym tekstem, zanim dostanie odmowę. + # Usługa składająca PDF (PRE-24) — osobny komponent. + - name: RENDER_URL + value: "http://render:8004" # discovery po nazwie Service + # Trzeci klucz łącza: prezentacja ↔ render. Osobny, bo tym łączem + # idzie CAŁY raport (dane urodzeniowe + opisy z baz). + - name: LINK_KEY_PRESENTATION_RENDER + valueFrom: + secretKeyRef: { name: astrololo-link, key: LINK_KEY_PRESENTATION_RENDER } - name: LINK_ENCRYPTION_REQUIRED value: "true" resources: diff --git a/astrololo/render.yaml b/astrololo/render.yaml new file mode 100644 index 0000000..a007bb2 --- /dev/null +++ b/astrololo/render.yaml @@ -0,0 +1,69 @@ +# Usługa render — składanie raportu PDF (PRE-24). +# +# OSOBNY komponent, nie część prezentacji, z tego samego powodu co silnik +# swisseph (LOG-27): obraz dźwiga TeX Live, czyli setki megabajtów. W obrazie +# produktu spowalniałby każdy build i deploy; tak aktualizuje się niezależnie, +# a jego awaria nie kładzie aplikacji — psuje się tylko przycisk „Pobierz PDF". +# +# Rozmawia WYŁĄCZNIE z prezentacją, po szyfrowanym łączu z własnym, trzecim +# kluczem. Wystawiona jako ClusterIP — bez NodePort i bez Ingressu, bo nie ma +# powodu, żeby ktokolwiek sięgał do niej z zewnątrz. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: render + namespace: astrololo +spec: + replicas: 1 + selector: { matchLabels: { app: render } } + template: + metadata: { labels: { app: render } } + spec: + imagePullSecrets: [{ name: gitea-registry }] + containers: + - name: render + image: gitea.czernobog.pl/gitea/astrololo-render:latest + ports: [{ containerPort: 8004 }] + env: + # Token międzywarstwowy (LOG-32) — ta usługa dostaje CAŁY raport: + # dane urodzeniowe i opisy z baz. + - name: INTERNAL_TOKEN + valueFrom: + secretKeyRef: { name: astrololo-auth, key: INTERNAL_TOKEN } + # Szyfrowanie łącza (PRE-16/PRE-24). OSOBNY klucz na parę rozmówców: + # przejęcie klucza renderu nie może otwierać łącza do logiki ani danych. + - name: LINK_KEY_PRESENTATION_RENDER + valueFrom: + secretKeyRef: { name: astrololo-link, key: LINK_KEY_PRESENTATION_RENDER } + - name: LINK_ENCRYPTION_REQUIRED + value: "true" + # XeLaTeX na obszernym raporcie potrafi zjeść sporo pamięci i CPU, + # ale tylko na chwilę — stąd wyraźna różnica między request a limit. + resources: + requests: { cpu: "100m", memory: "256Mi" } + limits: { cpu: "1500m", memory: "1Gi" } + # Kompilacja pisze wyłącznie do katalogu tymczasowego, który sprząta po + # sobie. Dajemy na to emptyDir i zamykamy resztę systemu plików — + # raport nie ma prawa zostawić śladu w kontenerze. + volumeMounts: + - { name: tmp, mountPath: /tmp } + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + readinessProbe: + httpGet: { path: /health, port: 8004 } + initialDelaySeconds: 5 + periodSeconds: 15 + volumes: + - name: tmp + emptyDir: { sizeLimit: 512Mi } +--- +apiVersion: v1 +kind: Service +metadata: + name: render + namespace: astrololo +spec: + type: ClusterIP # tylko dla prezentacji, bez wejścia z zewnątrz + selector: { app: render } + ports: [{ port: 8004, targetPort: 8004 }] -- 2.52.0