o11y: OpenTelemetry, Prometheus, Loki e Tempo no EKS [Lab Session]
Paulo Ponciano
Posted on February 1, 2024
Loki overview
Tempo architecture
- Repositório de infraestrutura (terraform) - EKS-Istio-Karpenter
- Repositório stack o11y
- Repositório K6
Lab architecture
- Deploy do EKS:
tofu init
tofu plan --var-file variables.tfvars
tofu apply --var-file variables.tfvars
- IAM Role para Loki e Tempo:
Para que o Loki e Tempo consigam gravar os dados coletados em um bucket S3, é necessário criar uma role contendo a policy com as permissões necessárias. Essa role será acionada via AssumeRole através de uma annotation que definimos nos arquivos values.yaml do loki e do tempo no deploy via helm chart.
Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowLokiandTempoBucketonK8s",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:AbortMultipartUpload",
"s3:ListBucket",
"s3:DeleteObject",
"s3:GetObjectVersion",
"s3:ListMultipartUploadParts"
],
"Resource": [
"arn:aws:s3:::<loki-bucket-name>/*",
"arn:aws:s3:::<loki-bucket-name>",
"arn:aws:s3:::<tempo-bucket-name>/*",
"arn:aws:s3:::<tempo-bucket-name>"
]
}
]
}
Coletando OIDC provider para utilizar na role
aws iam list-open-id-connect-providers
Role
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<ACCOUNT>:oidc-provider/oidc.eks.<REGION>.amazonaws.com/id/<ID>"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.<REGION>.amazonaws.com/id/<ID>:sub": [
"system:serviceaccount:o11y:loki-sa",
"system:serviceaccount:o11y:tempo-sa"
]
}
}
}
]
}
- Bucket S3:
- Conectar no EKS:
aws eks update-kubeconfig --region us-east-2 --name pegasus
Agora no repositório da stack de o11y, podemos iniciar os deploys com Helm.
- Criar namespace:
kubectl create namespace o11y
- Deploy promtail:
cd promtail
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
helm upgrade --install promtail grafana/promtail --values values.yaml -n o11y
- Deploy Loki:
cd loki
helm upgrade --install loki grafana/loki-distributed --values values.yaml -n o11y
- Deploy Tempo:
cd tempo
helm upgrade --install tempo grafana/tempo-distributed --values values.yaml -n o11y
- Deploy Prometheus:
cd prometheus-grafana
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm upgrade --install kube-prometheus-stack prometheus-community/kube-prometheus-stack --values values.yaml -n o11y
kubectl apply -f istio-ingress-prometheus.yaml
kubectl apply -f istio-ingress-grafana.yaml
Neste caso, criamos também o ingress para o Prometheus e o Grafana.
Temos agora tudo rodando no cluster:
kubectl get nodes
kubectl get pods -n o11y
- Registros no DNS (Route 53):
No DNS externo, criamos alguns registros direcionando para o NLB publico, que utilizamos como entrada. Para o Prometheus, Grafana e os apps que vamos utilizar para gerar dados.
- Deploy API de exemplo:
cd fastapi-observability
kubectl apply -f mono_manifest.yaml
Essa API está utilizando a biblioteca do OpenTelemetry para gerar os spans das operações que compõe os traces.
- Prometheus targets:
Podemos ver na interface do prometheus que ele já está coletando as métricas que a API de exemplo expõe no /metrics. Lembrando que temos a annotation no manifesto de deployment da API:
annotations:
prometheus.io/scrape: "true"
prometheus.io/path: "/metrics"
prometheus.io/port: "8000"
- Grafana:
Acessando o grafana, fazemos o import do dashboard que iremos utilizar. user: admin
, password: prom-operator
. O json do dashboard está em: fastapi-observability/etc/fastapi-dashboard.json
Dashboard importado
Data sources
Esses data sources são criados no momento do deploy da stack prometheus, os valores são informados no values.yaml do helm chart, em 'additionalDataSources'.
- Gerando dados com K6:
Utilizando o K6, podemos gerar requests na API de exemplo para que os dados sejam gerados e métricas capturadas para visualizarmos.
request.js
import { check } from 'k6';
import http from 'k6/http';
export const options = {
scenarios: {
constant_request_rate: {
executor: 'constant-arrival-rate',
rate: 100,
timeUnit: '1s', // 100 iterations per second, i.e. 100 RPS
duration: '120s',
preAllocatedVUs: 100, // how large the initial pool of VUs would be
maxVUs: 100, // if the preAllocatedVUs are not enough, we can initialize more
},
},
};
export function test(params) {
const res = http.get('https://app-a.pauloponciano.digital');
check(res, {
'is status 200': (r) => r.status === 200,
});
}
export default function () {
test();
}
k6 run request.js --vus=200 --duration=60m
- Visualização:
Ainda no grafana, no dashboard FastAPI Observability vamos visualizar as métricas, traces e logs da API de exemplo.
References:
Grafana Labs - FastAPI Observability
https://github.com/blueswen/fastapi-observability
Happy building!
Posted on February 1, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.