Photo de SuPatMaN sur Shutterstock
D'emblée, je tiens à le souligner : AWS Config est un excellent service. Si vous ne le connaissez pas encore, AWS Config permet d'évaluer, de surveiller et d'enregistrer en continu les modifications de configuration des ressources. Je ne vais pas énumérer toutes ses fonctionnalités, mais vous trouverez plus d'informations ici. La page tarification d'AWS Config détaille la manière dont le service est facturé, avec quelques exemples utiles à la compréhension. En résumé, la facturation d'AWS Config repose sur le nombre d'éléments de configuration enregistrés, le nombre d'évaluations actives de règles AWS Config et le nombre d'évaluations de packs de conformité dans votre compte, auxquels s'ajoutent quelques coûts annexes comme le stockage S3 et SNS. Si votre infrastructure est dynamique et fait l'objet de nombreuses modifications de configuration, les coûts d'AWS Config peuvent grimper de manière spectaculaire. Cet article a pour objectif de décortiquer ces coûts, de présenter des stratégies pour les réduire et de partager des conseils pour enquêter sur les pics de dépenses inattendus.
NOTE — Pour des raisons de confidentialité, j'utiliserai mon environnement AWS de test à des fins de démonstration. Je ne dispose pas de beaucoup de données Config, mais cela suffira pour illustrer la stratégie employée.
- Éléments de configuration enregistrés — Consultez les éléments de configuration enregistrés par AWS Config depuis le dashboard AWS Config (image1) ou retrouvez les mêmes métriques dans CloudWatch Metrics (image2).

image1 — Éléments de configuration enregistrés — dashboard AWS Config

image2 — Éléments de configuration enregistrés — AWS CloudWatch Metrics
- Cela ne nous apprend pas grand-chose, n'est-ce pas ? Pourtant, le nombre d'éléments enregistrés peut passer de quelques centaines à plusieurs milliers par jour selon ce qui se passe dans votre compte. Pour mieux comprendre ce qui est capté, j'ai exploité les données AWS Config livrées dans mon bucket S3 (image3) et j'ai tenté de les analyser avec le service AWS Athena. Vous trouverez cette configuration dans la section AWS Config > Settings > Delivery Method.

image3 — S3 utilisé comme méthode de livraison des enregistrements AWS Config
- Si vous vous rendez sur S3, vous y verrez plusieurs fichiers JSON livrés par AWS Config et organisés par ID d'organisation, ID de compte, région, mois, date, etc. (exemple ci-dessous). La taille des fichiers varie selon le volume d'éléments enregistrés par AWS Config.

