Bonjour ! et bienvenue !! Dans ce projet, nous allons créer une infrastructure simple avec Terraform tout en mettant en œuvre le flux de travail central de Terraform (qui consiste à écrire, planifier et appliquer) en collaboration pour un environnement de production. En termes simples, nous allons déployer une infrastructure avec Terraform d'une manière qui permet à une équipe d'ingénieurs d'introduire des modifications dans le système, de les examiner en détail, de les approuver ou de les refuser et (si elles sont approuvées) de les déployer en production.
Le système que nous allons construire dans ce projet sera adapté aux opérations de certaines petites et moyennes organisations (avec ou sans l'ajout possible de quelques éléments supplémentaires dont nous parlerons à la fin du projet).
Pour les besoins de ce projet, vous êtes un Ingénieur Infrastructure chargé de créer l'infrastructure initiale pour une entreprise de taille moyenne. Nous commencerons par créer notre infrastructure à partir de zéro, en travaillant avec le contrôle de version (Git) tout au long, en amorçant notre système via un Backend Local sur notre station de travail, en le migrant vers un Backend Distant pour permettre la collaboration et en créant des scripts pour automatiser l'ensemble du processus d'Intégration Continue et de Déploiement Continu.
Nous allons :
- Créer une infrastructure de base avec Terraform sur DigitalOcean & Cloudflare
- Configurer un Backend Distant Google Cloud Storage pour permettre la collaboration
- Configurer l'accès à notre backend GCS via Github Environments et les flux de travail Actions
- Créer des scripts de flux de travail Actions pour Initialiser, Valider, Prévisualiser et Appliquer nos modifications d'infrastructure.
- Utiliser Github Pull Requests et le Github Bot pour les examens (et approbations ou refus) des modifications d'infrastructure proposées.
Voici le dépôt du projet sur Github : https://github.com/obiMadu/terraform-github-workflow
Plongeons directement 🚀
1. Créer notre Infrastructure via Terraform

Nous allons créer l'infrastructure très simple illustrée dans le diagramme ci-dessus. Un simple serveur web exécutant Nginx sur Digital Ocean avec une adresse ipv4 et un DNS A record sur une zone Cloudflare qui pointe un sous-domaine vers lui. Nous y parviendrons en créant seulement deux ressources Terraform.
Vous pourriez facilement échanger Cloudflare contre n'importe quel autre service de noms de domaine de votre choix. Si vous gérez vos domaines via Amazon Route 53 par exemple, vous n'avez pas besoin de passer à Cloudflare pour ce tutoriel. Créez simplement les configurations Terraform appropriées nécessaires pour mapper l'adresse IPv4 de notre instance de serveur à un nom de domaine (il n'est pas non plus obligatoire que ce soit un sous-domaine, vous pouvez mapper un domaine Apex, comme vous le préférez).
Comme prévu (probablement), il s'ensuit également que vous n'avez pas besoin de créer votre serveur sur Digital Ocean, vous pourriez le déployer sur AWS ou tout autre fournisseur de votre choix, à condition que nous obtenions un serveur avec Nginx installé et une adresse IPv4.
Pour rendre les choses plus amusantes, vous pourriez même provisionner un serveur de base et utiliser un outil tel qu'Ansible pour y déployer Nginx ou toute autre application web. Vous pourriez construire votre propre image personnalisée avec des outils comme Packer et l'utiliser également. C'est votre choix. Ce projet se veut rapide et facile à suivre.
1.1 créer providers.tf
Ensuite, nous allons créer un fichier providers.tf pour configurer nos différents fournisseurs. Les contraintes de version des fournisseurs sont définies sur les plus récentes au moment de la rédaction de cet article.
terraform {
required_providers {
digitalocean = {
source = "digitalocean/digitalocean"
version = "2.34.1"
}
cloudflare = {
source = "cloudflare/cloudflare"
version = "4.24.0"
}
}
}
# Digital Ocean API credentials
provider "digitalocean" {
token = var.do_token
}
provider "cloudflare" {
api_token = var.cloudflare_api_token
}Ce qui précède représente les arguments minimums absolus requis par les différents fournisseurs pour fonctionner correctement. Une fois ce fichier créé, nous allons initialiser Git dans le répertoire de notre projet et faire de ce fichier notre tout premier commit via les commandes suivantes ;
git init .
git add .
git commit -m "Initial commit"Nous avons transformé les valeurs de nos arguments en variables pour éviter de coder en dur ces valeurs sensibles dans nos fichiers de configuration. N'oubliez pas non plus que vous pouvez personnaliser les messages de commit Git comme bon vous semble.
1.2 créer variables.tf
Puisque nous avons assigné des variables comme valeurs aux arguments dans nos configurations de fournisseurs, il est temps de déclarer ces variables. Nous faisons cela dans un fichier que nous appellerons variables.tf, avec le contenu suivant.
variable "do_token" {
type = string
}
variable "do_region" {
type = string
}
variable "cloudflare_api_token" {
type = string
}
variable cloudflare_zone_id" {
type = string
}Nous pouvons maintenant aller de l'avant et commiter ce nouveau fichier dans Git avec un message de commit approprié.
1.3 Initialiser Terraform
Maintenant que nous avons notre configuration de base, il est temps d'exécuter terraform init dans le répertoire de notre projet pour initialiser Terraform.

