Valider des applications par rapport aux règles de l'entreprise dans un pipeline de CI

Si votre organisation utilise Policy Controller pour gérer les règles de ses clusters Google Kubernetes Engine (GKE) Enterprise, vous pouvez valider la configuration de déploiement d'une application dans son pipeline d'intégration continue (CI). Ce tutoriel explique comment atteindre ce résultat. La validation de votre application est utile si vous êtes un développeur créant un pipeline de CI pour une application, ou un ingénieur de plate-forme créant un modèle de pipeline de CI pour plusieurs équipes en charge de l'application.

Les règles jouent un rôle important dans la sécurité et la conformité d'une organisation. Policy Controller permet à votre organisation de gérer ces règles de manière centralisée et déclarative pour tous vos clusters. En tant que développeur, vous pouvez profiter de la nature centralisée et déclarative de ces règles. Vous pouvez utiliser ces caractéristiques pour valider votre application par rapport à ces règles dès que possible dans votre workflow de développement. Il y a deux avantages à détecter les cas de non-respect des règles dans le pipeline de CI plutôt que lors du déploiement : cela vous permet de mettre l'accent sur la sécurité en amont (Shift Left) et de renforcer la boucle de rétroaction, réduisant ainsi le temps et les coûts nécessaires pour corriger ces non-respects.

Ce tutoriel utilise Cloud Build comme outil de CI, ainsi qu'un exemple de dépôt GitHub qui contient des règles servant de démonstrations.

Ressources

Ce tutoriel utilise plusieurs outils Kubernetes. Cette section explique ce que sont ces outils, comment ils interagissent entre eux et comment les remplacer par un autre élément le cas échéant.

Les outils suivants font partie des outils que vous utilisez dans ce tutoriel :

  • Policy Controller : basé sur le projet Open Source Open Policy Agent - Gatekeeper. Policy Controller applique des règles sur les objets créés dans un cluster Kubernetes (par exemple, en empêchant l'utilisation d'une option spécifique ou en forçant l'utilisation d'un libellé spécifique). Ces règles sont appelées contraintes. Les contraintes sont définies en tant que ressources personnalisées Kubernetes. Policy Controller est disponible dans l'édition Google Kubernetes Engine (GKE) Enterprise, mais vous pouvez utiliser Open Policy Agent - Gatekeeper au lieu de Policy Controller pour votre implémentation.

  • GitHub : dans ce tutoriel, nous utilisons GitHub pour héberger les dépôts Git: un pour un exemple d'application, et un autre qui contient les contraintes de Policy Controller. Pour plus de simplicité, les deux dépôts sont deux dossiers différents dans un même dépôt Git. En réalité, il s'agirait de dépôts distincts. Vous pouvez utiliser n'importe quelle solution Git.

  • Cloud Build : Cloud Build est la solution de CI de Google Cloud. Dans ce tutoriel, nous l'utilisons pour exécuter des tests de validation. Bien que les détails de la mise en œuvre puissent varier d'un système de CI à l'autre, les concepts décrits dans ce tutoriel peuvent être utilisés avec n'importe quel système de CI basé sur des conteneurs.

  • Kustomize : Kustomize est un outil de personnalisation pour les configurations Kubernetes. Il utilise des configurations "de base" et leur applique des personnalisations. Il permet d'adopter une approche DRY (Don't Repeat Yourself – Ne vous répétez pas) pour les configurations Kubernetes. Avec Kustomize, vous conservez les éléments communs à tous vos environnements dans les configurations de base, et vous créez des personnalisations par environnement. Dans ce tutoriel, nous conservons les configurations Kustomize dans le dépôt de l'application, et nous "créons" (par exemple, nous appliquons les personnalisations) les configurations dans le pipeline de CI. Vous pouvez utiliser les concepts décrits dans ce tutoriel avec n'importe quel outil générant des configurations Kubernetes prêtes à être appliquées à un cluster (tel que, par exemple, la commande helm template).

  • Kpt : Kpt est un outil permettant de créer des workflows pour les configurations Kubernetes. Kpt permet d'extraire, d'afficher, de personnaliser, de mettre à jour, de valider et d'appliquer des configurations Kubernetes. Comme Kpt fonctionne avec Git et des fichiers YAML, il est compatible avec la plupart des outils existants de l'écosystème Kubernetes. Dans ce tutoriel, nous utilisons kpt dans le pipeline CI pour récupérer les contraintes du dépôt anthos-config-management-samples et valider les configurations Kubernetes par rapport à ces contraintes.