Fichiers Config livrés dans S3
- J'ai ensuite essayé de lire ces fichiers pour voir leur contenu. Par exemple, j'ai pris les deux premiers.
nikhilpawar@MacBookPro Downloads % cat xxxxxxxxxx_Config_us-east-1_ConfigHistory_AWS__AppConfig__DeploymentStrategy_20241029T013419Z_20241029T013419Z_1.json
{"fileVersion":"1.0","configurationItems":[{"relatedEvents":[],"relationships":[],"configuration":{"Id":"AppConfig.AllAtOnce","ReplicateTo":"NONE","GrowthType":"LINEAR","Description":"Quick","DeploymentDurationInMinutes":0,"GrowthFactor":100.0,"FinalBakeTimeInMinutes":10,"Name":"AppConfig.AllAtOnce","Tags":[]},"supplementaryConfiguration":{},"tags":{},"configurationItemVersion":"1.3","configurationItemCaptureTime":"2024-10-29T01:34:19.420Z","configurationStateId":1730165659420,"awsAccountId":"xxxxxxxxxx","configurationItemStatus":"ResourceDiscovered","resourceType":"AWS::AppConfig::DeploymentStrategy","resourceId":"AppConfig.AllAtOnce","resourceName":"AppConfig.AllAtOnce","ARN":"arn:aws:appconfig:us-east-1:xxxxxxxxxx:deploymentstrategy/AppConfig.AllAtOnce","awsRegion":"us-east-1","availabilityZone":"Regional","configurationStateMd5Hash":""},{"relatedEvents":[],"relationships":[],"configuration":{"Id":"AppConfig.Canary10Percent20Minutes","ReplicateTo":"NONE","GrowthType":"EXPONENTIAL","Description":"AWS Recommended","DeploymentDurationInMinutes":20,"GrowthFactor":10.0,"FinalBakeTimeInMinutes":10,"Name":"AppConfig.Canary10Percent20Minutes","Tags":[]},"supplementaryConfiguration":{},"tags":{},"configurationItemVersion":"1.3","configurationItemCaptureTime":"2024-10-29T01:34:19.546Z","configurationStateId":1730165659546,"awsAccountId":"xxxxxxxxxx","configurationItemStatus":"ResourceDiscovered","resourceType":"AWS::AppConfig::DeploymentStrategy","resourceId":"AppConfig.Canary10Percent20Minutes","resourceName":"AppConfig.Canary10Percent20Minutes","ARN":"arn:aws:appconfig:us-east-1:xxxxxxxxxx:deploymentstrategy/AppConfig.Canary10Percent20Minutes","awsRegion":"us-east-1","availabilityZone":"Regional","configurationStateMd5Hash":""},{"relatedEvents":[],"relationships":[],"configuration":{"Id":"AppConfig.Linear20PercentEvery6Minutes","ReplicateTo":"NONE","GrowthType":"LINEAR","Description":"AWS Recommended","DeploymentDurationInMinutes":30,"GrowthFactor":20.0,"FinalBakeTimeInMinutes":30,"Name":"AppConfig.Linear20PercentEvery6Minutes","Tags":[]},"supplementaryConfiguration":{},"tags":{},"configurationItemVersion":"1.3","configurationItemCaptureTime":"2024-10-29T01:34:19.625Z","configurationStateId":1730165659625,"awsAccountId":"xxxxxxxxxx","configurationItemStatus":"ResourceDiscovered","resourceType":"AWS::AppConfig::DeploymentStrategy","resourceId":"AppConfig.Linear20PercentEvery6Minutes","resourceName":"AppConfig.Linear20PercentEvery6Minutes","ARN":"arn:aws:appconfig:us-east-1:xxxxxxxxxx:deploymentstrategy/AppConfig.Linear20PercentEvery6Minutes","awsRegion":"us-east-1","availabilityZone":"Regional","configurationStateMd5Hash":""},{"relatedEvents":[],"relationships":[],"configuration":{"Id":"AppConfig.Linear50PercentEvery30Seconds","ReplicateTo":"NONE","GrowthType":"LINEAR","Description":"Test/Demo","DeploymentDurationInMinutes":1,"GrowthFactor":50.0,"FinalBakeTimeInMinutes":1,"Name":"AppConfig.Linear50PercentEvery30Seconds","Tags":[]},"supplementaryConfiguration":{},"tags":{},"configurationItemVersion":"1.3","configurationItemCaptureTime":"2024-10-29T01:34:19.475Z","configurationStateId":1730165659475,"awsAccountId":"xxxxxxxxxx","configurationItemStatus":"ResourceDiscovered","resourceType":"AWS::AppConfig::DeploymentStrategy","resourceId":"AppConfig.Linear50PercentEvery30Seconds","resourceName":"AppConfig.Linear50PercentEvery30Seconds","ARN":"arn:aws:appconfig:us-east-1:xxxxxxxxxx:deploymentstrategy/AppConfig.Linear50PercentEvery30Seconds","awsRegion":"us-east-1","availabilityZone":"Regional","configurationStateMd5Hash":""}]}% nikhilpawar@MacBookPro Downloads % cat xxxxxxxxxx_Config_us-east-1_ConfigHistory_AWS__AppConfig__DeploymentStrategy_20241029T013419Z_20241029T013419Z_1.json | jq
{
"fileVersion": "1.0",
"configurationItems": [\
{\
"relatedEvents": [],\
"relationships": [],\
"configuration": {\
"Id": "AppConfig.AllAtOnce",\
"ReplicateTo": "NONE",\
"GrowthType": "LINEAR",\
"Description": "Quick",\
"DeploymentDurationInMinutes": 0,\
"GrowthFactor": 100.0,\
"FinalBakeTimeInMinutes": 10,\
"Name": "AppConfig.AllAtOnce",\
"Tags": []\
},\
"supplementaryConfiguration": {},\
"tags": {},\
"configurationItemVersion": "1.3",\
"configurationItemCaptureTime": "2024-10-29T01:34:19.420Z",\
"configurationStateId": 1730165659420,\
"awsAccountId": "xxxxxxxxxx",\
"configurationItemStatus": "ResourceDiscovered",\
"resourceType": "AWS::AppConfig::DeploymentStrategy",\
"resourceId": "AppConfig.AllAtOnce",\
"resourceName": "AppConfig.AllAtOnce",\
"ARN": "arn:aws:appconfig:us-east-1:xxxxxxxxxx:deploymentstrategy/AppConfig.AllAtOnce",\
"awsRegion": "us-east-1",\
"availabilityZone": "Regional",\
"configurationStateMd5Hash": ""\
},\
{\
"relatedEvents": [],\
"relationships": [],\
"configuration": {\
"Id": "AppConfig.Canary10Percent20Minutes",\
"ReplicateTo": "NONE",\
"GrowthType": "EXPONENTIAL",\
"Description": "AWS Recommended",\
"DeploymentDurationInMinutes": 20,\
"GrowthFactor": 10.0,\
"FinalBakeTimeInMinutes": 10,\
"Name": "AppConfig.Canary10Percent20Minutes",\
"Tags": []\
},\
"supplementaryConfiguration": {},\
"tags": {},\
"configurationItemVersion": "1.3",\
"configurationItemCaptureTime": "2024-10-29T01:34:19.546Z",\
"configurationStateId": 1730165659546,\
"awsAccountId": "xxxxxxxxxx",\
"configurationItemStatus": "ResourceDiscovered",\
"resourceType": "AWS::AppConfig::DeploymentStrategy",\
"resourceId": "AppConfig.Canary10Percent20Minutes",\
"resourceName": "AppConfig.Canary10Percent20Minutes",\
"ARN": "arn:aws:appconfig:us-east-1:xxxxxxxxxx:deploymentstrategy/AppConfig.Canary10Percent20Minutes",\
"awsRegion": "us-east-1",\
"availabilityZone": "Regional",\
"configurationStateMd5Hash": ""\
},\
{\
"relatedEvents": [],\
"relationships": [],\
"configuration": {\
"Id": "AppConfig.Linear50PercentEvery30Seconds",\
"ReplicateTo": "NONE",\
"GrowthType": "LINEAR",\
"Description": "Test/Demo",\
"DeploymentDurationInMinutes": 1,\
"GrowthFactor": 50.0,\
"FinalBakeTimeInMinutes": 1,\
"Name": "AppConfig.Linear50PercentEvery30Seconds",\
"Tags": []\
},\
"supplementaryConfiguration": {},\
"tags": {},\
"configurationItemVersion": "1.3",\
"configurationItemCaptureTime": "2024-10-29T01:34:19.475Z",\
"configurationStateId": 1730165659475,\
"awsAccountId": "xxxxxxxxxx",\
"configurationItemStatus": "ResourceDiscovered",\
"resourceType": "AWS::AppConfig::DeploymentStrategy",\
"resourceId": "AppConfig.Linear50PercentEvery30Seconds",\
"resourceName": "AppConfig.Linear50PercentEvery30Seconds",\
"ARN": "arn:aws:appconfig:us-east-1:xxxxxxxxxx:deploymentstrategy/AppConfig.Linear50PercentEvery30Seconds",\
"awsRegion": "us-east-1",\
"availabilityZone": "Regional",\
"configurationStateMd5Hash": ""\
}\
]
}
- Lire ces fichiers JSON manuellement ou via un script s'avère vite fastidieux. La meilleure approche reste AWS Athena, un autre service très puissant.
- Créer une table Athena — Lorsque vous créez des tables Athena pour vos données AWS Config, vous pouvez adapter vos requêtes à différentes périodes et plages de données. La syntaxe de création varie selon ce que vous souhaitez analyser :
- Instantanés sur une seule journée
- Données couvrant plusieurs jours
- Mois ou année spécifique
- Historique complet des données Config
NOTE — Remplacez xxxxxxxxxx par votre ID de compte AWS dans les requêtes ci-dessous. Je recommande également de ne récupérer que les données correspondant à la période qui vous intéresse, plutôt que de tout scanner. (tarification Athena)
1. Instantané sur une seule journée
1.1 :- Créer la table Athena : par exemple aws_config_table_single_day_2024_11_08
CREATE EXTERNAL TABLE aws_config_table_single_day_2024_11_08 (
fileversion string,
configSnapshotId string,
configurationitems ARRAY<STRUCT<
configurationItemVersion: STRING,
configurationItemCaptureTime: STRING,
configurationStateId: BIGINT,
awsAccountId: STRING,
configurationItemStatus: STRING,
resourceType: STRING,
resourceId: STRING,
resourceName: STRING,
ARN: STRING,
awsRegion: STRING,
availabilityZone: STRING,
configurationStateMd5Hash: STRING,
resourceCreationTime: STRING
>>
)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
LOCATION 's3://config-bucket-xxxxxxxxxxxx/AWSLogs/xxxxxxxxxxxx/Config/us-east-1/2024/11/8';

