Kubernetes manifest task

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

Overview

The following list shows the key benefits of this task:

  • Artifact substitution: The deployment action takes as input a list of container images that you can specify along with their tags and digests. The same input is substituted into the nontemplatized manifest files before application to the cluster. This substitution ensures that the cluster nodes pull the right version of the image.

  • Manifest stability: The rollout status of the deployed Kubernetes objects is checked. The stability checks are incorporated to determine whether the task status is a success or a failure.

  • Traceability annotations: Annotations are added to the deployed Kubernetes objects to superimpose traceability information. The following annotations are supported:

    • 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 lets Docker registry secrets be created using Docker registry service connections. It also lets generic secrets be created using either plain-text variables or secret variables. Before deployment to the cluster, you can use the secrets input along with the deploy action to augment the input manifest files with the appropriate imagePullSecrets value.

  • Bake manifest: The bake action of the task allows for baking templates into Kubernetes manifest files. The action uses tools such as Helm, Compose, and kustomize. With baking, these Kubernetes manifest files are usable for deployments to the cluster.

  • Deployment strategy: Choosing the canary strategy with the deploy action leads to creation of workloads having names suffixed with "-baseline" and "-canary". The task supports two methods of traffic splitting:

    • Service Mesh Interface: Service Mesh Interface (SMI) abstraction allows configuration with service mesh providers like Linkerd and Istio. The Kubernetes Manifest task maps SMI TrafficSplit objects to the stable, baseline, and canary services during the life cycle of the deployment strategy.

      Canary deployments that are based on a service mesh and use this task are more accurate. This accuracy comes because service mesh providers enable the granular percentage-based split of traffic. The service mesh uses the service registry and sidecar containers that are injected into pods. This injection occurs alongside application containers to achieve the granular traffic split.

    • Kubernetes with no service mesh: In the absence of a service mesh, you might not get the exact percentage split you want at the request level. But you can possibly do canary deployments by using baseline and canary variants next to the stable variant.

      The service sends requests to pods of all three workload variants as the selector-label constraints are met. Kubernetes Manifest honors these requests when creating baseline and canary variants. This routing behavior achieves the intended effect of routing only a portion of total requests to the canary.

    Compare the baseline and canary workloads by using either a Manual Intervention task in release pipelines or a Delay task in YAML pipelines. Do the comparison before using the promote or reject action of the task.

Deploy action

Parameter Description
action
Action
(Required)

Acceptable values are deploy, promote, reject, bake, scale, patch, and delete.
kubernetesServiceConnection
Kubernetes service connection
(Required)

The name of the Kubernetes service connection.
namespace
Namespace
(Required)

The namespace within the cluster to deploy to.
manifests
Manifests
(Required)

The path to the manifest files to be used for deployment. A file-matching pattern is an acceptable value for this input.
containers
Containers
(Optional)

The fully qualified URL of the image to be used for substitutions on the manifest files. This input accepts the specification of multiple artifact substitutions in newline-separated form. Here's an example:

containers: |
  contosodemo.azurecr.io/foo:test1
  contosodemo.azurecr.io/bar:test2

In this example, all references to contosodemo.azurecr.io/foo and contosodemo.azurecr.io/bar are searched for in the image field of the input manifest files. For each match found, the tag test1 or test2 replaces the matched reference.
imagePullSecrets
Image pulls secrets
(Optional)

Multiline input where each line contains the name of a Docker registry secret that has already been set up within the cluster. Each secret name is added under imagePullSecrets for the workloads that are found in the input manifest files.
strategy
Strategy
(Optional)

The deployment strategy used while manifest files are applied on the cluster. Currently, canary is the only acceptable deployment strategy.
trafficSplitMethod
Traffic split method
(Optional)

Acceptable values are pod and smi. The default value is pod.

For the value smi, the percentage traffic split is done at the request level by using a service mesh. A service mesh must be set up by a cluster admin. This task handles orchestration of SMI TrafficSplit objects.

For the value pod, the percentage split isn't possible at the request level in the absence of a service mesh. Instead, the percentage input is used to calculate the replicas for baseline and canary. The calculation is a percentage of replicas that are specified in the input manifests for the stable variant.
percentage
Percentage
(Required only if strategy is set to canary)

The percentage that is used to compute the number of baseline-variant and canary-variant replicas of the workloads that are contained in manifest files.