Votre message de succès devrait ressembler à celui ci-dessus.
Maintenant, nous devons faire deux choses de plus ;
- Ajouter un fichier
.gitignoreadapté à Terraform à notre projet - Fournir les valeurs aux différentes variables que nous avons configuré Terraform pour utiliser.
Nous pouvons récupérer un fichier .gitignore adapté à Terraform à l'adresse suivante https://github.com/github/gitignore/blob/main/Terraform.gitignoretext
Il est maintenant temps d'aller de l'avant et de récupérer les différentes clés API requises pour nos fournisseurs depuis leurs plateformes respectives. Nous aurons besoin de ;
- un Token API avec un accès en
writede Digital Ocean, ainsi qu'un code court de région (qui spécifie dans quelle région nous souhaitons déployer nos ressources) - un Token API de Cloudflare, ainsi que le Zone ID pour le domaine dans lequel nous souhaitons créer notre enregistrement DNS.
La manière exacte d'obtenir ces informations d'identification ne sera pas couverte ici (vous devriez être en mesure de les acquérir).
Par souci de simplicité, vous pouvez utiliser la région DigitalOcean fra1. Cela correspond au centre de données de Francfort.
Vient maintenant le moment de fournir à Terraform les valeurs que nous avons acquises. Pour être direct, nous allons créer un fichier terraform.tfvars et introduire nos valeurs de variables. Notre fichier devrait ressembler à ce qui suit ;
do_token = "value"
do_region = "fra1"
cloudflare_api_token = "value"
cloudflare_zone_id = "value"N'OUBLIEZ PAS : Vous ne devez jamais commiter le fichier terraform.tfvars dans Git. Ce fichier contient des secrets d'application importants qui ne doivent être partagés avec personne. Si un acteur malveillant accède à ces secrets, l'ensemble de notre infrastructure risque d'être compromise. Le seul but de ce fichier est pour un usage local. Nous emploierons une méthode plus sécurisée pour fournir ces valeurs à Terraform lorsque nous arriverons à l'environnement CI/CD.
1.4 Créer les Ressources
Il est maintenant temps de créer réellement les ressources pour notre Infrastructure. Nous allons créer deux fichiers : un fichier servers.tf et un fichier dns.tf.
- Le premier fichier,
servers.tf, nous le remplirons avec la configuration des ressources pour créer notre serveur DigitalOcean avec l'image officielle DigitalOcean Nginx. Ainsi (nous créerons une ressourcedigitalocean_droplet) ;
#create server with nginx image
resource "digitalocean_droplet" "server" {
name = "gate"
size = "s-1vcpu-1gb"
image = "nginx"
region = var.do_region
}- Le deuxième fichier,
dns.tfnous le configurerons comme suit (nous créons une ressourcecloudflare_record) ;
# Add a record to the domain
resource "cloudflare_record" "server" {
zone_id = var.cloudflare_zone_id
name = "server"
value = digitalocean_droplet.server.ipv4_address
type = "A"
ttl = 1
proxied = true
}Maintenant, enregistrez les deux fichiers et commitez-les dans Git avec des messages de commit appropriés.
À ce stade, l'arborescence de votre répertoire devrait ressembler exactement à ce qui suit ;

