Um cluster EKS sem Container Insights obriga você a descobrir problemas pelo kubectl, pod por pod. Com ele, CPU, memória, reinícios e logs de todos os containers caem no CloudWatch, com painéis prontos e consultas em segundos. E dá para ligar tudo com um único add-on gerenciado.
Este é o oitavo artigo da série artigos-eks, que começou com o cluster EKS com Terraform do zero. Aqui o add-on amazon-cloudwatch-observability recebe permissão pelo EKS Pod Identity, os logs ganham retenção definida e o custo de ingestão fica sob controle.
Segurança: os comandos deste guia usam o perfil do AWS CLI para autenticar. Nunca coloque access keys no código ou em .tfvars versionado; prefira aws sso login ou um perfil com credenciais temporárias. Logs de aplicação podem conter dados pessoais: revise o que os seus pods escrevem antes de enviar tudo ao CloudWatch.
Sumário
- Pré-requisitos
- Como o Container Insights funciona no EKS
- Log groups do Container Insights com retenção
- Permissão do CloudWatch agent com Pod Identity
- Add-on amazon-cloudwatch-observability
- terraform plan
- Outputs do Terraform
- Verificando o Container Insights no cluster
- Consultas úteis no Logs Insights
- Custos e limpeza
- Conclusão
- Referências oficiais
Pré-requisitos
Você vai precisar do AWS CLI v2 autenticado, do Terraform >= 1.5, do kubectl e de permissão para criar IAM roles, log groups e recursos do EKS. O provider usado é o hashicorp/aws ~> 6.0 e o cluster está na versão 1.36.
O ambiente deste artigo é autocontido: ele recria a VPC, o cluster e o node group do primeiro artigo e acrescenta o Container Insights. Se você já tem o cluster da série, basta copiar os blocos novos para o seu ambiente.
Antes de tudo, confira se o add-on tem versão para a versão do seu cluster e qual permissão ele pede:
aws eks describe-addon-versions \
--addon-name amazon-cloudwatch-observability \
--kubernetes-version 1.36 \
--query 'addons[0].addonVersions[0].addonVersion' --output text
aws eks describe-addon-configuration \
--addon-name amazon-cloudwatch-observability \
--addon-version <versao-acima> \
--query 'podIdentityConfiguration'
O segundo comando devolve a service account cloudwatch-agent e a política recomendada CloudWatchAgentServerPolicy. É exatamente o que o Terraform vai configurar.
Como o Container Insights funciona no EKS
O add-on amazon-cloudwatch-observability instala no namespace amazon-cloudwatch dois coletores que rodam como DaemonSet, um pod por nó:
- CloudWatch agent: coleta métricas de cluster, nó, pod e container e alimenta o Container Insights com observabilidade aprimorada, com painéis prontos no console do CloudWatch.
- Fluent Bit: lê os logs dos containers e do nó e envia para o CloudWatch Logs.
Como é um add-on gerenciado, o EKS cuida da versão compatível com o cluster. Você não mantém Helm chart nem manifesto de DaemonSet. Os dois coletores precisam de permissão para escrever no CloudWatch, e é aí que entra o Pod Identity.
Log groups do Container Insights com retenção
O Container Insights usa quatro log groups por cluster, no padrão /aws/containerinsights/<cluster>/<tipo>:
application: stdout e stderr dos containers.dataplane: kubelet, kube-proxy e runtime de containers.host: logs do sistema operacional dos nós.performance: eventos de desempenho que viram as métricas do Container Insights.
Se você deixar o Fluent Bit criar esses grupos, eles nascem com retenção “nunca expira”. O armazenamento cresce todo mês e ninguém percebe até a fatura. Por isso o ambiente cria os grupos antes do add-on, já com retenção:
resource "aws_cloudwatch_log_group" "container_insights" {
for_each = toset(["application", "dataplane", "host", "performance"])
name = "/aws/containerinsights/${var.cluster_name}/${each.key}"
retention_in_days = var.log_retention_days
}
Com os grupos existindo, o Fluent Bit só escreve neles. O padrão do ambiente é 7 dias. Ajuste log_retention_days conforme a sua política de auditoria.
Permissão do CloudWatch agent com Pod Identity
module "pi_cloudwatch" {
source = "../../terraform-eks-pod-identity-modules"
cluster_name = module.eks.name
role_name = "${var.cluster_name}-cloudwatch-agent"
service_accounts = []
policy_arns = ["arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"]
}
O módulo cria a IAM role que confia em pods.eks.amazonaws.com e anexa a CloudWatchAgentServerPolicy. Repare em service_accounts = []: a associação com a service account fica a cargo do próprio add-on, no bloco pod_identity_association. Se o módulo também criasse a associação, haveria duas apontando para a mesma service account e o apply falharia.
A vantagem sobre dar a política para a role dos nós é o escopo. Só os pods do agent recebem permissão de escrita no CloudWatch, e não qualquer pod que rode no nó.
Add-on amazon-cloudwatch-observability
module "addons" {
source = "../../terraform-eks-addon-modules"
cluster_name = module.eks.name
kubernetes_version = module.eks.kubernetes_version
addons = {
vpc-cni = {}
coredns = {}
kube-proxy = {}
eks-pod-identity-agent = {}
amazon-cloudwatch-observability = {
pod_identity_role_arn = module.pi_cloudwatch.role_arn
service_account = "cloudwatch-agent"
configuration_values = jsonencode({
containerLogs = { enabled = var.enable_container_logs }
})
}
}
depends_on = [module.ng_default, aws_cloudwatch_log_group.container_insights]
}
Três pontos do bloco:
eks-pod-identity-agentprecisa estar no cluster. É ele que entrega as credenciais temporárias aos pods do agent.configuration_valuesrecebe o JSON de configuração do add-on. Aqui só ligamos ou desligamos os logs de container (containerLogs.enabled). As outras chaves aceitas aparecem noconfigurationSchemadodescribe-addon-configuration.depends_ongarante nós para os DaemonSets e log groups já criados, com retenção, antes de o Fluent Bit começar a escrever.
Se você já usa outra ferramenta de logs no cluster, defina enable_container_logs = false. As métricas continuam e o Fluent Bit sai do cluster.
terraform plan
terraform init
terraform validate
terraform plan -var 'public_access_cidrs=["SEU_IP/32"]' -out=tfplan
O código deste artigo foi validado com terraform validate e terraform plan contra uma conta AWS real, sem apply. O plan fecha em 35 recursos: os 28 da base do cluster mais os quatro log groups, a role do agent, a anexação da política e o add-on.
# aws_cloudwatch_log_group.container_insights["application"] will be created
# aws_cloudwatch_log_group.container_insights["dataplane"] will be created
# aws_cloudwatch_log_group.container_insights["host"] will be created
# aws_cloudwatch_log_group.container_insights["performance"] will be created
# module.pi_cloudwatch.aws_iam_role.this will be created
# module.addons.aws_eks_addon.this["amazon-cloudwatch-observability"] will be created
+ resource "aws_eks_addon" "this" {
+ addon_name = "amazon-cloudwatch-observability"
+ addon_version = (known after apply)
+ configuration_values = jsonencode(
{
+ containerLogs = {
+ enabled = true
}
}
)
...
Plan: 35 to add, 0 to change, 0 to destroy.
A versão do add-on aparece como (known after apply) porque o módulo busca a mais recente compatível com o cluster no momento do apply.
Outputs do Terraform
O ambiente expõe cinco outputs. Como o código não foi aplicado, o bloco abaixo é o Changes to Outputs do plan: o que só existe depois do apply aparece como (known after apply).
Changes to Outputs:
+ addon_versions = {
+ amazon-cloudwatch-observability = (known after apply)
+ coredns = (known after apply)
+ eks-pod-identity-agent = (known after apply)
+ kube-proxy = (known after apply)
+ vpc-cni = (known after apply)
}
+ cloudwatch_agent_role_arn = (known after apply)
+ cluster_name = "eks-blog-castilho"
+ kubeconfig_command = "aws eks update-kubeconfig --region us-east-1 --name eks-blog-castilho"
+ log_groups = [
+ "/aws/containerinsights/eks-blog-castilho/application",
+ "/aws/containerinsights/eks-blog-castilho/dataplane",
+ "/aws/containerinsights/eks-blog-castilho/host",
+ "/aws/containerinsights/eks-blog-castilho/performance",
]
cluster_name: nome do cluster, para usar em scripts e no AWS CLI (aws eks describe-addon --cluster-name $(terraform output -raw cluster_name) ...).addon_versions: versão instalada de cada add-on. Útil para registrar o que está rodando antes de um upgrade:terraform output -json addon_versions.cloudwatch_agent_role_arn: ARN da role do CloudWatch agent. Serve para conferir a associação do Pod Identity e para auditar quem escreve no CloudWatch. Depois do apply, ele terá o formatoarn:aws:iam::111122223333:role/eks-blog-castilho-cloudwatch-agent(exemplo, com conta fictícia).log_groups: os quatro log groups com retenção. Use o nome direto nas consultas do Logs Insights ou emaws logs tail.kubeconfig_command: comando pronto para configurar okubectl. Rode com$(terraform output -raw kubeconfig_command).
Verificando o Container Insights no cluster
Depois do apply, estes comandos confirmam que o add-on subiu e que os pods do agent receberam a role:
$(terraform output -raw kubeconfig_command)
aws eks describe-addon \
--cluster-name eks-blog-castilho \
--addon-name amazon-cloudwatch-observability \
--query 'addon.status'
kubectl get pods -n amazon-cloudwatch -o wide
aws eks list-pod-identity-associations \
--cluster-name eks-blog-castilho \
--namespace amazon-cloudwatch
aws logs tail /aws/containerinsights/eks-blog-castilho/application --since 10m
O status esperado do add-on é ACTIVE, com um pod do agent e um do Fluent Bit por nó. Os painéis aparecem no console do CloudWatch, em Insights > Container Insights, alguns minutos depois do primeiro envio.
Consultas úteis no Logs Insights
Os painéis respondem “o que está alto”. O Logs Insights responde “por quê”. Três consultas que valem ter salvas.
Erros recentes por pod, no log group application:
fields @timestamp, kubernetes.namespace_name, kubernetes.pod_name, log
| filter log like /(?i)error/
| sort @timestamp desc
| limit 50
Quem mais gera log, no mesmo grupo. É a consulta que mostra onde está o custo:
stats count(*) as linhas by kubernetes.namespace_name, kubernetes.pod_name
| sort linhas desc
| limit 20
Pods com mais uso de CPU e memória, no log group performance:
filter Type = "Pod"
| stats avg(pod_cpu_utilization) as cpu, avg(pod_memory_utilization) as memoria by Namespace, PodName
| sort cpu desc
| limit 20
Restrinja sempre o intervalo de tempo da consulta. O Logs Insights cobra pelo volume de dados lido, e uma consulta de 30 dias no grupo application de um cluster movimentado pesa mais do que parece.
Custos e limpeza
Na maioria dos clusters, o item que mais pesa no Container Insights é a ingestão de logs, cobrada por GB enviado ao CloudWatch Logs. As métricas da observabilidade aprimorada têm cobrança própria, por observação. Confira os dois na página de preços do CloudWatch para a sua região. Formas de reduzir:
- Retenção curta nos log groups, como no ambiente deste artigo. Ela resolve o armazenamento, mas não a ingestão.
- Menos log na origem: nível
infoem produção, semdebugligado esquecido. A segunda consulta do Logs Insights mostra quem são os campeões. - Desligar os logs de container (
enable_container_logs = false) se outra ferramenta já coleta os logs. Pagar duas vezes pelo mesmo log é comum. - Classe Infrequent Access nos log groups que são só para auditoria. A ingestão é mais barata, mas o grupo perde alguns recursos, como filtros de métrica. Avalie antes de trocar.
Some a isso o custo da base do cluster: control plane, NAT Gateway e nós, detalhados no primeiro artigo da série. Para limpar o lab:
terraform destroy
O destroy apaga também os log groups e os logs dentro deles. Se precisar guardar algo, exporte antes.
Conclusão
O Container Insights no EKS cabe em três blocos de Terraform: log groups com retenção, uma role com Pod Identity e o add-on gerenciado. O resultado são métricas e logs de todo o cluster sem Helm chart para manter e com a permissão de escrita no CloudWatch restrita aos pods do agent.
O cuidado que fica é com o volume de logs. Crie os log groups antes do add-on e acompanhe a consulta de quem mais gera log desde o primeiro dia.
Referências oficiais
- Install the CloudWatch agent with the Amazon CloudWatch Observability EKS add-on — AWS Documentation
- Container Insights — AWS Documentation
- EKS Pod Identity — AWS Documentation
- aws_eks_addon — Terraform Registry
- Amazon CloudWatch pricing
Interessado em saber mais sobre esse assunto?