Lorsque nous combinons le cloud avec des outils IaC comme Terraform et le déploiement continu, nous obtenons la capacité presque magique de créer des ressources à la demande. Cependant, malgré tous ses avantages, le cloud a également introduit un ensemble de difficultés, dont l’une est l’estimation précise des coûts du cloud.
Les fournisseurs de cloud ont des structures de coûts complexes qui changent constamment. AWS, par exemple, propose 536 types de machines Linux EC2. Beaucoup d’entre eux ont des noms et des caractéristiques similaires. Prenez par exemple « m6g.2xlarge » et « m6gd.2xlarge » – la seule différence est que le second est livré avec un disque SSD, ce qui ajoutera 60 dollars à la facture. Souvent, se tromper dans la définition de votre infrastructure peut faire gonfler votre facture en fin de mois.
Infracost est un projet open source qui nous aide à comprendre comment et où nous dépensons notre argent. Il donne une ventilation détaillée des coûts d’infrastructure réels et calcule l’impact des changements sur ceux-ci. Fondamentalement, Infracost est un git diff
pour la facturation.
Infracost a deux versions : un addon VSCode et un programme en ligne de commande. Les deux font la même chose : analyser le code Terraform, extraire les prix de revient actuels d’une API de tarification cloud et générer une estimation.
Informations sur les changements de coût dans le PR.
Configuration d’Infracost
Pour essayer Infracost, nous aurons besoin des éléments suivants :
-
Une clé API Infracost. Vous pouvez en obtenir un en vous inscrivant gratuitement sur Infracost.io.
-
La CLI Infracost installée sur votre machine.
-
Certains fichiers Terraform.
Une fois l’outil CLI installé, exécutez infracost auth login
pour récupérer la clé API. Nous sommes maintenant prêts à partir.
La première commande que nous allons essayer est infracost breakdown
. Il analyse les plans Terraform et imprime un devis. Les --path
La variable doit pointer vers le dossier contenant vos fichiers Terraform. Par exemple, imaginons que nous souhaitions provisionner une instance EC2 « a1.medium » avec les éléments suivants :
provider "aws" {
region = "us-east-1"
skip_credentials_validation = true
skip_requesting_account_id = true
}
resource "aws_instance" "myserver" {
ami = "ami-674cbc1e"
instance_type = "a1.medium"
root_block_device {
volume_size = 100
}
}
Aux tarifs actuels, cette instance coûte 28,62 USD par mois pour s’exécuter :
$ infracost breakdown --path .
Name Monthly Qty Unit Monthly Cost
aws_instance.myserver
├─ Instance usage (Linux/UNIX, on-demand, a1.medium) 730 hours $18.62
└─ root_block_device
└─ Storage (general purpose SSD, gp2) 100 GB $10.00
OVERALL TOTAL $28.62
Si nous ajoutons du stockage supplémentaire (600 Go d’EBS), le coût passe à 155,52 $, comme indiqué ci-dessous :
$ infracost breakdown --path .
Name Monthly Qty Unit Monthly Cost
aws_instance.myserver
├─ Instance usage (Linux/UNIX, on-demand, a1.medium) 730 hours $18.62
├─ root_block_device
│ └─ Storage (general purpose SSD, gp2) 100 GB $10.00
└─ ebs_block_device[0]
├─ Storage (provisioned IOPS SSD, io1) 600 GB $75.00
└─ Provisioned IOPS 800 IOPS $52.00
OVERALL TOTAL $155.62
Infracost peut également calculer des ressources basées sur l’utilisation comme AWS Lambda. Voyons ce qui se passe lorsque nous échangeons l’instance EC2 contre des fonctions sans serveur :
provider "aws" {
region = "us-east-1"
skip_credentials_validation = true
skip_requesting_account_id = true
}
resource "aws_lambda_function" "my_lambda" {
function_name = "my_lambda"
role = "arn:aws:lambda:us-east-1:account-id:resource-id"
handler = "exports.test"
runtime = "nodejs12.x"
memory_size = 1024
}
En cours d’exécution infracost breakdown
donne un coût total de 0 dollars :
$ infracost breakdown --path .
Name Monthly Qty Unit Monthly Cost
aws_lambda_function.my_lambda
├─ Requests Monthly cost depends on usage: $0.20 per 1M requests
└─ Duration Monthly cost depends on usage: $0.0000166667 per GB-seconds
OVERALL TOTAL $0.00
Cela ne peut être vrai que si personne n’utilise notre fonction Lambda, ce qui est précisément ce que l’outil suppose par défaut. Nous pouvons résoudre ce problème en fournissant une estimation via un fichier d’utilisation.
Nous pouvons créer un exemple de fichier d’utilisation avec cette commande :
$ infracost breakdown --sync-usage-file --usage-file usage.yml --path .
Nous pouvons maintenant fournir des estimations en éditant usage.yml
. L’exemple suivant se compose de 5 millions de requêtes avec une durée d’exécution moyenne de 300 ms :
resource_usage:
aws_lambda_function.my_lambda:
monthly_requests: 5000000
request_duration_ms: 300
Nous dirons à Infracost d’utiliser le fichier d’utilisation avec --usage-file
pour obtenir une estimation correcte des coûts :
$ infracost breakdown --path . --usage-file usage.yml
Name Monthly Qty Unit Monthly Cost
aws_lambda_function.my_lambda
├─ Requests 5 1M requests $1.00
└─ Duration 1,500,000 GB-seconds $25.00
OVERALL TOTAL $26.00
C’est beaucoup mieux. Bien sûr, cela est exact tant que notre fichier d’utilisation est correct. En cas de doute, vous pouvez intégrer Infracost au fournisseur de cloud et extraire les métriques d’utilisation de la source.
Git Diff pour les changements de coût
Infracost peut enregistrer les résultats dans JSON en fournissant le --format json
et --out-file
options. Cela nous donne un fichier que nous pouvons vérifier dans le contrôle de code source et utiliser comme référence.
$ infracost breakdown --path . --format json --usage-file usage.yml --out-file baseline.json
Nous pouvons maintenant comparer les modifications en exécutant infracost diff
. Voyons ce qui se passe si le temps d’exécution Lambda passe de 300 à 350 ms :
$ infracost diff --path . --compare-to baseline.json --usage-file usage.yml
~ aws_lambda_function.my_lambda
+$4.17 ($26.00 → $30.17)
~ Duration
+$4.17 ($25.00 → $29.17)
Monthly cost change for TomFern/infracost-demo/dev
Amount: +$4.17 ($26.00 → $30.17)
Percent: +16%
Comme vous pouvez le voir, l’impact est une augmentation de 16 %.
Intégration d’Infracost avec CI/CD
Nous avons vu comment cet outil peut nous aider à estimer les coûts du cloud. Ce sont des informations précieuses, mais quel rôle joue Infracost dans l’intégration continue ? Pour y répondre, il faut comprendre ce que infracost comment
Est-ce que.
La commande comment prend un fichier JSON généré par infracost diff
et publie son contenu directement dans GitHub, Bitbucket ou GitLab. Ainsi, en exécutant Infracost dans CI, nous mettons à la disposition de tous les membres de l’équipe des informations pertinentes sur les coûts.
Commentaire Infracost sur la différence de coût dans un commit GitHub.
Si vous souhaitez apprendre à configurer CI/CD pour exécuter Infracost à chaque mise à jour, consultez ce didacticiel : Comment exécuter Infracost sur Semaphore.
Travailler avec Monorepos
Vous aurez probablement des fichiers Terraform distincts pour chaque sous-projet si vous travaillez avec un monorepo. Dans ce cas, vous devez ajouter un fichier de configuration infracost à la racine du projet. Cela vous permet de spécifier les noms de projet et l’emplacement des fichiers Terraform et d’utilisation. Vous pouvez également définir des variables d’environnement et d’autres options.
version: 0.1
projects:
- path: dev
usage_file: dev/infracost-usage.yml
env:
NODE_ENV: dev
- path: prod
usage_file: prod/infracost-usage.yml
env:
AWS_ACCESS_KEY_ID: ${PROD_AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${PROD_AWS_SECRET_ACCESS_KEY}
NODE_ENV: production
Lorsque le fichier de configuration est impliqué, vous devez remplacer le --path
dispute avec --config-file
dans toutes vos commandes.
Établir des politiques
Un autre truc qu’Infracost a dans sa manche est d’appliquer les politiques. Les politiques sont des règles qui évaluent la sortie de infracost diff
et arrêter le pipeline CI si une ressource dépasse le budget. Cette fonctionnalité permet aux responsables et aux chefs d’équipe d’appliquer des limites. Lorsque la stratégie échoue, le pipeline CI/CD s’arrête avec une erreur, empêchant le provisionnement de l’infrastructure.
Lorsqu’une politique est en place, Infracost nous avertit si des limites sont dépassées.
Infracost met en œuvre des politiques à l’aide d’Open Policy Agent (OPA), qui utilise le langage Rego pour coder les règles de politique.
Rego a une tonne de fonctionnalités, et cela vaut la peine de creuser pour l’apprendre à fond, mais pour nos besoins, nous n’avons besoin d’apprendre que quelques mots-clés :
-
deny[out]
définit une nouvelle règle de stratégie qui échoue si leout
l’objet afailed: true
-
msg
: définit le message d’erreur affiché lorsque la stratégie échoue. -
out
: définit la logique qui fait réussir ou échouer la stratégie. -
input
: référence le contenu de l’objet JSON généré avecinfracost diff
.
L’exemple suivant montre une règle qui échoue lorsque le budget total dépasse 1 000 USD :
# policy.rego
package infracost
deny[out] {
# define a variable
maxMonthlyCost = 1000.0
msg := sprintf(
"Total monthly cost must be less than $%.2f (actual diff is $%.2f)",
[maxMonthlyCost, to_number(input.totalMonthlyCost)],
)
out := {
"msg": msg,
"failed": to_number(input.totalMonthlyCost) >= maxMonthlyCost
}
}
Ceci est un autre exemple qui échoue si la différence de coût est égale ou supérieure à 500 $.
package...