Home >> Blog >> Provisionnez Azure pour sauvegarder un cluster AKS avec Terraform, Helm, Velero

Provisionnez Azure pour sauvegarder un cluster AKS avec Terraform, Helm, Velero

26 septembre 2023

By Lionel Gurret.

Introduction

Dans cet article, nous allons plonger dans le processus complexe de provisionnement d’une infrastructure Azure pour faciliter la sauvegarde d’un cluster Azure Kubernetes Service (AKS). Alors que des options telles qu’Azure Backup existent, elles laissent souvent à désirer en termes de capacités d’automatisation nécessaires pour orchestrer la création des diverses ressources essentielles via Terraform.

La sauvegarde et la gestion de l’environnement AKS nous conduira à explorer en détail comment définir notre infrastructure via Terraform.

Ensuite, nous déploierons la solution de sauvegarde Velero, tirant parti du potentiel d’Helm pour simplifier et optimiser le processus. Nous mettrons en lumière les meilleures pratiques et les astuces pour assurer une mise en place réussie de Velero.

Tout au long de cet article, nous aborderons des détails techniques, des conseils pratiques et des étapes à suivre pour vous armer de l’expertise nécessaire afin de gérer efficacement votre infrastructure AKS et de garantir la protection de vos données.

Attention : contrairement à ce qui est donné la documentation officielle de vmware pour velero, la solution ne permet pas d’utiliser les Workload Identities (cf. github issue).

Mise en place de l’infrastructure avec Terraform

Pré-requis

Dans notre contexte, le cluster AKS et son resource group ont déjà été provisionnés. Référez-vous à la documentation officielle de Terraform pour cette partie.

Voici le nom de nos ressources pour vous aider à comprendre d’avantage la suite de cet article :

resource "azurerm_resource_group" "rg" {
  ...
}
resource "azurerm_kubernetes_cluster" "k8s" {
  ...
}

Nous avons bien sûr dans notre repository, d’autres fichiers Terraform pour la déclaration des providers, des variables, du backend etc.
Ces manifestes Terraform ainsi que le pipeline de provisionnement Azure DevOps pour l’infrastructure ne seront pas couverts par cet article de blog.

Création de l’espace de stockage pour les backups

Pour pouvoir stocker nos backups et nos snapshots, il est nécessaire de prévoir un storage account et un container.
Vous pouvez choisir de le créer dans le même resource group que celui du cluster AKS, ou comme expliqué dans la documentation (cf. sources), utiliser un resource group dédié aux backups.

Voici le code Terraform utilisé dans notre cas :

resource "azurerm_storage_account" "storaccbackup" {
  name                     = "storaccbackup01"
  account_replication_type = "LRS"
  account_tier             = "Standard"
  location                 = azurerm_resource_group.rg.location
  resource_group_name      = azurerm_resource_group.rg.name
}

resource "azurerm_storage_container" "storcontbackup" {
  name                 = "velero"
  storage_account_name = azurerm_storage_account.storaccbackup.name
}

Vous pouvez ajouter le paramètre access_tier et le configurer à "Cool" si vos backups ne seront pas fréquemment accédés.

Création du service principal et de l’application

Pour établir un lien entre notre cluster AKS et notre storage account, nous nous reposerons sur un service principal. Comme expliqué précédemment, l’utilisation des Managed Identity n’est malheureusement pas encore disponible.

Voici un exemple de code de création de ce service principal et de ses ressources associées :

data "azuread_client_config" "current" {}

resource "azuread_application" "this" {
  display_name = "aks-backup-${local.basename}"
  owners       = [data.azuread_client_config.current.object_id]
}

resource "azuread_service_principal" "this" {
  application_id = azuread_application.this.application_id
}

resource "azuread_service_principal_password" "this" {
  service_principal_id = azuread_service_principal.this.object_id
}

Configuration du RBAC

Ce service principal doit avoir accès au storage account, nous allons lui ajouter le rôle Contributeur :

