Skip to main content

Orchestrating Resource Deployment

This topic describes how to orchestrate the deployment order of resources deployed as part of your application. The information in this topic applies to Helm chart- and standard manifest-based applications deployed with Replicated KOTS.

Overview

Many applications require that certain resources are deployed and in a ready state before other resources can be deployed.

When installing an application that includes one or more Helm charts, KOTS always deploys standard Kubernetes manifests to the cluster before deploying any Helm charts. For example, if your release contains a Helm chart, a CRD, and a ConfigMap, then the CRD and ConfigMap resources are deployed before the Helm chart.

For applications deployed with KOTS, you can manage the order in which resources are deployed using the following methods:

Helm Chart Deployment Order with weight

You can configure the weight property of the Replicated HelmChart custom resource to define the order in which the Helm charts in your release are installed.

KOTS directs Helm to install the Helm charts based on the value of weight in ascending order, deploying the chart with the lowest weight first. Any dependencies are installed along with the parent chart. For example, a chart with a weight of -1 deploys before a chart with a weight of 0.

The value for the weight property can be any negative or positive integer or 0. By default, when you do not provide a weight for a Helm chart, the weight is 0.

For example:

apiVersion: kots.io/v1beta2
kind: HelmChart
metadata:
name: samplechart
spec:
chart:
name: samplechart
chartVersion: 3.1.7
releaseName: samplechart-release-1
# weight determines the order that charts are applied, with lower weights first.
weight: 4

Limitations

The weight field in the HelmChart custom resource has the following limitations:

  • The weight field is not supported for HelmChart custom resources with useHelmInstall: false.

  • When installing a Helm chart-based application, KOTS always deploys standard Kubernetes manifests to the cluster before deploying Helm charts. For example, if your release contains a Helm chart, a CRD, and a ConfigMap, then the CRD and ConfigMap resources are deployed before the Helm chart. The weight property does not allow Helm charts to be deployed before standard manifests.

Standard Manifest Deployment Order with KOTS Annotations

You can use the KOTS annotations described in this section to control the order in which standard manifests are deployed.

Requirement

You must quote the boolean or integer values in annotations because Kubernetes annotations must be strings. For more information about working with annotations in Kubernetes resources, see Annotations in the Kubernetes documentation.

kots.io/creation-phase

When the kots.io/creation-phase: '<integer>' annotation is present on a resource, KOTS groups the resource into the specified creation phase. KOTS deploys each phase in order from lowest to highest. Phases can be any positive or negative integer ranging from '-9999' to '9999'.

Resources in the same phase are deployed in the same order that Helm installs resources. To view the order in which KOTS deploys resources of the same phase, see Helm installs resources in the following order in the Helm documentation.

The following example deploys the CustomResourceDefinition before the default creation phase:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: myresources.example.com
annotations:
kots.io/creation-phase: "-1"
...

kots.io/deletion-phase

When the kots.io/deletion-phase: '<integer>' annotation is present on a resource, KOTS groups the resource into the specified deletion phase. KOTS deletes each phase in order from lowest to highest. Resources within the same phase are deleted in the reverse order from which they were created. Phases can be any positive or negative integer ranging from '-9999' to '9999'.

The following example deploys the CustomResourceDefinition before the default creation phase and deletes the resource after the default deletion phase:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: myresources.example.com
annotations:
kots.io/creation-phase: "-1"
kots.io/deletion-phase: "1"
...

kots.io/wait-for-ready

When the kots.io/wait-for-ready: '<bool>' annotation is present on a resource and evaluates to 'true', KOTS waits for the resource to be in a ready state before deploying any other resources. For most resource types, KOTS has existing logic to determine if a resource is ready. If there is no existing logic for the given resource type, then KOTS waits until the resource exists and is queryable from the Kubernetes API server.

In the following example, KOTS waits for the Postgres StatefulSet to be ready before continuing to deploy other resources:

apiVersion: apps/v1
kind: Statefulset
metadata:
name: postgresql
annotations:
kots.io/wait-for-ready: 'true'
labels:
app: postgresql
spec:
selector:
matchLabels:
app: postgresql
strategy:
type: Recreate
template:
metadata:
labels:
app: postgresql
spec:
containers:
- name: postgresql
image: "postgres:9.6"
imagePullPolicy: ""
...

kots.io/wait-for-properties

When the kots.io/wait-for-properties: '<jsonpath>=<value>,<jsonpath>=<value>' annotation is present on a resource, KOTS waits for one or more specified resource properties to match the desired values before deploying other resources. This annotation is useful when the kots.io/wait-for-ready annotation, which waits for a resource to exist, is not sufficient.

The value for this annotation is a comma-separated list of key-value pairs, where the key is a JSONPath specifying the path to the property and the value is the desired value for the property. In the following example, KOTS waits for a resource to reach a desired state before deploying other resources. In this case, KOTS waits until each of the three status properties have the target values:

kind: MyResource
metadata:
name: my-resource
annotations:
kots.io/wait-for-properties: '.status.tasks.extract=true,.status.tasks.transform=true,.status.tasks.load=true'
...
status:
tasks:
extract: false
transform: false
load: false