Arquitectura de Paquetes TGZ para Productive K3S¶
Objetivo¶
Definir una arquitectura unificada y simétrica para:
- instalar add-ons en Core
- instalar profiles en Infra desde fuentes de scenario desacopladas
- distribuir paquetes
.tgzdesacoplados - soportar catálogos públicos y privados
- ejecutar paquetes como artefactos autocontenidos
- mantener independiente la lógica del CLI y los runtimes
Todo lo instalable en el ecosistema Productive K3S debe poder distribuirse y ejecutarse como un paquete autocontenido TGZ.
Esto aplica a:
- Add-ons (
productive-k3s-addons) - Profiles/Escenarios (
productive-k3s-profiles)
Conceptos clave¶
| Concepto | Significado |
|---|---|
| Scenario | motor de implementación reusable |
| Profile | preset/configuración lista para usar |
| Add-on | extensión instalable sobre Core |
| TGZ Package | unidad distribuible autocontenida |
Intención arquitectónica¶
La arquitectura debe sentirse igual en todos los niveles.
Ejemplo conceptual¶
| Capa | Recibe | Ejecuta |
|---|---|---|
| CLI | TGZ | delega |
| Core | Add-on TGZ | instala add-ons |
| Infra | Profile TGZ | ejecuta escenarios |
| Motor de scenario | definición YAML | corre la implementación |
Filosofía¶
El CLI NO debe saber:
- lógica de instalación
- templates específicos
- motores cloud
- detalles internos
- charts de Helm particulares
- cómo instalar un add-on
- cómo ejecutar AWS/Azure/etc.
El CLI solamente:
- descarga y resuelve paquetes
- valida metadata
- delega la ejecución al runtime adecuado
Superficie pública y superficie de desarrollo¶
La arquitectura de Productive K3S expone dos superficies distintas de forma intencional:
- una superficie pública package-first para usuarios finales
- una superficie source-first de desarrollo para authoring, testing y CI
Estas dos superficies resuelven necesidades distintas y no son intercambiables.
Superficie pública del CLI¶
pk3s es el CLI público.
Su contrato es package-oriented:
- los add-ons se consumen como
addon.tgz - los profiles se consumen como
profile.tgz - la resolución de catálogo debe terminar en un artefacto TGZ descargable
El CLI público no expone:
- archivos de profile
.envcrudos - paths directos a scenarios
- atajos de desarrollo orientados al árbol fuente
Superficie de desarrollo del runtime¶
productive-k3s-core.sh y productive-k3s-infra.sh son runtime tools.
Exponen:
- una superficie pública runtime orientada a paquetes
- una superficie explícita
devpara flujos de desarrollo y testing
La superficie dev existe para que:
- autores de paquetes puedan iterar sobre source files sin generar un TGZ primero
- CI pueda validar contratos de authoring antes del empaquetado
- maintainers puedan testear profiles y add-ons directamente desde el árbol fuente
Esto significa que el contrato source-oriented de desarrollo sigue siendo válido, pero deja de ser el contrato principal expuesto al usuario.
El paquete primero, el repositorio después¶
El repositorio es fuente de desarrollo, pero el runtime no debe depender del árbol de código fuente.
El runtime debe poder instalar o ejecutar desde un archivo .tgz local sin necesitar el repositorio completo.
Al mismo tiempo, el repositorio fuente sigue siendo el entorno de authoring.
Eso significa:
- el uso público es package-first
- el uso de desarrollo puede seguir siendo source-first bajo comandos
devexplícitos - el empaquetado es la frontera entre authoring y distribución
Roles de los repositorios¶
productive-k3s-core: runtime de instalación de add-onsproductive-k3s-addons: catálogo público de add-onsproductive-k3s-addons-pro: add-ons pagos/privadosproductive-k3s-infra: runtime/engine de empaquetado y ejecución de profilesproductive-k3s-profiles: profiles y escenarios públicosproductive-k3s-profiles-pro: profiles/escenarios pagosproductive-k3s-cli: orquestadorproductive-k3s-catalogs: índices de paquetes publicados
Formato TGZ de add-ons¶
Un paquete de add-on de Productive K3S es un archivo .tgz autocontenido con metadata y activos de instalación.
Ejemplo de estructura¶
Ejemplo mínimo de addon.yaml¶
apiVersion: addons.productive-k3s.io/v1
kind: Addon
metadata:
name: longhorn
version: 1.0.0
category: storage
spec:
type: helm
chart:
path: charts/longhorn
install:
script: scripts/install.sh
dependencies:
- cert-manager
compatibility:
architectures:
- amd64
- arm64
k3s:
minVersion: "1.31"
Flujo de instalación de add-ons¶
- El CLI resuelve el paquete y descarga TGZ
- Core recibe
addon.tgz - Core extrae el archivo
- Core lee
addon.yaml - Core ejecuta el instalador
- Helm/scripts/hooks realizan la instalación
El CLI no debe implementar la lógica de instalación de Helm.
Formato TGZ de profiles/infra¶
Un profile debe ser portable, ejecutable, autocontenido y desacoplado del repositorio fuente.
Ejemplo de estructura¶
Ejemplo mínimo de profile.yaml¶
apiVersion: infra.productive-k3s.io/v1
kind: Profile
metadata:
name: aws-single-node-basic
version: 1.0.0
category: cloud
spec:
scenario:
type: aws-single-node
engine:
type: opentofu
runtime:
os:
- ubuntu-24.04
architectures:
- amd64
inputs:
- name: AWS_REGION
required: true
sensitive: false
source: package-default
description: Región AWS por defecto usada para aprovisionar
- name: AWS_KEY_PAIR_NAME
required: true
sensitive: false
source: local-override
description: Nombre de un key pair existente en AWS EC2
- name: AWS_SSH_KEY_PATH
required: true
sensitive: false
source: local-override
description: Ruta absoluta local a la clave privada correspondiente
execution:
installScript: scenario/install.sh
profile.env sigue formando parte del paquete, pero se trata como el contrato base/default del package, no como la configuración final específica de la instalación. spec.inputs define qué valores pueden venir de los defaults del paquete y cuáles deben ser provistos desde la máquina que invoca mediante --env-file.
Flujo Infra¶
- El CLI resuelve el paquete y descarga TGZ
- El runtime de Infra recibe
profile.tgz - Infra extrae el archivo
- Infra lee
profile.yaml - Infra ejecuta el scenario referenciado
- OpenTofu/Ansible/scripts realizan la implementación
Modelo orientado a profile¶
Productive K3S Infra sigue siendo profile-oriented.
El profile es la unidad ejecutable de intención y configuración. El scenario es el engine genérico reusable que implementa ese profile.
Esto es cierto tanto en desarrollo como en distribución:
- en desarrollo, el profile puede existir como
.envfuente junto con un scenario en el árbol fuente - en distribución, ese mismo profile se distribuye como un
profile.tgzautocontenido
El scenario no es el contrato primario user-facing. Es el backend reusable de implementación seleccionado por la metadata del profile.
Semántica de carpetas¶
profiles/¶
Contiene presets, variables .env y configuraciones listas para ejecutar.
No contiene:
- lógica compleja
- implementación cloud
- templates internos reutilizables
scenarios/¶
Contiene activos de implementación reutilizables:
- Terraform/OpenTofu
- Ansible
- scripts
- templates
- lógica cloud
- lógica de motor
Un scenario es el motor reutilizable.
shared/¶
Contiene helpers, librerías bash, templates comunes y utilidades reutilizables.
Composición del paquete y encapsulamiento¶
Los profiles se distribuyen como unidades empaquetadas profile + scenario.
Ese encapsulamiento es intencional.
Un profile.tgz distribuible contiene:
- metadata del profile
- variables y defaults a nivel profile
- los activos de implementación del scenario requeridos para ejecutar ese profile
- cualquier template, script y archivo auxiliar necesario en runtime
En otras palabras, distribución no publica solamente un puntero fino al profile. Publica un paquete ejecutable autocontenido que embebe el contrato del profile junto con los activos del scenario requeridos para ese camino de instalación.
Esto es especialmente importante para:
- paquetes privados o comerciales, donde el source code no es visible públicamente
- ejecución estable en runtime, donde el artefacto instalado no debe depender de un source checkout vivo
- testing reproducible del payload exacto distribuido
Modelo de catálogo¶
El CLI consume índices publicados.
Ejemplo de entrada de catálogo¶
apiVersion: catalog.productive-k3s.io/v1
entries:
- name: longhorn
version: 1.0.0
type: addon
url: https://...
- name: aws-single-node-basic
version: 1.0.0
type: profile
url: https://...
Tipos de catálogo:
- Público: GitHub Pages, OSS
- Privado: S3/Auth
- Enterprise: pago o protegido
- Local filesystem
Los paquetes públicos/open pueden seguir respaldados por repositorios donde el source code sea visible. Los paquetes privados/comerciales pueden exponer solamente la URL del artefacto o una URL protegida/comercial de acceso.
En ambos casos, el contrato del catálogo es el mismo para el consumidor: la unidad instalable es el artefacto TGZ.
Empaquetado y artefactos de release¶
Los paquetes TGZ son artefactos de distribución.
Eso implica que los repositorios que authoran profiles o add-ons necesitan un paso de empaquetado que:
- ensamble la estructura final del paquete
- valide la metadata del paquete
- produzca el
.tgz - publique el artefacto resultante como parte de la distribución
Ese paso de empaquetado pertenece a la automatización, por ejemplo:
- targets de
make - scripts de release
- jobs de release en CI/CD
El ciclo exacto de publicación puede variar por repositorio, pero el requerimiento arquitectónico no cambia:
- los source trees son para authoring
- los artefactos TGZ son para distribución e instalación
Que una versión de paquete se publique:
- como parte del release del repositorio correspondiente, o
- a través de un ciclo separado de artefactos
es una decisión de release management, no una decisión del contrato de runtime.
El modelo de runtime y de catálogo soporta ambos enfoques siempre que cada entrada instalable resuelva a una URL estable de artefacto TGZ.
Uso recomendado del CLI¶
Instalar add-on¶
Flujo interno:
- resolver catálogo
- descargar TGZ
- delegar a Core
Instalar profile¶
Flujo interno:
- resolver profile
- descargar TGZ
- delegar a Infra runtime
Separación de UX en runtime¶
Los contratos runtime user-facing y development-facing son intencionalmente distintos.
Ejemplos públicos orientados a paquetes¶
./productive-k3s-core.sh addon install --tgz ./longhorn-addon.tgz
./productive-k3s-core.sh addon validate --tgz ./longhorn-addon.tgz
./productive-k3s-infra.sh profile install --tgz ./aws-single-node-basic.tgz
./productive-k3s-infra.sh profile validate --tgz ./aws-single-node-basic.tgz
./productive-k3s-infra.sh profile plan --tgz ./aws-single-node-basic.tgz
./productive-k3s-infra.sh profile status --tgz ./aws-single-node-basic.tgz
./productive-k3s-infra.sh profile destroy --tgz ./aws-single-node-basic.tgz
Ejemplos de desarrollo orientados a source¶
./productive-k3s-core.sh dev addon validate --source ./addons/longhorn
./productive-k3s-infra.sh dev profile validate --profile-env ./profiles/cloud/aws-single-node/basic.env
./productive-k3s-infra.sh dev profile plan --profile-env ./profiles/cloud/aws-single-node/basic.env
./productive-k3s-infra.sh dev profile apply --profile-env ./profiles/cloud/aws-single-node/basic.env
El prefijo dev es la frontera explícita que mantiene disponibles los workflows source-oriented sin convertirlos en parte del contrato público de instalación.
Modelo de testing¶
La arquitectura requiere tanto testing a nivel source como testing a nivel package.
Testing a nivel source¶
El testing a nivel source valida flujos de authoring antes del empaquetado:
- validación del contrato del profile desde
.envfuente - ejecución del scenario desde el árbol del repositorio
- ciclos de CI orientados a desarrollo sin requerir un TGZ en cada iteración local
Testing a nivel package¶
El testing a nivel package valida el comportamiento real distribuido:
- descomprimir TGZ
- validar metadata del paquete
- ejecutar el runtime contra el paquete extraído
- verificar que la instalación funciona sin depender del repositorio fuente
Por eso, la suite de tests debe incluir paquetes TGZ mock o fixture tanto para:
- add-ons
- profiles
Esos artefactos de test deben imitar suficientemente la estructura real del paquete para ejercitar:
- validación de empaquetado
- extracción
- delegación de comandos
- caminos de ejecución del runtime
Reglas arquitectónicas¶
El CLI NO debe:¶
- tener templates
- tener charts de Helm
- conocer proveedores cloud
- conocer lógica OpenTofu
- conocer escenarios
- saber cómo instalar add-ons
Core debe:¶
- conocer el formato de add-ons
- gestionar el lifecycle y hooks
- ejecutar Helm
- validar dependencias y compatibilidad
Infra debe:¶
- conocer escenarios y runtimes
- ejecutar OpenTofu/Ansible
- validar variables de runtime
- validar la compatibilidad del target
Modelo mental final¶
Productive K3S = Runtime + Packages
scenario= motor reusableprofile= preset ejecutableaddon= extensión instalabletgz= unidad distribuiblecatalog= índice de descubrimientocli= orquestador mínimocore/infra= runtimes