1.1 :- Table Athena — instantané sur une journée
1.2 :- Compter le nombre total d'enregistrements : (Optionnel ; vous pouvez vérifier le total, qui devrait correspondre aux métriques CloudWatch examinées au départ.)
SELECT
COUNT(1) AS record_count
FROM
default.aws_config_table_single_day_2024_11_08
CROSS JOIN
UNNEST(configurationitems) AS t(configurationItem)
WHERE
configurationItem.resourceType IS NOT NULL

1.2 :- Total des enregistrements pour la journée
1.3 :- Obtenir le type de ressource et le nombre de modifications enregistrées : La requête suivante permet d'identifier les types de ressources qui génèrent le plus grand nombre de modifications de configuration, afin de cerner les principaux postes de coûts dans votre suivi AWS Config.
SELECT
configurationItem.resourceType,
COUNT(configurationItem.resourceId) AS NumberOfChanges
FROM
default.aws_config_table_single_day_2024_11_08
CROSS JOIN
UNNEST(configurationitems) AS t(configurationItem)
GROUP BY
configurationItem.resourceType
ORDER BY
NumberOfChanges DESC;

1.3 :- Types de ressources et nombre de modifications enregistrées
1.4 :- Obtenir les ID de ressources : Pour approfondir l'analyse des types de ressources les plus actifs, vous pouvez descendre au niveau des ressources individuelles. Par exemple, la requête précédente a révélé que AWS:EC2:Subnet présente le plus grand nombre de modifications de configuration. La requête suivante permet d'identifier les ID de sous-réseaux à l'origine de cette fréquence de changement.
SELECT
configurationItem.resourceType,
configurationItem.resourceId,
COUNT(configurationItem.resourceId) AS NumberOfChanges
FROM
default.aws_config_table_single_day_2024_11_08
CROSS JOIN
UNNEST(configurationitems) AS t(configurationItem)
GROUP BY
configurationItem.resourceType,
configurationItem.resourceId
ORDER BY
NumberOfChanges DESC

