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 o 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 público, 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õem 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:
Happy building!
































Top comments (0)