2. Créer et Initialiser le Backend Distant
Il est temps d'ajouter un backend distant à notre projet. Puisque je suis un Google Cloud Engineer, je travaillerai avec un backend distant gcs dans ce projet. Vous pouvez modifier cela pour n'importe quel autre backend distant de votre choix, comme un backend s3.
J'ai donc procédé à la création d'un Google Cloud Storage Bucket avec le nom terraform-github-workflow. J'ai créé un compte de service sous le même nom et attribué au principal la permission Storage Object Admin sur le bucket gcs. Cela permettra au compte de service de créer et de gérer des objets dans le bucket terraform-github-workflow. Ensuite, j'ai procédé à la création d'une JSON service account key pour le principal du compte de service, que j'ai téléchargée et stockée dans un endroit sûr sur ma station de travail locale.
La dernière étape consistait à définir la variable d'environnement GOOGLE_APPLICATION_CREDENTIALS sur le chemin absolu de la clé JSON téléchargée sur mon PC, comme ceci ;
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/json/key/filePour être sécurisé, vous pourriez toujours créer une différente service account key à utiliser lorsque nous arriverons à l'environnement CI/CD.
Enfin, il est temps d'exécuter terraform init pour initialiser ce nouveau backend. Selon le backend que vous avez choisi, vous devriez voir un message de réussite très similaire à celui ci-dessous ;

3. Créer des flux de travail Github Actions
Maintenant que notre backend distant Terraform est initialisé, il est temps de créer les scripts Github Actions pour notre pipeline CI/CD. Nous créerons au total 3 flux de travail différents comme suit ;
- un flux de travail
validatequi se déclenche à chaque push vers la brancheplande notre projet. Cela validera toute nouvelle modification de notre base de code à l'aide de la commandeterraform validate. - un flux de travail
planqui se déclenche à chaque Pull request vers la branchemaindu projet. Ce flux de travail exécutera à blanc les changements d'infrastructure à venir et utilisera le Github Bot pour faire de ces changements un commentaire sur ladite Pull request. - un flux de travail
deployqui se déclenche à chaque push/merge vers la branchemain. Cela déploie nos changements d'infrastructure approuvés.
3.1 créer workflows/validate.yml
Nous commencerons par créer un dossier .github/workflows à la racine de notre répertoire de projet. Dans le répertoire workflows, nous créerons un fichier validate.yml. Notre arborescence de répertoire à ce stade devrait ressembler à ceci ;