For the specified percentage input, calculate:

(percentage × number of replicas) / 100

If the result isn't an integer, the mathematical floor of the result is used when baseline and canary variants are created.

For example, assume the deployment hello-world is in the input manifest file and that the following lines are in the task input:

replicas: 4
strategy: canary
percentage: 25

In this case, the deployments hello-world-baseline and hello-world-canary are created with one replica each. The baseline variant is created with the same image and tag as the stable version, which is the four-replica variant before deployment. The canary variant is created with the image and tag corresponding to the newly deployed changes.
baselineAndCanaryReplicas
Baseline and canary replicas
(Optional, and relevant only if trafficSplitMethod is set to smi)

When you set trafficSplitMethod to smi, the percentage traffic split is controlled in the service mesh plane. But you can control the actual number of replicas for canary and baseline variants independently of the traffic split.

For example, assume that the input deployment manifest specifies 30 replicas for the stable variant. Also assume that you specify the following input for the task:

strategy: canary
trafficSplitMethod: smi
percentage: 20
baselineAndCanaryReplicas: 1

In this case, the stable variant receives 80% of the traffic, while the baseline and canary variants each receive half of the specified 20%. But baseline and canary variants don't receive three replicas each. They instead receive the specified number of replicas, which means they each receive one replica.

The following YAML code is an example of deploying to a Kubernetes namespace by using manifest files:

steps:
- task: KubernetesManifest@0
  displayName: Deploy
  inputs:
    kubernetesServiceConnection: someK8sSC1
    namespace: default
    manifests: manifests/deployment.yml|manifests/service.yml
    containers: |
      foo/demo:$(tagVariable1)
      bar/demo:$(tagVariable2)
    imagePullSecrets: |
      some-secret
      some-other-secret

In the above example, the task tries to find matches for the images foo/demo and bar/demo in the image fields of manifest files. For each match found, the value of either tagVariable1 or tagVariable2 is appended as a tag to the image name. You can also specify digests in the containers input for artifact substitution.

Note

While you can author deploy, promote, and reject actions with YAML input related to deployment strategy, support for a Manual Intervention task is currently unavailable for build pipelines.

For release pipelines, we advise you to use actions and input related to deployment strategy in the following sequence:

  1. A deploy action specified with strategy: canary and percentage: $(someValue).
  2. A Manual Intervention task so that you can pause the pipeline and compare the baseline variant with the canary variant.
  3. A promote action that runs if a Manual Intervention task is resumed and a reject action that runs if a Manual Intervention task is rejected.

Promote and reject actions

Parameter Description
action
Action
(Required)

Acceptable values are deploy, promote, reject, bake, scale, patch, and delete.
kubernetesServiceConnection
Kubernetes service connection
(Required)

The name of the Kubernetes service connection.
namespace
Namespace
(Required)

The namespace within the cluster to deploy to.
manifests
Manifests
(Required)

The path to the manifest files to be used for deployment. A file-matching pattern is an acceptable value for this input.
containers
Containers
(Optional)

The fully qualified resource URL of the image to be used for substitutions on the manifest files. The URL contosodemo.azurecr.io/helloworld:test is an example.
imagePullSecrets
Image pull secrets
(Optional)

Multiline input where each line contains the name of a Docker registry secret that is already set up within the cluster. Each secret name is added under the imagePullSecrets field for the workloads that are found in the input manifest files.
strategy
Strategy
(Optional)

The deployment strategy used in the deploy action before a promote action or reject action. Currently, canary is the only acceptable deployment strategy.

Create secret action

Parameter Description
action
Action
(Required)

Acceptable values are deploy, promote, reject, bake, scale, patch, and delete.
secretType
Secret type
(Required only if action is set to secret)

Acceptable values are dockerRegistry and generic. The default value is dockerRegistry.

If you set secretType to dockerRegistry, the imagePullSecrets field is created or updated in a cluster to help image pull from a private container registry.
secretName
Secret name
(Required)

The name of the secret to be created or updated.
dockerRegistryEndpoint
Docker registry service connection
(Required only if action is set to createSecret and secretType is set to dockerRegistry)

The credentials of the specified service connection are used to create a Docker registry secret within the cluster. Manifest files under the imagePullSecrets field can then refer to this secret's name.
secretArguments
Secret arguments
(Required only if action is set to createSecret and secretType is set to generic)

