Configuring Services
To define a Service, create a Prodvana config in a directory of your choosing, e.g. if you have an existing directory you use to store other configurations for the Service, use that. Below is an example of a Service defined to read in Kubernetes configurations in the same directory.
service:
name: nginx
application: my-application
kubernetesConfig:
type: KUBERNETES
local:
path: .
Use pvnctl to apply this config file:
pvnctl configs apply path/to/my-service.pvn.yaml
Once applied, the Service will be configured but not deployed. You can see it by going to my-demo-organization.runprodvana.com -> Applications -> your Application -> your Service.
Releasing from UI
To deploy the Service from the Service UI, click "create release" and follow the on-screen instructions.
Parametrizing from UI
You can define parameters in your service config that can then be set at Release time in the UI. This is useful for fast changes of safe fields, such as replica count or container image, without going through a code commit.
service:
name: nginx
application: my-application
kubernetesConfig:
type: KUBERNETES
local:
path: .
parameters:
- name: image
required: true
dockerImage:
imageRegistryInfo:
containerRegistry: dockerhub-public
imageRepository: library/nginx
You can then use {{.Params.image}}
where you'd like the image name to be templated in, including in your Kubernetes configuration.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: "{{.Params.image}}"
Template Variables
Template variables are available for Service configs and any Kubernetes, Kustomize, or Helm configs they reference. These variables are replaced with their actual values for each Release Channel. Template variables are referenced using the {{ .SomeVariable.nestedField }}
or {{ .SomeVariable["nestedField"] }}
syntax.
Variable | Value |
---|---|
.Params.<parameter name> , e.g. .Params.image | The parameter value for that Release Channel |
.Constants.<constant name> , e.g. .Constants.env | The constant value for that Release Channel. Services inherit constants from release channels but may supply their own override. See "Defining Constants" below. |
.Builtins.ReleaseChannel.Name | The Release Channel name |
.Builtins.ReleaseChannel.Labels.<label name> , e.g. .Builtins.ReleaseChannel.Labels.env | The label value for the Release Channel. See Labels. |
.Builtins.Runtime.Name | The Runtime name this Service runs on for this release channel |
.Builtins.Runtime.Labels.<label name> , e.g. .Builtins.Runtime.Labels.env | The label value for the Runtime. See Labels. |
Template variables can be used anywhere a string is expected, with the following exceptions:
local.path
andlocal.excludePatterns
underkubernetesConfig
Common Examples
Using Kubernetes Config
Prodvana works natively with your Kubernetes configs. When using Kubernetes configs, Prodvana will automatically replace the namespace with the namespace of the release channel being deployed. Prodvana will also add additional environment variables (PVN_*
) as well as any environment variables that are set in the release channel config as defaults, as long as it recognizes the Kubernetes objects (deployment
, job
supported today).
service:
name: my-service
kubernetesConfig:
type: KUBERNETES
local:
path: path/to/config/relative/to/this/file # can also be a directory, in which case all yaml files are selected
Parameters can be used with Kubernetes configs.
service:
name: my-service
kubernetesConfig:
type: KUBERNETES
local:
path: path/to/config/relative/to/this/file # can also be a directory, in which case all yaml files are selected
parameters:
- name: image
required: true
dockerImage:
imageRegistryInfo:
containerRegistry: my-registry-name
imageRepository: my-repository
The template variables should be used directly inside Kubernetes configurations, such as
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 1
selector:
matchLabels:
app: my-deployment
template:
metadata:
labels:
app: my-deployment
spec:
containers:
- name: api
image: "{{.Params.image}}"
The order of operation is:
pvnctl
reads in your local config file and passes it as a string to Prodvana.- Prodvana sets namespace and injects environment variables.
- Prodvana evaluates and applies template variables.
Templating Kubernetes Config Path
local.path
field under kubernetesConfig
does not support the use of template variables, as pvnctl
uses this value to read your local config files before evaluating variables.
To use template variables in config paths, use path
to specify an overarching directory and use subPath
instead to control which file or directory under path
to read.
service:
name: my-service
application: my-application
kubernetesConfig:
type: KUBERNETES
local:
path: configs
subPath: "{{.Params.myParam}}"
...
In the example above, say the value of myParam
is my-value
, the config being used will be under configs/my-value
.
When subPath
is used:
path
must be a directory- the entirety of
path
is uploaded to Prodvana as a tarball
If the config type is KUSTOMIZE
, pvnctl
will find all kustomization files and run kubectl kustomize
to get the materialized config. This can result in errors if kustomization components are included under path
and cannot be evaluated on their own. To exclude them, use excludePatterns
.
service:
name: my-service
application: my-application
kubernetesConfig:
type: KUSTOMIZE
local:
path: configs
subPath: "{{.Params.myParam}}"
excludePatterns: # follows gitignore convention
- components
Different Kubernetes Config Per Release Channel
If you need to customize Kubernetes configs per Release Channel beyond namespaces and environment variables, the easiest way is to use template variables with subPath
. For example:
service:
name: my-service
kubernetesConfig:
type: KUBERNETES
local:
path: .
subPath: "{{.Builtins.ReleaseChannel.Name}}"
If needed, you can also explicitly pass a different config per Release Channel.
service:
name: my-service
application: my-application
perReleaseChannel:
- releaseChannel: staging
kubernetesConfig:
type: KUBERNETES
local:
path: staging-configs/
- releaseChannel: prod
kubernetesConfig:
type: KUBERNETES
local:
path: prod-configs/
perReleaseChannel
acts as an override, so if you have all but one release channel needing a different set of configs, you can also set it as:
service:
name: my-service
kubernetesConfig:
type: KUBERNETES
local:
path: global
perReleaseChannel:
- releaseChannel: staging
kubernetesConfig:
type: KUBERNETES
local:
path: staging-configs/
Patching Kubernetes Config
Patching can be useful where templating directly into the Kubernetes config is not possible. For example, you may be using a strict Kubernetes YAML linter that will not let you put the template variable string into places where an int is expected.
For example, here is how you would patch the replica count of a Deployment
named my-deployment
, with the value of a constant, so that the Release Channel production
has a different replica count than everything else.
service:
name: my-service
kubernetesConfig:
type: KUBERNETES
local:
path: .
patches:
- target: # omit to patch every Kubernetes object referenced
kind: Deployment
name: my-deployment
replace:
path: /spec/replicas # json6902 path
intAsString: '{{.Constants.replicas}}'
constants:
- name: replicas
string:
value: '3'
perReleaseChannel:
- releaseChannel: 'production'
constants:
- name: replicas
string:
value: '5'
Patching also works with Kustomize configs, the exact same way.
service:
name: my-service
kubernetesConfig:
type: KUSTOMIZE # works with Kustomize
local:
path: .
patches:
- target:
kind: Deployment
name: my-deployment
replace:
path: /spec/replicas # json6902 path
intAsString: '{{.Constants.replicas}}'
... # the rest of configs here
Using Public Helm Charts
To deploy public Helm charts:
service:
name: kubecost
application: my-app
helm:
remote:
repo: https://kubecost.github.io/cost-analyzer/
chart: kubecost/cost-analyzer
chartVersion: "1.102.2"
Values.yaml can also be specified, like:
service:
name: my-service
application: my-app
helm:
remote: ... # helm chart reference here
valuesOverride:
- local:
path: my-local-values.yaml
Values.yaml have access to template variables like parameters, too.
service:
name: my-service
application: my-app
helm:
remote: ... # helm chart reference here
valuesOverride:
- local:
path: my-local-values.yaml # the content of this file can reference template variables, like {{.Params.myImage}}
parameters:
- name: myImage
required: true
dockerImage:
imageRegistryInfo:
containerRegistry: my-registry-name
imageRepository: my-repository
Using Local Helm Charts
To use Helm charts defined locally in your own repository (that is, you have a Chart.yaml file):
service:
name: my-service
application: my-app
helm:
local:
path: . # path to directory containing Chart.yaml
valuesOverride: ... # as needed
In this mode, pvnctl configs apply
must be run on a machine with helm
installed. pvnctl
will run helm package
to package your chart into a tarball and upload it to Prodvana.
With Metadata
Services can have metadata like descriptions and links. This should be included in the same config file.
service:
... # service config here
serviceMetadata:
description: "description here"
links:
- url: "http link for your service"
displayName: "display name"
Skipping Cleanup on Deletion
By default, Prodvana will attempt to delete any objects it created (such as, Kubernetes deployments) when a Service is deleted. This can be undesirable during the migration period to Prodvana and can be skipped by a flag in the config file:
service:
... # service config here
noCleanupOnDelete: true
Referencing Multiple Kubernetes/Kustomize Configs, Controlling Order
It is possible to reference multiple Kubernetes configs (either in Kubernetes yaml format or Kustomize).
service:
name: my-service
kubernetesConfig:
type: KUBERNETES # or, KUSTOMIZE
local:
paths:
- path/to/config/relative/to/this/file
- path/to/other/config/relative/to/this/file
At pvnctl configs apply
time, the configs are read in order. For directories, all yaml files (except .pvn.yaml files) are read in. The configs are then joined into a single YAML file delimited by ---
.
Currently, mixing and matching Kubernetes configs with Kustomize configs are not supported.
Defining Constants
Constants can be defined and used in Service configs to customize the fully materialized configs in each release channel. Constants defined by Services override any defined by Release Channels. See .Configuring Applications.
service:
name: my-service
... # refer to `{{.Constants.myConstant}}` to access the value of your constants anywhere in your configuration, including Kubernetes configurations.
perReleaseChannel:
- releaseChannel: production
constants:
- name: myConstant
string:
value: myProductionValueForThisService
- releaseChannel: staging
constants:
- name: myConstant
string:
value: myStagingValueForThisService
Constants can also be used in Kubernetes configs directly, the same as parameters.
Adding Environment Variables
Services can have environment variables defined at the Service and Service Instance level.
Specifying environment variables at the Service scope can be helpful for a few use cases:
- overriding Release Channel default environment variables (see Configuring Applications)
- passing different environment variables per Release Channel while using a single Kubernetes config file
- injecting environment variables for a Kubernetes config file you do not own or do not want to modify
When environment variables are specified at multiple locations, they are given the following precedence (from highest to lowest):
- per-Release-Channel environment variables at the service config layer
- top-level environment variables at the Service config layer
- environment variables at the Application's Release Channel config layer
service:
name: my-service
env:
MY_ENV:
value: value
perReleaseChannel:
- releaseChannel: staging
env:
MY_OTHER_ENV:
value: staging-value
# the rest of config here, including Kubernetes configs
Disable Automatic Rollbacks
By default, releases initiated from the Prodvana UI will automatically roll back to the last known converged version when the Release fails. To disable this behavior, add the following to your service config:
service:
name: my-service
autoRollback:
disabled: true
...
Customizing Bundle Naming Schemes
As part of creating a release, Prodvana will create a new bundle of configuration files for your Service. By default, it will name this bundle using contextual information from Service parameters, falling back to $serviceName-{NN}
when it can't. You can customize this naming convention.
service:
name: my-service
bundleName: some-templated-bundle-name
... # rest of config here
For example, if you have a semantic version string (e.g. v1.0.2) as parameter and always wants to use that, you can do:
service:
name: my-service
bundleName: '{{.Params.semanticVersion}}'
parameters:
- name: semanticVersion
required: true
string: {}
You can make the templating arbitrarily complex. For example, if you have two parameters, one semantic version string and one docker image, and you want the bundle name to be the version string and the first 6 letters of the image tag, you can do:
service:
name: my-service
bundleName: '{{.Params.semanticVersion}}-{{ slice .Params.image.Tag 0 6 }}'
... # rest of config here
parameters:
- name: semanticVersion
required: true
string: {}
- name: image
required: true
dockerImage:
imageRegistryInfo:
containerRegistry: my-registry
imageRepository: my-repo
Updated 8 months ago