Symphony, as a toolchain orchestrator, is designed to provide consistent, end-to-end management workflows across heterogeneous edge environments. Key features include:
- Deploying distributed applications and device updates across various device types.
- Managing workflows with distributed stages, such as running tests on remote machines and collecting results.
- Centrally managing configurations with context-specific overrides.
Symphony provides flexible options to connect to underlying systems like Eclipse BlueChi, Eclipse Pullpiri and Eclipse Ankaios, as shown in the following diagram. A key construct of extension is called a provider. Symphony allows extensions with two types of providers:
- A Target Provider that participates in Symphony's state-seeking process, such as applying a software to a custom system.
- A Stage Provider that participates in Symphony's distributed workflow, such as running a task on a specific machine.
For this challenge, we'll mostly focus on the target providers. However, we are also open to scenarios that leverage custom stage providers.
-
Symphony offers a collection of native providers to interact with common software deployment and management tools like Helm, Docker, Azure IoT Edge, Device Update for IoT Hub, Windows 10/11 Sideloading and Kubernetes artifacts.
-
Symphony also welcome contributions of providers, such as the recent Eclipse Pullpiri provider contributed by LGE.
-
Symphony supports a remote agent written in any programming language and communicates with the Symphony control plane over MQTT. A remote agent can:
- Participate in Symphony state-seeking process, such as applying software to a custom system.
- Participate in Symphony workflow, such as running a task on a specific system.
For example, Eclipse Ankaios is exploring this route using Symphony's Python SDK (PoC).
-
Symphony also provides a pre-built agent over MQTT. This full-featured agent is able to load additional providers, such as a script provider that can perform software update operations using PowerShell or Bash. This route can be used for USB-attached devices such as flashing a RTOS system.
-
Symphony also allows a remote agent to implement Symphony target provider interface as a web server. Although this can be used for a remote agent, it's more commonly used in a sidecar pattern for process isolation on the same control plane (such as granting minimum required access to a provider process).
-
Similar to the MQTT-based agent, Symphony also provides a pre-built agent over HTTP that is able to load additional providers, such as a script provider.
-
For constrained devices, you can implement a pulling agent, which is essentially a web client querying Symphony for stated states for the represented target devices. Symphony offers a sample pulling agent named Piccolo that supports Docker, WebAssembly and eBPF payloads. Piccolo is written in Rust and is 4MB in side. We anticipate even smaller pulling agents can be authored for the most constrained devices.
-
The script provider can also be directly loaded to the Symphony control plane. This can be used for cases like managing cloud-based resources, or resources co-located with the control plane itself.
-
Symphony provides HTTP(S) and MQTT binding out-of-box. Additional protocols like CAN can be supported with additional protocol bindings.
You can use Symphony's CLI, maestro, to install Symphony. To get maestro, run this command:
wget -q https://raw.githubusercontent.com/eclipse-symphony/symphony/master/cli/install/install.sh -O - | /bin/bash
And once maestro is installed, you can use this command to install Symphony to your current K8s context:
maestro up
NOTE: If you don't have a current K8s context, maestro can install Minikube on your machine first and then install Symphony. Because Minikube can't assign a public IP, the post-command condition check will fail. Use
Ctrl+C
to stop the command. You'll still be able to access Symphony usingkubectl
.
Alternatively, you can use Helm (v3) to install Symphony on to a Kubernetes cluster such as AKS, K3s and Minikube:
helm install symphony oci://ghcr.io/eclipse-symphony/helm/symphony --version '0.48.32'
NOTE: For this hackathon, make sure to use the 0.48.32 version.
Once you've installed Symphony, you can use standard K8s tools like kubectl
to interact with Symphony. Essentially, you need to create Solution
objects that describe your applications, Target
objects that describe your infrastructure, and Instance
objects that describe an deployment, which maps a Solution
to one mor multiple Target
s.
A Solution
is comprised of one or multiple Component
, and each Component
has an associated type
. Corresponding, a Target
has one or more bindings that bind a component type to a Target Provider.
You can follow instructions here to deploying a hello-world solution to K8s using Symphony. And additional scenarios can be found here.
In this hackathon, we'll use a MQTT broker to facilitate communication between Symphony and the remote agent, which you'll run from your machine or on your target device.
We offer a sample deployment file at eclispe-symphony/mosquitto/mosquitto.yaml
, which you can use to deploy a mosquitto test MQTT broker with anoymous access enabled.
kubectl apply -f eclipse-symphony/mosquitto/mosquitto.yaml
Once deployment is complete, you should see a mosquitto-service
service in your service list. This will the broker your agents connect to.
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
...
mosquitto-service LoadBalancer 10.0.231.136 172.179.118.100 1883:32640/TCP
...
If you are using Minikube, you'll need to use K8s port forwarding to expose the service to your local machine. Then, you'll be able to access the MQTT broker through tcp://localhost:1883
.
kubectl port-forward svc/mosquitto-service 1883:1883
When a truck docks at a field office, a Symphony workflow (Campaign
) is executed to register the truck as a Target
object with Symphony, using a predefined truck template. We offer four sample truck templates (as Catalog objects) under the eclipse-symphony/truck-templates
folder:
Template (Catalog) | Description |
---|---|
mock-truck.yaml |
A truck that uses a mock Target provider, which doesn't do any actual deployments. |
reefer-truck.yaml |
A reefer truck with built-in refrigeration units to transport perishable goods like food and pharmaceuticals. |
box-truck.yaml |
A Trucks with enclosed cargo areas. |
flatbed-truck.yaml |
A Truck with an open, flat trailer, used for transporting large, heavy items that don’t fit within standard truck dimensions. |
Except for the mock-truck
, all truck templates are configured to use a MQTT Target Provider that delegate state-seeking calls to a remote agent, which you'll set up later.
To provision these templates, simply use the kubectl command from the truck-templates
folder:
kubectl apply -f eclipse-symphony/truck-templates/.
Once the Catalogs are provisioned, you can use kubectl
to list them out (Each Catalog
belongs to a CatalogContainer
, which can contain multiple versions of the Catalog
):
kubectl get catalogcontainer
NAME AGE
box-truck 8s
flatbed-truck 8s
mock-truck 5m33s
reefer-truck 102s
kubectl get catalog
NAME AGE
box-truck-v-v1 12s
flatbed-truck-v-v1 12s
mock-truck-v-v1 5m36s
reefer-truck-v-v1 106s
NOTE: If you are using a local mosquitto broker, you need to update
brokerAddress
in the templates totcp://localhost:1883
.
The truck docking workflow is defined as a Symphony Campaign
object. To define the docker working flow:
kubectl apply -f eclipse-symphony/workflows/docking.yaml
To deploy Symphony sample portal, review the eclipse-symphony/portal/opera-deployment.yaml
file. Especially, if you want to use OpenAI features, you need to set OPENAI_API_KEY
to your OpenAI API key. Then, you can deploy the portal using kubectl
:
kubectl apply -f eclipse-symphony/portal/opera-deployment.yaml
If you are using Minikube, you'll need to use K8s port forwarding to expose the service to your local machine.
kubectl port-forward svc/opera-service 3000:3000
To test out the docking workflow, you can create an Activation
object to activate the above Campaign
. For example, the following activation activates the docking workflow using the mock-truck
template:
apiVersion: workflow.symphony/v1
kind: Activation
metadata:
name: mock-truck-docking-activation
spec:
campaign: "docking:v1"
stage: ""
inputs:
truck-template: mock-truck:v1
To apply the activation, use kubectl
:
kubectl apply -f <your activation file>
NOTE: You can use the provided
*-activation.yaml
files to activate the workflow for different truck types.
NOTE: Once an activation is created it can't be updated, as it serves as workflow executiong record. To re-activate a campaign, you'll need to re-create the activation object (by deleting it and recreating it), or to create a new activation object.
If you've activated the workflow for all truck templates, you should see a number of Target
objects created:
kubectl get target
NAME STATUS
box-truck Succeeded
flatbed-truck Succeeded
mock-truck Succeeded
reefer-truck Succeeded
You can also see these targets on the Opera targets view if you've deployed Opera:
You can generate a Symphony Agent configuration file using maestro
(see Installing Symphony section for instructions to install maestro
using a single command).
Run maestro
with the following paramters:
Parameter | Value |
---|---|
--mqtt-broker |
MQTT broker address. If you've deployed MQTT broker as instructed above, you should set this value to the public IP of your mosquitto-service , for example tcp://172.179.118.110:1883 or tcp://localhost:1883 . |
--mqtt-client-id |
An unique MQTT client id of your choice. |
--target |
Symphony Target object name that this agent represents. This needs to match with the Symphony Target object name. |
--config-only |
Use this flag to generate the configuration file only. Otherwise, the agent will be directly launched. |
For example:
maestro agent --mqtt-broker tcp://172.179.118.110:1883 --mqtt-client-id box-truck --target box-truck --config-only
The above command generates a symphony-agent-box-truck.json
file under the <you home>/.symphony
folder. We also provides sample agent configuration files under the eclipse-symphony/agent
folder for your reference.
By default, the generated agent configuration file uses a mock Target provider (providers.target.mock). You can switch to a different Target Provider as needed - such as using a script provider, a Docker provider, or a custom provider (requires rebuild Symphony binary).
For example, instead of the default mock provider:
"box-truck": {
"type": "providers.target.mock",
"config": {}
},
You can switch to a Docker provider:
"box-truck": {
"type": "providers.target.docker",
"config": {}
},
Once you've created the customized agent configuration file, you can launch a new instance of Symphony Agent through command line:
~/.symphony/symphony-api -c <your agent configuration file> -l Debug
# for example
~/.symphony/symphony-api -c ~/.symphony/symphony-agent-box-truck.json -l Debug
We offer a few sample applications that you can use for quick tests.
Solution | Target | Instance | Description |
---|---|---|---|
box-solution.yaml |
box-truck |
box-instance.yaml |
Deploy a Redis container to the box truck, which uses a Docker provider |
kubectl apply -f eclipse-symphony/solution/box-solution.yaml
kubectl apply -f eclipse-symphony/solution/box-instance.yaml
This deployes a Redis container to your target machine. If you use docker ps
you should see the container running.
Optionally, you can use docker rm -r <container id>
to remove the container and observe Symphony brings it back to its desired state.
To delete the app, use:
kubectl delete instance box-instance
You should obseve the Docker container removed from your machine.