Kubernetes manifest task

Use this task in a build or release pipeline to bake and deploy manifests to Kubernetes clusters.

Overview

Following are the key benefits of this task -

  • Artifact substitution - The deploy action takes as input a list of container images which can be specified along with their tags or digests. The same is substituted into the non-templatized version of manifest files before application to the cluster to ensure that the right version of the image is pulled by the cluster nodes.
  • Manifest stability - Rollout status is checked for the Kubernetes objects deployed. This is done to incorporate stability checks while computing the task status as success/failure.
  • Traceability annotations - Annotations are added to the deployed Kubernetes objects to superimpose traceability information in the form of following annotations -
    • azure-pipelines/org
    • azure-pipelines/project
    • azure-pipelines/pipeline
    • azure-pipelines/pipelineId
    • azure-pipelines/execution
    • azure-pipelines/executionuri
    • azure-pipelines/jobName
  • Secret handling - The createSecret action enables creation of docker-registry secrets using Docker Registry Service Connections and generic secrets using plain-text/secret variables. The secrets input can be used along with deploy action so that the manifest files specfied as inputs are augmented with appropriate imagePullSecrets before deploying to the cluster.
  • Bake manifest - The bake action of the task allows for baking Helm charts into Kubernetes manifest files so that the same can be applied onto the cluster.
  • Deployment strategy - Choosing canary strategy with deploy action leads to creation of desired percentage of workloads suffixed with '-baseline' and '-canary'. These variants can be compared during a ManualIntervention task before utilizing the promote/reject action of the task to finalize the version to be retained.

Deploy action

Parameters Description
action
Action
(Required) Acceptable values: deploy/promote/reject/bake/scale/patch/delete
kubernetesServiceConnection
Kubernetes service connection
(Required) Name of the Kubernetes service connection
namespace
Namespace
(Required) Namespace within the cluster to deploy to
manifests
Manifests
(Required) Path to the manifest files to be used for deployment. Regular expression (RE2 syntax) form specification of path is accepted.
containers
Containers
(Optional) Fully qualified resource URL of the image to be used for substitutions on the manifest files
Example: contosodemo.azurecr.io/helloworld:test
imagePullSecrets
Image pull secrets
(Optional) Multiline input where each line contains the name of a docker-registry secret that has already been setup within the cluster. Each of these secret names are added under imagePullSecrets field for the workloads found in the input manifest files
strategy
Strategy
(Optional) Deployment strategy to be used while applying manifest files on the cluster. Currently, 'canary' is the only acceptable deployment strategy
percentage
Percentage
(Required if strategy == canary) Percentage used to compute the number of replicas of '-baseline' and '-canary' varaints of the workloads found in manifest files. For the specified percentage input, if (percentage * numberOfDesirerdReplicas)/100 is not a round number, the floor of this number is used while creating '-baseline' and '-canary'
Example: If Deployment hello-world was found in the input manifest file with 'replicas: 4' and if 'strategy: canary' and 'percentage: 25' are given as inputs to the task, then the Deployments hello-world-baseline and hello-world-canary are created with 1 replica each. The '-baseline' variant is created with the same image and tag as the stable version (4 replica variant prior to deployment) while the '-canary' variant is created with the image and tag correspoding to the new changes being deployed

Following is an example YAML snippet for deploying to a K8s namespace using manifest files -

