mirror of
https://gitee.com/pnoker/iot-dc3.git
synced 2026-08-30 17:19:58 +08:00
docs(usage): add swarm, kubernetes and helm deployment guides
This commit is contained in:
@@ -107,3 +107,403 @@ All images are built for multiple platforms:
|
||||
| SQL Server Driver | `pnoker/dc3-driver-sqlserver:${DC3_IMAGE_TAG}` | `registry.cn-beijing.aliyuncs.com/dc3/dc3-driver-sqlserver:${DC3_IMAGE_TAG}` |
|
||||
| TCP/UDP Driver | `pnoker/dc3-driver-tcp-udp:${DC3_IMAGE_TAG}` | `registry.cn-beijing.aliyuncs.com/dc3/dc3-driver-tcp-udp:${DC3_IMAGE_TAG}` |
|
||||
| Zigbee Driver | `pnoker/dc3-driver-zigbee:${DC3_IMAGE_TAG}` | `registry.cn-beijing.aliyuncs.com/dc3/dc3-driver-zigbee:${DC3_IMAGE_TAG}` |
|
||||
|
||||
## 🐝 Docker Swarm
|
||||
|
||||
> All images are plain multi-arch OCI images, so the same stack can be scheduled with `docker stack deploy`.
|
||||
> The compose files under `dc3/` are not directly deployable as a stack — Swarm ignores `depends_on` conditions,
|
||||
> `container_name`, and `build:` — so deploy from a dedicated stack file like the one below.
|
||||
|
||||
Service names double as DNS names on the overlay network. Keep the names the images resolve by default
|
||||
(`dc3-postgres`, `dc3-rabbitmq`, `dc3-center-auth`, `dc3-center-manager`, `dc3-center-data`, `dc3-center-agentic`,
|
||||
`dc3-gateway`, `dc3-web`), or override `POSTGRES_HOST`, `RABBITMQ_HOST`, `MQTT_BROKER_HOST`, `CENTER_*_HOST`, and
|
||||
`APP_API_HOST` to point at services deployed differently.
|
||||
|
||||
```bash
|
||||
cd iot-dc3
|
||||
make up-db # build dc3-postgres and dc3-rabbitmq locally (single-node swarm)
|
||||
docker swarm init # skip on an existing swarm manager
|
||||
docker stack deploy -c dc3/docker-stack.yml dc3
|
||||
DC3_IMAGE_REGISTRY=registry.cn-beijing.aliyuncs.com/dc3 docker stack deploy -c dc3/docker-stack.yml dc3
|
||||
```
|
||||
|
||||
> On a multi-node swarm, push `dc3-postgres` and `dc3-rabbitmq` to a registry every node can pull, or run
|
||||
> PostgreSQL/RabbitMQ outside the cluster and override the host variables. Swarm has no `depends_on`: services keep
|
||||
> restarting until their dependencies answer, so startup order is self-healing. `NODE_ENV: test` mirrors the compose
|
||||
> stack; set `NODE_ENV: pro` to run the hardened production profile (OpenAPI/Swagger UI disabled).
|
||||
|
||||
Save the following stack file as `dc3/docker-stack.yml`, then add the drivers you need with the same `app-env` anchor:
|
||||
|
||||
```yaml
|
||||
x-app-env: &app-env
|
||||
NODE_ENV: test
|
||||
DC3_SECURITY_KEY: ${DC3_SECURITY_KEY:-dc3.security.key.2026.io.github.pnoker}
|
||||
AUTH_HMAC_SECRET: ${AUTH_HMAC_SECRET:-io.github.pnoker.dc3}
|
||||
POSTGRES_HOST: dc3-postgres
|
||||
POSTGRES_PORT: "5432"
|
||||
POSTGRES_USERNAME: ${POSTGRES_USERNAME:-dc3}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-dc3dc3dc3}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-dc3}
|
||||
RABBITMQ_VIRTUAL_HOST: ${RABBITMQ_VIRTUAL_HOST:-dc3}
|
||||
RABBITMQ_HOST: dc3-rabbitmq
|
||||
RABBITMQ_PORT: "5672"
|
||||
RABBITMQ_USERNAME: ${RABBITMQ_USERNAME:-dc3}
|
||||
RABBITMQ_PASSWORD: ${RABBITMQ_PASSWORD:-dc3dc3dc3}
|
||||
MQTT_BROKER_HOST: dc3-rabbitmq
|
||||
MQTT_BROKER_PORT: "1883"
|
||||
MQTT_USERNAME: ${MQTT_USERNAME:-dc3}
|
||||
MQTT_PASSWORD: ${MQTT_PASSWORD:-dc3dc3dc3}
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: ${DC3_IMAGE_REGISTRY:-pnoker}/dc3-postgres:${DC3_IMAGE_TAG:-2026.6}
|
||||
environment:
|
||||
POSTGRES_DB: ${POSTGRES_DB:-dc3}
|
||||
POSTGRES_USER: ${POSTGRES_USERNAME:-dc3}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-dc3dc3dc3}
|
||||
volumes:
|
||||
- postgres:/var/lib/postgresql
|
||||
healthcheck:
|
||||
test: [ "CMD-SHELL", "pg_isready -U ${POSTGRES_USERNAME:-dc3} -d ${POSTGRES_DB:-dc3}" ]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 15s
|
||||
networks: [ dc3net ]
|
||||
|
||||
rabbitmq:
|
||||
image: ${DC3_IMAGE_REGISTRY:-pnoker}/dc3-rabbitmq:${DC3_IMAGE_TAG:-2026.6}
|
||||
environment:
|
||||
RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_VIRTUAL_HOST:-dc3}
|
||||
RABBITMQ_DEFAULT_USER: ${RABBITMQ_USERNAME:-dc3}
|
||||
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD:-dc3dc3dc3}
|
||||
RABBITMQ_MQTT_EXCHANGE: ${RABBITMQ_MQTT_EXCHANGE:-dc3.e.mqtt}
|
||||
volumes:
|
||||
- rabbitmq:/var/lib/rabbitmq
|
||||
healthcheck:
|
||||
test: [ "CMD", "rabbitmq-diagnostics", "-q", "ping" ]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
networks: [ dc3net ]
|
||||
|
||||
auth:
|
||||
image: ${DC3_IMAGE_REGISTRY:-pnoker}/dc3-center-auth:${DC3_IMAGE_TAG:-2026.6}
|
||||
environment: *app-env
|
||||
healthcheck:
|
||||
test: [ "CMD-SHELL", "curl -fsS http://127.0.0.1:8300/auth/actuator/health/readiness >/dev/null || exit 1" ]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 40s
|
||||
networks: [ dc3net ]
|
||||
|
||||
manager:
|
||||
image: ${DC3_IMAGE_REGISTRY:-pnoker}/dc3-center-manager:${DC3_IMAGE_TAG:-2026.6}
|
||||
environment: *app-env
|
||||
healthcheck:
|
||||
test: [ "CMD-SHELL", "curl -fsS http://127.0.0.1:8400/manager/actuator/health/readiness >/dev/null || exit 1" ]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 40s
|
||||
networks: [ dc3net ]
|
||||
|
||||
data:
|
||||
image: ${DC3_IMAGE_REGISTRY:-pnoker}/dc3-center-data:${DC3_IMAGE_TAG:-2026.6}
|
||||
environment: *app-env
|
||||
healthcheck:
|
||||
test: [ "CMD-SHELL", "curl -fsS http://127.0.0.1:8500/data/actuator/health/readiness >/dev/null || exit 1" ]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 40s
|
||||
networks: [ dc3net ]
|
||||
|
||||
agentic:
|
||||
image: ${DC3_IMAGE_REGISTRY:-pnoker}/dc3-center-agentic:${DC3_IMAGE_TAG:-2026.6}
|
||||
environment:
|
||||
<<: *app-env
|
||||
AGENTIC_FALLBACK_OPENAI_BASE_URL: ${AGENTIC_FALLBACK_OPENAI_BASE_URL:-https://api.openai.com}
|
||||
AGENTIC_FALLBACK_OPENAI_API_KEY: ${AGENTIC_FALLBACK_OPENAI_API_KEY:-}
|
||||
AGENTIC_FALLBACK_OPENAI_MODEL: ${AGENTIC_FALLBACK_OPENAI_MODEL:-gpt-4o}
|
||||
healthcheck:
|
||||
test: [ "CMD-SHELL", "curl -fsS http://127.0.0.1:8600/agentic/actuator/health/readiness >/dev/null || exit 1" ]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 40s
|
||||
networks: [ dc3net ]
|
||||
|
||||
gateway:
|
||||
image: ${DC3_IMAGE_REGISTRY:-pnoker}/dc3-gateway:${DC3_IMAGE_TAG:-2026.6}
|
||||
environment: *app-env
|
||||
ports:
|
||||
- "8000:8000"
|
||||
healthcheck:
|
||||
test: [ "CMD-SHELL", "curl -fsS http://127.0.0.1:8000/actuator/health/readiness >/dev/null || exit 1" ]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 30s
|
||||
networks: [ dc3net ]
|
||||
|
||||
web:
|
||||
image: pnoker/dc3-web:latest
|
||||
environment:
|
||||
APP_API_HOST: dc3-gateway
|
||||
APP_API_PORT: "8000"
|
||||
ports:
|
||||
- "8080:80"
|
||||
networks: [ dc3net ]
|
||||
|
||||
# Drivers follow the same pattern, for example:
|
||||
# virtual:
|
||||
# image: ${DC3_IMAGE_REGISTRY:-pnoker}/dc3-driver-virtual:${DC3_IMAGE_TAG:-2026.6}
|
||||
# environment: *app-env
|
||||
# networks: [ dc3net ]
|
||||
# Listening drivers additionally publish their device ingress ports
|
||||
# (TCP 6270 / UDP 6271 for dc3-driver-listening-virtual).
|
||||
|
||||
networks:
|
||||
dc3net:
|
||||
driver: overlay
|
||||
attachable: true
|
||||
|
||||
volumes:
|
||||
postgres:
|
||||
rabbitmq:
|
||||
```
|
||||
|
||||
## ☸️ Kubernetes
|
||||
|
||||
> Deploy the same images as Deployments behind Services that keep the default DNS names. The images resolve each
|
||||
> other through those names, so either create Services named `dc3-center-auth`, `dc3-center-manager`,
|
||||
> `dc3-center-data`, `dc3-center-agentic`, `dc3-gateway`, `dc3-postgres`, and `dc3-rabbitmq` in one namespace, or
|
||||
> override `CENTER_*_HOST`, `POSTGRES_HOST`, `RABBITMQ_HOST`, and `MQTT_BROKER_HOST`.
|
||||
|
||||
Service ports and probe paths:
|
||||
|
||||
| Service | HTTP | gRPC | Readiness path |
|
||||
|-----------------------|------|------------|---------------------------------------|
|
||||
| `dc3-gateway` | 8000 | — (client) | `/actuator/health/readiness` |
|
||||
| `dc3-center-auth` | 8300 | 9300 | `/auth/actuator/health/readiness` |
|
||||
| `dc3-center-manager` | 8400 | 9400 | `/manager/actuator/health/readiness` |
|
||||
| `dc3-center-data` | 8500 | 9500 | `/data/actuator/health/readiness` |
|
||||
| `dc3-center-agentic` | 8600 | — (client) | `/agentic/actuator/health/readiness` |
|
||||
| `dc3-web` | 80 | — | `/` |
|
||||
|
||||
Representative manifest (namespace, shared configuration, one Deployment, and its Service):
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: dc3
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: dc3-runtime
|
||||
namespace: dc3
|
||||
data:
|
||||
NODE_ENV: "test" # "pro" disables OpenAPI/Swagger UI
|
||||
POSTGRES_HOST: dc3-postgres
|
||||
POSTGRES_PORT: "5432"
|
||||
POSTGRES_DB: dc3
|
||||
RABBITMQ_VIRTUAL_HOST: dc3
|
||||
RABBITMQ_HOST: dc3-rabbitmq
|
||||
RABBITMQ_PORT: "5672"
|
||||
MQTT_BROKER_HOST: dc3-rabbitmq
|
||||
MQTT_BROKER_PORT: "1883"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: dc3-credentials
|
||||
namespace: dc3
|
||||
stringData:
|
||||
DC3_SECURITY_KEY: change-me
|
||||
AUTH_HMAC_SECRET: change-me
|
||||
POSTGRES_USERNAME: dc3
|
||||
POSTGRES_PASSWORD: dc3dc3dc3
|
||||
RABBITMQ_USERNAME: dc3
|
||||
RABBITMQ_PASSWORD: dc3dc3dc3
|
||||
MQTT_USERNAME: dc3
|
||||
MQTT_PASSWORD: dc3dc3dc3
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: dc3-center-auth
|
||||
namespace: dc3
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: dc3-center-auth
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: dc3-center-auth
|
||||
spec:
|
||||
containers:
|
||||
- name: dc3-center-auth
|
||||
image: pnoker/dc3-center-auth:2026.6
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: dc3-runtime
|
||||
- secretRef:
|
||||
name: dc3-credentials
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /auth/actuator/health/readiness
|
||||
port: 8300
|
||||
initialDelaySeconds: 40
|
||||
periodSeconds: 15
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /auth/actuator/health/readiness
|
||||
port: 8300
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 30
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: dc3-center-auth
|
||||
namespace: dc3
|
||||
spec:
|
||||
selector:
|
||||
app: dc3-center-auth
|
||||
ports:
|
||||
- name: http
|
||||
port: 8300
|
||||
targetPort: 8300
|
||||
- name: grpc
|
||||
port: 9300
|
||||
targetPort: 9300
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- Repeat the Deployment/Service pair for the other centers using the port and probe-path table above (`dc3-center-agentic` has no gRPC port), then deploy `dc3-gateway` (HTTP 8000) and `dc3-web` (port 80, env `APP_API_HOST=dc3-gateway`, `APP_API_PORT=8000`) behind an Ingress or LoadBalancer.
|
||||
- Drivers are plain Deployments with the same `envFrom` blocks and no Service; expose device ingress ports only for listening drivers (TCP 6270 / UDP 6271 for `dc3-driver-listening-virtual`).
|
||||
- Dependencies: reuse the `dc3-postgres` and `dc3-rabbitmq` images (push them to a registry the cluster can pull; give PostgreSQL a PersistentVolumeClaim — the seed SQL under `/docker-entrypoint-initdb.d` runs only on first start), or use managed services and override `POSTGRES_HOST`/`RABBITMQ_HOST`/`MQTT_BROKER_HOST`. A self-managed PostgreSQL needs the TimescaleDB extension; a self-managed RabbitMQ needs the MQTT plugin and the `dc3.e.mqtt` exchange.
|
||||
- Verify rollout with `kubectl -n dc3 get pods -w`; pods stay unready until their dependencies answer.
|
||||
|
||||
## ⎈ Helm
|
||||
|
||||
> There is no official chart yet; a minimal chart wrapping the manifests above is enough to manage releases with Helm.
|
||||
|
||||
Create the chart and drive the service list from values:
|
||||
|
||||
```bash
|
||||
helm create dc3
|
||||
```
|
||||
|
||||
`dc3/values.yaml`:
|
||||
|
||||
```yaml
|
||||
image:
|
||||
registry: pnoker # registry.cn-beijing.aliyuncs.com/dc3 in mainland China
|
||||
tag: "2026.6" # the release series to deploy
|
||||
|
||||
runtime:
|
||||
nodeEnv: test # pro disables OpenAPI/Swagger UI
|
||||
|
||||
services:
|
||||
- name: dc3-center-auth
|
||||
port: 8300
|
||||
grpcPort: 9300
|
||||
readinessPath: /auth/actuator/health/readiness
|
||||
- name: dc3-center-manager
|
||||
port: 8400
|
||||
grpcPort: 9400
|
||||
readinessPath: /manager/actuator/health/readiness
|
||||
- name: dc3-center-data
|
||||
port: 8500
|
||||
grpcPort: 9500
|
||||
readinessPath: /data/actuator/health/readiness
|
||||
- name: dc3-center-agentic
|
||||
port: 8600
|
||||
readinessPath: /agentic/actuator/health/readiness
|
||||
- name: dc3-gateway
|
||||
port: 8000
|
||||
readinessPath: /actuator/health/readiness
|
||||
- name: dc3-driver-virtual # drivers: no Service, no probe
|
||||
```
|
||||
|
||||
`dc3/templates/workloads.yaml` (replace the generated `deployment.yaml`/`service.yaml`, and keep the ConfigMap/Secret from the Kubernetes section as chart templates):
|
||||
|
||||
```yaml
|
||||
{{- range .Values.services }}
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ .name }}
|
||||
labels:
|
||||
app: {{ .name }}
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ .name }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ .name }}
|
||||
spec:
|
||||
containers:
|
||||
- name: {{ .name }}
|
||||
image: "{{ $.Values.image.registry }}/{{ .name }}:{{ $.Values.image.tag }}"
|
||||
env:
|
||||
- name: NODE_ENV
|
||||
value: {{ $.Values.runtime.nodeEnv | quote }}
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: dc3-runtime
|
||||
- secretRef:
|
||||
name: dc3-credentials
|
||||
{{- if .readinessPath }}
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: {{ .readinessPath }}
|
||||
port: {{ .port }}
|
||||
initialDelaySeconds: 40
|
||||
periodSeconds: 15
|
||||
{{- end }}
|
||||
{{- if .port }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ .name }}
|
||||
spec:
|
||||
selector:
|
||||
app: {{ .name }}
|
||||
ports:
|
||||
- name: http
|
||||
port: {{ .port }}
|
||||
targetPort: {{ .port }}
|
||||
{{- with .grpcPort }}
|
||||
- name: grpc
|
||||
port: {{ . }}
|
||||
targetPort: {{ . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
```
|
||||
|
||||
Install and upgrade:
|
||||
|
||||
```bash
|
||||
helm lint dc3
|
||||
helm install dc3 ./dc3 --namespace dc3 --create-namespace
|
||||
helm upgrade dc3 ./dc3 --namespace dc3 --set image.tag=2026.7
|
||||
```
|
||||
|
||||
> The `dc3-web` image is tagged with `latest` and full release versions rather than the series tag, so deploy it as
|
||||
> its own template (see the Kubernetes section) instead of adding it to `services`.
|
||||
|
||||
Reference in New Issue
Block a user