resource "azurerm_role_assignment" "contributor_velero" {
  principal_id         = azuread_service_principal.this.object_id
  scope                = azurerm_storage_account.storaccbackup.id
  role_definition_name = "Contributor"
}

Il est possible de définir un custom role afin de limiter les droits accordés à notre service principal (cf. sources).

Stockage des variables générées par l’IaC dans un Keyvault

Certains paramètres vont devoir être utilisés par Helm lorsque nous installerons Velero sur notre cluster AKS. Il est donc important de stocker les informations suivantes dans un Azure Key Vault :

resource "azurerm_key_vault" "aks_kv" {
  ...
}

locals {
  keyvault_secrets = {
    aks-backup-resource-group-name = azurerm_storage_account.storaccbackup.resource_group_name
    aks-backup-storage-account-name = azurerm_storage_account.storaccbackup.name
    azure-tenant-id = data.azuread_client_config.current.tenant_id
    azure-backup-sp-client-id = azuread_application.this.application_id
    azure-backup-sp-client-secret = azuread_service_principal_password.this.value
  }
}

resource "azurerm_key_vault_secret" "keyvault_secrets" {
  for_each     = local.keyvault_secrets
  name         = each.key
  value        = each.value
  key_vault_id = azurerm_key_vault.aks_kv.id
}

Ces variables pourront ainsi être récupérées via un vargroup Azure DevOps lié à notre Azure Key Vault et utilisées dans nos pipelines helm.

Provisionnement de l’architecture Azure

Toute l’infrastructure a été définie, on peut à présent la provisionner avec les commandes Terraform bien connues :

terraform init
terraform plan
terraform apply

Installation de Velero avec Helm

Dans un autre repository Azure DevOps, nous allons maintenant préparer notre pipeline de déploiement et les fichiers de configuration de Velero.

Fichier credentials-velero

Premièrement, nous devons créer un fichier credentials-velero contenant les informations suivantes :

AZURE_SUBSCRIPTION_ID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX
AZURE_TENANT_ID=#{azure-tenant-id}#
AZURE_CLIENT_ID=#{azure-backup-sp-client-id}#
AZURE_CLIENT_SECRET=#{azure-backup-sp-client-secret}#
AZURE_RESOURCE_GROUP=MC_XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
AZURE_CLOUD_NAME=AzurePublicCloud

Prenez soin d’adapter la variable pour la subscription ID ainsi que l’Azure resource group. Il s’agit du resource group auto généré lors de la création du cluster AKS !
Les variables entre balises seront quant à elles modifiées par notre pipeline Azure DevOPs. Cela nous permet de ne pas afficher de données sensibles dans notre code.

Fichier Helm values velero-values.yaml

Nous allons aussi passer nos différentes valeurs à Helm avant d’installer le helm chart Velero. Pour cela nous créons le fichier velero-values.yaml dans notre repository :

configuration:
  backupStorageLocation:
    - name: azure
      bucket: velero
      provider: azure
      config:
        resourceGroup: #{aks-backup-resource-group-name}#
        storageAccount: #{aks-backup-storage-account-name}#
  volumeSnapshotLocation:
    - name: azure
      provider: azure
      config:
        resourceGroup: #{aks-backup-resource-group-name}#
        storageAccount: #{aks-backup-storage-account-name}#

snapshotsEnabled: true
deployNodeAgent: true

image:
  repository: velero/velero
  pullPolicy: Always

initContainers:
  - name: velero-plugin-for-microsoft-azure
    image: velero/velero-plugin-for-microsoft-azure:master
    volumeMounts:
      - mountPath: /target
        name: plugins

Vous pouvez vous référer à la documentation suivante pour les autres configurations.

Fichier azure-pipelines.yml

Voici à présent une partie du contenu de notre fichier de pipeline Azure DevOps qui nous servira à installer Velero sur notre cluster AKS :

...
# We load our variable from our Azure Key Vault
variables:
  - group: vargroup-k8s-kv
