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 :
- /gameday/gameday-infra/init/stage/service/cloudwatch/terragrunt.hcl
- rajouter au pattern les valeurs eventSource et eventName que l'application doit désormais traquer :
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'interfaceResource
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 ressourcesRESOURCES
.
☑ 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énementCreateFunction
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"
}),