Voici le contenu du fichier de flux de travail validate ;
name: Validate
on:
push:
branches: [plan]
env:
GOOGLE_APPLICATION_CREDENTIALS: ${{ vars.GOOGLE_APPLICATION_CREDENTIALS }}
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: true # Fetch submodules (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_wrapper: true
- name: Setup Backend Credentials
id: backend
run: echo '${{ secrets.GCS_KEY }}' > ${{ vars.GOOGLE_APPLICATION_CREDENTIALS }}
- name: Terraform Init
id: init
run: terraform init
- name: Terraform Validate
id: terraform
run: terraform validate -no-colorCe flux de travail :
- se déclenche à chaque push vers la branche
plan - s'exécute sur l'image
latest Ubuntu - récupère notre code en tant que première étape
- configure ensuite Terraform
- configure les identifiants du backend
gcs - exécute
terraform init& - exécute
terraform validatesur notre base de code
Maintenant, commitons ce fichier dans Git et passons à la suite.
3.2 créer workflows/deploy.yml
Ensuite, nous créerons notre flux de travail deploy avec le contenu suivant ;
name: Deploy
on:
push:
branches: [main]
env:
GOOGLE_APPLICATION_CREDENTIALS: ${{ vars.GOOGLE_APPLICATION_CREDENTIALS }}
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: true # Fetch submodules (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
- name: Setup Backend Credentials
id: backend
run: echo '${{ secrets.GCS_KEY }}' > ${{ vars.GOOGLE_APPLICATION_CREDENTIALS }}
- name: Terraform Init
id: init
run: terraform init
- name: Terraform Apply
id: apply
env:
TF_VAR_do_token: ${{ secrets.do_token }}
TF_VAR_do_region: ${{ secrets.do_region }}
TF_VAR_cloudflare_api_token: ${{ secrets.cloudflare_api_token }}
TF_VAR_cloudflare_zone_id: ${{ secrets.cloudflare_zone_id }}
run: terraform apply -auto-approveCe flux de travail :
- se déclenche à chaque push/merge vers la branche
main - s'exécute sur l'image
latest Ubuntu - récupère notre code en tant que première étape
- configure ensuite Terraform
- configure les identifiants du backend
gcs - exécute
terraform init& - exécute
terraform applyavec-auto-approvepour déployer notre infrastructure
Une fois de plus, commitez ce flux de travail dans Git avec un message approprié et nous créerons notre flux de travail final.
3.3 créer workflows/plan.yml
Le dernier (mais non le moindre) flux de travail que nous allons créer est le flux de travail plan. Nous créons ce flux de travail en dernier car c'est en lui que nous intègrerons notre Github Bot pour nous aider à fournir les résultats de nos tests à blanc afin que les examens de nos Pull-requests soient plus faciles et plus pertinents.
Nous allons donc d'abord créer le flux de travail avec les fonctionnalités nécessaires, puis intégrer le Bot à l'étape suivante. Voici le code pour notre flux de travail plan ;
name: Plan
on:
pull_request:
branches: [main]
env:
GOOGLE_APPLICATION_CREDENTIALS: ${{ vars.GOOGLE_APPLICATION_CREDENTIALS }}
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v2
with:
submodules: true # Fetch submodules (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_wrapper: true
- name: Setup Backend Credentials
id: backend
run: echo '${{ secrets.GCS_KEY }}' > ${{ vars.GOOGLE_APPLICATION_CREDENTIALS }}
- name: Terraform Init
id: init
run: terraform init
- name: Terraform fmt
id: fmt
run: terraform fmt -check
continue-on-error: true
- name: Terraform Validate
id: validate
run: terraform validate -no-color
- name: Terraform Plan
id: plan
env:
TF_VAR_do_token: ${{ secrets.do_token }}
TF_VAR_do_region: ${{ secrets.do_region }}
TF_VAR_cloudflare_api_token: ${{ secrets.cloudflare_api_token }}
TF_VAR_cloudflare_zone_id: ${{ secrets.cloudflare_zone_id }}
run: terraform plan -no-colorCe flux de travail :
- se déclenche à chaque pull-request vers la branche
main - s'exécute sur l'image
latest Ubuntu - acquiert la permission d'écrire sur les Pull requests
- récupère notre code en tant que première étape
- configure ensuite Terraform
- configure les identifiants du backend
gcs - exécute
terraform init - exécute
terraform fmt - exécute
terraform validate(à nouveau) - exécute
terraform planavec un test à blanc de notre infrastructure
Parfait ! Nous pouvons maintenant aller de l'avant et ajouter le Bot dans la section suivante. N'oubliez pas de commiter votre nouveau flux de travail plan dans Git.
4. Configurer le Github Bot
Ajouter le Github Bot à notre flux de travail est assez simple. Il s'agit juste d'une étape supplémentaire sur notre flux de travail plan.
Ajoutez l'étape suivante à votre fichier de flux de travail plan.yml :
- name: Comment plan on PR
uses: actions/github-script@v6
if: github.event_name == 'pull_request'
env:
PLAN: "terraform\n${{ steps.plan.outputs.stdout }}"
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
// 1. Retrieve existing bot comments for the PR
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
})
const botComment = comments.find(comment => {
return comment.user.type === 'Bot' && comment.body.includes('Terraform Format and Style')
})
// 2. Prepare format of the comment
const output = ` ## Terraform Results
#### Terraform Format and Style 🖌\`${{ steps.fmt.outcome }}\`
#### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\`
#### Terraform Validation 🤖\`${{ steps.validate.outcome }}\`
<details><summary>Validation Output</summary>
\`\`\`\n
${{ steps.validate.outputs.stdout }}
\`\`\`
</details>
#### Terraform Plan 📖\`${{ steps.plan.outcome }}\`
<details><summary>Show Plan</summary>
\`\`\`\n
${process.env.PLAN}
\`\`\`
</details>
*Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`, Working Directory: \`${{ env.tf_actions_working_dir }}\`, Workflow: \`${{ github.workflow }}\`*`;
// 3. If we have a comment, update it, otherwise create a new one
if (botComment) {
github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: output
})
} else {
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
}Votre fichier plan.yml en entier devrait maintenant ressembler exactement à ceci :
name: Plan
on:
pull_request:
branches: [main]
env:
GOOGLE_APPLICATION_CREDENTIALS: ${{ vars.GOOGLE_APPLICATION_CREDENTIALS }}
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v2
with:
submodules: true # Fetch submodules (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_wrapper: true
- name: Setup Backend Credentials
id: backend
run: echo '${{ secrets.GCS_KEY }}' > ${{ vars.GOOGLE_APPLICATION_CREDENTIALS }}
- name: Terraform Init
id: init
run: terraform init
- name: Terraform fmt
id: fmt
run: terraform fmt -check
continue-on-error: true
- name: Terraform Validate
id: validate
run: terraform validate -no-color
- name: Terraform Plan
id: plan
env:
TF_VAR_do_token: ${{ secrets.do_token }}
TF_VAR_do_region: ${{ secrets.do_region }}
TF_VAR_cloudflare_api_token: ${{ secrets.cloudflare_api_token }}
TF_VAR_cloudflare_zone_id: ${{ secrets.cloudflare_zone_id }}
run: terraform plan -no-color
- name: Comment plan on PR
uses: actions/github-script@v6
if: github.event_name == 'pull_request'
env:
PLAN: "terraform\n${{ steps.plan.outputs.stdout }}"
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
// 1. Retrieve existing bot comments for the PR
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
})
const botComment = comments.find(comment => {
return comment.user.type === 'Bot' && comment.body.includes('Terraform Format and Style')
})
// 2. Prepare format of the comment
const output = ` ## Terraform Results
#### Terraform Format and Style 🖌\`${{ steps.fmt.outcome }}\`
#### Terraform Initialization ⚙️\`${{ steps.init.outcome }}\`
#### Terraform Validation 🤖\`${{ steps.validate.outcome }}\`
<details><summary>Validation Output</summary>
\`\`\`\n
${{ steps.validate.outputs.stdout }}
\`\`\`
</details>
#### Terraform Plan 📖\`${{ steps.plan.outcome }}\`
<details><summary>Show Plan</summary>
\`\`\`\n
${process.env.PLAN}
\`\`\`
</details>
*Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`, Working Directory: \`${{ env.tf_actions_working_dir }}\`, Workflow: \`${{ github.workflow }}\`*`;
// 3. If we have a comment, update it, otherwise create a new one
if (botComment) {
github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: output
})
} else {
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
}5. Pousser la base de code vers Github
Une fois que vous avez terminé de commiter les nouveaux ajouts ci-dessus dans Git, il est temps de publier (publish) notre base de code d'infrastructure sur Github.
Maintenant, rendez-vous simplement sur Github et créez un dépôt public (ou privé), ajoutez le dépôt comme remote origin pour le projet sur notre machine locale, et poussez (push).
Immédiatement après avoir fait cela, votre flux de travail deploy devrait commencer à s'exécuter, mais ne vous inquiétez pas car il va échouer. Il échouera parce que l'environnement Github Actions n'a pas été configuré avec les identifiants appropriés pour à la fois Initialiser notre Backend Terraform et fournir les valeurs appropriées aux variables définies dans notre infrastructure.


