Saltar al contenido principal

Despliegue y operador

DeviceChain se despliega en dos capas declarativas: un chart de Helm renderiza las cargas de trabajo de la plataforma, y un operador de Kubernetes (construido con controller-runtime) gestiona el ciclo de vida de Instance. Ambas son declarativas y compatibles con GitOps. (Los inquilinos no forman parte del trabajo del operador — son registros de base de datos del plano de control, vea abajo.)

Estado

El chart de Helm renderiza las cargas de trabajo y la configuración por servicio hoy. La agregación de estado de instancia del operador y la recarga en caliente de configuración están en curso. Los overlays de Kustomize por entorno están planificados.

Desplegando con Helm

El chart en deploy/helm/devicechain renderiza un Deployment + Service por área funcional habilitada, junto con los ConfigMaps de configuración por servicio y el Secret de configuración de instancia (porta credenciales de persistencia, por lo que es un Secret en lugar de un ConfigMap). Cada pod expone /healthz (liveness) y /readyz (readiness) para que un servicio que no está listo se mantenga fuera de rotación.

Usted elige qué servicios ejecutar con ya sea un perfil nombrado o un conjunto explícito:

PerfilÁreas funcionales
defaultuser-management, device-management, event-sources, event-management, device-state, dashboard-management, command-delivery, notification-management, event-processing — el sistema estándar, y a lo que resuelve un perfil sin establecer
fulltodo lo de default, más ai-inference, outbound-connectors, y mcp: las áreas que alcanzan fuera de la instancia, cada una de las cuales conlleva una decisión que tomar deliberadamente (una clave de proveedor de pago, una superficie de salida, una API orientada a agentes)
telemetryuser-management, device-management, event-sources, event-management, device-state, dashboard-management
ingest-onlyuser-management, device-management, event-sources

Cualquier perfil que ejecute un área con almacén de secretos —como hace el perfil default, a través de notification-management— requiere la clave raíz del almacén de secretos de la instancia, y el chart falla el renderizado sin ella en lugar de dejar que el área entre en crash-loop. Genera un valor (openssl rand -base64 32), consérvalo y pasa el mismo valor en cada instalación y actualización: una clave nueva vuelve ilegibles los secretos ya almacenados bajo la anterior. dcctl bootstrap acuña y deposita en escrow esta clave por ti; solo tienes que suministrarla tú cuando manejas el chart directamente.

DC_ROOT_KEY="$(openssl rand -base64 32)" # genérala UNA vez, y consérvala

helm install dc deploy/helm/devicechain \
--set instance.id=devicechain \
--set instance.config.infrastructure.secrets.rootKey="$DC_ROOT_KEY"

# Ejecuta un conjunto menor de servicios. `telemetry` no ejecuta ningún área con
# almacén de secretos, así que no necesita clave raíz.
helm install dc deploy/helm/devicechain --set profile=telemetry

Para instalar una versión publicada, fije la etiqueta de imagen a una versión — las imágenes publicadas son públicas en ghcr.io/devicechain-io, así que no hace falta construir nada localmente:

Sustituya <version> por una etiqueta realmente publicada; la página de versiones las lista.

helm install dc deploy/helm/devicechain \
--set instance.id=devicechain \
--set instance.config.infrastructure.secrets.rootKey="$DC_ROOT_KEY" \
--set image.tag=<version>

Vea Versiones y actualizaciones para el modelo de versionado y el procedimiento de actualización. Para una instancia que arrancó con el bootstrap es un único dcctl upgrade, que mueve a la vez el operador, el documento de configuración y la versión desplegada —el operador no forma parte del chart, así que algo externo al chart tiene que mover ambas cosas—. Para una instancia gobernada solo desde el chart es helm upgrade, con sus valores trasladados a mano.

user-management y device-management son el núcleo requerido; event-management, device-state, y command-delivery son opcionales de forma independiente. El chart falla el renderizado si una selección omite un servicio del núcleo requerido o una dependencia dura de un servicio habilitado — de modo que una topología rota se detecta en el momento de instalación, no después de que los pods entren en crash-loop. Los valores se validan contra el values.schema.json del chart en el momento de aplicación.

Recursos personalizados

  • Instance (con alcance de clúster; instances.core.devicechain.io, nombre corto dci) — uno por instalación, declarando la identidad y configuración de la instancia.

Los inquilinos no son recursos personalizados — son registros de base de datos del plano de control creados a través de la API de administración de instancia y la consola /admin, compartiendo los servicios de la instancia (vea Multitenencia).

