Synthesizers are containerized programs that transform input Kubernetes resources into output resources using a simple JSON protocol over stdin/stdout. They enable declarative resource generation within Eno compositions.
Synthesis is the process where Eno runs your containerized synthesizer in a short-lived pod to generate Kubernetes resources. Your synthesizer receives input resources via stdin as JSON and returns generated resources via stdout, also as JSON.
The fastest way to get started is with one of our language-specific libraries:
- Go: Use the Go synthesizer library
- Helm: Use the Helm shim
- KCL: Use the KCL library
- Any language: Implement the JSON protocol directly
Your synthesizer needs to:
- Read a JSON ResourceList from stdin
- Process the input resources
- Write a JSON ResourceList with generated resources to stdout
Eno automatically triggers synthesis when any of these conditions occur:
- Composition changes: The composition resource itself is modified
- Synthesizer changes: The synthesizer container image or configuration changes
- Input changes: Any input resource bound to the composition changes
Some changes can affect many compositions simultaneously. These are marked as "deferred" to prevent overwhelming your cluster:
- Synthesizer updates: Changes to synthesizer images/config
- Deferred inputs: Input resources with
defer: truein their binding
Deferred changes use a global cooldown period (configurable with --rollout-cooldown) to stagger synthesis across compositions.
Opting out of deferred synthesis:
metadata:
annotations:
eno.azure.io/ignore-side-effects: "true"With this annotation, only changes to the composition spec will trigger synthesis.
Sometimes you need multiple input resources to be synchronized before synthesis runs.
Revision-based synchronization:
# On input resources
metadata:
annotations:
eno.azure.io/revision: "123"Synthesis waits until all inputs have the same revision number.
Generation-based synchronization:
# On input resources
metadata:
annotations:
# Wait for synthesizer to reach generation 123
eno.azure.io/synthesizer-generation: "123"
# Wait for composition to reach generation 321
eno.azure.io/composition-generation: "321"This blocks synthesis until input controllers have "seen" the requested synthesizer/composition state.
Your synthesizer communicates with Eno using JSON over stdin/stdout, following the KRM Functions Specification.
💡 Recommendation: Use our language-specific libraries (Go, Helm, KCL) instead of implementing the protocol directly.
Eno sends input resources as a JSON ResourceList via stdin:
{
"apiVersion": "config.kubernetes.io/v1",
"kind": "ResourceList",
"items": [
{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {
"name": "my-app-config",
"annotations": {
"eno.azure.io/input-key": "app-config"
}
},
"data": {
"replicas": "3",
"image": "nginx:1.21"
}
}
]
}The eno.azure.io/input-key annotation identifies which input binding this resource came from.
Return generated resources using the same ResourceList format via stdout:
{
"apiVersion": "config.kubernetes.io/v1",
"kind": "ResourceList",
"items": [
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"name": "my-app"
},
"spec": {
"replicas": 3,
"selector": {
"matchLabels": {"app": "my-app"}
},
"template": {
"metadata": {
"labels": {"app": "my-app"}
},
"spec": {
"containers": [{
"name": "app",
"image": "nginx:1.21"
}]
}
}
}
}
]
}Report errors using the results field. The first error will appear in the composition status:
{
"apiVersion": "config.kubernetes.io/v1",
"kind": "ResourceList",
"results": [
{
"severity": "error",
"message": "Invalid configuration: replicas must be a positive integer"
}
]
}This error will be visible when checking composition status:
$ kubectl get compositions
NAME SYNTHESIZER AGE STATUS ERROR
my-app my-synthesizer 10s NotReady Invalid configuration: replicas must be a positive integer