1.4 :- ID de ressources identifiés
Vous y voyez désormais plus clair. Les mêmes schémas de requêtes s'appliquent à différentes plages temporelles. Que vous souhaitiez analyser des tendances mensuelles, des plages de dates précises ou l'intégralité de votre historique Config, il suffit d'ajuster les paramètres de temps tout en conservant la même logique d'analyse.
2. Mois spécifique
2.1 :- Créer la table Athena : par exemple aws_config_table_november_2024
CREATE EXTERNAL TABLE aws_config_table_november_2024 (
fileversion string,
configSnapshotId string,
configurationitems ARRAY<STRUCT<
configurationItemVersion: STRING,
configurationItemCaptureTime: STRING,
configurationStateId: BIGINT,
awsAccountId: STRING,
configurationItemStatus: STRING,
resourceType: STRING,
resourceId: STRING,
resourceName: STRING,
ARN: STRING,
awsRegion: STRING,
availabilityZone: STRING,
configurationStateMd5Hash: STRING,
resourceCreationTime: STRING
>>
)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
LOCATION 's3://config-bucket-xxxxxxxxxxxx/AWSLogs/xxxxxxxxxxxx/Config/us-east-1/2024/10/';

2.1 :- Table Athena — données d'un mois
2.2 :- Compter le nombre total d'enregistrements : Reportez-vous à l'étape 1.2 (Compter le nombre total d'enregistrements) et mettez à jour le nom de la table.

2.2 :- Total des enregistrements pour le mois
2.3 :- Obtenir le type de ressource et le nombre de modifications enregistrées : Reportez-vous à l'étape 1.3 (Obtenir le type de ressource et le nombre de modifications enregistrées) et mettez à jour le nom de la table.

2.3 :- Types de ressources et nombre de modifications enregistrées
2.4 :- Obtenir les ID de ressources : Reportez-vous à l'étape 1.4 (Obtenir les ID de ressources) et mettez à jour le nom de la table.

2.4 :- ID de ressources identifiés
3. Toutes les données Config
3.1 :- Créer la table Athena : par exemple aws_config_table_all
CREATE EXTERNAL TABLE aws_config_table_all (
fileversion string,
configSnapshotId string,
configurationitems ARRAY<STRUCT<
configurationItemVersion: STRING,
configurationItemCaptureTime: STRING,
configurationStateId: BIGINT,
awsAccountId: STRING,
configurationItemStatus: STRING,
resourceType: STRING,
resourceId: STRING,
resourceName: STRING,
ARN: STRING,
awsRegion: STRING,
availabilityZone: STRING,
configurationStateMd5Hash: STRING,
resourceCreationTime: STRING
>>
)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
LOCATION 's3://config-bucket-XXXXXXXXXXXX/AWSLogs/XXXXXXXXXXXX/Config/us-east-1/';

3.1 :- Table Athena — toutes les données Config
3.2 :- Total des enregistrements : Reportez-vous à l'étape 1.2 (Compter le nombre total d'enregistrements) et mettez à jour le nom de la table.

