diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/Makefile b/manufacturing-ai-suite/industrial-edge-insights-multimodal/Makefile index 257365b9b..83dd9ff4b 100644 --- a/manufacturing-ai-suite/industrial-edge-insights-multimodal/Makefile +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/Makefile @@ -172,6 +172,24 @@ push_images: build @echo "Pushing the images to docker registry" docker compose -f $(DOCKER_COMPOSE_FILE) push + +# Generate helm packages +.PHONY: gen_helm_charts +gen_helm_charts: + @echo "Generating Helm packages" + @cp -f configs/grafana/* helm/ + @cp -f configs/influxdb/config/*.conf helm/ + @cp -f configs/influxdb/init-influxdb.sh helm/ + @cp -f configs/mqtt-broker/*.conf helm/ + @cp -f configs/telegraf/config/*.conf helm/ + @cp -f configs/telegraf/entrypoint.sh helm/telegraf_entrypoint.sh + @cp -f configs/time-series-analytics-microservice/config.json helm/ + @cp -f configs/nginx/nginx-cert-gen.sh helm/nginx-cert-gen.sh + @cp -f configs/nginx/nginx.conf helm/nginx.conf + @cp -f configs/dlstreamer-pipeline-server/config.json helm/dlstreamer-pipeline-server.json + @sed -i 's/"auto_start": true,/"auto_start": false,/' helm/dlstreamer-pipeline-server.json + @echo "Helm packages generated" + # Help .PHONY: help help: @@ -183,4 +201,5 @@ help: @echo " make restart - Restart Docker containers" @echo " make clean - Remove all stopped containers and unused images" @echo " make push_images - Push the images to docker registry" + @echo " make gen_helm_charts - Generate Helm packages for the selected sample app" @echo " make help - Display this help message" diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/docs/user-guide/how-to-deploy-with-helm.md b/manufacturing-ai-suite/industrial-edge-insights-multimodal/docs/user-guide/how-to-deploy-with-helm.md new file mode 100644 index 000000000..7e30ee4c3 --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/docs/user-guide/how-to-deploy-with-helm.md @@ -0,0 +1,204 @@ +# Deploy with Helm + +This guide provides step-by-step instructions for deploying the MultiModal - Weld Defect Detection sample application using Helm. + +## Prerequisites + +- [System Requirements](system-requirements.md) +- K8s installation on single or multi node must be done as prerequisite to continue the following deployment. Note: The Kubernetes cluster is set up with `kubeadm`, `kubectl` and `kubelet` packages on single and multi nodes with `v1.30.2`. + Refer to tutorials such as and many other + online tutorials to setup kubernetes cluster on the web with host OS as Ubuntu 22.04. +- For Helm installation, refer to [helm website](https://helm.sh/docs/intro/install/) + +> **Note** +> If Ubuntu Desktop is not installed on the target system, follow the instructions from Ubuntu to [install Ubuntu desktop](https://ubuntu.com/tutorials/install-ubuntu-desktop). The target system refers to the system where you are installing the application. + +## Step 1: Generate or download the Helm charts + +You can either generate or download the Helm charts. + + +- To download the Helm charts: + + Follow this procedure on the target system to install the package. + + 1. Download Helm chart with the following command: + + `helm pull oci://registry-1.docker.io/intel/multimodal-weld-defect-detection-sample-app --version 1.0.0-weekly` + + 2. Unzip the package using the following command: + + `tar -xvzf multimodal-weld-defect-detection-sample-app-1.0.0-weekly.tgz` + + - Get into the Helm directory: + + `cd multimodal-weld-defect-detection-sample-app` + +- To generate the Helm charts: + + ```bash + cd edge-ai-suites/manufacturing-ai-suite/industrial-edge-insights-multimodal # path relative to git clone folder + + make gen_helm_charts + + cd helm/ + ``` + +## Step 2: Configure and update the environment variables + +1. Update the following fields in `values.yaml` file of the helm chart + + ```bash + WORK_DIR: # Update with the absolute path to your industrial-edge-insights-multimodal directory + INFLUXDB_USERNAME: + INFLUXDB_PASSWORD: + VISUALIZER_GRAFANA_USER: + VISUALIZER_GRAFANA_PASSWORD: + HTTP_PROXY: # example: http_proxy: http://proxy.example.com:891 + HTTPS_PROXY: # example: http_proxy: http://proxy.example.com:891 + MTX_WEBRTCICESERVERS2_0_USERNAME: + MTX_WEBRTCICESERVERS2_0_PASSWORD: + HOST_IP: # IP address of server where DL Streamer Pipeline Server is running + ``` + +## Step 3: Install Helm charts + +> **Note:** +> 1. Uninstall the Helm charts if already installed. +> 2. Note the `helm install` command fails if the above required fields are not populated +> as per the rules called out in `values.yaml` file. + +To install Helm charts, use one of the following options: + + ```bash + helm install multimodal-weld-defect-detection . -n multimodal-sample-app --create-namespace + ``` + +**Verify Installation:** + +> **Note:** +> 1. `deployment-coturn`, `deployment-fusion-analytics`, `deployment-ia-weld-data-simulator` and `deployment-telegraf` pods might restart since its depended on `deployment-mqtt-broker` and `deployment-mediamtx` + +Use the following command to verify if all the application resources got installed w/ their status: + + ```bash + kubectl get all -n multimodal-sample-app + ``` + +## Step 4: Copy the udf package for helm deployment + +**DL Streamer Pipeline Server** + +To copy your own or existing model into DL Streamer Pipeline Server in order to run this sample application in Kubernetes environment: + +The model package is available in the repository at `edge-ai-suites/manufacturing-ai-suite/industrial-edge-insights-multimodal/configs/dlstreamer-pipeline-server/`. + +Copy the resources such as video and model from local directory to the to the `dlstreamer-pipeline-server` pod to make them available for application while launching pipelines. + + ```bash + cd edge-ai-suites/manufacturing-ai-suite/industrial-edge-insights-multimodal/configs/dlstreamer-pipeline-server/ + + POD_NAME=$(kubectl get pods -n multimodal-sample-app -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\n' | grep deployment-dlstreamer-pipeline-server | head -n 1) + + kubectl cp models $POD_NAME:/home/pipeline-server/resources/ -c dlstreamer-pipeline-server -n multimodal-sample-app + ``` + +**Time Series Analytics Microservice** + +To copy your own or existing model into Time Series Analytics Microservice in order to run this sample application in Kubernetes environment: + +1. The following udf package is placed in the repository under `edge-ai-suites/manufacturing-ai-suite/industrial-edge-insights-multimodal/configs/time-series-analytics-microservice`. + + ``` + - time-series-analytics-microservice/ + - models/ + - weld_anomaly_detector.cb + - tick_scripts/ + - weld_anomaly_detector.tick + - udfs/ + - requirements.txt + - weld_anomaly_detector.py + ``` + +2. Copy your new UDF package to the `time-series-analytics-microservice` pod: + ```bash + cd edge-ai-suites/manufacturing-ai-suite/industrial-edge-insights-multimodal/configs/time-series-analytics-microservice # path relative to git clone folder + mkdir -p weld_anomaly_detector + cp -r models tick_scripts udfs weld_anomaly_detector/. + + POD_NAME=$(kubectl get pods -n multimodal-sample-app -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\n' | grep deployment-time-series-analytics-microservice | head -n 1) + + kubectl cp weld_anomaly_detector $POD_NAME:/tmp/ -n multimodal-sample-app + ``` + +> **Note:** +> Run the commands only after performing the Helm install. + +## Step 5: Activate the Pipeline/UDF Deployment Package + + +**DL Streamer Pipeline Server** + +You use a Client URL (cURL) command to start the pipeline. Start this pipeline with the following cURL command. + + curl -k https://localhost:30001/dsps-api/pipelines/user_defined_pipelines/weld_defect_classification -X POST -H 'Content-Type: application/json' -d '{ + "destination": { + "metadata": { + "type": "mqtt", + "topic": "vision_weld_defect_classification" + }, + "frame": { + "type": "webrtc", + "peer-id": "samplestream" + } + }, + "parameters": { + "classification-properties": { + "model": "/home/pipeline-server/resources/models/weld-defect-classification-f16-DeiT/deployment/Classification/model/model.xml", + "device": "CPU" + } + } + }' + +**Time Series Analytics Microservice** + +> **NOTE**: UDF inferencing on GPU is not supported. + +Run the following command to activate the UDF deployment package: + +```bash + curl -k -X 'GET' \ + 'https://localhost:30001/ts-api/config?restart=true' \ + -H 'accept: application/json' +``` + +## Step 6: Verify the Results + +Follow the verification steps in the [Get Started guide](get-started.md#verify-the-weld-defect-detection-results) + +## Uninstall Helm Charts + +To uninstall Helm charts: + +```bash +helm uninstall multimodal-weld-defect-detection -n multimodal-sample-app +kubectl get all -n multimodal-sample-app # It may take a few minutes for all application resources to be cleaned up. +``` + +## Configure Alerts in Time Series Analytics Microservice + +To configure alerts in Time Series Analytics Microservice, follow the steps [here](./how-to-configure-alerts.md#helm-deployment). + +## Troubleshooting + +- Check pod details or container logs to diagnose failures: + ```bash + kubectl get pods -n multimodal-sample-app + kubectl describe pod -n multimodal-sample-app # Shows details of the pod + kubectl logs -f -n multimodal-sample-app # Shows logs of the container in the pod + ``` + +## Known Issues + +- The video stream is not rendering in the Grafana. +- Time Series data and Fusion analytics results are initially displayed for the first 2-3 minutes, but then stop updating and no new results are loaded. diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/docs/user-guide/how-to-guides/how-to-configure-alerts.md b/manufacturing-ai-suite/industrial-edge-insights-multimodal/docs/user-guide/how-to-guides/how-to-configure-alerts.md index 0966b70c9..416124bd3 100644 --- a/manufacturing-ai-suite/industrial-edge-insights-multimodal/docs/user-guide/how-to-guides/how-to-configure-alerts.md +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/docs/user-guide/how-to-guides/how-to-configure-alerts.md @@ -66,6 +66,47 @@ docker exec -ti ia-mqtt-broker mosquitto_sub -h localhost -v -t vision_weld_defe docker exec -ti ia-mqtt-broker mosquitto_sub -h localhost -v -t fusion/anomaly_detection_results -p 1883 ``` +## Helm Deployment + +### Helm - Publish MQTT Alerts + +For detailed instructions on configuring and publishing MQTT alerts, refer to the [Publish MQTT Alerts](#docker---publish-mqtt-alerts) section. + +### Helm - Subscribe to MQTT Alerts + +Follow the steps to subscribe to the published MQTT alerts. + +To subscribe to MQTT topics in a Helm deployment, execute the following command: + +- Identify the MQTT broker pod name by running: + +```bash +kubectl get pods -n multimodal-sample-app | grep mqtt-broker +``` + +- Use the pod name from the output of the above command to subscribe to all topics: +```bash +kubectl exec -it -n multimodal-sample-app -- mosquitto_sub -h localhost -v -t '#' -p 1883 +``` + +#### Helm - Subscribing to Time Series Analytics Microservice Alerts + +```bash +kubectl exec -it -n multimodal-sample-app -- mosquitto_sub -h localhost -v -t alerts/weld_defect_detection -p 1883 +``` + +#### Helm - Subscribing to DL Streamer Pipeline Server Results + +```bash +kubectl exec -it -n multimodal-sample-app -- mosquitto_sub -h localhost -v -t vision_weld_defect_classification -p 1883 +``` + +#### Helm - Subscribing to Fusion Analytics Results + +```bash +kubectl exec -it -n multimodal-sample-app -- mosquitto_sub -h localhost -v -t fusion/anomaly_detection_results -p 1883 +``` + ## Supporting Resources - [Kapacitor MQTT Alert Documentation](https://docs.influxdata.com/kapacitor/v1/reference/event_handlers/mqtt/). diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/Chart.yaml b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/Chart.yaml new file mode 100644 index 000000000..1eb1cee80 --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/Chart.yaml @@ -0,0 +1,30 @@ +# +# Apache v2 license +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: v2 +name: multimodal-weld-defect-detection-sample-app +description: Helm charts for multimodal-weld-defect-detection sample app + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 1.0.0-weekly + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.0.0-weekly" diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/README.md b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/README.md new file mode 100644 index 000000000..5de4e48a3 --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/README.md @@ -0,0 +1 @@ +Please refer [link](../docs/user-guide/how-to-deploy-with-helm.md) for the helm deployment \ No newline at end of file diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/NOTES.txt b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/NOTES.txt new file mode 100644 index 000000000..1f023a22d --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/NOTES.txt @@ -0,0 +1,25 @@ +CHART NAME: {{ .Chart.Name }} +CHART VERSION: {{ .Chart.Version }} +APP VERSION: {{ .Chart.AppVersion }} + +** Please be patient while the chart is being deployed ** + +Get the list of pods by executing: + +`kubectl get pods --namespace {{ $.Values.namespace }}` + +By default, all our helm charts are deployed with `{{ $.Values.namespace }}` namespace, below commands will help us to deploy helm chart and kube pods with specific namespace + + +`helm install --set namespace= / --namespace --create-namespace` + +Access the pod you want to debug by executing + +`kubectl exec --namespace {{ $.Values.namespace }} -ti -- bash` + +Verify the pod logs by executing + +`kubectl logs -f ` + +Access Grafana at `https://nodeip:{{ $.Values.config.nginx.ext.https_port }}` + diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/broker.yaml b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/broker.yaml new file mode 100755 index 000000000..1bc047f21 --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/broker.yaml @@ -0,0 +1,62 @@ +# +# Apache v2 license +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.config.mqttbroker.name }} + namespace: {{ .Values.namespace }} +spec: + clusterIP: None + selector: + app: ia-mqtt-broker + ports: + - name: broker-port + port: {{ .Values.config.mqttbroker.mqttbroker_port }} + targetPort: {{ .Values.config.mqttbroker.mqttbroker_port }} + protocol: TCP + publishNotReadyAddresses: false +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: ia-mqtt-broker + name: deployment-mqtt-broker + namespace: {{ .Values.namespace }} + +spec: + selector: + matchLabels: + app: ia-mqtt-broker + template: + metadata: + labels: + app: ia-mqtt-broker + spec: + containers: + - name: ia-mqtt-broker + image: eclipse-mosquitto:2.0.21 + imagePullPolicy: {{ .Values.imagePullPolicy }} + securityContext: + runAsUser: {{ $.Values.env.TIMESERIES_UID }} + runAsGroup: {{ $.Values.env.TIMESERIES_UID }} + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + volumeMounts: + - name: mosquitto-conf + mountPath: /mosquitto/config/mosquitto.conf + subPath: mosquitto.conf + + volumes: + - name: mosquitto-conf + configMap: + name: mosquitto-conf \ No newline at end of file diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/coturn.yaml b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/coturn.yaml new file mode 100644 index 000000000..69727a1c4 --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/coturn.yaml @@ -0,0 +1,73 @@ +# +# Apache v2 license +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: v1 +kind: Service +metadata: + name: coturn + namespace: {{ .Values.namespace }} +spec: + type: NodePort # Exposes the service externally + selector: + app: coturn + ports: + - name: "coturn-tcp" + protocol: TCP + port: {{ $.Values.config.coturn.int.coturn_tcp_port }} + targetPort: {{ $.Values.config.coturn.int.coturn_tcp_port }} + nodePort: {{ $.Values.config.coturn.ext.coturn_tcp_port }} # Exposed on the node + - name: "coturn-udp" + protocol: UDP + port: {{ $.Values.config.coturn.int.coturn_udp_port }} + targetPort: {{ $.Values.config.coturn.int.coturn_udp_port }} + nodePort: {{ $.Values.config.coturn.ext.coturn_udp_port }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: coturn + name: deployment-coturn + namespace: {{ .Values.namespace }} +spec: + replicas: 1 + selector: + matchLabels: + app: coturn + template: + metadata: + labels: + app: coturn + spec: + {{- if and .Values.DOCKER_USERNAME .Values.DOCKER_PASSWORD }} + imagePullSecrets: + - name: registryauth + {{- end }} + securityContext: + runAsNonRoot: true + runAsUser: 1000 + containers: + - name: coturn + image: coturn/coturn:4.7.0 + args: ["-v"] # Enable verbose logging + ports: + - containerPort: {{ $.Values.config.coturn.int.coturn_tcp_port }} + protocol: TCP + - containerPort: {{ $.Values.config.coturn.int.coturn_udp_port }} + protocol: UDP + imagePullPolicy: {{ .Values.imagePullPolicy }} + # Added security context to improve container hardening + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + capabilities: + drop: + - ALL + add: + - NET_BIND_SERVICE + restartPolicy: Always \ No newline at end of file diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/dlstreamer-pipeline-server.yaml b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/dlstreamer-pipeline-server.yaml new file mode 100644 index 000000000..463a5adbf --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/dlstreamer-pipeline-server.yaml @@ -0,0 +1,189 @@ +# +# Apache v2 license +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: v1 +kind: Service +metadata: + name: {{ $.Values.config.dlstreamer_pipeline_server.name }} + namespace: {{ $.Values.namespace }} +spec: + type: NodePort + selector: + app: dlstreamer-pipeline-server + ports: + - name: "rest-api" + port: {{ $.Values.config.dlstreamer_pipeline_server.int.rest_api_port }} + targetPort: {{ $.Values.config.dlstreamer_pipeline_server.int.rest_api_port }} + - name: "rtsp-output-streaming" + port: {{ $.Values.config.dlstreamer_pipeline_server.int.rtsp_output_port }} + targetPort: {{ $.Values.config.dlstreamer_pipeline_server.int.rtsp_output_port }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: dlstreamer-pipeline-server + name: deployment-{{ $.Values.config.dlstreamer_pipeline_server.name }} + namespace: {{ $.Values.namespace }} +spec: + replicas: 1 + selector: + matchLabels: + app: dlstreamer-pipeline-server + template: + metadata: + labels: + app: dlstreamer-pipeline-server + spec: + securityContext: + supplementalGroups: [109,110,992] # render group IDs for ubuntu 20.04, 22.04 and 24.04 host OS + {{- if and $.Values.DOCKER_USERNAME $.Values.DOCKER_PASSWORD }} + imagePullSecrets: + - name: registryauth + {{- end }} + containers: + - name: {{ $.Values.config.dlstreamer_pipeline_server.name }} + image: {{ $.Values.DOCKER_REGISTRY }}{{ $.Values.images.dlstreamer_pipeline_server }} + imagePullPolicy: {{ $.Values.imagePullPolicy }} + {{- if $.Values.privileged_access_required }} + securityContext: + privileged: true # Required for direct access to /dev + readOnlyRootFilesystem: true + allowPrivilegeEscalation: true + capabilities: + drop: + - ALL + {{- else }} + securityContext: + runAsNonRoot: true + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + runAsUser: 1999 + capabilities: + drop: + - ALL + {{- end }} + terminationMessagePath: /tmp/termination-log + {{- if $.Values.gpu.enabled }} + resources: + limits: + {{ $.Values.gpu.type }}: {{ $.Values.gpu.count }} + {{- end }} + volumeMounts: + - mountPath: /var/cache/pipeline_root + name: vol-pipeline-root-tmpfs0 + - name: dev + mountPath: /dev + readOnly: true # Reduce risk while preserving access to GPU/NPU devices + - name: dev-shm + mountPath: /dev/shm + - name: tmp + mountPath: /tmp + - name: var-tmp + mountPath: /var/tmp + - name: run-udev + mountPath: /run/udev + - name: {{ $.Values.volumes.pipelines.name }} + mountPath: {{ $.Values.volumes.pipelines.location }} + - name: dlstreamer-pipeline-server-input + mountPath: /home/pipeline-server/config.json + subPath: config.json + - name: model-registry-temp-models + mountPath: /home/pipeline-server/mr_models + - name: pipeline-resources-models + mountPath: /home/pipeline-server/resources/ + - name: pipeline-resources-videos + mountPath: /home/pipeline-server/resources/videos + env: + - name: AppName + value: 'DLStreamerPipelineServer' + - name: ENABLE_WEBRTC + value: "true" + - name: ENABLE_RTSP + value: "true" + - name: WEBRTC_SIGNALING_SERVER + value: "http://mediamtx:{{ $.Values.config.mediamtx.int.webrtc_port }}" + - name: SERVICE_NAME + value: "dlstreamer-pipeline-server" + - name: REST_SERVER_PORT + value: "8080" + - name: no_proxy + value: localhost,127.0.0.1,.intel.com,{{ $.Values.env.RTSP_CAMERA_IP }},{{ $.Values.env.HOST_IP }},otel-collector,mediamtx,ia-mqtt-broker + - name: NO_PROXY + value: localhost,127.0.0.1,.intel.com,{{ $.Values.env.RTSP_CAMERA_IP }},{{ $.Values.env.HOST_IP }},otel-collector,mediamtx,ia-mqtt-broker + - name: http_proxy + value: {{ $.Values.env.HTTP_PROXY }} + - name: https_proxy + value: {{ $.Values.env.HTTPS_PROXY }} + - name: S3_STORAGE_HOST + value: "{{ $.Values.env.HOST_IP }}" + - name: S3_STORAGE_PORT + value: "{{ $.Values.env.S3_STORAGE_PORT }}" + - name: S3_STORAGE_USER + value: "{{ $.Values.env.MINIO_ACCESS_KEY }}" + - name: S3_STORAGE_PASS + value: "{{ $.Values.env.MINIO_SECRET_KEY }}" + - name: ENABLE_OPEN_TELEMETRY + value: "{{ $.Values.env.ENABLE_OPEN_TELEMETRY }}" + - name: OTEL_COLLECTOR_HOST + value: "{{ $.Values.env.HOST_IP }}" + - name: OTEL_COLLECTOR_PORT + value: "{{ $.Values.env.OTEL_COLLECTOR_PORT }}" + - name: OTEL_EXPORT_INTERVAL_MILLIS + value: "{{ $.Values.env.OTEL_EXPORT_INTERVAL_MILLIS }}" + - name: OPCUA_SERVER_IP + value: "{{ $.Values.env.OPCUA_SERVER_IP }}" + - name: OPCUA_SERVER_PORT + value: "{{ $.Values.env.OPCUA_SERVER_PORT }}" + - name: OPCUA_SERVER_USERNAME + value: "{{ $.Values.env.OPCUA_SERVER_USERNAME }}" + - name: OPCUA_SERVER_PASSWORD + value: "{{ $.Values.env.OPCUA_SERVER_PASSWORD }}" + - name: MR_URL + value: "{{ $.Values.env.MR_URL }}" + - name: MR_SAVED_MODELS_DIR + value: "{{ $.Values.env.MR_SAVED_MODELS_DIR }}" + - name: MR_REQUEST_TIMEOUT + value: "{{ $.Values.env.MR_REQUEST_TIMEOUT }}" + - name: MR_VERIFY_CERT + value: "{{ $.Values.env.MR_VERIFY_CERT }}" + - name: MQTT_HOST + value: '{{ .Values.config.mqttbroker.name }}' + - name: MQTT_PORT + value: '{{ .Values.config.mqttbroker.mqttbroker_port }}' + - name: LOG_LEVEL + value: "{{ $.Values.env.LOG_LEVEL }}" + volumes: + - name: vol-pipeline-root-tmpfs0 + emptyDir: {} + - name: dev + hostPath: + path: /dev + - name: dev-shm + hostPath: + path: /dev/shm + - name: tmp + hostPath: + path: /tmp + - name: var-tmp + hostPath: + path: /var/tmp + - name: run-udev + hostPath: + path: /run/udev + - name: model-registry-temp-models + emptyDir: {} + - name: pipeline-resources-models + emptyDir: {} + - name: pipeline-resources-videos + emptyDir: {} + - name: {{ $.Values.volumes.pipelines.name }} + hostPath: + path: {{ $.Values.volumes.pipelines.hostpath }} + #type: DirectoryOrCreate + - name: dlstreamer-pipeline-server-input + configMap: + name: dlstreamer-pipeline-server-config-input \ No newline at end of file diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/fusion-analytics.yaml b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/fusion-analytics.yaml new file mode 100644 index 000000000..53c07ec57 --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/fusion-analytics.yaml @@ -0,0 +1,97 @@ +# +# Apache v2 license +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: fusion-analytics + name: deployment-fusion-analytics + namespace: {{ .Values.namespace }} +spec: + replicas: 1 + selector: + matchLabels: + app: fusion-analytics + template: + metadata: + labels: + app: fusion-analytics + spec: + {{- if and .Values.DOCKER_USERNAME .Values.DOCKER_PASSWORD }} + imagePullSecrets: + - name: registryauth + {{- end }} + containers: + - name: fusion-analytics + image: {{ .Values.DOCKER_REGISTRY }}{{ .Values.images.fusion_analytics_image }}{{ if .Values.images.image_suffix }}-{{ .Values.images.image_suffix }}{{ end }} + imagePullPolicy: {{ .Values.imagePullPolicy }} + securityContext: + runAsUser: {{ .Values.env.TIMESERIES_UID }} + runAsGroup: {{ .Values.env.TIMESERIES_UID }} + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + env: + # MQTT Configuration + - name: MQTT_BROKER + value: "{{ .Values.config.mqttbroker.name }}" + - name: MQTT_PORT + value: "{{ .Values.config.mqttbroker.mqttbroker_port }}" + - name: no_proxy + value: "{{ .Values.config.mqttbroker.name }},{{ .Values.config.influx_db_server.name }},{{ .Values.env.timeseries_no_proxy }}" + - name: NO_PROXY + value: "{{ .Values.config.mqttbroker.name }},{{ .Values.config.influx_db_server.name }},{{ .Values.env.timeseries_no_proxy }}" + # Topic Configuration + - name: VISION_TOPIC + value: "vision_weld_defect_classification" + - name: TS_TOPIC + value: "ts_weld_anomaly_detection" + - name: FUSION_TOPIC + value: "fusion/anomaly_detection_results" + # Performance Configuration + - name: BUFFER_SIZE + value: "100" + - name: TOLERANCE_NS + value: "{{ .Values.env.TOLERANCE_NS }}" + # InfluxDB Configuration + - name: INFLUXDB_HOST + value: "{{ .Values.config.influx_db_server.name }}" + - name: INFLUXDB_PORT + value: "{{ .Values.config.influx_db_server.influx_http }}" + - name: INFLUXDB_DB + value: "datain" + - name: INFLUXDB_USERNAME + value: "{{ .Values.env.INFLUXDB_USERNAME }}" + - name: INFLUXDB_PASSWORD + value: "{{ .Values.env.INFLUXDB_PASSWORD }}" + # Python Configuration + - name: PYTHONUNBUFFERED + value: "1" + - name: FUSION_MODE + value: "{{ .Values.env.FUSION_MODE }}" + - name: LOG_LEVEL + value: "{{ .Values.env.LOG_LEVEL }}" + # Proxy Configuration + - name: HTTP_PROXY + value: "{{ .Values.env.HTTP_PROXY }}" + - name: HTTPS_PROXY + value: "{{ .Values.env.HTTPS_PROXY }}" + volumeMounts: + - name: tmp-volume + mountPath: /tmp + - name: app-volume + mountPath: /app/data + volumes: + - name: tmp-volume + emptyDir: {} + - name: app-volume + emptyDir: {} + restartPolicy: Always diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/grafana.yaml b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/grafana.yaml new file mode 100644 index 000000000..07671c4b3 --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/grafana.yaml @@ -0,0 +1,116 @@ +# +# Apache v2 license +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: v1 +kind: Service +metadata: + name: {{ $.Values.config.grafana.name }} + namespace: {{ $.Values.namespace }} +spec: + type: NodePort + selector: + app: ia-grafana + ports: + - name: grafana-port + port: {{ $.Values.config.grafana.grafana_port }} + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: ia-grafana + name: deployment-grafana + namespace: {{ $.Values.namespace }} + +spec: + selector: + matchLabels: + app: ia-grafana + template: + metadata: + labels: + app: ia-grafana + spec: + {{- if and $.Values.DOCKER_USERNAME $.Values.DOCKER_PASSWORD }} + imagePullSecrets: + - name: registryauth + {{- end }} + containers: + - name: ia-grafana + image: grafana/grafana-oss:12.0.0-ubuntu + imagePullPolicy: {{ $.Values.imagePullPolicy }} + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + volumeMounts: + - name: vol-temp-grafana + mountPath: /tmp + - name: vol-grafana-data + mountPath: /var/lib/grafana + - name: grafana-dashboard-json + mountPath: /etc/grafana/provisioning/dashboards/grafana-dashboard.json + subPath: grafana-dashboard.json + - name: grafana-dashboard-yml + mountPath: /etc/grafana/provisioning/dashboards/dashboards.yml + subPath: dashboards.yml + - name: grafana-datasource + mountPath: /etc/grafana/provisioning/datasources/datasources.yml + subPath: datasources.yml + env: + - name: GF_SERVER_PROTOCOL + value: "http" + - name: INFLUXDB_USERNAME + value: '{{ $.Values.env.INFLUXDB_USERNAME }}' + - name: INFLUXDB_PASSWORD + value: '{{ $.Values.env.INFLUXDB_PASSWORD }}' + - name: INFLUX_SERVER + value: "influxdb" + - name: GRAFANA_SERVER + value: "0.0.0.0" + - name: GF_SECURITY_ADMIN_USER + value: '{{ $.Values.env.VISUALIZER_GRAFANA_USER }}' + - name: GF_SECURITY_ADMIN_PASSWORD + value: '{{ $.Values.env.VISUALIZER_GRAFANA_PASSWORD }}' + - name: GF_PROVISIONING_ENABLE + value: "true" + - name: INFLUXDB_DB + value: "datain" + - name: GF_PROVISIONING_DASHBOARDS + value: "/etc/grafana/provisioning/dashboards" + - name: GF_LOG_LEVEL + value: '{{ $.Values.env.LOG_LEVEL }}' + - name: GF_SERVER_SERVE_FROM_SUB_PATH + value: "true" + - name: GF_PANELS_DISABLE_SANITIZE_HTML + value: "true" + - name: GF_SECURITY_ALLOW_EMBEDDING + value: "true" + - name: GF_AUTH_LOGIN_MAXIMUM_INACTIVE_LIFETIME_DURATION + value: '{{ $.Values.env.VISUALIZER_GRAFANA_INACTIVE_TIMEOUT }}' + - name: GF_AUTH_LOGIN_MAXIMUM_LIFETIME_DURATION + value: '{{ $.Values.env.VISUALIZER_GRAFANA_INACTIVE_TIMEOUT }}' + - name: GF_SECURITY_LOGIN_REMEMBER_DAYS + value: "1" + volumes: + - name: vol-temp-grafana + emptyDir: {} + - name: vol-grafana-data + emptyDir: {} + - name: grafana-dashboard-json + configMap: + name: grafana-dashboard-json + - name: grafana-datasource + configMap: + name: grafana-datasource + - name: grafana-dashboard-yml + configMap: + name: grafana-dashboard-yml \ No newline at end of file diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/influxdb.yaml b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/influxdb.yaml new file mode 100644 index 000000000..6725acd9c --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/influxdb.yaml @@ -0,0 +1,90 @@ +# +# Apache v2 license +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.config.influx_db_server.name }} + namespace: {{ .Values.namespace }} +spec: + ports: + - port: {{ .Values.config.influx_db_server.influx_http }} + name: influx-db-port + selector: + app: influxdb +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: influxdb + name: deployment-influxdb + namespace: {{ .Values.namespace }} + +spec: + selector: + matchLabels: + app: influxdb + template: + metadata: + labels: + app: influxdb + spec: + {{- if and .Values.DOCKER_USERNAME .Values.DOCKER_PASSWORD }} + imagePullSecrets: + - name: registryauth + {{- end }} + containers: + - name: ia-influxdb + image: influxdb:1.11.8 + imagePullPolicy: {{ .Values.imagePullPolicy }} + securityContext: + runAsUser: {{ $.Values.env.TIMESERIES_UID }} + runAsGroup: {{ $.Values.env.TIMESERIES_UID }} + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + env: + - name: INFLUXDB_CONFIG_PATH + value: /etc/influxdb/influxdb.conf + - name: INFLUXDB_DB + value: 'datain' + - name: INFLUXDB_ADMIN_PASSWORD + value: '{{ .Values.env.INFLUXDB_PASSWORD }}' + - name: INFLUXDB_ADMIN_USER + value: 'admin' + - name: INFLUXDB_USER_PASSWORD + value: '{{ .Values.env.INFLUXDB_PASSWORD }}' + - name: INFLUXDB_USER + value: '{{ .Values.env.INFLUXDB_USERNAME }}' + - name: INFLUXDB_LOGGING_LEVEL + value: '{{ .Values.env.LOG_LEVEL }}' + - name: RETENTION_DURATION + value: '{{ .Values.env.INFLUXDB_RETENTION_DURATION }}' + - name: INFLUXDB_TLS_CIPHERS + value: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" + volumeMounts: + - name: tmpfs-data-volume + mountPath: /var/lib/influxdb + - name: influx-config + mountPath: /etc/influxdb/influxdb.conf + subPath: influxdb.conf + - name: init-influxdb + mountPath: /docker-entrypoint-initdb.d/init-influxdb.sh + subPath: init-influxdb.sh + volumes: + - name: init-influxdb + configMap: + name: init-influxdb + - name: influx-config + configMap: + name: influxdb-conf-input + - name: tmpfs-data-volume + emptyDir: {} diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/mediamtx.yaml b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/mediamtx.yaml new file mode 100644 index 000000000..2fc6f0b15 --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/mediamtx.yaml @@ -0,0 +1,104 @@ +# +# Apache v2 license +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: v1 +kind: Service +metadata: + name: mediamtx + namespace: {{ $.Values.namespace }} +spec: + type: NodePort + selector: + app: mediamtx + ports: + - name: "mediamtx-rtsp-port" + port: {{ $.Values.config.mediamtx.int.rtsp_port }} + targetPort: {{ $.Values.config.mediamtx.int.rtsp_port }} + nodePort: {{ $.Values.config.mediamtx.ext.rtsp_port }} + - name: "mediamtx-webrtc-port" + port: {{ $.Values.config.mediamtx.int.webrtc_port }} + targetPort: {{ $.Values.config.mediamtx.int.webrtc_port }} + nodePort: {{ $.Values.config.mediamtx.ext.webrtc_port }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: mediamtx-secret + namespace: {{ .Values.namespace }} +type: Opaque +data: + MTX_WEBRTCICESERVERS2_0_USERNAME: {{ .Values.env.MTX_WEBRTCICESERVERS2_0_USERNAME | b64enc }} + MTX_WEBRTCICESERVERS2_0_PASSWORD: {{ .Values.env.MTX_WEBRTCICESERVERS2_0_PASSWORD | b64enc }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: mediamtx + name: deployment-mediamtx + namespace: {{ .Values.namespace }} +spec: + replicas: 1 + selector: + matchLabels: + app: mediamtx + template: + metadata: + labels: + app: mediamtx + spec: + {{- if and .Values.DOCKER_USERNAME .Values.DOCKER_PASSWORD }} + imagePullSecrets: + - name: registryauth + {{- end }} + securityContext: + runAsNonRoot: true + runAsUser: 1000 + containers: + - name: mediamtx + env: + - name: http_proxy + value: {{ $.Values.env.http_proxy }} + - name: https_proxy + value: {{ $.Values.env.https_proxy }} + - name: no_proxy + value: "{{ $.Values.env.no_proxy }},{{ $.Values.env.HOST_IP }}" + - name: MTX_WEBRTCICESERVERS2_0_URL + value: "turn:{{ $.Values.env.HOST_IP }}:{{ $.Values.config.coturn.ext.coturn_udp_port }}" + - name: MTX_WEBRTCICESERVERS2_0_USERNAME + valueFrom: + secretKeyRef: + name: mediamtx-secret + key: MTX_WEBRTCICESERVERS2_0_USERNAME + - name: MTX_WEBRTCICESERVERS2_0_PASSWORD + valueFrom: + secretKeyRef: + name: mediamtx-secret + key: MTX_WEBRTCICESERVERS2_0_PASSWORD + - name: MTX_LOGLEVEL + value: "debug" + - name: MTX_API + value: "yes" + - name: MTX_RTSP + value: "yes" + - name: MTX_RTMP + value: "no" + - name: MTX_SRT + value: "no" + - name: MTX_HLS + value: "no" + image: bluenviron/mediamtx:1.11.3 + imagePullPolicy: {{ .Values.imagePullPolicy }} + # Added security context to restrict container privileges + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + capabilities: + drop: + - ALL + restartPolicy: Always \ No newline at end of file diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/network-policy.yaml b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/network-policy.yaml new file mode 100644 index 000000000..aafd150d7 --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/network-policy.yaml @@ -0,0 +1,36 @@ +# +# Apache v2 license +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ .Values.namespace }}-egress + namespace: {{ .Values.namespace }} +spec: + egress: + - {} + - to: + - namespaceSelector: + matchLabels: + name: {{ .Values.namespace }} + policyTypes: + - Egress +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ .Values.namespace }}-ingress + namespace: {{ .Values.namespace }} +spec: + ingress: + - {} + - from: + - namespaceSelector: + matchLabels: + name: {{ .Values.namespace }} + podSelector: {} + policyTypes: + - Ingress \ No newline at end of file diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/nginx.yaml b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/nginx.yaml new file mode 100644 index 000000000..9e04a5c7b --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/nginx.yaml @@ -0,0 +1,93 @@ +# +# Apache v2 license +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.config.nginx.name }} + namespace: {{ .Values.namespace }} +spec: + type: NodePort + selector: + app: nginx + ports: + - name: https + port: {{ $.Values.config.nginx.int.https_port }} + targetPort: {{ $.Values.config.nginx.int.https_port }} + nodePort: {{ $.Values.config.nginx.ext.https_port }} + - name: mqtt + port: {{ $.Values.config.nginx.int.mqtt_port }} + targetPort: {{ $.Values.config.nginx.int.mqtt_port }} + nodePort: {{ $.Values.config.nginx.ext.mqtt_port }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: nginx + name: deployment-nginx + namespace: {{ .Values.namespace }} + +spec: + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx-proxy + image: nginx:1.29.1-bookworm-perl + imagePullPolicy: {{ .Values.imagePullPolicy }} + securityContext: + runAsUser: {{ $.Values.env.TIMESERIES_UID }} + runAsGroup: {{ $.Values.env.TIMESERIES_UID }} + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + command: ["/bin/bash", "-c", "/usr/local/bin/nginx-cert-gen.sh && exec nginx -g 'daemon off;'"] + env: + - name: no_proxy + value: "ia-grafana,ia-time-series-analytics-microservice,ia-mqtt-broker,{{ .Values.env.timeseries_no_proxy }},coturn,mediamtx,{{ .Values.env.HOST_IP }},dlstreamer-pipeline-server" + - name: NO_PROXY + value: "ia-grafana,ia-time-series-analytics-microservice,ia-mqtt-broker,{{ .Values.env.timeseries_no_proxy }},coturn,mediamtx,{{ .Values.env.HOST_IP }},dlstreamer-pipeline-server" + - name: HOST_IP + value: "{{ .Values.env.HOST_IP }}" + - name: MEDIAMTX_SERVER + value: "{{ .Values.config.mediamtx.name }}" + - name: WHIP_SERVER_PORT + value: "{{ .Values.config.mediamtx.int.webrtc_port }}" + volumeMounts: + - name: nginx-conf + mountPath: /tmp/default.conf.template + subPath: nginx.conf + - name: nginx-cert-gen + mountPath: /usr/local/bin/nginx-cert-gen.sh + subPath: nginx-cert-gen.sh + - name: vol-temp-nginx + mountPath: /opt/nginx/certs + - name: vol-temp-nginx + mountPath: /var/cache/nginx + - name: vol-temp-nginx + mountPath: /run + - name: vol-temp-nginx + mountPath: /etc/nginx/ + volumes: + - name: nginx-conf + configMap: + name: nginx-conf + - name: nginx-cert-gen + configMap: + name: nginx-cert-gen + defaultMode: 0705 + - name: vol-temp-nginx + emptyDir: {} diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/provision-configmap.yaml b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/provision-configmap.yaml new file mode 100644 index 000000000..c8eb3b7c4 --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/provision-configmap.yaml @@ -0,0 +1,142 @@ +# +# Apache v2 license +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Values.namespace }} + name: telegraf-conf-input +data: + Telegraf.conf: |- +{{ .Files.Get "Telegraf.conf" | indent 4 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Values.namespace }} + name: influxdb-conf-input +data: + influxdb.conf: |- +{{ .Files.Get "influxdb.conf" | indent 4 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Values.namespace }} + name: init-influxdb +data: + init-influxdb.sh: |- +{{ .Files.Get "init-influxdb.sh" | indent 4 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Values.namespace }} + name: mosquitto-conf +data: + mosquitto.conf: |- +{{ .Files.Get "mosquitto.conf" | indent 4 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Values.namespace }} + name: grafana-dashboard-json +data: + grafana-dashboard.json: |- +{{ .Files.Get "weld_defect_detection.json" | indent 4 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Values.namespace }} + name: grafana-datasource +data: + datasources.yml: |- +{{ .Files.Get "datasources.yml" | indent 4 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Values.namespace }} + name: telegraf-entrypoint +data: + entrypoint.sh: |- +{{ .Files.Get "telegraf_entrypoint.sh" | indent 4 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Values.namespace }} + name: time-series-analytics-microservice-config +data: + config.json: |- +{{ .Files.Get "config.json" | indent 4 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Values.namespace }} + name: grafana-dashboard-yml +data: + dashboards.yml: |- +{{ .Files.Get "dashboards.yml" | indent 4 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Values.namespace }} + name: nginx-cert-gen +data: + nginx-cert-gen.sh: |- +{{ .Files.Get "nginx-cert-gen.sh" | indent 4 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Values.namespace }} + name: nginx-conf +data: + nginx.conf: |- +{{ .Files.Get "nginx.conf" | indent 4 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: {{ .Values.namespace }} + name: dlstreamer-pipeline-server-config-input +data: + config.json: |- +{{ .Files.Get "dlstreamer-pipeline-server.json" | indent 4 }} +--- +apiVersion: v1 +# PersistentVolume for entire simulation data folder +apiVersion: v1 +kind: PersistentVolume +metadata: + name: simulation-data-pv +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteMany + hostPath: + path: {{ .Values.env.WORK_DIR }}/weld-data-simulator/simulation-data + storageClassName: standard + persistentVolumeReclaimPolicy: Retain +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: simulation-data-pvc + namespace: {{ .Values.namespace }} +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 2Gi + storageClassName: standard + volumeName: simulation-data-pv \ No newline at end of file diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/telegraf.yaml b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/telegraf.yaml new file mode 100755 index 000000000..dbe445d48 --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/telegraf.yaml @@ -0,0 +1,86 @@ +# +# Apache v2 license +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: telegraf + name: deployment-telegraf + namespace: {{ .Values.namespace }} + +spec: + selector: + matchLabels: + app: telegraf + template: + metadata: + labels: + app: telegraf + spec: + {{- if and .Values.DOCKER_USERNAME .Values.DOCKER_PASSWORD }} + imagePullSecrets: + - name: registryauth + {{- end }} + containers: + - name: ia-telegraf + image: telegraf:1.34.3 + imagePullPolicy: {{ .Values.imagePullPolicy }} + command: ["/bin/sh"] + args: ["/entrypoint.sh"] + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + volumeMounts: + - name: tmpfs-volume + mountPath: /tmp + - name: telegraf-entrypoint + mountPath: /entrypoint.sh + subPath: entrypoint.sh + - name: telegraf-conf-input + mountPath: /etc/telegraf/Telegraf.conf + subPath: Telegraf.conf + + env: + - name: TELEGRAF_INPUT_PLUGIN + value: '{{ .Values.env.TELEGRAF_INPUT_PLUGIN }}' + - name: MQTT_BROKER_HOST + value: '{{ .Values.config.telegraf.MQTT_BROKER_HOST }}' + - name: INFLUXDB_USERNAME + value: '{{ .Values.env.INFLUXDB_USERNAME }}' + - name: INFLUXDB_PASSWORD + value: '{{ .Values.env.INFLUXDB_PASSWORD }}' + - name: INFLUX_SERVER + value: "influxdb" + - name: INFLUXDB_DBNAME + value: "datain" + - name: INFLUXDB_PORT + value: "8086" + - name: LOG_LEVEL + value: '{{ .Values.env.LOG_LEVEL }}' + - name: TELEGRAF_METRIC_BATCH_SIZE + value: '{{ .Values.env.TELEGRAF_METRIC_BATCH_SIZE }}' + - name: TELEGRAF_CONFIG_PATH + value: /etc/telegraf/Telegraf.conf + + - name: TS_MS_SERVER_URL + value: "http://{{ .Values.config.time_series_analytics_microservice.name }}:{{ .Values.config.time_series_analytics_microservice.kapacitor_port }}" + - name: OPCUA_SERVER + value: "opc.tcp://ia-opcua-server:4840/freeopcua/server/" + volumes: + - name: tmpfs-volume + emptyDir: {} + - name: telegraf-entrypoint + configMap: + name: telegraf-entrypoint + - name: telegraf-conf-input + configMap: + name: telegraf-conf-input \ No newline at end of file diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/time-series-analytics-microservice.yaml b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/time-series-analytics-microservice.yaml new file mode 100755 index 000000000..ee8f3d403 --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/time-series-analytics-microservice.yaml @@ -0,0 +1,126 @@ +# +# Apache v2 license +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.config.time_series_analytics_microservice.name }} + namespace: {{ .Values.namespace }} +spec: + type: NodePort + ports: + - port: {{ .Values.config.time_series_analytics_microservice.kapacitor_port }} + name: kapacitor-port + - name: rest-api-port + port: {{ .Values.config.time_series_analytics_microservice_rest_api.rest_api_port }} + selector: + app: ia-time-series-analytics-microservice +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: ia-time-series-analytics-microservice + name: deployment-time-series-analytics-microservice + namespace: {{ .Values.namespace }} + +spec: + selector: + matchLabels: + app: ia-time-series-analytics-microservice + template: + metadata: + labels: + app: ia-time-series-analytics-microservice + spec: + {{- if and .Values.DOCKER_USERNAME .Values.DOCKER_PASSWORD }} + imagePullSecrets: + - name: registryauth + {{- end }} + securityContext: + supplementalGroups: [109,110,992] # render group IDs for ubuntu 20.04, 22.04 and 24.04 host OS + containers: + - name: ia-time-series-analytics-microservice + image: {{ .Values.DOCKER_REGISTRY }}{{ .Values.images.time_series_analytics_image }}{{ if .Values.images.image_suffix }}-{{ .Values.images.image_suffix }}{{ end }} + imagePullPolicy: {{ .Values.imagePullPolicy }} + securityContext: + {{- if .Values.privileged_access_required }} + privileged: true # Required for /dev/dri access, if using GPU devices + allowPrivilegeEscalation: true + {{- else }} + privileged: false + allowPrivilegeEscalation: false + {{- end }} + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + volumeMounts: + - name: vol-temp-time-series-analytics-microservice + mountPath: /tmp + - name: time-series-analytics-microservice-config + mountPath: /app/config.json + subPath: config.json + - name: dev-dri + mountPath: /dev/dri + readOnly: true # Reduce risk while preserving access to GPU/NPU devices + - name: run-udev + mountPath: /run/udev + readOnly: true # Reduce risk while preserving access to udev information + + env: + - name: HTTP_PROXY + value: '{{ .Values.env.HTTP_PROXY }}' + - name: HTTPS_PROXY + value: '{{ .Values.env.HTTPS_PROXY }}' + - name: NO_PROXY + value: "influxdb,ia-time-series-analytics-microservice,ia-mqtt-broker,ia-opcua-server,localhost,model-registry" + - name: TIMESERIES_NO_PROXY + value: '{{ .Values.env.TIMESERIES_NO_PROXY }}' + - name: PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION + value: python + - name: KAPACITOR_INFLUXDB_0_USERNAME + value: '{{ .Values.env.INFLUXDB_USERNAME }}' + - name: KAPACITOR_PORT + value: '{{ .Values.config.time_series_analytics_microservice.kapacitor_port }}' + - name: KAPACITOR_INFLUXDB_0_PASSWORD + value: '{{ .Values.env.INFLUXDB_PASSWORD }}' + - name: KAPACITOR_URL + value: "http://ia-time-series-analytics-microservice:{{ .Values.config.time_series_analytics_microservice.kapacitor_port }}/" + - name: KAPACITOR_UNSAFE_SSL + value: "true" + - name: KAPACITOR_INFLUXDB_0_URLS_0 + value: "http://influxdb:{{ .Values.config.influx_db_server.influx_http }}/" + - name: INFLUX_SERVER + value: "influxdb" + - name: INFLUXDB_PORT + value: "8086" + - name: INFLUXDB_DBNAME + value: "datain" + - name: KAPACITOR_LOGGING_LEVEL + value: '{{ .Values.env.LOG_LEVEL }}' + - name: MQTT_BROKER_HOST + value: "ia-mqtt-broker" + - name: MQTT_BROKER_PORT + value: "1883" + - name: MODEL_REGISTRY_URL + value: "http://model-registry:8111" + - name: REST_API_ROOT_PATH + value: "/ts-api" + volumes: + - name: vol-temp-time-series-analytics-microservice + emptyDir: {} + - name: time-series-analytics-microservice-config + configMap: + name: time-series-analytics-microservice-config + - name: dev-dri + hostPath: + path: /dev/dri + - name: run-udev + hostPath: + path: /run/udev \ No newline at end of file diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/weld-data-simulator.yaml b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/weld-data-simulator.yaml new file mode 100644 index 000000000..30f8c61ef --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/templates/weld-data-simulator.yaml @@ -0,0 +1,69 @@ +# +# Apache v2 license +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: ia-weld-data-simulator + name: deployment-ia-weld-data-simulator + namespace: {{ .Values.namespace }} + +spec: + selector: + matchLabels: + app: ia-weld-data-simulator + template: + metadata: + labels: + app: ia-weld-data-simulator + spec: + {{- if and .Values.DOCKER_USERNAME .Values.DOCKER_PASSWORD }} + imagePullSecrets: + - name: registryauth + {{- end }} + containers: + - name: ia-weld-data-simulator + image: {{ .Values.DOCKER_REGISTRY }}{{ .Values.images.weld_data_simulator_image }}{{ if .Values.images.image_suffix }}-{{ .Values.images.image_suffix }}{{ end }} + imagePullPolicy: {{ .Values.imagePullPolicy }} + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + env: + - name: MQTT_BROKER + value: '{{ .Values.config.telegraf.MQTT_BROKER_HOST }}' + - name: MEDIAMTX_SERVER + value: "{{ .Values.config.mediamtx.name }}" + - name: MEDIAMTX_PORT + value: "{{ .Values.config.mediamtx.int.rtsp_port }}" + - name: RTSP_STREAM_NAME + value: "live.stream" + - name: TS_TOPIC + value: "{{ .Values.env.TS_TOPIC }}" + - name: LOG_LEVEL + value: '{{ .Values.env.LOG_LEVEL }}' + - name: CONTINUOUS_SIMULATOR_INGESTION + value: '{{ .Values.env.CONTINUOUS_SIMULATOR_INGESTION }}' + - name: SIMULATION_TARGET_FPS + value: "{{ .Values.env.SIMULATION_TARGET_FPS }}" + - name: TS_MS_SERVER + value: "{{ .Values.config.time_series_analytics_microservice.name }}" + - name: TS_MS_PORT + value: "{{ .Values.config.time_series_analytics_microservice.kapacitor_port }}" + volumeMounts: + - name: simulation-data + mountPath: /simulation-data + readOnly: true + + volumes: + - name: simulation-data + persistentVolumeClaim: + claimName: simulation-data-pvc \ No newline at end of file diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/values.schema.json b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/values.schema.json new file mode 100644 index 000000000..0c836952f --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/values.schema.json @@ -0,0 +1,59 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "env": { + "type": "object", + "properties": { + "INFLUXDB_USERNAME": { + "type": "string", + "pattern": "^[A-Za-z]{5,}$", + "not": { "pattern": "^admin$" }, + "description": "At least 5 characters - only alphabets allowed, cannot be 'admin'." + }, + "INFLUXDB_PASSWORD": { + "type": "string", + "pattern": "^[A-Za-z0-9]{10,}$", + "allOf": [ + { "pattern": ".*[0-9].*" }, + { "pattern": ".*[A-Za-z].*" } + ], + "description": "At least 10 alphanumeric, at least one digit." + }, + "VISUALIZER_GRAFANA_USER": { + "type": "string", + "pattern": "^[A-Za-z]{5,}$", + "description": "At least 5 characters - only alphabets allowed" + }, + "VISUALIZER_GRAFANA_PASSWORD": { + "type": "string", + "pattern": "^[A-Za-z0-9]{10,}$", + "allOf": [ + { "pattern": ".*[0-9].*" }, + { "pattern": ".*[A-Za-z].*" } + ], + "description": "At least 10 alphanumeric, at least one digit." + }, + "MTX_WEBRTCICESERVERS2_0_USERNAME": { + "type": "string", + "pattern": "^[A-Za-z]{5,}$", + "description": "At least 5 characters - only alphabets allowed" + }, + "MTX_WEBRTCICESERVERS2_0_PASSWORD": { + "type": "string", + "pattern": "^[A-Za-z0-9]{10,}$", + "allOf": [ + { "pattern": ".*[0-9].*" }, + { "pattern": ".*[A-Za-z].*" } + ], + "description": "At least 10 alphanumeric, at least one digit." + }, + "HOST_IP": { + "type": "string", + "pattern": "^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$", + "description": "Must be a valid IPv4 address (e.g., 192.168.1.1)." + } + } + } + } +} diff --git a/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/values.yaml b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/values.yaml new file mode 100644 index 000000000..6992a344d --- /dev/null +++ b/manufacturing-ai-suite/industrial-edge-insights-multimodal/helm/values.yaml @@ -0,0 +1,151 @@ +# +# Apache v2 license +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + + +namespace: multimodal-sample-app +# Please provide docker registry details below for docker images pull/push operations. +# Please provide full registry url with port trail by / +# e.q. localhost:5000/ +DOCKER_REGISTRY: '' +DOCKER_USERNAME: '' +DOCKER_PASSWORD: '' +imagePullPolicy: IfNotPresent +storageClassName: manual +env: + # The INFLUXDB_USERNAME must contain only alphabets and be at least 5 characters minimum + # Do not set INFLUXDB_USERNAME to 'admin'. + INFLUXDB_USERNAME: + + # The INFLUXDB_PASSWORD length must be a minimum of 10 alphanumeric characters with at least one digit + # Do not use the following special characters in the INFLUXDB_PASSWORD "~:'+[/@^{%(-"*|,&<`}._=}!>;?#$)\" + INFLUXDB_PASSWORD: + + # The VISUALIZER_GRAFANA_USER must contain only alphabets and be at least 5 characters minimum + VISUALIZER_GRAFANA_USER: + + # The VISUALIZER_GRAFANA_PASSWORD length must be a minimum of 10 alphanumeric characters with at least one digit + VISUALIZER_GRAFANA_PASSWORD: + + # If your environment requires a proxy to access external resources, please set the following variables. + # If no proxy is required, please leave them empty. + HTTP_PROXY: + HTTPS_PROXY: + + # Update with the absolute path to your industrial-edge-insights-multimodal directory + # Example: /home/user/edge-ai-suites/manufacturing-ai-suite/industrial-edge-insights-multimodal + WORK_DIR: "" + # If CONTINUOUS_SIMULATOR_INGESTION is set to true (default), continuous looping of simulator data is enabled. + # To ingest the simulator data only once (without looping), set this variable to false. + CONTINUOUS_SIMULATOR_INGESTION: true + TELEGRAF_INPUT_PLUGIN: mqtt_consumer + TIMESERIES_USER_NAME: timeseries_user + TIMESERIES_UID: 1999 + TIMESERIES_NO_PROXY: influxdb,ia-time-series-analytics-microservice,mqttbroker,ia-mqtt-broker,ia-opcua-server + # For proxy environment, please append IP addresses or Range IP addresses of each node of the cluster to no_proxy + # e.q. timeseries_no_proxy=localhost,127.0.0.1,10.223.109.130,10.223.109.170 + timeseries_no_proxy: localhost,127.0.0.1,.intel.com + # The InfluxDB retention policy durations can be configured using a combination of time units such as hours(h), minutes(m), and seconds(s), eg., 1h0m0s for 1 hour. + INFLUXDB_RETENTION_DURATION: 1h0m0s + # The Telegraf metric_batch_size specifies the number of metrics or data points that are grouped together and sent in a single batch to the InfluxDB. + TELEGRAF_METRIC_BATCH_SIZE: 100 + LOG_LEVEL: INFO + # Weld Data Simulator config + TS_TOPIC: weld-data + SIMULATION_TARGET_FPS: 10 + + ## DL Streamer Pipeline Server + # HOST_IP is the IP address of server where DLStreamer Pipeline Server is running + HOST_IP: + REST_SERVER_PORT: 8080 + RTSP_CAMERA_IP: mediamtx + + # Open Telemetry related config + ENABLE_OPEN_TELEMETRY: false + OTEL_COLLECTOR_HOST: otel-collector + OTEL_COLLECTOR_PORT: 4318 + OTEL_EXPORT_INTERVAL_MILLIS: 5000 + PROMETHEUS_PORT: 9999 + + # Webrtc related config + # mediamtx-port for streaming + WHIP_SERVER_PORT: 8889 + MTX_WEBRTCICESERVERS2_0_USERNAME: + MTX_WEBRTCICESERVERS2_0_PASSWORD: + COTURN_UDP_PORT: 3478 + + # Fusion Analytics config + FUSION_MODE: OR + TOLERANCE_NS: "50e6" + + # The VISUALIZER_GRAFANA_INACTIVE_TIMEOUT sets the duration after which Grafana logs out an inactive user + VISUALIZER_GRAFANA_INACTIVE_TIMEOUT: 1h +gpu: + enabled: false + type: "gpu.intel.com/i915" + count: 1 +images: + # Please provide the suffix for the image version you want to use like rc1, rc2, git hash id etc. + image_suffix: "weekly" + time_series_analytics_image: intel/ia-time-series-analytics-microservice:1.1.0 + weld_data_simulator_image: intel/ia-weld-data-simulator:1.0.0 + dlstreamer_pipeline_server: intel/dlstreamer-pipeline-server:2025.2.0-ubuntu24 + fusion_analytics_image: intel/ia-multimodal-fusion-analytics:1.0.0 +privileged_access_required: false +config: + influx_db_server: + name: influxdb + influx_http: 8086 + grafana: + name: ia-grafana + grafana_port: "3000" + telegraf: + name: telegraf + MQTT_BROKER_HOST: "ia-mqtt-broker" + time_series_analytics_microservice: + name: ia-time-series-analytics-microservice + kapacitor_port: 9092 + time_series_analytics_microservice_rest_api: + name: time-series-analytics-microservice-rest-api + rest_api_port: 5000 + mqttbroker: + name: ia-mqtt-broker + mqttbroker_port: 1883 + nginx: + name: nginx + int: + https_port: "15443" + mqtt_port: "1883" + ext: + https_port: "30001" + mqtt_port: "30002" + mediamtx: + name: mediamtx + int: + webrtc_port: "8889" + rtsp_port: "8554" + ext: + rtsp_port: "31111" + webrtc_port: "31112" + dlstreamer_pipeline_server: + name: dlstreamer-pipeline-server + int: + rest_api_port: "8080" + rtsp_output_port: "8554" + + coturn: + name: coturn + int: + coturn_tcp_port: "3478" + coturn_udp_port: "3478" + ext: + coturn_tcp_port: "30478" + coturn_udp_port: "30478" +volumes: + pipelines: + name: vol-pipelines + size: 100Mi + location: "/home/pipeline-server/pipelines" + hostpath: "/opt/intel/eii/pipelines"