Pipeline

Le pipeline de CI que nous utilisons dans ce tutoriel est illustré dans le schéma suivant :

Pipeline de CI pour Policy Controller

Le pipeline s'exécute dans Cloud Build et les commandes sont exécutées dans un répertoire contenant une copie du dépôt de l'exemple d'application. Le pipeline commence par générer les configurations Kubernetes finales avec Kustomize. Ensuite, il extrait à partir du dépôt anthos-config-management-samples les contraintes pour lesquelles nous voulons effectuer la validation à l'aide de kpt. Enfin, il utilise Kpt pour valider les configurations Kubernetes par rapport à ces contraintes. Pour effectuer cette dernière étape, nous utilisons une fonction de configuration spécifique appelée gatekeeper, qui effectue cette validation. Dans ce tutoriel, vous allez déclencher le pipeline de CI manuellement, mais en réalité, vous devez le configurer pour qu'il s'exécute après un git push vers votre dépôt Git.

Objectifs

  • Exécuter un pipeline de CI pour un exemple d'application avec Cloud Build.
  • Constater que le pipeline échoue car des règles ne sont pas respectées.
  • Modifier le dépôt de l'exemple d'application de façon à respecter les règles.
  • Exécuter à nouveau le pipeline de CI.

Coûts

Ce tutoriel utilise les composants facturables suivants de Google Cloud :

  • Cloud Build
  • Édition Google Kubernetes Engine (GKE) Enterprise

Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût.

Une fois que vous avez terminé ce dernier, vous pouvez éviter de continuer à payer des frais en supprimant les ressources que vous avez créées. Pour en savoir plus, consultez la section Nettoyer.

Avant de commencer

  1. Sélectionnez ou créez un projet Google Cloud. Dans Google Cloud Console, accédez à la page Gérer les ressources.

    Accéder à la page Gérer les ressources

  2. Activez la facturation pour votre projet.

  3. Pour exécuter les commandes répertoriées dans ce tutoriel, ouvrez Cloud Shell :

    Accéder à Cloud Shell

  4. Dans Cloud Shell, exécutez gcloud config get-value project.

    Si la commande ne renvoie pas l'ID du projet que vous venez de sélectionner, configurez Cloud Shell pour utiliser votre projet.

    gcloud config set project PROJECT_ID
    

    Remplacez PROJECT_ID par l'ID du projet.

  5. Dans Cloud Shell, activez l'API Cloud Build requise à l'aide de la commande suivante :

    gcloud services enable cloudbuild.googleapis.com
    

Valider les configurations de l'application d'exemple

Dans cette section, vous allez exécuter à l'aide de Cloud Build un pipeline de CI sur le dépôt de l'exemple d'application que nous fournissons. Ce pipeline valide la configuration Kubernetes disponible dans ce dépôt d'application exemple par rapport aux contraintes disponibles dans un dépôt anthos-config-management-samples.

