Search…
Velocity Annotations

Basic definitions

Velocity Annotations are added to the standard Kubernetes entity definitions. There are two types of annotations:
  • Velocity Annotations: These are added to your K8s entity definitions under the metadata.annotations tag. They add important information about your application, such as: Identifier, dependencies, connectivity definitions and more.
    • Velocity Annotations are located under metadata.annotations
    • Velocity Annotations use the following syntax: velocity.tech.v1/{directive}
  • Velocity Templates - These are placeholders that you add anywhere in your K8s entity definitions which will be set by Velocity during provisioning. Templates are used to set dynamic values in environment variables or define unique identifiers to cloud resources and more.
    • Velocity Templates are located anywhere along your K8s resource definitions
    • Velocity Templates use the following syntax: {velocity.v1.<Property>}for global templates or {velocity.v1:<Velocity Service>.<Property>} for service-level templates.
Example:
1
apiVersion: apps/v1
2
kind: Deployment
3
metadata:
4
name: backend
5
# <------- START OF VELOCITY ANNOTATIONS ------->
6
annotations:
7
velocity.tech.v1/id: backend # Service Identifier
8
velocity.tech.v1/dependsOn: mysql # Service Dependency
9
# <------- END OF VELOCITY ANNOTATIONS --------->
10
spec:
11
containers:
12
- name: backend
13
env:
14
- name: DB_CONNECTION_STRING
15
# <VELOCITY_TEMPLATE that is set dynamically upon provisioning>
16
value: '{velocity.v1:mysql.exposures(port=mysqlport).uri}'
Copied!

Velocity Services

A Velocity Service is a standalone application deployed in your environment.
Your blueprint defines Velocity Services, with their dependencies and required configuration.
Velocity Services are created from a Deployment Kubernetes Resource.

Velocity service identifier

Every Velocity Service must have a unique identifier.
The identifier sets the name of the service in Velocity, and allows referencing it from other Velocity Services.
The identifier is set on the Kubernetes Deployment Resource using the following annotation format: velocity.tech.v1/id: {value}.
For example:
1
apiVersion: apps/v1
2
kind: Deployment
3
metadata:
4
name: backend-deployment
5
annotations:
6
velocity.tech.v1/id: backend . # Service Identifier
Copied!

Dependencies

In Velocity, you can define dependencies between Velocity Services.
Dependencies are used to build a dependency-map that helps provision the environment correctly.
Common use cases for dependencies:
  1. 1.
    Provisioning order: Velocity uses dependencies to determine the optimal provisioning order.
  2. 2.
    Environment completeness: When a new environment is created, Velocity ensures that services have all the necessary dependencies ready.
  3. 3.
    Connectivity and configuration: Velocity allows you to set connection strings and other environment variables dynamically using properties from the service dependencies.
The dependencies are defined by adding velocity.tech.v1/dependsOn with a comma-separated list of velocity identifiers (defined by the velocity.tech.v1/id annotation) of the dependent services.
For example:
1
apiVersion: apps/v1
2
kind: Deployment
3
metadata:
4
name: backend-deployment
5
annotations:
6
velocity.tech.v1/id: backend
7
velocity.tech.v1/dependsOn: mysql, postgres # Dependency
8
--
9
apiVersion: apps/v1
10
kind: Deployment
11
metadata:
12
name: mysql
13
annotations:
14
velocity.tech.v1/id: mysql
15
--
16
apiVersion: apps/v1
17
kind: Deployment
18
metadata:
19
name: postgres
20
annotations:
21
velocity.tech.v1/id: postgres
Copied!

In-Cluster Connectivity

To enable in-cluster communication, Velocity provides a flexible configuration model that is based on your existing K8s definitions extended with Velocity's Exposures annotation.

The Exposures Annotation

Exposures is an entity that Velocity creates for every Velocity service.
It is generated from your Kubernetes Service Port definition and can be extended with application properties such as username, password, and scheme to construct generic URI templates used to connect your Velocity Services.
For example, if your configuration includes an environment variable that points to a static address, it will not be suitable for creating ephemeral environments. Therefore, Velocity allows you to replace it with a generic Velocity Template that will be resolved automatically upon environment provisioning:'{velocity.v1:mysql.exposures(port=mysqlport).uri}'
Connectivity details (Username, Password, and Application Scheme)
To enable Velocity to generate URIs in the form of schema://user:[email protected] you need to explicitly define the application parameters when exposing a port.
This can be done by adding the following Velocity Annotations to your Velocity Service definition:
  1. 1.
    Constant values