...
          # We install Helm
          - task: HelmInstaller@0
            displayName: Install helm
            inputs:
              helmVersion: '3.12.2'
              installKubectl: true

          # We add the necessary helm repository for Velero
          - task: CmdLine@2
            displayName: Add helm repos
            inputs:
              script: |
                helm repo add vmware-tanzu https://vmware-tanzu.github.io/helm-charts
                helm repo update

          # We replace our variables from our "KeyVault vargroup"
          - task: replacetokens@5
            displayName: Replace tokens in Velero config files
            inputs:
              rootDirectory: './'
              targetFiles: '**/*'
              encoding: 'auto'
              tokenPattern: 'default'
              writeBOM: true
              actionOnMissing: 'warn'
              keepToken: true
              actionOnNoFiles: 'continue'
              enableTransforms: false
              enableRecursion: false
              useLegacyPattern: false
              enableTelemetry: true

          # We install Velero !
          - task: HelmDeploy@0
            displayName: Helm Velero
            inputs:
              connectionType: 'Kubernetes Service Connection'
              kubernetesServiceConnection: 'XXXXXXXXXXXXXXXXXX'
              namespace: 'velero'
              command: 'upgrade'
              chartType: 'Name'
              chartName: 'vmware-tanzu/velero'
              releaseName: 'velero'
              valueFile: 'velero-values.yaml'
              arguments: "--create-namespace --set-file credentials.secretContents.cloud=./credentials-velero"

Une fois le pipeline lancé et exécuté, nous pouvons vérifier si l’espace de stockage est bien connecté avec notre cluster AKS :

$ kubectl get BackupStorageLocation -n velero
NAME    PHASE       LAST VALIDATED   AGE   DEFAULT
azure   Available   0s               26m

Nous venons d’installer Velero et son infrastructure avec succès !

Test de sauvegarde et de restauration

Installation du CLI Velero

Pour créer nos backups, il sera nécessaire d’utiliser le CLI velero.
Voici comment l’installer (documentation) :

wget https://github.com/vmware-tanzu/velero/releases/download/v1.11.1/velero-v1.11.1-linux-amd64.tar.gz
tar -xzvf velero-v1.11.1-linux-amd64.tar.gz
sudo chmod +x ~/velero-v1.11.1-linux-amd64/velero
sudo cp ~/velero-v1.11.1-linux-amd64/velero /usr/local/bin/
velero version

Mise en place d’une application de test

Le backup étant en place, il nous reste bien sûr à valider son fonctionnement. Pour cela, nous allons nous baser sur une application de test fournie par Velero.

Commençons par télécharger et installer l’application sur notre serveur AKS :

cd ~/velero-v1.11.1-linux-amd64/examples/nginx-app
kubectl apply -f base.yml

Vérifions que l’application a été déployée avec succès :

$ kubectl -n nginx-example get all
NAME                                    READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-747864f4b5-8cwv2   1/1     Running   0          22h
pod/nginx-deployment-747864f4b5-w8d48   1/1     Running   0          22h

NAME               TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)        AGE
service/my-nginx   LoadBalancer   10.0.24.168   20.250.58.191   80:30605/TCP   22h

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   2/2     2            2           22h

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-747864f4b5   2         2         2       22h

Création de notre premier backup Velero

Pour lancer notre premier backup, nous lançons la commande suivante :

$ velero backup create test-backup --include-namespaces nginx-example --wait --storage-location azure
Backup request "test-backup" submitted successfully.
Waiting for backup to complete. You may safely press ctrl-c to stop waiting - your backup will continue in the background.
.....
Backup completed with status: Completed. You may check for more information using the commands `velero backup describe test-backup` and `velero backup logs test-backup`.

Nous pouvons vérifier que le backup s’est déroulé correctement et que des fichiers ont été ajoutés dans notre storage container :

On peut également voir notre backup sur le serveur directement :

$ velero backup get
NAME          STATUS      ERRORS   WARNINGS   CREATED                         EXPIRES   STORAGE LOCATION   SELECTOR
test-backup   Completed   0        0          2023-08-15 08:36:58 +0000 UTC   29d       azure              <none>