steps:
- task: KubernetesManifest@0
  displayName: Deploy
  inputs:
    kubernetesServiceConnection: someK8sSC1
    namespace: default
    manifests: manifests/*
    containers: 'foobar/demo:$(tagVariable)'
    imagePullSecrets: |
      some-secret
      some-other-secret

In the above example, the tasks tries to find matches for the image foobar/demo in the image fields of manifest files. If a match is found, the value of tagVariable is appended as tag to the image name. Note that it is also possible to specify digests in the containers input for artifact substitution.

Note

While it is possible to author deploy, promote and reject actions with deployment strategy related inputs in YAML, support for ManualIntervention task is currently not in place for build pipeline. It is thus advisable to use the deployment strategy related actions and inputs in release pipelines in the following sequence - 1. Deploy action with strategy: canary and percentage: $(someValue). 2. ManaulIntervention task so that one can pause the pipeline and compare the baseline with canary. 3. Promote (run if ManualIntervention is resumed) and reject actions (run if ManualIntervention is rejected)

Promote and reject actions

Parameters Description
action
Action
(Required) Acceptable values: deploy/promote/reject/bake/scale/patch/delete
kubernetesServiceConnection
Kubernetes service connection
(Required) Name of the Kubernetes service connection
namespace
Namespace
(Required) Namespace within the cluster to deploy to
manifests
Manifests
(Required) Path to the manifest files to be used for deployment. Regular expression (RE2 syntax) form specification of path is accepted.
containers
Containers
(Optional) Fully qualified resource URL of the image to be used for substitutions on the manifest files
Example: contosodemo.azurecr.io/helloworld:test
imagePullSecrets
Image pull secrets
(Optional) Multiline input where each line contains the name of a docker-registry secret that has already been setup within the cluster. Each of these secret names are added under imagePullSecrets field for the workloads found in the input manifest files
strategy
Strategy
(Optional) Deployment strategy that was used in the deploy action prior to promote/reject. Currently, 'canary' is the only acceptable deployment strategy

Create secret action

Parameters Description
action
Action
(Required) Acceptable values: deploy/promote/reject/bake/scale/patch/delete
secretType
Secret type
(Required if action == secret) Acceptable values: dockerRegistry/generic. Set dockerRegistry option for creating/updating imagePullSecret in cluster to facilitate image pull from a private container registry
Default value: dockerRegistry
secretName
Secret name
(Required) Name of the secret to be created/updated
dockerRegistryEndpoint
Docker registry service connection
(Required if action == createSecret and secretType == dockerRegistry) The specified service connection's credentials are used to create a docker-registry secret within the cluster. This secret's name can then be referred to from manifest files under the imagePullSecrets field
secretArguments
Secret arguments
(Required if action == createSecret and secretType == generic) Multiline input accepting keys and literal values to be used for secret creation/updation. Example: --from-literal=key1=value1 --from-literal=key2="top secret"."
kubernetesServiceConnection
Kubernetes service connection
(Required) Name of the Kubernetes service connection
namespace
Namespace
(Required) Namespace within the cluster to create secret in

Following is an example YAML snippet for creation of docker registry secrets using Docker Registry service connection-

steps:
- task: KubernetesManifest@0
  displayName: Create secret
  inputs: 
    action: createSecret
    secretType: dockerRegistry
    secretName: foobar
    dockerRegistryEndpoint: demoACR
    kubernetesServiceConnection: someK8sSC
    namespace: default

Following is an example YAML snippet for creation of generic secrets -

steps:
- task: KubernetesManifest@0
  displayName: Create secret
  inputs: 
    action: createSecret
    secretType: generic
    secretName: some-secret
    secretArguments: --from-literal=key1=value1
    kubernetesServiceConnection: someK8sSC
    namespace: default

Bake action

Parameters Description
action
Action
(Required) Acceptable values: deploy/promote/reject/bake/scale/patch/delete
renderType
Render engine
(Required if action == bake) Acceptable values: helm2. Render type to be used for producing the manifest files
Default value: helm2
helmChart
Helm chart
(Required if action == bake and renderType == helm2) Path to the helm chart to be used for bake
overrideFiles
Overridee files
(Optional; Relevant if action == bake and renderType == helm2) Multiline input accepting path to the override files that are to be used when baking manifest files from helm charts
Overrides
Override values
(Optional; Relevant if action == bake and renderType == helm2) Additional override values that are to be used via --values switch when baking manifest files using helm

Following is an example YAML snippet for baking manifest files from Helm charts. Note the usage of name input in the first task which is later referenced from the subsequent deploy step for specifying path to the manifests that were produced by the bake step -

steps:
- task: KubernetesManifest@0
  name: bake
  displayName: Bake K8s manifests from Helm chart
  inputs:
    action: bake
    helmChart: charts/sample
    overrides: 'image.repository:nginx'

- task: KubernetesManifest@0
  displayName: Deploy K8s manifests
  inputs:
    kubernetesServiceConnection: someK8sSC
    namespace: default
    manifests: $(bake.manifestsBundle)
    containers: |
      nginx: 1.7.9

Scale action

Parameters Description
action
Action
(Required) Acceptable values: deploy/promote/reject/bake/scale/patch/delete
kind
Kind
(Required) Kind of Kubernetes object (ReplicaSet/StatefulSet/...) to be scaled up/down
name
Name
(Required) Name of Kubernetes object to be scaled up/down
replicas
Replica count
(Required) Number of replicas to scale to
kubernetesServiceConnection
Kubernetes service connection
(Required) Name of the Kubernetes service connection
namespace
Namespace
(Required) Namespace within the cluster to deploy to

Following is an example YAML snippet for scaling objects -

steps:
- task: KubernetesManifest@0
  displayName: Scale
  inputs: 
    action: scale
    kind: deployment
    name: bootcamp-demo
    replicas: 5
    kubernetesServiceConnection: someK8sSC
    namespace: default

Patch action

Parameters Description
action
Action
(Required) Acceptable values: deploy/promote/reject/bake/scale/patch/delete
resourceToPatch
Resource to patch
(Required) Acceptablee values: file/name. Indicates whether a manifest file is to be used to identify the objects to be patched or if an individual object is to be identified by kind and name as the target for patch
Default value: file
resourceFiletoPatch
File path
(Required if action == patch and resourceToPatch == file) Path to the file used for patch
kind
Kind
(Required if action == patch and resourceToPatch == name) Kind of Kubernetes object (ReplicaSet/StatefulSet/...)
name
Name
(Required if action == patch and resourceToPatch == name) Name of Kubernetes object to be patched
mergeStrategy
Merge strategy
(Required) Acceptable values: json/merge/strategic. Strategy to be used for applying the patch.
Default: strategic
patch
Patch
(Required) Contents of the patch
kubernetesServiceConnection
Kubernetes service connection
(Required) Name of the Kubernetes service connection
namespace
Namespace
(Required) Namespace within the cluster to deploy to

Following is an example YAML snippet for patching an object -

steps:
- task: KubernetesManifest@0
  displayName: Patch
  inputs: 
    action: patch
    kind: pod
    name: demo-5fbc4d6cd9-pgxn4
    mergeStrategy: strategic
    patch: '{"spec":{"containers":[{"name":"demo","image":"foobar/demo:2239"}]}}'
    kubernetesServiceConnection: someK8sSC
    namespace: default

Delete action

Parameters Description
action
Action
(Required) Acceptable values: deploy/promote/reject/bake/scale/patch/delete
arguments
Arguments
(Required) Arguments to be passed onto kubectl for deleting the necessary objects. For example -
arguments: deployment hello-world foo-bar
kubernetesServiceConnection
Kubernetes service connection
(Required) Name of the Kubernetes service connection
namespace
Namespace
(Required) Namespace within the cluster to deploy to

Following is an example YAML snippet for deleting objects -

steps:
- task: KubernetesManifest@0
  displayName: Delete
  inputs: 
    action: delete
    arguments: deployment expressapp
    kubernetesServiceConnection: someK8sSC
    namespace: default

Open source

This task is open source on GitHub. Feedback and contributions are welcome.