Multi-cloud Kubernetes deployments

Azure DevOps Services

Kubernetes has a standard interface and runs the same way on all cloud providers. Azure Pipelines can be used for deploying to Azure Kubernetes Service (AKS), Google Kubernetes Engine (GKE), Amazon Elastic Kubernetes Service (EKS), or clusters from any other cloud providers. This article explains how to connect to each of these clusters, and how to perform parallel deployments to multiple clouds.

Setup environment and Kubernetes resources

Kubernetes resources belonging to environments can be targeted from deployment jobs to enable pipeline traceability and ability to diagnose resource health.

Note

Deployments to Kubernetes clusters are possible using regular jobs as well, but the benefits of pipeline traceability and ability to diagnose resource health are not available in this option.

To set up multi-cloud deployment, create an environment and then add your Kubernetes resources associated with namespaces of Kubernetes clusters. Follow the steps under the linked sections based on the cloud provider of your Kubernetes cluster -

Tip

The generic provider approach based on existing service account works with clusters from any cloud provider, including Azure. The incremental benefit of using the Azure Kubernetes Service option instead is that it involves creation of new ServiceAccount and RoleBinding objects (instead of reusing an existing ServiceAccount) so that the newly created RoleBinding object limits the operations of the ServiceAccount to the chosen namespace only.

Parallel deployments to multiple clouds

The following YAML snippet showcases how to perform parallel deployments to clusters from multiple clouds. In this example, deployments are done to resources corresponding to namespaces from AKS, GKE, EKS, and OpenShift clusters. These four namespaces are associated with Kubernetes resources under the 'contoso' environment.

trigger:
- main

jobs:
- deployment:
  displayName: Deploy to AKS
  pool:
    vmImage: ubuntu-latest
  environment: contoso.aksnamespace
  strategy:
    runOnce:
      deploy:
        steps:
        - checkout: self
        - task: KubernetesManifest@0
          displayName: Deploy to Kubernetes cluster
          inputs:
            action: deploy
            kubernetesServiceConnection: serviceConnection #replace with your service connection
            namespace: aksnamespace
            manifests: manifests/*
- deployment:
  displayName: Deploy to GKE
  pool:
    vmImage: ubuntu-latest
  environment: contoso.gkenamespace
  strategy:
    runOnce:
      deploy:
        steps:
        - checkout: self
        - task: KubernetesManifest@0
          displayName: Deploy to Kubernetes cluster
          inputs:
            action: deploy
            kubernetesServiceConnection: serviceConnection #replace with your service connection
            namespace: gkenamespace
            manifests: manifests/*
- deployment:
  displayName: Deploy to EKS
  pool:
    vmImage: ubuntu-latest
  environment: contoso.eksnamespace
  strategy:
    runOnce:
      deploy:
        steps:
        - checkout: self
        - task: KubernetesManifest@0
          displayName: Deploy to Kubernetes cluster
          inputs:
            action: deploy
            kubernetesServiceConnection: serviceConnection #replace with your service connection
            namespace: eksnamespace
            manifests: manifests/*
- deployment:
  displayName: Deploy to OpenShift
  pool:
    vmImage: ubuntu-latest
  environment: contoso.openshiftnamespace
  strategy:
    runOnce:
      deploy:
        steps:
        - checkout: self
        - task: KubernetesManifest@0
          displayName: Deploy to Kubernetes cluster
          inputs:
            action: deploy
            kubernetesServiceConnection: serviceConnection #replace with your service connection
            namespace: openshiftnamespace
            manifests: manifests/*
- deployment:
  displayName: Deploy to DigitalOcean
  pool:
    vmImage: ubuntu-latest
  environment: contoso.digitaloceannamespace
  strategy:
    runOnce:
      deploy:
        steps:
        - checkout: self
        - task: KubernetesManifest@0
          displayName: Deploy to Kubernetes cluster
          inputs:
            action: deploy
            kubernetesServiceConnection: serviceConnection #replace with your service connection
            namespace: digitaloceannamespace
            manifests: manifests/*

Note

When using the service account option, ensure that a RoleBinding exists, which grants permissions in the edit ClusterRole to the desired service account. This is needed so that the service account can be used by Azure Pipelines for creating objects in the chosen namespace.