Deployment stages
Kubernetes resources are deployed in the following stages:
-
Deploying
CustomResourceDefinitions
from thecrds
directories of the included charts. -
Deploying
pre-install
,pre-upgrade
orpre-rollback
hooks, starting with hooks with less weight to greater weight. -
Deploying basic resources: the resources with the same weight are combined into groups (resources without a specified weight are assigned a weight of 0) and deployed one group at a time, starting with groups with lower-weight resources to groups with higher-weight resources.
-
Deploying
post-install
,post-upgrade
orpost-rollback
hooks, starting with hooks with less weight to ones with greater weight.
Resources with werf.io/deploy-dependency-<name>
annotation do not belong to any stage and are deployed as soon as their dependencies satisfied.
Deploying CustomResourceDefinitions
To deploy CustomResourceDefinitions, put the CRD manifests in the crds/*.yaml
non-template files in any of the included charts. During the following deployment, these CRDs will be deployed first, with hooks and core resources following them.
Example:
# .helm/crds/crontab.yaml:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
# ...
spec:
names:
kind: CronTab
# .helm/templates/crontab.yaml:
apiVersion: example.org/v1
kind: CronTab
# ...
werf converge
In this case, the CRD for the CronTab resource will be deployed first, followed by the CronTab resource.
Resource deployments ordering via weight groups (werf only)
By default, werf combines all the main resources (“main” means those are not hooks or CRDs from crds/*.yaml
) into one group, creates resources for that group and tracks their readiness.
To change the order in which resources are deployed, you can create new resource groups by assigning resources a weight other than the default 0
. All resources with the same weight are combined into their respective groups, and then the resource groups are deployed sequentially starting with the group with the lesser weight and progressing to the greater weight, for example:
# .helm/templates/example.yaml:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: database
annotations:
werf.io/weight: "-1"
# ...
---
apiVersion: batch/v1
kind: Job
metadata:
name: database-migrations
# ...
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app1
annotations:
werf.io/weight: "1"
# ...
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app2
annotations:
werf.io/weight: "1"
# ...
werf converge
In this case, the database
resource was deployed first, followed by database-migrations
, and then app1
and app2
were deployed in parallel.
Resource deployments ordering via direct dependencies (werf only)
Annotation werf.io/deploy-dependency-<name>
can be used to set resources ordering during deployment. These resources will not belong to any particular resource group or stage and are deployed as soon as their dependencies are satisfied, for example:
# .helm/templates/example.yaml:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: database
# ...
---
apiVersion: batch/v1
kind: Job
metadata:
name: database-migrations
annotations:
werf.io/deploy-dependency-db: state=ready,kind=StatefulSet,name=database
# ...
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app1
annotations:
werf.io/deploy-dependency-migrations: state=ready,kind=Job,name=database-migrations
# ...
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app2
annotations:
werf.io/deploy-dependency-migrations: state=ready,kind=Job,name=database-migrations
# ...
In this case, the database
resource was deployed first, followed by database-migrations
, and then app1
and app2
were deployed in parallel.
Check out all capabilities of this annotation here.
This is a more flexible and effective way to set the order of resource deployments in comparison to werf.io/weight
and other methods, as it allows you to deploy resources in a graph-like order.
Running tasks before/after installing, upgrading, rolling back or deleting a release
To deploy certain resources before or after installing, upgrading, rolling back or deleting a release, convert the resource to a hook by adding the helm.sh/hook
annotation to it, for example:
# .helm/templates/example.yaml:
apiVersion: batch/v1
kind: Job
metadata:
name: database-initialization
annotations:
helm.sh/hook: pre-install
# ...
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
werf converge
In this case, the database-initialization
resource will be deployed during the first-time installation of the release, while the myapp
resource will be deployed whenever the release is installed, upgraded, or rolled back.
The helm.sh/hook
annotation sets the resource as a hook and defines the conditions on which the resource should be deployed (you can specify several comma-separated conditions). The available conditions for deploying a hook are listed below:
-
pre-install
— during the release installation before installing the main resources; -
pre-upgrade
— when upgrading the release before upgrading the main resources; -
pre-rollback
— when rolling back the release before rolling back the main resources; -
pre-delete
— when deleting the release before deleting the main resources; -
post-install
— when installing the release after installing the main resources; -
post-upgrade
— when upgrading the release after upgrading the main resources; -
post-rollback
— when rolling back the release after rolling back the main resources; -
post-delete
— when deleting the release after deleting the main resources;
To set the order in which hooks are deployed, assign them different weights (the default is 0
), so that hooks are deployed sequentially starting with a hook with a lower weight and proceeding to ones with a higher weight, for example:
# .helm/templates/example.yaml:
apiVersion: batch/v1
kind: Job
metadata:
name: first
annotations:
helm.sh/hook: pre-install
helm.sh/hook-weight: "-1"
# ...
---
apiVersion: batch/v1
kind: Job
metadata:
name: second
annotations:
helm.sh/hook: pre-install
# ...
---
apiVersion: batch/v1
kind: Job
metadata:
name: third
annotations:
helm.sh/hook: pre-install
helm.sh/hook-weight: "1"
# ...
werf converge
In this case, the first
hook will be deployed first, followed by the second
hook, and then the third
hook.
By default, redeploying the same hook will delete the old hook in the cluster just before deploying the new one. You can change the deletion policy for the old hook using the helm.sh/hook-delete-policy
annotation. It can have the following values:
-
hook-succeeded
— delete the new hook once it has been successfully deployed; do not delete it if it has failed to deploy; -
hook-failed
— delete the new hook once it has failed to deploy; do not delete it if it has been deployed successfully; -
before-hook-creation
— (default) delete the old hook right before creating a new one.
Waiting for non-release resources to be ready (werf only)
The resources deployed as part of the current release may depend on resources that do not belong to this release. werf can wait for these external resources to be ready — you just need to add the <name>.external-dependency.werf.io/resource
annotation as follows:
# .helm/templates/example.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
annotations:
secret.external-dependency.werf.io/resource: secret/my-dynamic-vault-secret
# ...
werf converge
The myapp
deployment will start deploying only after the my-dynamic-vault-secret
(it is created automatically by the operator in the cluster) has been created and is ready.
And here is how you can configure werf to wait for multiple external resources to be ready:
# .helm/templates/example.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
annotations:
secret.external-dependency.werf.io/resource: secret/my-dynamic-vault-secret
database.external-dependency.werf.io/resource: statefulset/my-database
# ...
By default, werf looks for the external resource in the release Namespace (unless, of course, the resource is a cluster-wide). You can change the Namespace of the external resource by attaching the <name>.external-dependency.werf.io/namespace
annotation to it:
# .helm/templates/example.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
annotations:
secret.external-dependency.werf.io/resource: secret/my-dynamic-vault-secret
secret.external-dependency.werf.io/namespace: my-namespace