CSv3 template values
Overview
Every CSv3 application is defined by a set of templates: the Kubernetes manifests (Deployments, Services, ConfigMaps, Secrets and so on) that Cloud 66 renders and applies to your cluster on every deployment. You manage them in the Dashboard under your application's Settings → Templates, either by uploading YAML files or by connecting a GitHub repo.
A template can be plain Kubernetes YAML, or it can use ytt expressions to pull in values that Cloud 66 manages for you, such as a service's image, its replica count, or your application's environment variables and secrets:
This page covers:
- How Cloud 66 renders a template
- Substituting values into your templates
- Linking a template to a service with an annotation
- The values reference: everything available under
cloud66.appandcloud66.service - A complete example and troubleshooting
How Cloud 66 renders a template
On every deployment Cloud 66 takes a snapshot of your application's current state (its namespace, environment variables, secrets and services) and renders each template against it:
- A template with no ytt expression in it (no
#@and no(@= ... @)) is applied exactly as written. - Any other template is rendered with ytt. Cloud 66 hands the snapshot to your template as a struct called
cloud66, so you never declare or load data values yourself. - Cloud 66 stamps every rendered resource with its tracking annotations and labels, then applies the result to your cluster with
kubectl apply.
Cloud 66 never rewrites a field on its own. If a template hardcodes replicas: 3, scaling the service in the Dashboard changes nothing on the cluster. The new count reaches the cluster only if the template says replicas: #@ cloud66.service.replicas.
Things to know about the rendering environment:
- The
cloud66struct is already defined. Reference it directly. - The ytt modules
base64,json,yaml,structandtemplateare already loaded. Loading them again in your template is harmless. - Plain
#YAML comments are fine: ytt is run so that it ignores comments it doesn't recognise. (@= ... @)text templating is switched on automatically for any template that uses it. You don't need to add#@yaml/text-templated-stringsyourself.- When you upload a file with several YAML documents (separated by
---), each document becomes its own template. Documents produced inside a ytt block (between#@ foror#@ ifand its#@ end) stay together in one template.
What Cloud 66 adds to your resources
Cloud 66 adds the same two entries, as both annotations and labels, to every resource it renders:
They are added to the resource's own metadata and to its pod template (spec.template.metadata, or spec.jobTemplate.spec.template.metadata for a CronJob). Cloud 66 uses them to keep track of the resources it manages, so don't set or remove them yourself.
Because pod templates are stamped too, a workload that was already running before Cloud 66 managed it (for example on an imported application) restarts once, on its first deployment through Cloud 66.
Substituting values
Whole values
Use #@ to set a field to a value. The value keeps its type: replicas renders as a number, image as a string.
Inside strings and keys
Use (@= ... @) to place a value inside a larger string, or to template a key:
Text templating only accepts strings. Wrap numbers in str(), or build the whole string in a #@ expression instead:
Conditions and loops
#@ if/end and #@ for/end apply to the single YAML node that follows them. Apply list values such as commands, args and ports with a loop, inside a condition when the field should be left out for an empty list. This sets a container's command and args only when the service has them:
And this renders one port entry per service port:
To wrap several nodes, or a whole document, use the block form and close it with #@ end:
Looking up a single variable
cloud66.app.envVars and cloud66.app.secrets are lists, which makes them easy to loop over. To pick out one entry by its key, define a small function at the top of the template:
For everything else ytt can do, see the ytt documentation.
Linking a template to a service
cloud66.app is available in every template. cloud66.service is only available in a template that is linked to a service, and it holds the values of that one service.
To link a template, add the cloud66.com/service annotation with the service's uid to the template's top-level metadata.annotations:
The rules:
- Top-level metadata only. Cloud 66 reads the link from the template's own
metadata.annotations. The templates Cloud 66 generates repeat the annotation on the pod template, but on its own that copy links nothing. - A literal uid. The link is read before the template is rendered, so the value can't be a ytt expression.
- One link per template. A template is a single YAML document, so in a multi-document file every document that uses
cloud66.serviceneeds its own annotation. Any kind of resource can be linked: a Deployment, its Service, a ConfigMap and so on. - The service must exist. A template whose uid doesn't match a service of this application is rejected.
Linking is also what groups a template with its service in the Dashboard: the Associations column of the templates table shows which service each template belongs to.
Finding a service's uid
A service uid looks like service- followed by 32 hexadecimal characters. To find it:
- In the Dashboard: open Settings → Templates and open any template that Cloud 66 generated for the service, such as its Deployment. The
cloud66.com/serviceannotation holds the uid. Cloud 66 only generates templates on clusters it created; on an external cluster, use the MCP server. - Through the MCP server: the service tools of the Cloud 66 MCP server return each service's
uid.
The templates Cloud 66 generates for your application use these same values, so they are a good starting point for your own. They may also reference values that aren't listed on this page. Those are internal and can change without notice, so rely only on the values documented here.
Values reference
cloud66.app
Available in every template.
| Value | Type | Description |
|---|---|---|
namespace | string | The Kubernetes namespace of the application. Set it as the metadata.namespace of every namespaced resource (see Namespaces). |
envVars | list | The application's environment variables. Each entry has a key and a value. |
secrets | list | The application's Secrets, sorted by key: account-level Secrets merged with application-level ones, where the application level wins. Each entry has a key, a plain-text value, and value64, the same value base64-encoded and ready for the data of a Kubernetes Secret. |
buildgridImagePullCredentials | string | Credentials for the image registries of Cloud 66's build service (BuildGrid), as a base64-encoded .dockerconfigjson. Always present, whether or not a service pulls from those registries. See Pulling images built by Cloud 66. |
cloud66.service
Available in templates linked to a service.
| Value | Type | Description |
|---|---|---|
name | string | The name of the service. |
resourceName | string | The name to give the service's Kubernetes resources. It is the service name, followed by - and the variantTag when there is one. Use it for resource names, container names and selector labels. |
variantTag | string | The tag of the service variant being rendered. It is empty for a service's default variant, and it is already part of resourceName when set. |
image | string | The image to run, including its tag. For a service that Cloud 66 builds from Git it is *applied-after-build* until the deployment's build has produced the image, so never hardcode it. |
replicas | number | The number of replicas the service is scaled to. |
kind | string | The workload kind chosen for the service: Deployment or DaemonSet. |
ports | list | One entry per port of the service, in the shape of a Kubernetes Service port: name (a unique name generated by Cloud 66), port, targetPort (both the container port) and protocol (TCP or UDP). |
baseCommand | string | The service's command, exactly as entered. Empty when the service uses the image's default command. |
commands | list | The first word of the command as a one-element list, for a container's command. Empty when there is no command. Apply it with a loop (see Conditions and loops). |
args | list | The remaining words of the command, split the way a shell would split them, for a container's args. Empty when there are none. Apply it with a loop as well. |
restartTrigger | string | A timestamp that changes whenever you restart the service from the Dashboard. See Restarting a service. |
Using the values
Namespaces
An application manages resources in its own namespace only. Cloud 66 applies your templates without a -n flag, so set metadata.namespace on every namespaced resource:
Writing the namespace out literally works too. Templates synced from a Git repo or imported in bulk are rejected when a resource has no namespace, targets a different namespace, or computes it with any expression other than cloud66.app.namespace.
Restarting a service
Restart in the Dashboard works by changing cloud66.service.restartTrigger. The workload only restarts if that value is part of its pod template, so render it into a pod template annotation of every linked workload:
A linked workload without this annotation ignores the restart button. Note that changing a ConfigMap or a Secret doesn't restart the pods that use it either.
Environment variables and secrets
The application's environment variables are rendered into a ConfigMap and its Secrets into a Kubernetes Secret, and containers load both with envFrom. On a cluster created by Cloud 66, every application already has these two templates: a ConfigMap called c66-env-vars and a Secret called c66-secrets. On an external cluster nothing is generated, so add them yourself:
Pulling images built by Cloud 66
When Cloud 66 builds a service from Git, the image is stored in a Cloud 66 registry. Clusters created by Cloud 66 can already pull from it. On an external cluster (a Kubernetes cluster you run yourself and connect to Cloud 66), render the credentials into an image pull Secret:
Then name it in the pod spec of each workload that runs a Cloud 66-built image:
A complete example
This is the Deployment template that Cloud 66 generates for a service, trimmed to the parts that use the values documented on this page. It is linked to the service, rendered only when the service's kind is Deployment, and controlled from the Dashboard (image, scaling, command and restarts):
With a service called web, set to 3 replicas of ghcr.io/acme-corp/storefront-web:2.4.1 and the command bundle exec puma -C config/puma.rb, Cloud 66 renders and applies:
The generated Kubernetes Service template, linked to the same service and rendered only when the service has ports:
Troubleshooting
To check a template before you deploy, open it under Settings → Templates and choose Download rendered template from the More menu. Cloud 66 renders the template against your application's current values and gives you the result, or tells you why it failed to render.
A template that is rejected when you upload or sync it usually carries a cloud66.com/service annotation whose uid doesn't match any service of this application.
These are the rendering errors you are most likely to meet:
| Error message | What it means |
|---|---|
struct has no .service field or method | The template references cloud66.service but isn't linked to a service. Add the cloud66.com/service annotation to its top-level metadata.annotations. |
cannot set non-string value (int64), consider using str(...) to convert to string | A (@= ... @) expression produced a number. Wrap it in str(), or use a #@ expression instead. |
struct has no .<name> field or method | The template references a value that doesn't exist. Check the spelling against the values reference; names are case-sensitive. |