Pour valider les configurations d'application, procédez comme suit :

  1. Dans Cloud Shell, clonez le dépôt de l'exemple d'application à l'aide de la commande suivante :

    git clone https://github.com/GoogleCloudPlatform/anthos-config-management-samples.git
    
  2. Exécutez le pipeline de CI avec Cloud Build. Les journaux de la compilation s'affichent directement dans Cloud Shell.

    cd anthos-config-management-samples/ci-app/app-repo
    gcloud builds submit .
    

    Le pipeline que vous exécutez est défini dans le fichier suivant.

    steps:
    - id: 'Prepare config'
      # This step builds the final manifests for the app
      # using kustomize and the configuration files
      # available in the repository.
      name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
      entrypoint: '/bin/sh'
      args: ['-c', 'mkdir hydrated-manifests && kubectl kustomize config/prod > hydrated-manifests/prod.yaml']
    - id: 'Download policies'
      # This step fetches the policies from the Anthos Config Management repository
      # and consolidates every resource in a single file.
      name: 'gcr.io/kpt-dev/kpt'
      entrypoint: '/bin/sh'
      args: ['-c', 'kpt pkg get https://github.com/GoogleCloudPlatform/anthos-config-management-samples.git/ci-app/acm-repo/cluster@main constraints
                      && kpt fn source constraints/ hydrated-manifests/ > hydrated-manifests/kpt-manifests.yaml']
    - id: 'Validate against policies'
      # This step validates that all resources comply with all policies.
      name: 'gcr.io/kpt-fn/gatekeeper:v0.2'
      args: ['--input', 'hydrated-manifests/kpt-manifests.yaml']

    Dans Policy Controller, les contraintes sont instanciées à partir de modèles de contraintes. Les modèles de contrainte contiennent le code Rego qui est réellement utilisé pour mettre en œuvre la contrainte. La fonction gcr.io/kpt-fn/gatekeeper a besoin à la fois du modèle de contrainte et des définitions de contrainte pour fonctionner. Le dépôt de l'exemple de règles contient ces deux ressources. Dans un cas réel, elles pourraient très bien être stockées dans des emplacements différents. Utilisez la commande kpt pkg get si nécessaire pour télécharger à la fois les modèles de contrainte et les contraintes.

    Ce tutoriel utilise gcr.io/kpt-fn/gatekeeper avec Cloud Build pour valider les ressources, mais vous pouvez également utiliser deux autres alternatives :

    kpt fn eval hydrated-manifests/kpt-manifests.yaml --image gcr.io/kpt-fn/gatekeeper:v0.2
    
    • Utilisez l'outil de ligne de commande gator :
    gator test -f hydrated-manifests/kpt-manifests.yaml
    
  3. Après quelques minutes, vous constatez que le pipeline échoue et affiche l'erreur suivante :

    [...]
    Step #2 - "Validate against policies": [error] apps/v1/Deployment/nginx-deployment : Deployment objects should have an 'owner' label indicating who created them.
    Step #2 - "Validate against policies": violatedConstraint: deployment-must-have-owner
    Finished Step #2 - "Validate against policies"
    2022/05/11 18:55:18 Step Step #2 - "Validate against policies" finished
    2022/05/11 18:55:19 status changed to "ERROR"
    ERROR
    ERROR: build step 2 "gcr.io/kpt-fn/gatekeeper:v0.2" failed: exit status 1
    2022/05/11 18:55:20 Build finished with ERROR status
    

    La contrainte que la configuration enfreint est définie dans le fichier suivant. Il s'agit d'une ressource personnalisée Kubernetes appelée K8sRequiredLabels.

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sRequiredLabels
    metadata:
      name: deployment-must-have-owner
    spec:
      match:
        kinds:
          - apiGroups: ["apps"]
            kinds: ["Deployment"]
      parameters:
        labels:
          - key: "owner"
        message: "Deployment objects should have an 'owner' label indicating who created them."

    Pour en savoir plus sur le modèle de contrainte correspondant à cette contrainte, consultez requiredlabels.yaml sur GitHub.

  4. Créez vous-même la configuration Kubernetes complète pour vérifier que le libellé owner est bel et bien manquant. Pour créer la configuration, procédez comme suit :

    kubectl kustomize config/prod
    

Corriger l'application pour qu'elle respecte les règles de l'entreprise

Dans cette section, vous corrigez le cas de non-respect des règles à l'aide de Kustomize :

  1. Dans Cloud Shell, ajoutez une section commonLabels au fichier Kustomize de base :

    cat <<EOF >> config/base/kustomization.yaml
    commonLabels:
      owner: myself
    EOF
    
  2. Créez la configuration Kubernetes complète et vérifiez que le libellé owner est maintenant présent :

    kubectl kustomize config/prod
    
  3. Relancez le pipeline de CI avec Cloud Build :

    gcloud builds submit .
    

    À présent, le pipeline se termine sans erreur et génère le résultat suivant :

    [...]
    Step #2 - "Validate against policies": [RUNNING] "gcr.io/kpt-fn/gatekeeper:v0"
    Step #2 - "Validate against policies": [PASS] "gcr.io/kpt-fn/gatekeeper:v0"
    [...]
    

Effectuer un nettoyage

  1. Dans la console Google Cloud, accédez à la page Gérer les ressources.

    Accéder à la page Gérer les ressources

  2. Dans la liste des projets, sélectionnez le projet que vous souhaitez supprimer, puis cliquez sur Supprimer.
  3. Dans la boîte de dialogue, saisissez l'ID du projet, puis cliquez sur Arrêter pour supprimer le projet.

Étapes suivantes