I denne øvingen skal dere bli kjent med hvordan man instrumenterer en Spring Boot applikasjon med Metrics.
- Vi skal også se på hvordan vi kan visualisere Metrics i ved hjelp av dashboard med grafer og statistikk i tjenesten CloudWatch
- Vi skal naturligvis la GitHub Actions til å kjøre terraform for oss
- Vi skal se på CloudWatch alarmer
Logg på Cloud 9 miljøet ditt som vanlig
Installer terraform
wget https://releases.hashicorp.com/terraform/1.9.0/terraform_1.9.0_linux_amd64.zip
unzip terraform_1.9.0_linux_amd64.zip
sudo mv terraform /usr/local/bin/
terraform -v
Hvis du vil teste ut TFENV som støtter installasjon og bruk av mange Terraformversjoner kan du gå til en tidligere lab og se hvordan det gjøres https://github.com/glennbechdevops/terraform-cloudwatch-dashboard?tab=readme-ov-file#terraform-pro-tip
- Lag en Fork av dette repoet til Cloud9 miljøet ditt. Se i katalogen "infra" - her finner dere filen main.tf som inneholder Terraformkode for et CloudWatch Dashboard.
- Git Clone din egen fork inn i Cloud9 miljøet ditt
- Som dere ser beskrives dashboardet i et JSON-format. Her finner dere dokumentasjon https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/CloudWatch-Dashboard-Body-Structure.html
- Her ser dere også hvordan man ofte inkluderer tekst eller kode ved hjelp av "Heredoc" syntaks i Terraformkode, slik at vi ikke trenger å tenke på "newline", "Escaping" av spesialtegn osv (https://developer.hashicorp.com/terraform/language/expressions/strings)
resource "aws_cloudwatch_dashboard" "main" {
dashboard_name = var.student_name
dashboard_body = <<THEREBEDRAGONS
{
"widgets": [
{
"type": "metric",
"x": 0,
"y": 0,
"width": 12,
"height": 6,
"properties": {
"metrics": [
[
"${var.student_name}",
"account_count.value"
]
],
"period": 300,
"stat": "Maximum",
"region": "eu-west-1",
"title": "Total number of accounts"
}
}
]
}
THEREBEDRAGONS
}
- Skriv en provider.tf i samme katalog som main.tf
- For å gjøre senere oppgaver enklere, så lag en S3 backend for state filen.
- Se gjerne på https://github.com/glennbechdevops/terraform-app-runner - for inspirasjon
- Kjør terraform init / plan / apply fra Cloud 9 miljøet ditt
- Gå til tjenesten CloudWatch og se at det blir opprettet et Dashboard
- Når du kjører plan- eller apply vil Terraform spørre deg om ditt studentnavn.
- Hvordan kan du sende variabelverdier direkte i terraform kommandolinjen?
- Lag en Defaultverdi for variabelen, se at du da også ikke blir bedt om å oppgi studentnavn på
plan/apply
- Kjør Terraform init / plan / apply from Cloud9-miljøet ditt
Åpne BankAccountController.Java , Her finner dere koden
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
Gauge.builder("account_count", theBank,
b -> b.values().size()).register(meterRegistry);
}
Denne lager en Ny metric - av typen Gauge. Hver gang din applikasjon sender data til CloudWatch - sendes denne verdien - hvor mange bank-kontoer som eksisterer i systemet
Du må endre på klassen MetricsConfig og bruke ditt egent studentnavn istedet for glennbech i kodeblokken
return new CloudWatchConfig() {
private Map<String, String> configuration = Map.of(
"cloudwatch.namespace", "<studentnavn>",
"cloudwatch.step", Duration.ofSeconds(5).toString());
....
};
Installer maven / jq i Cloud 9. Vi skal forsøke å kjøre Spring Boot applikasjonen fra Maven i terminalen
sudo wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo
sudo sed -i s/\$releasever/6/g /etc/yum.repos.d/epel-apache-maven.repo
sudo yum install -y apache-maven
sudo yum install jq
Start applikasjonen med Cloud 9
mvn spring-boot:run
Spring Boot applikasjonen i dette repoet eksponerer et REST Endepunkt på http://localhost:8080/account
- Opprette konto, eller sette saldo
curl --location --request POST 'http://localhost:8080/account' \
--header 'Content-Type: application/json' \
--data-raw '{
"id": 1,
"balance" : "100000"
}'|jq
- Se info om en konto
curl --location --request GET 'http://localhost:8080/account/1' \
--header 'Content-Type: application/json'|jq
- Overføre penger fra en konto til en annen
curl --location --request POST 'http://localhost:8080/account/2/transfer/3' \
--header 'Content-Type: application/json' \
--data-raw '{
"fromCountry": "SE",
"toCountry" : "US",
"amount" : 500
}
'|jq
Det skal se omtrent slik ut
- Gå til AWS UI, og tjenesten CloudWatch. Velg "Dashboards".
- Søk på ditt eget studentnavn og åpne dashboardet du lagde
- Se at du får målepunkter på grafen
Du skal nå lage en Micrometer Gauge
som viser nettobeholdningen til banken.
Oppgave Finn riktig plass for denne i koden.
// Denne meter-typen "Gauge" rapporterer hvor mye penger som totalt finnes i banken
Gauge.builder("bank_sum", theBank,
b -> b.values()
.stream()
.map(Account::getBalance)
.mapToDouble(BigDecimal::doubleValue)
.sum())
.register(meterRegistry);
Utvid Terraformkoden slik at den viser en ekstra widget for metrikken bank_sum
Hint: du må endre på X/Y verdiene for at de ikke skal overlappe!
Vi vil lage en Alarm som utløses dersom banken sin totale sum overstiger et gitt beløp.
Dette kan vi gjøre ved å bruke CloudWatch. Vi skal også lage en modul for denne alarmen, så andre potensielt også kan dra nytte av den, eller for å gjøre det enkelt å lage flere alarmer.
Vi skal også bruke tjenesten SNS. Simple notification Service. Ved å sende en melding en melding til en SNS topic når alarmen løses ut, så kan vi reagere på en slik melding, og for eksempel sende en epost, kjøre en lambdafunksjon osv.
Vi skal nå lage en terraform modul. Mens vi jobber med den, er det smart å ha den på et lokalt filsystem slik at vi ikke må gjøre git add/commit/push osv for å få oppdatert koden.
I denne mappen, lag en ny terraform fil, med navn main.tf
resource "aws_cloudwatch_metric_alarm" "threshold" {
alarm_name = "${var.prefix}-threshold"
namespace = var.prefix
metric_name = "bank_sum.value"
comparison_operator = "GreaterThanThreshold"
threshold = var.threshold
evaluation_periods = "2"
period = "60"
statistic = "Maximum"
alarm_description = "This alarm goes off as soon as the total amount of money in the bank exceeds an amount "
alarm_actions = [aws_sns_topic.user_updates.arn]
}
resource "aws_sns_topic" "user_updates" {
name = "${var.prefix}-alarm-topic"
}
resource "aws_sns_topic_subscription" "user_updates_sqs_target" {
topic_arn = aws_sns_topic.user_updates.arn
protocol = "email"
endpoint = var.alarm_email
}
- Namespace er typisk studentnavnet ditt. Det er den samme verdien som du endret i MetricsConfig.java filen.
- Det finnes en lang rekke
comparison_operator
alternativer å velge mellom, vi bruker "GreaterThanThreshold" evaluation_periods
ogperiod
jobber sammen for å unngå at alarmen går av ved en kortvarige "spikes" eller uteliggende observasjoner.statistic
er en operasjon som utføres på alle verdier i ett tidsintervall gitt avperiod
- for enGauge
metric, i dette tilfelle her velger vi Maximum.- Legg merke til hvordan en
resource
refererer til en annen i Terraform! - Terraform lager både en SNS Topic og en email subscription.
Lag en ny fil i mappen infra/alarm_module , variables.tf
variable "threshold" {
default = "50"
type = string
}
variable "alarm_email" {
type = string
}
variable "prefix" {
type = string
}
Lag en ny fil i samme mappe, outputs.tf
output "alarm_arn" {
value = aws_sns_topic.user_updates.arn
}
Gratululerer!! Du har nå laget en Terraform modul!
Du kan nå endre main.tf, under /infra katalogen til å inkludere modulen din. Den vil da se slik ut. Husk å sette inn din egen epost i koden.
resource "aws_cloudwatch_dashboard" "main" {
dashboard_name = var.student_name
dashboard_body = <<DASHBOARD
{
"widgets": [
{
"type": "metric",
"x": 0,
"y": 0,
"width": 12,
"height": 6,
"properties": {
"metrics": [
[
"${var.student_name}",
"account_count.value"
]
],
"period": 300,
"stat": "Maximum",
"region": "eu-west-1",
"title": "Total number of accounts"
}
}
]
}
DASHBOARD
}
module "alarm" {
source = "./alarm_module"
alarm_email = "<[email protected]>
prefix = var.student_name
}
Oppgave - Lag en ny variabel i infra/variables.tf som heter alarm_email
bruk denne i modul-blokken så du ikke trenger å putte inn din egen epost.
Gå til infra mappen. Kjør
terraform init
terraform apply
Legg merke til at Terraform spør deg om verdier for variabler som ikke har default verdier. Dette vil ikke fungere når vi skal la GitHub Actions kjøre terraform for oss.
- Husker du hvordan du kan gi disse argumentene på kommandolinjen?
- Du kan også lage defaultverdier for variablene om du ønsker det - så lenge du skjønner hvordan dette fungerer.
For at SNS skal få lov til å sende deg epost, må du bekrefte epost-addressen din. Du vil få en e-post med en lenke du må klikke på første gangen
du kjører terraform apply
første gang.
- Gå til AWS console
- Gå til SNS
- Fra venstremenyen velg "Topics"
- Finn din egen Topic
- (Dette er ikke alltid nødvendig) Under Subscriptions, finn epost-linjen, og velg "Request Confirmation" - sjekk eposten din, du skal ha fått en epost med en bekreftelseslenke.
- Test å sende en mail, ved å trykke "Publish message" øverst til høyre på siden
- Forsøk å lage nye kontoer, eller en ny konto, slik at bankens totale sum overstiger 1 MNOK.
For eksmpel ;
curl --location --request POST 'http://localhost:8080/account' \
--header 'Content-Type: application/json' \
--data-raw '{
"id": 999,
"balance" : "5000000"
}'|jq
- Sjekk at alarmen går ved å se at du har fått en epost
- Gå til CloudWatch Alarms i AWS og se at alarmen sin tilstand er
IN_ALARM
- Få balansen i banken tilbake til 0, for eksempel ved å lage en konto med negativ saldo
- Se at alarmen sin tilstand går vekk fra
IN_ALARM
.
Basert på for eksempel denne labben https://github.com/glennbechdevops/terraform-app-runner - lag en GitHub actions workflow fil for Terraform-koden i dette repositoryet slik at
- Hver commit på main branch kjører Terraform-apply
- For en Pull request, gjør bare Terraform plan
- Legg til nye Metrics i koden og Widgets i Dashboardet ditt
- Kan du lage en eller flere nye alarmer? Eksempel; En alarm trigges av antall requests over en tidsperiode går over en terskelverdi? Sett verdien lavt så du klarer å teste :)
- Kan du lage en ny Controller metode med ny funksjonalitet i Javakoden ?
- Bruk gjerne følgende guide som inspirasjon https://www.baeldung.com/micrometer
- Referanseimplementasjon; https://micrometer.io/docs/concepts
- Lag en container av Java applikasjon og bygg den og push til ECR via GitHub Actions
- Lag terraformkode for en Apprunner servie for aplkasjonen
- Pass på å lage avhengighet mellom jobbene som bygger container og terraformkoden
- Lag modulen din som et eget GitHub repository .
Nyttig informasjon;