3.2 :- Total des enregistrements
3.3 :- Obtenir le type de ressource et le nombre de modifications enregistrées : Reportez-vous à l'étape 1.3 (Obtenir le type de ressource et le nombre de modifications enregistrées) et mettez à jour le nom de la table.

3.3 :- Types de ressources et nombre de modifications enregistrées
3.4 :- Obtenir les ID de ressources : Reportez-vous à l'étape 1.4 (Obtenir les ID de ressources) et mettez à jour le nom de la table.

3.4 :- ID de ressources identifiés
4. Données couvrant plusieurs jours
4.1 Créer la table Athena : Dans ce scénario, nous allons partitionner la table Athena à l'aide de la projection de partitions, du 7/11/2024 au 10/11/2024. Adaptez cette période à vos besoins.
CREATE EXTERNAL TABLE aws_config_table_period_2024_11_07to2024_11_10 (
fileversion string,
configSnapshotId string,
configurationitems ARRAY<STRUCT<
configurationItemVersion: STRING,
configurationItemCaptureTime: STRING,
configurationStateId: BIGINT,
awsAccountId: STRING,
configurationItemStatus: STRING,
resourceType: STRING,
resourceId: STRING,
resourceName: STRING,
ARN: STRING,
awsRegion: STRING,
availabilityZone: STRING,
configurationStateMd5Hash: STRING,
resourceCreationTime: STRING
>>
)
PARTITIONED BY (`year` string,`month` string,`day` string)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
LOCATION 's3://config-bucket-xxxxxxxxxxxx/AWSLogs/xxxxxxxxxxxx/Config/us-east-1'
TBLPROPERTIES (
'projection.enabled'='true',
'projection.year.interval'='1',
'projection.year.range'='2024,2024',
'projection.year.type'='integer',
'projection.month.interval'='1',
'projection.month.range'='10,11',
'projection.month.type'='integer',
'projection.day.interval'='1',
'projection.day.range'='7,10',
'projection.day.type'='integer',
'storage.location.template'='s3://config-bucket-xxxxxxxxxxxx/AWSLogs/xxxxxxxxxxxx/Config/us-east-1/${year}/${month}/${day}/ConfigHistory/')

