Open Horizon Deployment Strings
When defining services in the Horizon Exchange, the deployment field defines how the service will be deployed. There are two deployment fields for a service, deployment
and clusterDeployment
. You can define either one or both depending on the type of the service you want it to be. The deployment
field is used by an edge node which tells Horizon how the docker images should be deployed on the node. The clusterDeployment
field is used by an Horizon agent running in a Kubernetes cluster. It tells Horizon how the application should be deployed in the Kubernetes cluster.
This page documents what can be specified in the deployment
and the clusterDeployment
fields.
Deployment String Format
The deployment
and clusterDeployment
strings are JSON which have been “stringified” (double quotes escaped, new lines removed, etc.). It should look like this:
"deployment": "{\"services\":{\"gps\":{\"image\":\"openhorizon/x86/gps:2.0.3\",\"privileged\":true,\"devices\":[\"/dev/bus/usb/001/001:/dev/bus/usb/001/001\"],\"network\":\"host\"}}}",
"clusterDeployment": "{\"operatorYamlArchive\":\"H4sIAEu8lF4AA+1aX2/bNhDPcz4FkT4EGGZZsmxn0JuXZluxtjGcoHsMaIm2uVKiRlLO0mHffUfq..."
Note: You do not need to stringify the deployment strings if you use the hzn
command to create the service in the exchange. However, if you use curl
command to create the service, you must stringify it.
Deployment string fields
Because Open Horizon uses the docker API to start the containers on an edge node, many of the fields that can be specified in the deployment string are similar to docker run
options.
services
: a list of docker images that are part of this service<container-name>
: the name docker should give the container. Equivalent to thedocker run --name
flag. Horizon will also define this as the hostname for the container on the docker network, so other containers in the same network can connect to it using this name.image
: the docker image to be downloaded from the Horizon image server. The same name:tag format as used fordocker pull
.privileged
:{true|false}
- set to true if the container needs privileged mode. When set to true, the service can only be deployed to nodes with property openhorizon.allowPrivileged set to true.cap_add
:["SYS_ADMIN"]
- grant an individual authority to the container. See https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities for a list of capabilities that can be added.environment
:["FOO=bar","FOO2=bar2"]
- (deprecated) environment variables that should be set in the container.devices
:["/dev/bus/usb/001/001:/dev/bus/usb/001/001",...]
- device files that should be made available to the container.binds
:["/outside/container_path:/inside/container_path1:rw","docker_volume_name:/inside/container_path2:ro"...]
- directories from the host or docker volumes that should be bind mounted in the container. Equivalent to thedocker run --volume
flag. If the first field is not in the directory format, it will be treated as a docker volume. The directory or the docker volume will be created on the host if it does not exist when the containers starts. The last field is the mount options.ro
means readonly,rw
means read/write (default). To bind to directories that are only available to root on the host system, the container needs to have ‘privileged’ set to true.tmpfs
:{"/app":""}
- There is no source for tmpfs mounts. It creates a tmpfs mount at /appports
:[{"HostPort":"5555:7777/udp","HostIP":"1.2.3.4"},{"HostPort":"8888/udp","HostIP":"1.2.3.4"}...]
- container ports that should be mapped to the host. “5555” is the host port number, if omitted, the same container port number (“7777”) will be used. If the protocol is not specified after the port number, it defaults totcp
. TheHostIP
identifies what host network interfaces this port should listen on. Use0.0.0.0
to specify all interfaces. To use ports reserved for root, ‘privileged’ must be set to true.ephemeral_ports
:[{"localhost_only":true, "port_and_protocol":"7777/udp"}, {"port_and_protocol":"8888"}...]
- publish a container port to an ephemeral host port. Iflocalhost_only
is set to true, the localhost ip address (127.0.0.1
) will be used as the host network interface this port should listen on. Otherwise, all the host network interfaces on the host will be listened by this port. If the protocol is not specified after the port number forport_and_protocol
, it defaults totcp
.command
:["--myfirstarg","argvalue",...]
- override the start CMD specified the Dockerfile, or append to the ENTRYPOINT specified in the dockerfile.network
:"host"
- start the container with host network mode. When network is set to host, the service can only be deployed to nodes with property openhorizon.allowPrivileged set to true.entrypoint
:["executable", "param1", "param2"]
- override ENTRYPOINT specified in the Dockerfile.max_memory_mb
:4096
- the maximum amount of memory the service container can usemax_cpus
:1.5
- how much of the available CPU resources the service container can use. For instance, if the host machine has two CPUs and you set value to 1.5, the container is guaranteed to use at most one and a half of the CPUslog_driver
: the logging driver (for examplejson-file
) to use for container logs, instead of default one (syslog)secrets
:{"ai_secret": {"description": "The token for cloud AI service."}, "sql_secret": {}}
- a list of secret names and the descriptions. Thedescription
can be omitted. A secret name is just a user defined string. A pattern or a deployment policy will associate it with the name of the secret in the secret provider. The horizon agent will mount the secrets at ‘/open-horizon-secrets’ within the service’s containers. Each secret name appears as a file in that directory, containing the details of the secret from the secret provider. Each secret file is a JSON encoded file containing the ‘key’ and ‘value’ set when the secret was created with the hzn secretsmanager secret add command.user
: Sets the username or UID used. root (id = 0) is the default user within a container. The image developer can create additional users. Those users are accessible by name. When passing a numeric ID, the user does not have to exist in the container.pid
: Set the PID (Process) Namespace mode for the container.container:<name|id>
joins another container’s PID namespace.host
use the host’s PID namespace inside the container. In certain cases you want your container to share the host’s process namespace, basically allowing processes within the container to see all of the processes on the system.sysctls
: Sysctl settings are exposed by Kubernetes, allowing users to modify certain kernel parameters at runtime for namespaces within a container. The parameters cover various subsystems, such as: networking (common prefix: net.), kernel (common prefix: kernel.), virtual memory (common prefix: vm.), MDADM (common prefix: dev.). To get a list of all parameters, you can run:sudo sysctl -a
ipc
: Sets the IPC mode for the container. Equivalent to thedocker run --ipc
flag. The accepted values are:"", "none", "private", "shareable", "container:<name-or-id>", "host"
. If not specified, daemon default is used.
clusterDeployment String Fields
Because Open Horizon uses operators to deploy the applications in a Kubernetes cluster, the clusterDeployment
contains the contents of the operator yaml archive files.
operatorYamlArchive
: The content of the operator yaml archive files. These files are compressed (tarred and gzipped). And then the compressed content is converted to a base64 string.metadata
: A list of key-value paries. It is for internal use only. Do not put it in theclusterDeployment
when publishing a service.
Deployment String Examples
This is a deployment
string JSON example:
{
"deployment": {
"services": {
"gps": {
"image": "openhorizon/x86/gps:2.0.3",
"privileged": true,
"devices": [
"/dev/bus/usb/001/001:/dev/bus/usb/001/001"
],
"binds": [
"/tmp/testdata:/tmp/mydata:ro",
"myvolume1:/tmp/mydata2"
],
"tmpfs": {
"/app":""
},
"ports": [
{
"HostPort":"5200:6414/tcp",
"HostIP": "0.0.0.0"
}
],
"network": "host"
}
}
}
}
When stringified, the above example would look like:
"deployment": "{\"services\":{\"gps\":{\"image\":\"openhorizon/x86/gps:2.0.3\",\"privileged\":true,\"devices\":[\"/dev/bus/usb/001/001:/dev/bus/usb/001/001\"],\"binds\":[\"/tmp/testdata:/tmp/mydata:ro\",\"myvolume1:/tmp/mydata2\"],\"tmpfs\":{\"/app\":\"\"},\"ports\":[{\"HostPort\":\"5200:6414/tcp\",\"HostIP\":\"0.0.0.0\"}]}}}"
A clusterDeployment
string JSON would look like this when defining a service using hzn
command:
"clusterDeployment": {
"operatorYamlArchive": "/filepath/k8s_operator_deployment_files.tar.gz"
}
When the content is encoded and stringified, the above would look like:
"clusterDeployment": "{\"operatorYamlArchive\":\"H4sIAEu8lF4AA+1aX2/bNhDPcz4FkT4EGGZZsmxn0JuXZluxtjGcoHsMaIm2uVKiRlLO0mHffUfqjyVXkZLNcTCUvxeLR/J4vDse7yQ7w4ikjD8MT14OLuBi4ppfwP6vefb86Xji+ZOL6fjE9byRNz1BkxeUqUImFRYInQjOVde4vv7..."