Test de restauration

Nous allons commencer par supprimer toutes les ressources de notre namespace nginx-example pour simuler une perte de données :

$ kubectl -n nginx-example delete service my-nginx
service "my-nginx" deleted

$ kubectl -n nginx-example delete deployment nginx-deployment --force --grace-period=0
Warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
deployment.apps "nginx-deployment" force deleted

$ kubectl -n nginx-example get all
No resources found in nginx-example namespace.

On peut lancer la restauration :

$ velero restore create --from-backup test-backup
Restore request "test-backup-20230815084245" submitted successfully.
Run `velero restore describe test-backup-20230815084245` or `velero restore logs test-backup-20230815084245` for more details.

Comme indiqué par le message de sortie, nous pouvons suivre le processus de restore via la commande suivante comme indiqué :

$ velero restore logs test-backup-20230815084245
time="2023-08-15T08:42:46Z" level=info msg="starting restore" logSource="pkg/controller/restore_controller.go:458" restore=velero/test-backup-20230815084245
time="2023-08-15T08:42:46Z" level=info msg="Starting restore of backup velero/test-backup" logSource="pkg/restore/restore.go:396" restore=velero/test-backup-20230815084245
time="2023-08-15T08:42:46Z" level=info msg="Resource 'customresourcedefinitions.apiextensions.k8s.io' will be restored at cluster scope" logSource="pkg/restore/restore.go:2030" restore=velero/test-backup-20230815084245
time="2023-08-15T08:42:46Z" level=info msg="Getting client for apiextensions.k8s.io/v1, Kind=CustomResourceDefinition" logSource="pkg/restore/restore.go:918" restore=velero/test-backup-20230815084245
time="2023-08-15T08:42:46Z" level=info msg="restore status includes excludes: <nil>" logSource="pkg/restore/restore.go:1189" restore=velero/test-backup-20230815084245
time="2023-08-15T08:42:46Z" level=info msg="Executing item action for customresourcedefinitions.apiextensions.k8s.io" logSource="pkg/restore/restore.go:1196" restore=velero/test-backup-20230815084245
...

Enfin, nous observons que nos ressources sont de nouveau disponibles :

$ kubectl -n nginx-example get all
NAME                                    READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-747864f4b5-8cwv2   1/1     Running   0          15s
pod/nginx-deployment-747864f4b5-w8d48   1/1     Running   0          15s

NAME               TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
service/my-nginx   LoadBalancer   10.0.196.243   20.250.76.149   80:31188/TCP   15s

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   2/2     2            2           15s

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-747864f4b5   2         2         2       15s

Tout est à présent en place pour automatiser la création des backups !

/! Ne suivez pas (pour le moment) la documentation relative aux Workload Identities

Conclusion

En conclusion, nous avons exploré ensemble comment mettre en place des sauvegardes Velero sur Azure AKS en utilisant Infrastructure as Code (IaC). Il est important de noter que cette méthode offre une solution de sauvegarde robuste pour vos clusters AKS, mais elle peut devenir obsolète à mesure que les fournisseurs Terraform et les services Azure continuent d’évoluer et de s’améliorer.

Chez SoKube, nous comprenons la nature dynamique des technologies cloud et nous nous engageons à rester à la pointe de ces avancées. Notre équipe d’experts est prête à vous aider à naviguer dans le paysage en constante évolution d’Azure et de Terraform. Que vous ayez besoin de guidance, de consultation ou de formation, nous sommes là pour mettre à profit notre expertise et vous fournir les connaissances et les outils nécessaires pour gérer efficacement votre infrastructure cloud.

N’hésitez pas à nous contacter pour tous vos besoins en matière d’Azure et de Terraform. Ensemble, nous pouvons garantir que votre infrastructure reste résiliente, sécurisée et à jour dans cette ère numérique en constante évolution.

Sources

VMWare Tanzu
Velero Documentation

Laisser un commentaire

  Edit this page