1
velocity.tech.v1/exposures-<port_name>-user: const="username"
2
velocity.tech.v1/exposures-<port_name>-password: const="password"
3
velocity.tech.v1/exposures-<port_name>-scheme: const="https"
Copied!
You can also use a shorthand:
1
velocity.tech.v1/exposures-<port_name>-user: "username"
2
velocity.tech.v1/exposures-<port_name>-password: "password"
3
velocity.tech.v1/exposures-<port_name>-scheme: "https"
Copied!
2. Values specified using a Kubernetes resource path
1
velocity.tech.v1/exposures-<port_name>-user: path="<path in k8s resource>"
2
velocity.tech.v1/exposures-<port_name>-password: path="<path in k8s resource>"
3
velocity.tech.v1/exposures-<port_name>-scheme: path="<path in k8s resource>"
Copied!

Auto-generated URI Segments

The Exposures entity automatically generates pre-built parameters that you can use in your configuration. The basic 'host' and 'port' parameters are defined by your Kubernetes Service Port specifications, while complex parameters such as 'URI' combine the 'host' and 'port' with the relevant application properties.
Velocity Template Syntax: {velocity.v1:<id>.exposures(port=<port_id>).<internal_url_segment>}
Auto-generated properties for <internal_url_segment>:
  • uri -> scheme://user:[email protected]:port
  • scheme -> scheme (http, https, etc...)
  • user -> user (the username segment of the exposure)
  • password -> password (the password segment of the exposure)
  • host -> host (service name)
  • port -> port (service port)

In-Cluster Connectivity Example

1
apiVersion: apps/v1
2
kind: Deployment
3
metadata:
4
name: backend
5
# <------- START OF VELOCITY ANNOTATIONS ------->
6
annotations:
7
velocity.tech.v1/dependsOn: mysql
8
velocity.tech.v1/id: backend
9
# <------- END OF VELOCITY ANNOTATIONS ------->
10
spec:
11
containers:
12
- name: backend
13
env:
14
# <VELOCITY_TEMPLATE: The uri will be set upon provisioning -->
15
- name: DB_CONNECTION_STRING
16
value: '{velocity.v1:mysql.exposures(port=mysqlport).uri}'
17
---
18
apiVersion: apps/v1
19
kind: Deployment
20
metadata:
21
name: mysql
22
# <------- START OF VELOCITY ANNOTATIONS ------->
23
annotations:
24
velocity.tech.v1/id: mysql
25
velocity.tech.v1/exposures-mysqlport-user: const="username"
26
velocity.tech.v1/exposures-mysqlport-password: const="password"
27
velocity.tech.v1/exposures-mysqlport-scheme: const="https"
28
# <------- END OF VELOCITY ANNOTATIONS ------->
29
spec:
30
containers:
31
- name: mysql
32
env:
33
- name: DATABASE_NAME
34
value: 'orders'
35
ports:
36
- name: port
37
containerPort: 3306
38
protocol: TCP
39
---
40
apiVersion: v1
41
kind: Service
42
metadata:
43
name: mysql
44
spec:
45
selector:
46
app: mysql
47
ports:
48
- name: mysqlport
49
port: 3306
50
targetPort: mysql
51
protocol: TCP
Copied!

External Connectivity

To enable public access from the internet to your Velocity Services, you can use your existing Kubernetes Ingress definition.
Velocity use your Ingress definition and create an Ingress resource in every new environment created in your cluster.
To make your Ingress definition unique for every environment, Velocity provides the {velocity.v1.domainSuffix}template that generates a different domain suffix for each created environment
Velocity Template
Description
{velocity.v1.domainSuffix}
A combination of the environment name and the domain name in the form of: environmentName.domainName
Please note that using Ingress requires installing an Ingress Controller in your cluster.
External Connectivity Example
1
apiVersion: networking.k8s.io/v1
2
kind: Ingress
3
metadata:
4
annotations:
5
kubernetes.io/ingress.class: traefik
6
traefik.ingress.kubernetes.io/router.entrypoints: websecure
7
traefik.ingress.kubernetes.io/router.tls: "true"
8
name: backend-ingress
9
spec:
10
rules:
11
# <VELOCITY_TEMPLATE: Host will be set upon environment provisioning -->
12
- host: "backend-{velocity.v1.domainSuffix}"
13
http:
14
paths:
15
- backend:
16
service:
17
name: viron-backend
18
port:
19
number: 80
20
path: /
21
pathType: Prefix
Copied!

Using random values