Il est maintenant temps de configurer correctement l'environnement CI/CD de Github Actions avec les identifiants d'accès appropriés pour déployer notre charge de travail.
6. Configurer Github Environments pour le Backend Terraform et les Variables
Maintenant, nous devons nous rendre dans Github Environments et configurer les secrets et les env vars nécessaires au succès de notre flux de travail.
Si vous l'avez remarqué tout au long de nos flux de travail Github Actions, pour chaque opération qui affecte l'état de Terraform, nous avons inclus les différentes variables d'environnement nécessaires à Terraform pour s'exécuter. Une instance de ceci se trouve au niveau de la commande terraform apply dans le flux de travail deploy. L'extrait de code est le suivant ;
- name: Terraform Apply
id: apply
env:
TF_VAR_do_token: ${{ secrets.do_token }}
TF_VAR_do_region: ${{ secrets.do_region }}
TF_VAR_cloudflare_api_token: ${{ secrets.cloudflare_api_token }}
TF_VAR_cloudflare_zone_id: ${{ secrets.cloudflare_zone_id }}
run: terraform apply -auto-approveVoici donc ci-dessous une liste de tous les différents secrets et env vars que nous devons définir (vous verrez que tous ont été intégrés dans les différents flux de travail aux endroits appropriés) ;
- Variables Terraform
TF_VAR_do_tokenTF_VAR_do_regionTF_VAR_cloudflare_api_tokenTF_VAR_cloudflare_zone_id
- Secrets et variables du Backend Distant
GCS_KEY- La clé Google Cloud Storage.GOOGLE_APPLICATION_CREDENTIALS- Chemin vers la clé Google Cloud Storage dans le système de fichiers
N'oubliez pas de créer une différente GCS Key pour l'environnement Github Actions, et de désactiver celle que nous avons utilisée pour Initialiser Terraform localement, à partir de maintenant toute nouvelle modification de l'infrastructure sera traitée via notre flux de travail. Vous ne devriez pas utiliser votre clé, même pour le déploiement initial des ressources.
Très bien, rendez-vous maintenant sur votre page Github Dashboard -> Settings -> Secrets and Variables -> Actions. C'est la page illustrée ci-dessous.