4.1 :- Table Athena — période sélectionnée
4.2 :- Total des enregistrements :
SELECT result.configurationitemcapturetime,
count(result.configurationitemcapturetime) AS NumberOfChanges
FROM
(SELECT regexp_replace(configurationItem.configurationItemCaptureTime,
'(.+)(T.+)', '$1') AS configurationitemcapturetime
FROM default.aws_config_table_period_2024_11_07to2024_11_10
CROSS JOIN UNNEST(configurationitems) AS t(configurationItem)
WHERE "$path" LIKE '%ConfigHistory%'
AND configurationItem.configurationItemCaptureTime >= '2024-11-05T%'
AND configurationItem.configurationItemCaptureTime <= '2024-11-12T%') result
GROUP BY result.configurationitemcapturetime
ORDER BY result.configurationitemcapturetime

4.2 :- Total des enregistrements
4.3 :- Obtenir le type de ressource et le nombre de modifications enregistrées :
SELECT configurationItem.resourceType,
configurationItem.resourceId,
COUNT(configurationItem.resourceId) AS NumberOfChanges
FROM default.aws_config_table_period_2024_11_07to2024_11_10
CROSS JOIN UNNEST(configurationitems) AS t(configurationItem)
WHERE "$path" LIKE '%ConfigHistory%'
AND configurationItem.configurationItemCaptureTime >= '2024-11-05T%'
AND configurationItem.configurationItemCaptureTime <= '2024-11-12T%'
GROUP BY configurationItem.resourceType, configurationItem.resourceId
ORDER BY NumberOfChanges DESC
### ou ###
SELECT configurationItem.resourceType,
configurationItem.resourceId,
CAST(COUNT(configurationItem.resourceId) AS INTEGER) AS NumberOfChanges
FROM default.aws_config_table_period_2024_11_07to2024_11_10
CROSS JOIN UNNEST(configurationitems) AS t(configurationItem)
WHERE "$path" LIKE '%ConfigHistory%'
AND configurationItem.configurationItemCaptureTime >= '2024-11-05T%'
AND configurationItem.configurationItemCaptureTime <= '2024-11-12T%'
GROUP BY configurationItem.resourceType, configurationItem.resourceId
ORDER BY NumberOfChanges DESC

4.3 :- Types de ressources et nombre de modifications enregistrées
4.4 :- Obtenir les ID de ressources
SELECT configurationItem.resourceId,
configurationItem.resourceType,
COUNT(configurationItem.resourceId) AS NumberOfChanges
FROM default.aws_config_table_period_2024_11_07to2024_11_10
CROSS JOIN UNNEST(configurationitems) AS t(configurationItem)
WHERE "$path" LIKE '%ConfigHistory%'
AND configurationItem.configurationItemCaptureTime >= '2024-11-05T%'
AND configurationItem.configurationItemCaptureTime <= '2024-11-12T%'
GROUP BY
configurationItem.resourceId,
configurationItem.resourceType
ORDER BY NumberOfChanges DESC

4.4 :- ID de ressources identifiés
- Vous avez désormais identifié l'ID et le type des ressources qui présentent le plus d'éléments enregistrés sur la période souhaitée.
Depuis juin 2023, AWS Config prend en charge l'exclusion d'enregistrement par type de ressource. Vous pouvez ainsi réévaluer vos paramètres pour chaque type de ressource et les ajuster en conséquence, ou enquêter sur des pics de coûts inhabituels survenus à des dates précises.

Ressources enregistrées
Autre point à signaler : la durée de rétention des données. Vous pouvez l'ajuster selon vos besoins.

Période de rétention
En conclusion, AWS Config est un service puissant, mais il peut vite devenir coûteux, en particulier dans les environnements dynamiques. En adoptant des approches stratégiques telles que l'analyse des éléments de configuration enregistrés, le recours à AWS Athena pour des investigations détaillées, l'exploitation des exclusions d'enregistrement et une gestion rigoureuse des durées de rétention, les organisations gagnent une vision granulaire de leurs coûts AWS Config tout en conservant une solide visibilité sur leur infrastructure. L'objectif n'est pas de supprimer la surveillance, mais d'optimiser ce que vous suivez et la manière dont vous le suivez. En cernant les schémas de modification propres à vos ressources et en enregistrant les configurations de façon sélective, vous conciliez surveillance complète et gestion économique.
Pour tirer le meilleur parti d'AWS Config ou en savoir plus sur nos services, n'hésitez pas à nous contacter ici.