In some cases, you might need to generate random strings in your configuration.
A common use case for using random strings is generating passwords, or secured tokens when provisioning new infrastructure resources.
Velocity allows you to use the {velocity.v1.generate:random}Velocity Template which will be resolved into a string upon provisioning. The syntax supports two options:
  1. 1.
    A simple random string that translates into an 8 character string: {velocity.v1.generate:random}
  2. 2.
    A custom regular expression: {velocity.v1.generate:random([a-zA-Z0-9]{8})}
The random generator uses the name of the environment as a seed
Example:
1
apiVersion: apps/v1
2
kind: Deployment
3
metadata:
4
name: mysql
5
annotations:
6
velocity.tech.v1/id: mysql
7
spec:
8
containers:
9
- name: mysql
10
env:
11
- name: DATABASE_NAME
12
value: 'orders'
13
14
# <VELOCITY_TEMPLATE: The value will be generated upon provisioning -->
15
- name: DATABASE_PASSWORD
16
value: '{velocity.v1.generate:random}'
Copied!

Using auto-generated values

Velocity provides you with auto-generated Velocity Templates that are resolved upon environment provisioning and can help use dynamic values in your environment provisioning.
Velocity Template
Description
{velocity.v1.envName}
The name of the environment For example: angry-hero
{velocity.v1.domainName}
The name of the domain. For example: viron.com
{velocity.v1.domainSuffix}
The full domain suffix for the specific environment. For example: angry-hero.viron.com

Defining variables

Using variables and referencing them from your services is very powerful. It allows you to initialize the service with values defined during the environment setup. For example: Initiating an environment variable with the connection string of another service.
To use variables, you first need to export them from your source service, as explained below, and then reference them from your target service (see: Using variables).
Exporting a variable is done by adding the following annotation to your Velocity Service: velocity.tech.v1/exports-<variable>
The export format supports two options:
A constant value
1
apiVersion: apps/v1
2
kind: Deployment
3
metadata:
4
name: mysql-database
5
annotations:
6
velocity.tech.v1/id: mysql
7
velocity.tech.v1/exports-db_name: const="orders"
8
Copied!
A value specified using a Kubernetes resource path
1
apiVersion: apps/v1
2
kind: Deployment
3
metadata:
4
name: mysql-database
5
annotations:
6
velocity.tech.v1/id: mysql
7
velocity.tech.v1/exports-db_name: path="spec.template.spec.containers.(name=my-sql).env.[0].value"
8
spec:
9
selector:
10
matchLabels:
11
app: mysql
12
template:
13
metadata:
14
labels:
15
app: mysql
16
spec:
17
containers:
18
- name: my-sql
19
env:
20
- name: DATABASE
21
value: 'orders'
22
Copied!

Using variables

To reference an exported variable:
  1. 1.
    Explicitly declare a dependency on the exporting Velocity Service using the velocity.tech.v1/dependsOn annotation.
  2. 2.
    Use the following a Velocity Template in the following format to reference the exported variable's value{key}: {velocity/v1:id.exports.variable}
For Example:
1
apiVersion: apps/v1
2
kind: Deployment
3
metadata:
4
name: backend-deployment
5
annotations:
6
velocity.tech.v1/dependsOn: mysql-database
7
velocity.tech.v1/id: backend
8
spec:
9
containers:
10
- name: backend
11
env:
12
# <VELOCITY_TEMPLATE: using a db name defined in a dependent service -->
13
- name: DATABASE_NAME
14
value: '{velocity.v1:mysql-database.exports.dbname}'
15
Copied!

Using Variables in Kubernetes secrets

In order to use variables in Kubernetes secrets, Kubernetes requires you to base64 encode your secret.
For Example:
1
apiVersion: v1
2
kind: Secret
3
metadata:
4
name: db-credentials
5
type: Opaque
6
data:
7
# "{velocity.v1:mysql.exposures(port=mysql).user}" base64 encoded
8
DB_USER: e3ZlbG9jaXR5LnYxOm15c3FsLmV4cG9zdXJlcyhwb3J0PW15c3FsKS51c2VyfQ==
9
# "{velocity.v1:mysql.exposures(port=mysql).password}" base64 encoded
10
DB_PASSWORD: e3ZlbG9jaXR5LnYxOm15c3FsLmV4cG9zdXJlcyhwb3J0PW15c3FsKS5wYXNzd29yZH0=
Copied!
Click here for helm usage

Local Development

When developing locally we create proxies for every dependency your Velocity Service is using. If you want the proxy to occupy the same port defined in your dependency you should use use-same-port:true
Example:
velocity.tech.v1/local-useSamePort: "true"