Templates¶
Sovereign uses a templating system to make it easier to turn Instances into Envoy configuration.
Using templates you can represent most of your configuration as YAML or Python code, with various parts filled in by data that comes from your Instances.
Discovery Types¶
A template must be configured for each discovery type that you want to provide from your sovereign server.
As of this writing, the discovery types supported are:
- CDS: Cluster Discovery Service
- LDS: Listener Discovery Service
- RDS: Route Discovery Service
- SRDS: Scoped-Routes Discovery Service
- SDS: Secret Discovery Service
And I'm sure there are more. We don't need to list them all because Sovereign supports them all by default, as long as they don't require gRPC.
Writing a template¶
Given the inline sources that we configured in the last section, it makes sense to create a template for clusters to represent the data as clusters:
YAML + Jinja2 example¶
To get started, it may sometimes help to get an example configuration file from the Envoy examples, and to replace bits of the example with the template syntax.
resources:
{% for cluster in clusters %}
- '@type': type.googleapis.com/envoy.api.v2.Cluster
name: {{ cluster['name'] }}
connect_timeout: 0.25s
type: STATIC
load_assignment:
cluster_name: {{ cluster['name'] }}
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: {{ cluster['address'] }}
port_value: 80
{% endfor %}
Info
If you're unfamiliar with YAML and/or Jinja2, the following may help:
Python example¶
For better performance, it's recommended to use Python to describe the templating logic.
The below is an equivalent of the above YAML+Jinja2 example.
def endpoint(address):
"""
You can write any Python code you like
to support generating the template
"""
return {'endpoint': {
'address': {
'socket_address': {
'address': address,
'port_value': 80}}}}
def call(clusters, discovery_request, **kwargs):
"""
This function must be defined
"""
for cluster in clusters:
# Every yielded item is considered one resource
# You can also return a list, which will be considered all resources.
yield {
'@type': 'type.googleapis.com/envoy.api.v2.Cluster',
'name': cluster['name'],
'connect_timeout': '0.25s',
'type': 'STATIC',
'load_assignment': {
'endpoints': [{
'lb_endpoints': [
endpoint(cluster['address'])
]
}]
}
}
Once you've written your first template, you can repeat this process for all other discovery types that you wish to support.
Tip
If you haven't by now, then you should at least read up on the Envoy API
to see exactly what can be configured.
I thoroughly recommend keeping this bookmarked.
I also really recommend becoming familiar with the location of each resource type such as Clusters, Listeners, Routes, and filters such as the Http Connection Manager.
This will help you immensely when writing templates, and also when considering what data you can include in your Sources.
Configuring Sovereign with the Templates¶
Once you have finalized the contents of all your templates, they can be added to Sovereign via it's main configuration file that we created in the previous section:
If you used the Python example above to create your templates, your config might look similar to the following:
templates:
default:
type: clusters
spec:
protocol: python
path: templates/default/clusters.py
Otherwise, if you went with YAML+Jinja2, it may look like:
templates:
default:
type: clusters
spec:
protocol: file
serialization: jinja2
path: templates/default/clusters.j2.yaml
Templates for specific versions of Envoy¶
In the previous configuration examples you'll notice a key called default
.
This means that if the Envoy version does not match a specifically configured version, Sovereign will
use the default
templates to generate configuration for the Node.
If your fleet of Envoys contains multiple different versions, and the same template wouldn't work across all of them due to backward compatibility issues, you can configure templates for each version of Envoy that you need to support
Example
templates:
# Sovereign will match all patch versions of an envoy release when given a short version as follows
1.13: # Versions 1.13.0, 1.13.1, etc
type: clusters
spec:
protocol: file
serialization: jinja2
path: templates/v13/clusters.j2.yaml
1.12: # Versions 1.12.0, 1.12.1, 1.12.2, etc
type: clusters
spec:
protocol: file
serialization: jinja2
path: templates/v12/clusters.j2.yaml
# Everything that doesn't match will use this
default:
type: clusters
spec:
protocol: file
serialization: jinja2
path: templates/default/clusters.j2.yaml