Application Development Guide

Application development is greatly simplified when using the Grey Matter mesh, allowing developers to focus on the most important part of their applications, the business logic. For details on the core components of Grey Matter please read Core Components.

As depicted in the above image, all requests between services flow through their sidecars. We always deploy our web applications into multiple sidecar/service deployments, with a separate deployment for the UI and at least one backend deployment. This model allows for independent management and scaling of your web application components. In Kubernetes, a deployment model would be comprised of multiple pods, each containing a sidecar and a service.

The rule of thumb in Grey Matter, is to route all requests through sidecars. In a zero-trust framework like Grey Matter you can easily and consistently secure traffic between sidecars using TLS. Furthermore, you can implement fine grained resiliency control with health checks, circuit breaking, and rate limiting.

There are a few core things to consider when developing applications using Grey Matter.

  • Sidecar Features

  • Routing

  • Configuration

Sidecar Features

The role of the sidecar is to proxy request traffic between downstream clients and upstream services. Downstream refers to requests coming from clients to sidecars and upstream refers to sidecars making requests to services on behalf of clients. All traffic sent to/from an application will flow through a sidecar, which introduces a significant feature set to an application. For a full feature list, read through the following documentation:

Leveraging these features leads to simpler business logic because these capabilities do not need to exist in your application code.

Configuration is managed by Grey Matter Control, a centralized "control-plane", and pushed to sidecars, a decentralized "data-plane". In the context of a web application you can do things like:

  1. Route matching and traffic direction

  2. TLS configuration

    1. Certificates

    2. Server Name Indication (SNI)

    3. Ciphers

  3. Custom headers

  4. Connection upgrades e.g. to support WebSockets

To illustrate these features let's take an example Nginx configuration and map it to Grey Matter Control objects.

Route Matching and Traffic Direction

Nginx

# location block
location /apps/myapp {
proxy_pass http://1.2.3.4:3000;
}

Grey Matter Control

# route.json
{
"route_key": "myapp-route",
"domain_key": "edge",
"zone_key": "default",
"path": "/apps/myapp",
"match_type": "prefix",
"rules": [{
"rule_key": "default",
"constraints": {
"light": [
{
"cluster_key": "myapp-cluster",
"weight": 1
}
]
}
}]
}
# cluster.json
{
"cluster_key": "myapp-cluster",
"zone_key": "default",
"instances": [
{
"host": "1.2.3.4",
"port": "3000"
}
]
}

Similar to Nginx's location block, Grey Matter matches on a route string and directs traffic to an intended target. For more on route matching, such as matching via regular expressions, see route_match. In the above scenario, the target is the host IP and port of the service in the cluster object. In Grey Matter, a Route is linked to a Cluster via inline rules or a separate Shared Rules object.

Grey Matter Control configurations are spread out across multiple objects which allow for shared configurations and a wide array of features. See what a cluster can provide like health checks and circuit breakers, similar to Nginx's circuit breaker pattern.

TLS Configuration

Nginx

# TLS block
ssl on;
proxy_ssl_certificate certs/server.crt;
proxy_ssl_certificate_key certs/server.key;
proxy_ssl_trusted_certificate certs/ca.crt;
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
proxy_ssl_ciphers 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA256';

Grey Matter Control

# domain.json
{
"domain_key": "edge",
"zone_key": "default",
"name": "*",
"port": 8443,
"ssl_config": {
"cipher_filter": "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA256",
"protocols": [
"TLSv1",
"TLSv1.1",
"TLSv1.2"
],
"cert_key_pairs": [
{
"certificate_path": "/etc/proxy/tls/edge/server.crt",
"key_path": "/etc/proxy/tls/edge/server.key"
}
],
"require_client_certs": true,
"trust_file": "/etc/proxy/tls/edge/ca.crt",
"sni": null
},
"force_https": true
}

The above example leverages the Grey Matter sidecar's domain configuration to define mutual TLS (mTLS), where both client and server must verify each other's certificates. Once configured, this feature can be easily toggled off by setting force_https: false. For all Grey Matter TLS capabilities, read the TLS documentation.

Custom Headers

Nginx

# location block
location /apps/myapp {
proxy_pass http://1.2.3.4:3000;
add_header HELLO world
}

Grey Matter Control

# domain.json
{
"domain_key": "myapp",
"zone_key": "default",
"name": "*",
"port": "3000",
"custom_headers": [
{
"key": "HELLO",
"value": "world"
}
]
}

The above example demonstrates how simple it is to add customer headers to a request that is sent "upstream" to a service. Again, it's important to reiterate that request traffic can be augmented by the Grey Matter sidecar, versus instrumenting your own business logic.

Connection Upgrades

Common connection upgrades include upgrading the HTTP protocol to WebSockets or HTTP2.

Nginx

# location block
location /wsapp/ {
proxy_pass http://wsbackend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}

Grey Matter Control

# proxy.json
{
"proxy_key": "myapp-proxy",
"zone_key": "default-zone",
"name": "myapp-proxy",
"domain_keys": ["domain"],
"listener_keys": ["listener"],
"upgrades": "websocket"
}

Connection upgrades in Envoy are mainly for WebSockets but can support non-WebSocket upgrades.

Routing

Routing is the glue of applications and services. A standard request flow entails:

  1. Application is requested from https://domain.io/app

  2. Server responds with HTML, and additional requests are made to static assets (HTML, JavaScript, CSS)

  3. Application makes JavaScript calls to RESTful services for data

Throughout this process, communication is executed by invoking RESTful routes. Here are some routes that you can configure with Grey Matter Control.

  • Client

    • index route

    • route to service(s)

    • WebSocket route

  • Service

    • index route

    • routes to services

Top Tip

If you make your application routes relative, your app can easily be deployed to any level of sub-routes. You can rewrite an absolute URL using Grey Matter Control but it's far simpler to make routes relative.

Configuration

It's important to be able to configure an application once its deployed. This is most commonly achieved by passing environment variables at runtime and is another benefit for deploying a UI as a service. In Kubernetes, this would be achieved by setting an environment variable on a deployment. When a new pod is instantiated from that deployment, the environment variable can be set on a Docker container serving up static assets from a NodeJS Express server. Express has access to the operating system's environment variables and you can then a) use a template mechanism to replace strings or b) manipulate the <head> of your HTML by placing a <script> tag with JavaScript variables.

Here are some common examples of runtime environment variables:

  • BASE_PATH for client side routing

  • WEBSOCKET_BASE_PATH required if using a custom path for socket.io