kubectl get instances # platform

La declaración de la instancia

dcctl bootstrap escribe uno de estos objetos para la instancia que está a punto de construir, y después lo vuelve a leer y trabaja con lo que ha leído en lugar de con los flags que lo produjeron. Eso hace que el registro de lo que es la instancia esté en el clúster, y no en la máquina donde se escribió el comando: a qué proveedor y clúster pertenece, el perfil y la versión de imagen que ejecuta, si sus bases de datos se recuperaron desde un archivo, qué compilación de dcctl lo escribió por última vez y qué estaba intentando hacer la última ejecución.

Un operador en una segunda máquina puede, por tanto, leer la instancia sin ningún estado local:

kubectl --context <kube-context> get instances
kubectl --context <kube-context> get instance <id> -o yaml

Parte de la especificación es inmutable una vez escrita —el vínculo con el clúster ante todo, porque reescribirlo apuntaría dcctl destroy a un clúster distinto. Es el servidor de la API el que rechaza esas ediciones, no una comprobación de dcctl.

kubectl delete instance no termina

Una declaración lleva un finalizador, así que borrarla a mano deja el objeto en su sitio, marcado para eliminación, hasta que dcctl lo libere:

kubectl delete instance prod # no retorna; el objeto permanece, ahora terminando

Es deliberado, y protege dos cosas distintas. Una declaración borrada a mano dejaría huérfana una instancia viva —namespaces, bases de datos, volúmenes y cargas de trabajo todos en marcha, sin nada en el clúster que registre a qué pertenecen. Y como las reglas de inmutabilidad funcionan comparando la nueva versión del objeto con la anterior, un objeto recreado no tiene versión anterior contra la que comparar: borrar y volver a aplicar reapuntaría el vínculo con el clúster en dos pasos que, por separado, parecen legítimos.

dcctl destroy libera el finalizador por sí mismo, como último paso, una vez que la instancia ya no está —así que en el caso normal no hay nada que hacer a mano. (Cuando destroy elimina el clúster entero, la declaración se va con él.)

Un destroy que falla deja la declaración en su sitio a propósito

Sigue registrando en qué clúster vive la instancia, que es lo que necesita una nueva ejecución, y dice Destroying en lugar de Ready, de modo que el siguiente lector puede saber que está mirando un desmontaje en curso. Un dcctl bootstrap sobre una declaración así se niega en lugar de construir media instancia nueva sobre media instancia antigua; le indica que termine primero el desmontaje.

Eliminar una declaración sin destruir nada

dcctl instances release <id> --kube-context <kube-context>

Esto libera el finalizador y borra la declaración. No destruye nada. Los namespaces, las bases de datos, los volúmenes y las cargas de trabajo siguen todos en marcha después, y dcctl simplemente deja de tener un registro de a qué pertenecen —que es justamente por lo que el comando le obliga a decir en voz alta que eso es lo que quiere. Existe porque, de lo contrario, un finalizador cuyo liberador ha desaparecido dejaría al clúster con un objeto que nadie puede borrar.

Imprime lo que va a hacer y le pide que escriba de vuelta el nombre de la instancia; --yes omite esa confirmación para uso automatizado. --kube-context hace falta desde cualquier máquina que no haya arrancado la instancia, ya que es lo que le dice a dcctl qué clúster tiene la declaración.

Si lo que quiere es eliminar la instancia, ejecute dcctl destroy en su lugar.

Separación de responsabilidades

DeviceChain divide deliberadamente cada capa:

CapaHerramientaResponsabilidad
InfraestructuraOpenTofuNATS, TimescaleDB, namespaces, ingress, TLS
Cargas de trabajoChart de HelmDeployments, Services, ConfigMaps de configuración por área, y el Secret de configuración de instancia
Ciclo de vidaOperadorAgregación de estado de Instance y recarga en caliente de configuración
Configuración de negociokubectl / UIinquilinos y sus ajustes

OpenTofu se ejecuta una vez en la creación del clúster; el chart renderiza las cargas de trabajo; el operador se ejecuta de forma continua, reconciliando el ciclo de vida. El arranque del clúster nunca vive en el código de la aplicación o del operador — es responsabilidad de la capa de infraestructura. Los módulos de OpenTofu viven en deploy/opentofu; aprovisionan el nivel de base de datos con guardas de retención para que sobreviva al desmontaje de la aplicación (vea Versiones y actualizaciones).