Ensuite, nous allons procéder et remplir les valeurs pour les différents secrets et variables d'environnement.
En raison du fait que nous ne travaillons qu'avec un seul environnement dans ce projet, nous allons les remplir en tant que secrets et variables de Référentiel. Dans une configuration plus avancée où nous aurions des environnements dev, stage, qa, prod, nous utiliserions la solution principale Github Environments. Ce projet n'est pas aussi avancé, et nous allons donc nous en tenir aux secrets et variables du Repo.
-
En dehors de la variable
GOOGLE_APPLICATION_CREDENTIALS, tout le reste devrait être un secret. Utilisez une valeur de./key.jsonpour cette variable, pour rester simple. -
Pour basculer entre les
secretset lesvariables, utilisez les onglets sous les mêmes noms sur la page.
Lorsque tout est réglé, nous devrions avoir des pages qui ressemblent à ce qui suit :


Maintenant, tous nos secrets et variables sont configurés. 🎉 🎉
7. Tester l'ensemble du flux de travail
Enfin, il est temps de mettre cette roue géante en mouvement.
7.1 créer la branche plan
La première étape consistera à créer la branche plan du projet. Nous y avons beaucoup fait référence tout au long des étapes précédentes, il est temps de la créer réellement.
Nous y parviendrons donc avec la commande suivante :
git checkout -b planCela créera la nouvelle branche plan et nous y déplacera dans notre répertoire de travail actuel. Ensuite, nous pousserons cette branche vers Github et la configurerons pour suivre une nouvelle branche origin sous le même nom plan.
git push -u origin planCe push devrait déclencher un flux de travail validate sur Github, si celui-ci réussit, alors nous sommes sur la bonne voie. S'il ne réussit pas, alors vous devez chercher pour découvrir ce que vous avez pu manquer, afin de le corriger. Jetez un œil aux journaux d'erreurs du flux de travail Actions pour comprendre les erreurs.
Cependant, si vous avez suivi cette procédure pas à pas religieusement, vous devriez avoir des écrans de succès similaires à ceux ci-dessous. Votre tout premier flux de travail validate devrait être un succès.


7.2 préparer et créer la toute première PR vers main
Maintenant, pour lancer notre flux de travail, nous devons créer notre première Pull request vers la branche main. À ce stade, ce sera impossible car nos branches main et plan sont synchronisées. Pour que cela fonctionne, nous devons faire un commit factice sur la branche plan.
Pour faire simple, nous allons simplement ajouter un commentaire à l'un de nos fichiers d'Infrastructure, commiter la modification et faire une PR vers main.
Vous pouvez ajouter un commentaire à n'importe quel fichier de votre choix. Je le ferai sur le fichier backend.tf. J'ajouterai les lignes suivantes au début du fichier
# Configure the remote gcs backendMaintenant, enregistrez votre fichier modifié, commitez-le et poussez-le vers Github. Cela devrait lancer une nouvelle exécution de flux de travail validate sur Github ;

Et il devrait réussir.

Nous pouvons maintenant aller de l'avant et créer notre première Pull request vers main. Si tout fonctionne bien, vous devriez obtenir des résultats similaires à ceux que j'ai obtenus ci-dessous.


Tout devrait être vert dans votre Pull Request maintenant 🎉 🎉
7.3 examiner les résultats du plan via le commentaire du Bot
Maintenant que vos flux de travail se sont exécutés avec succès, vous devriez être en mesure de voir le nouveau commentaire du Bot qui contient des détails très importants sur les modifications d'infrastructure que vous proposez.

