Skip to main content

Ajouter une ressource au scoring

Identifier les événements pertinents

☑ Identifier la ressource à ajouter au score (exemple : une instance EC2, une Lambda, une instance RDS).

☑ Identifier l'événement associé à la création de la ressource.

  • Exemple: dans le cas d'une instance EC2 il s'agit de l'événement nommé RunInstances.

Comment trouver les événements pertinents ?

Via la documentation officielle :

Documentation officielle AWS des events

En expérimentant :

  • Créer une règle dans CloudWatch et sélectionner le service associé à la ressource. Pour l'event type, il est recommandé de choisir AWS API Call Via CloudTrail, cette option permet de capturer un événement avec plus de détails (notamment sur la partie IAM).
  • Rediriger les events vers SNS par exemple, pour pouvoir les recevoir par mail lors de cette phase de test.

  • Simuler le scénario souhaité : dans notre exemple nous créons une instance EC2 puis nous l'arrêtons.
  • Les events vous seront envoyés presque instantanément. Il s'agit de documents json de ce type :
// JSON Simplifié généré lorsqu'un événement est capturé :

{
"detail-type": "AWS API Call via CloudTrail",
"source": "aws.ec2",
"account": "448878779811",
"time": "2020-03-30T12:39:03Z",
"detail": {
"eventSource": "ec2.amazonaws.com",
"eventName": "RunInstances",
"requestParameters": {
//...
},
"responseElements": {
//...
},
}
}
  • Dans ce cas, nous pouvons déterminer que le nom de l'événement associé à la création d'une EC2 (l'attribut eventName dans le JSON de l'événement) est RunInstances.

Modifier l'event pattern utilisé par la règle du GameDay

☑ Modifier l'event pattern dans le code terraform permettant de mettre en place l'architecture du jeu :

rule-event_pattern = <<PATTERN
{
"detail-type": [
"AWS API Call via CloudTrail"
],
"detail": {
"eventSource": [
"autoscaling.amazonaws.com",
# ... other eventSources
# <ADD HERE YOUR NEW EVENT SOURCE>
],
"eventName": [
"RunInstances",
"TerminateInstances",
# ... other eventNames
# <ADD HERE YOUR NEW EVENT NAME>
]
}
}
PATTERN

}

Ajouter la logique de scoring à la code base

Nous sommes désormais dans le repo gameday-master du gameday.

Définition des Interfaces des événements

☑ Créer le fichier propre à la ressource : admin-server\src\cloudwatch\<NOM DE VOTRE RESSOURCE>.ts.

☑ Dans admin-server\src\cloudwatch\<NOM DE VOTRE RESSOURCE>.ts ajouter pour chaque événement ces deux interfaces que vous pouvez définir à partir des json type de l'événement en question :

export interface CloudWatchEvent_<NAME OF YOUR EVENT> extends CloudWatchEvent {
detail: CloudWatchEvent_details_<NAME OF YOUR EVENT>
}

export interface CloudWatchEvent_details_<NAME OF YOUR EVENT> extends CloudWatchEvent_details {
// specify here everything you need for your scoring
}
  • NB : Ne typer que ce qui est important, les interfaces sont ouvertes : c'est-à-dire qu'un objet avec des propriétés supplémentaires pourra toujours implémenter votre interface si les champs spécifiés dans celle-ci sont présents dans l'objet.

Définition de la Ressource

☑ Dans admin-server\src\cloudwatch\resources.ts :

  • Mettre à jour l'enum SourceName.
  • Mettre à jour l'enum EventName.
  • Créer une constante globale RESOURCE_<NOM DE VOTRE RESSOURCE> qui implémente l'interface Resource n'oubliez pas d'indiquer dans cette structure le prix par seconde d'utilisation de la ressource (comment calculer le juste prix ;) de ma ressource ?).
  • Ajouter RESOURCE_<NOM DE VOTRE RESSOURCE> au tableau des ressources RESOURCES.

☑ Dans admin-server\src\teams.ts ajouter dans l'interface Team dans events, la source de votre event et les entrées associées.

☑ Dans admin-server\src\teams.ts modifier la fonction registerTeam pour qu'elle initialise correctement une team incluant votre nouveau scoring.

Récupérer les informations pour le scoring

☑ Dans admin-server\src\cloudwatch\scores.ts rajouter dans la fonction updateScores votre ressource et comment calculer son score.

Cas : calcul de la durée d'utilisation de la resource en faisant la différence des timestamps des événements de création et de terminaison :

☑ Vous devez spécifier les fonctions getIdsFromStartEvent et getEndEventFromId qui permettent respectivement :

  • getIdsFromStartEvent: d'extraire les ids des ressources à partir d'un event de création (exemple : quels sont les ids des EC2 créées lors de l'event RunInstances).
  • getEndEventFromId : de trouver dans le state global du jeu, l'event de terminaison en fonction de l'id de la ressource

☑ Ces deux fonctions peuvent être spécifiées dans un fichier à part et propre à la ressource : admin-server\src\cloudwatch\<NOM DE VOTRE RESSOURCE>.ts.

 const score: Score = {
timestamp: new Date(),
up: team.up,
down: team.down,
[ResourceName.<NOM DE VOTRE RESOURCE>]: computeResource({
team,
resource: RESOURCE_<NOM DE VOTRE RESOURCE>,
getIdsFromStartEvent: getResourceIdsFromCloudWatchEvent_Start,
getEndEventFromId: findCloudWatchEvent_EndByResourceId
}),

Cas : calcul de la durée d'utilisation de la resource à partir d'une requête CloudWatch Logs Insights

☑ Parfois la ressource à monitorer ne produit pas les événements souhaités (exemple: dans le cas d'une lambda, aucun événement n'est produit lors de son appel).

☑ Dans ce cas, on peut utiliser une requête CloudWatch logs Insights afin d'analyser les fichiers de logs produits par la ressource afin de pouvoir déterminer sa durée totale d'utilisation.

☑ Vous devez spécifier la fonction getIdsFromStartEvent qui permet de récupérer l'identifiant utilisé pour la création du logs group lié à la ressource dans CloudWatch.

  • Exemple : dans le cas d'une lambda, le log group de la lambda est : /aws/lambda/<NOM DE LA LAMBDA>.
  • getIdsFromStartEvent doit donc pouvoir extraire de l'événement CreateFunction le nom de la lambda.

☑ Vous devez également spécifier la query (que l'on pourra placer définir dans admin-server\src\cloudwatch\<NOM DE VOTRE RESSOURCE>.ts) qui sera exécutée sur le log group /aws/<RESOURCE_NAME>/<RESOURCE_ID>.

  • Exemple : pour récupérer la somme des durées d'exécution d'une lambda, on peut utiliser la query suivante :
const QUERY_LAMBDA_SUM_BILLED_DURATION =
`filter @type = "REPORT"
| stats sum(@billedDuration)`;
 const score: Score = {
timestamp: new Date(),
up: team.up,
down: team.down,
[ResourceName.<NOM DE VOTRE RESOURCE>]: await computeResourceFromLogs({
team,
resource: RESOURCE_<NOM DE VOTRE RESOURCE>,
getIdsFromStartEvent: getResourceIdsFromCloudWatchEvent_Start,
query: "YOUR CLOUD WATCH LOGS INSIGHTS QUERY"
}),

Annexes

UML : Diagramme de Séquence - traitement des événements

UML : Diagramme de Séquence - calcul du score