Skip to main content

RFC 0002 — CDN

CampoValor
StatusProposed
Data2026-03-16
Afetacharts/kelbi-app, halk-en-cdn, halk-jp-cdn, kelbi-cdn
Depende deRFC 0001 — Storage

Contexto

Existem dois padrões de CDN no cluster, ambos hoje usando nginx.conf embutido em values.yaml:

AppPadrãoDescrição
halk-en-cdn, halk-jp-cdnProxy reversoEncaminha para API; API decide quais arquivos servir via X-Accel-Redirect
kelbi-cdnArquivo estáticoServe arquivos diretamente de um storage

Ambos compartilham o mesmo problema: o desenvolvedor precisa conhecer e escrever nginx para declarar intenção de negócio.


Problema

Acoplamento ao provedor

# valores atuais — nginx embutido nos dois padrões
configmapData:
contents:
nginx.conf: |
server {
location / { proxy_pass http://...; } # halk-cdn
location /assets { alias /data/assets; } # kelbi-cdn
Risco

Se o provedor mudar (nginx → Caddy, Envoy, Traefik), todos os values.yaml de todos os apps CDN precisariam ser reescritos. A troca de implementação vaza para o domínio do desenvolvedor.

Duplicação entre halk-en e halk-jp

Os dois apps diferem em apenas 4 campos, mas carregam 80 linhas de nginx.conf duplicadas em cada values.yaml. Qualquer mudança precisa ser replicada manualmente.

Outros problemas

ProblemaAppDetalhe
DNS hardcodedhalk-*-cdnprod-halk-en-api.apps.svc.cluster.local:4000 em string multiline
HPA inútilhalk-*-cdnminReplicas: 1 / maxReplicas: 1 — nunca age
Typokelbi-cdnapp.name: kelbi-cdb

Princípio de design

Regra central

O desenvolvedor declara o que quer entregar. A plataforma decide como entregar.

CamadaResponsávelExemplo
IntençãoDesenvolvedor"proxy para o serviço X" ou "serve arquivos de /assets"
ImplementaçãoPlataforma (chart)nginx proxy_pass, X-Accel-Redirect, alias, sendfile
InfraestruturaPlataforma (ops)DNS interno, namespace
O que nunca deve aparecer em values.yaml

nginx, proxy_pass, server_name, alias, sendfile, DNS de cluster (*.svc.cluster.local).


Proposta

O novo bloco cdn unifica os dois padrões sob um vocabulário intencional. O tipo é declarado por mode.

Modo: proxy

Para apps que encaminham tráfego para uma API com suporte a file serving via X-Accel-Redirect.

cdn:
- mode: proxy
host: release.halk-en.arcamh.com
backend:
service: halk-en-api # plataforma resolve o DNS
port: 4000
fileServing: # intenção: API redireciona downloads para storage local
- mountPath: /_release/
storage: patch-data # referência ao storage do RFC 0001
subPath: release/mhfdat
- mountPath: /_base/
storage: patch-data
subPath: base/mhfdat
- mode: proxy
host: pre-release.halk-en.arcamh.com
backend:
service: halk-en-api
port: 4001
fileServing:
- mountPath: /_pre_release/
storage: patch-data
subPath: pre-release/mhfdat
- mountPath: /_base/
storage: patch-data
subPath: base/mhfdat

Modo: static

Para apps que servem arquivos diretamente de um storage.

cdn:
- mode: static
path: /assets # path público de acesso
storage: static-assets # referência ao storage do RFC 0001
autoindex: true

Vocabulário

CampoModoSignificadoO que evita
cdn[].modeambosproxy ou staticmistura de conceitos num único bloco
cdn[].hostproxyVirtual hostserver_name (nginx)
cdn[].backend.serviceproxyNome do serviço KubernetesDNS hardcoded de cluster
cdn[].backend.portproxyPorta do serviçoproxy_pass :port (nginx)
cdn[].fileServing[].mountPathproxyPath de acesso internolocation + internal (nginx)
cdn[].fileServing[].storageproxyStorage lógico do RFC 0001alias /path/ (nginx)
cdn[].fileServing[].subPathproxySubdiretório dentro do storagepath absoluto no container
cdn[].pathstaticPath público de acessolocation /assets (nginx)
cdn[].storagestaticStorage lógico do RFC 0001alias /data/assets (nginx)
cdn[].autoindexstaticListagem de diretórioautoindex on (nginx)

O que o chart gera

# gerado pelo chart — o dev nunca vê isso
server {
listen 80;
server_name release.halk-en.arcamh.com;

location / {
proxy_pass http://halk-en-api.apps.svc.cluster.local:4000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}

location /_release/ {
internal;
alias /app/data/release/mhfdat/;
sendfile on;
}

location /health {
access_log off;
add_header Content-Type text/plain;
return 200 "healthy\n";
}
}

Impacto nos apps

halk-en-cdn

configmapData:
name: prod-halk-en-cdn
contents:
nginx.conf: |
events { ... }
http {
server {
listen 80;
server_name release.halk-en.arcamh.com;
location / {
proxy_pass http://prod-halk-en-api.apps.svc.cluster.local:4000/;
...
}
location /_release/ { internal; alias /data/release/mhfdat/; sendfile on; }
# ... mais 40 linhas
}
}
volumes:
- name: data
hostPath:
path: /root/volumes/halk-patch-server/en
type: Directory
- name: nginx-conf
configMap:
name: prod-halk-en-cdn
volumeMounts:
- name: data
mountPath: /app/data
- name: nginx-conf
mountPath: /etc/nginx
readOnly: true
autoscaling:
enabled: true
minReplicas: 1
maxReplicas: 1

halk-jp-cdn segue o mesmo padrão trocando enjp e claim: halk-jp-patch-data.


kelbi-cdn

app:
name: "kelbi-cdb" # typo
image: "nginx:1.29-alpine"

volumes:
- name: cache
emptyDir: {}
- name: static
hostPath:
path: /root/volumes/kelbi/static
type: Directory
- name: nginx-conf
configMap:
name: prod-kelbi-cdn-kelbi-cdb
volumeMounts:
- name: static
mountPath: /data/assets
readOnly: true
- name: nginx-conf
mountPath: /etc/nginx
readOnly: true
- name: cache
mountPath: /var/cache/nginx

configmapData:
name: prod-kelbi-cdn-kelbi-cdb
contents:
nginx.conf: |
http {
server {
listen 80;
location /assets {
alias /data/assets;
autoindex on;
}
location /health { ... }
}
}

Arquitetura futura — Nginx centralizado

Por que não agora

Requer um controller/reloader que ainda não existe no cluster. A interface cdn[] é idêntica entre a arquitetura atual (nginx por app) e a futura (nginx centralizado). Migrar não exige nenhuma mudança nos values.yaml.


Mudanças no chart (kelbi-app 3.3.0)

ArquivoMudança
templates/_helpers.tplHelper kelbi-app.cdnConf — gera nginx.conf a partir de cdn[] e storage
templates/cdn-configmap.yamlNovo — cria ConfigMap <fullname>-cdn-conf quando cdn é definido
templates/deployment.yamlInjeta volume e volumeMount do cdn-conf automaticamente
values.yamlAdiciona cdn: [] com comentário de exemplo

Compatibilidade

Sem breaking changes

cdn é um novo bloco opcional. Apps sem esse campo continuam funcionando sem nenhuma alteração.

  • Chart version: 3.3.0 (minor bump, junto com RFC 0001)
  • Apps que migram: halk-en-cdn, halk-jp-cdn, kelbi-cdn
  • Apps sem mudança: todos os outros

Pré-requisitos

Antes do deploy

Os PVCs precisam existir antes da migração. Requer RFC 0001 — Storage implementado.

  • halk-en-patch-data
  • halk-jp-patch-data
  • kelbi-static-assets

Fora do escopo

  • Abstração de volumes — RFC 0001 — Storage
  • Nginx centralizado — arquitetura futura, sem data definida
  • Headers de cache customizados por path
  • Rate limiting declarativo
  • Helper de DNS entre serviços — roadmap

Critério de aceitação

  • cdn[].mode: proxy gera nginx.conf com proxy_pass e locações internas corretas
  • cdn[].mode: static gera nginx.conf com alias e autoindex corretos
  • DNS resolvido pelo chart a partir de backend.service + namespace do release
  • fileServing[].storage + subPath resolve para o alias correto usando storage[].mountPath
  • Volume e volumeMount do cdn-conf injetados automaticamente no Deployment
  • Apps sem cdn continuam renderizando sem alteração
  • halk-en-cdn e halk-jp-cdn migrados — sem nginx.conf raw, sem DNS hardcoded
  • kelbi-cdn migrado — sem nginx.conf raw, typo corrigido
  • Testes: ambos os modos, DNS correto, alias calculado, sem cdn = sem ConfigMap