Allez-y et développez les différentes sections du commentaire pour obtenir plus de détails. En cliquant sur le bouton Show Plan, par exemple, vous verrez le résultat de la commande terraform plan.
Comme vous pouvez le voir, étant donné que nous n'avons que deux ressources définies dans notre configuration, nous voyons un plan pour créer deux ressources.

7.4 examiner, itérer sur, et approuver (ou refuser) le plan
À ce stade, en utilisant les règles de Branche natives de Github, un nombre minimum d'examinateurs peut être requis pour examiner les nouvelles modifications d'Infrastructure et les valider. L'équipe peut modifier tout ce dont elle a besoin, les nouveaux commits sur la branche plan s'empileront sous cette pull request, déclenchant une réexécution du plan workflow à chaque fois, s'assurant que l'équipe voit les modifications les plus à jour à apporter lors du prochain apply.
Maintenant, parce que nous voulons voir ce flux de travail jusqu'à la fin et nous assurer que notre Infrastructure est réellement créée, nous allons supposer que l'Équipe adore absolument notre nouvelle Infra et que les responsables l'ont validée. Nous allons donc aller de l'avant et fusionner (Merge) cette Pull Request #1 et faire déployer notre Infra.
7.5 et... c'est Noël

Je fais un rebasing juste parce que j'aime un historique de commits bien ordonné.


Cela devrait déclencher notre flux de travail deploy dans la branche main, et comme prévu, il devrait fonctionner sans faille, comme ceci ;


NOUS L'AVONS FAIT !!! 🎉 🎉
Pour confirmer que notre infrastructure est en ligne dans le monde réel, nous pouvons visiter son adresse web. La mienne était server.obi.ninja et elle a fonctionné sans faille.

J'ai https:// car j'ai configuré le service SSL gratuit de Cloudflare. J'ai fait cela en dehors de Terraform, en même temps que la configuration de la zone Cloudflare elle-même, pour garder ce projet et ce tutoriel simples.
8. Notes Supplémentaires
8.1 Règles de Protection de Branche Github
Pour rendre ce projet à toute épreuve afin qu'il fonctionne de manière fiable pour votre organisation, vous devez utiliser les Règles de Protection de Branche Github. Avec ces règles, vous pourrez appliquer des choses importantes telles que ;
- s'assurer que les branches
mainetplanne peuvent pas être supprimées - n'autoriser une fusion (merge) vers
mainqu'après le succès des deux flux de travailvalidateetplan - spécifier le nombre minimum de personnes autorisées à valider tout nouveau changement
- etc.
8.2 Outils Supplémentaires
Vous souhaiterez peut-être développer les différentes parties de ce projet avec des outils supplémentaires pour améliorer la sécurité. Des outils tels que :
- Hashicorp Vault pour la gestion des secrets
- Sonarqube pour une analyse statique et de qualité du code supplémentaire
- etc.
8.3 Détruire l'Infrastructure
Il s'agit d'un flux de travail d'équipe, et c'est la colonne vertébrale de l'infrastructure de l'entreprise. En conséquence, toute destruction de ressources doit être effectuée en supprimant ou en commentant le code Terraform pour lesdites ressources et en faisant passer cette modification par un examen par l'Équipe responsable. Personne ne sera en mesure de simplement exécuter terraform destroy et de détruire des ressources, tant que les secrets de l'Infrastructure sont gérés correctement.
8.4 Conclusion
Je me suis beaucoup amusé à imaginer, exécuter et documenter ce projet. J'espère que vous le trouverez utile. N'hésitez pas à me faire savoir ce que vous en pensez, toute erreur ou marge d'amélioration dans la section des commentaires ci-dessous.
Lire la suite
Projet Self-Hosting (Infrastructure DevOps from Scratch)
Un guide complet pour construire une infrastructure DevOps auto-hébergée de A à Z en utilisant Terraform, Ansible et Docker.
Déployer un serveur sur Digital Ocean via Terraform (Tutoriel)
Un guide étape par étape pour approvisionner un droplet DigitalOcean à l'aide de Terraform et des pratiques de base de l'Infrastructure as Code.
Déploiement automatique de Jenkins sur un serveur distant (avec SSL gratuit) via Ansible (Tutoriel)
Apprenez à déployer automatiquement un serveur Jenkins auto-hébergé avec des certificats SSL gratuits à renouvellement automatique à l'aide d'Ansible.