Multiline input that accepts keys and literal values to be used for creation and updating of secrets. Here's an example:
--from-literal=key1=value1 --from-literal=key2="top secret"
kubernetesServiceConnection
Kubernetes service connection
(Required)

The name of the Kubernetes service connection.
namespace
Namespace
(Required)

The cluster namespace within which to create a secret.

The following YAML code shows a sample creation of Docker registry secrets by 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

This YAML code shows a sample 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

Parameter Description
action
Action
(Required)

Acceptable values are deploy, promote, reject, bake, scale, patch, and delete.
renderType
Render engine
(Required only if action is set to bake)

The render type used to produce the manifest files.

Acceptable values are helm2, kompose, and kustomize. The default value is helm2.
helmChart
Helm chart
(Required only if action is set to bake and renderType is set to helm2)

The path to the Helm chart used for baking.
overrideFiles
Override files
(Optional, and relevant only if action is set to bake and renderType is set to helm2)

Multiline input that accepts the path to the override files. The files are used when manifest files from Helm charts are baked.
overrides
Override values
(Optional, and relevant only if action is set to bake and renderType is set to helm2)

Additional override values that are used via the command-line switch --set when manifest files using Helm are baked.

Specify override values as key-value pairs in the format key:value. If you use multiple overriding key-value pairs, specify each key-value pair in a separate line. Use a newline character as the delimiter between different key-value pairs.
releaseName
Release name
(Optional, and relevant only if action is set to bake and renderType is set to helm2)

The name of the release used when baking Helm charts.
kustomizationPath
Kustomization path
(Optional, and relevant only if action is set to bake and renderType is set to kustomize)

The path to the directory containing the file kustomization.yaml.
dockerComposeFile
Path to Docker compose file
(Optional, and relevant only if action is set to bake and renderType is set to kompose)

The path to the Docker compose file.

The following YAML code is an example of baking manifest files from Helm charts. Note the usage of name input in the first task. This name is later referenced from the deploy step for specifying the 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

Parameter Description
action
Action
(Required)

Acceptable values are deploy, promote, reject, bake, scale, patch, and delete.
kind
Kind
(Required)

The kind of Kubernetes object to be scaled up or down. Examples include ReplicaSet and StatefulSet.
name
Name
(Required)

The name of the Kubernetes object to be scaled up or down.
replicas
Replica count
(Required)

The number of replicas to scale to.
kubernetesServiceConnection
Kubernetes service connection
(Required)

The name of the Kubernetes service connection.
namespace
Namespace
(Required)

The namespace within the cluster to deploy to.

The following YAML code shows an example of scaling objects:

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

Patch action

Parameter Description
action
Action
(Required)

Acceptable values are deploy, promote, reject, bake, scale, patch, and delete.
resourceToPatch
Resource to patch
(Required)

Indicates one of the following patch methods:
  • A manifest file identifies the objects to be patched.
  • An individual object is identified by kind and name as the patch target.
Acceptable values are file and name. The default value is file.
resourceFiletoPatch
File path
(Required only if action is set to patch and resourceToPatch is set to file)

The path to the file used for the patch.
kind
Kind
(Required only if action is set to patch and resourceToPatch is set to name)

The kind of the Kubernetes object. Examples include ReplicaSet and StatefulSet.
name
Name
(Required only if action is set to patch and resourceToPatch is set to name)

The name of the Kubernetes object to be patched.
mergeStrategy
Merge strategy
(Required)

The strategy to be used for applying the patch.

Acceptable values are json, merge, and strategic. The default value is strategic.
patch
Patch
(Required)

The contents of the patch.
kubernetesServiceConnection
Kubernetes service connection
(Required)

The name of the Kubernetes service connection.
namespace
Namespace
(Required)

The namespace within the cluster to deploy to.

The following YAML code shows an example of object patching:

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

Parameter Description
action
Action
(Required)

Acceptable values are deploy, promote, reject, bake, scale, patch, and delete.
arguments
Arguments
(Required)

Arguments to be passed on to kubectl for deleting the necessary objects. An example is:
arguments: deployment hello-world foo-bar
kubernetesServiceConnection
Kubernetes service connection
(Required)

The name of the Kubernetes service connection.
namespace
Namespace
(Required)

The namespace within the cluster to deploy to.

This YAML code shows a sample object deletion:

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.