Blog de Amazon Web Services (AWS)

Observabilidad en EKS

Nicolás Santisteban, DevOps Consultant, AWS WWCO ProServe – Latam
Eduardo Miranda, DevOps Consultant, AWS WWWCO ProServe – Latam y
Sebastian Ovalle, Senior Solutions Architect, AWS WWCSGeoSolutionArch – Latam

 

Resumen de la solución

Este blog busca mostrar las herramientas de monitoreo para un clúster de Amazon Elastic Kubernetes Service (EKS), con servicios administrados por AWS como, Amazon Managed Prometheus (AMP), Amazon Managed Grafana (AMG) y AWS Single Sign-On como capa de autenticación para hacer inicio de sesión en Grafana. Estos servicios liberan una responsabilidad en la administración y operación de los clientes pues no hay recursos extras que administrar dentro del cluster.

Respecto a la observabilidad dentro del clúster de EKS, el objetivo es mostrar como integrar los servicios para hacer rastreo de peticiones con AWS X-Ray que proporciona una vista completa de las peticiones que atraviesan la aplicación. Estos servicios simplifican el análisis y diagnóstico de las tareas productivas, dándonos la capacidad de rastreo, únicamente instrumentando las aplicaciones, implica el envío de datos de rastreo de las solicitudes entrantes y salientes y de otros eventos dentro de la aplicación, junto con los metadatos de cada petición. La ventaja de la instrumentación de nuestro aplicativo es poder, definir lo que nos da valor así prescindir de los patrones como sidecar disminuyendo el consumo de recursos, latencia y una capa de administración a adicional que hay que mantener y gestionar.

Adicionalmente debemos contar con una visibilidad operativa de los recursos de AWS, lo cual la implementación y uso de Amazon CloudWatch Container Insights nos permite recopilar métricas de los clústeres implementados en Fargate tanto para ECS como para AWS EKS. Estas métricas incluyen el uso de recursos como CPU, memoria y redes, están disponibles en los paneles automáticos de CloudWatch y también se pueden ver en la sección Métricas (Metrics) de la consola de CloudWatch. De esta manera la operación gana visibilidad, planificación, ejecutar políticas de escalamiento, optimización apoyando a la toma de decisiones, de esa manera podemos asignar los recursos óptimos a las aplicaciones basado en datos.

Visibilidad del Costo

Se debe considerar que la ejecución de los recursos usados en este blog van incurrir en gastos, los cuales para clarificar los servicios que participan los especificamos en la calculadora con costos bajo demanda(esto puede cambiar en el tiempo).

Los recursos que incurren en costos serán:

  • Un clúster de EKS.
  • 3 instancias EC2 de tipo t3.xlarge.
  • Un Workspace de Amazon Managed Grafana.
  • Un Workspace de Amazon Managed Service for Prometheus.
  • Métricas de Amazon CloudWatch y log groups de Amazon CloudWatch Logs.
  • Ingestión en AWS X-Ray.

Existe la opción de poder bajar los costos de las EC2, utilizando instancias spot donde puedes ahorras hasta el 90% sobre los precios bajo demanda. Los precios cambian gradualmente (se pueden revisar asesor de instancias spot). Los posibles eventos llamados “interrupción de instancia de spot” las razon de esta interrupción son por capacidad, EC2 recupera la instancia principal para reutilizar la capacidad, pero también puede ser por otras razones (mantenimiento del host o desmantelamiento de equipos, alta demanda de recursos ec2 en la zona de disponibilidad). Precio, si tenemos políticas específicas de precio sobre la instancia de spot, las instancias se interrumpirán y por Restricciones, estas se interrumpen cuando se incluye una restricción en la instancia spot, como grupo de lanzamiento o una zona de disponibilidad, si no se puede cumplir se interrumpen.

por lo cual recuerde de limpiar los recursos al finalizar la prueba es importante.

Instalación:

Los recursos usados en este patrón pueden ser consultados en sus respectivos repositorios de GitHub que se encuentran enlazados en los siguientes pasos.

Prerrequisitos:

Para esta instalación se necesitan los siguientes prerrequisitos

Pasos:

La siguiente infraestructura base será creada la cual consiste en una VPC con subnets públicas y privadas, 3 instancias EC2 de tipo t3.xlarge para conformar el Node Group de EKS el cual tendrá sus endpoints públicos.

Se usarán los Terraform Blueprints que están disponibles en GitHub para crear un clúster público de EKS en una nueva VPC que las plantillas también crearán, por lo tanto se deben ejecutar los siguientes comandos en orden:

git clone https://github.com/aws-observability/terraform-aws-observability-accelerator.git

cd terraform-aws-observability-accelerator/examples/eks-cluster-with-vpc

terraform init

Se debe modificar el archivo variables.tf donde se debe cambiar el valor de la variable eks_version, se puede actualizar a la versión 1.28 que hasta el momento es la última, las versiones soportadas se pueden consultar en este enlace.

Luego se deben aplicar los cambios de Terraform ejecutando los siguientes comandos:

terraform apply

El estado de Terraform se almacenará localmente en el directorio actual de trabajo.

En este punto se debe introducir la región deseada donde se realizará el despliegue, tal como us-east-1, luego esperar a que Terraform arroje el plan de ejecución y se confirma con yes. Luego de varios minutos el cluster con nombre eks-cluster-with-vpc será creado.

Para poder manipular el cluster en la misma línea de comandos con eksctl se debe ejecutar:

aws eks update-kubeconfig --name eks-cluster-with-vpc --region us-east-1

Luego, para obtener los nodos desplegados y confirmar que todo fue desplegado correctamente se debe ejecutar:

kubectl get nodes

La salida debe ser similar a la siguiente:

Como se están desplegando las plantillas del Terraform Blueprint, se puede obtener más detalles de las configuraciones disponibles en este enlace.

Ahora que se tiene el cluster correctamente configurado se puede iniciar a instalar las herramientas de observabilidad, asi que iniciaremos con Amazon Managed Prometheus (AMP).

Para hacerlo se debe crear un Workspace, esto se realiza desde la consola de AWS buscando prometheus en la barra de búsqueda:

Desde ahí se puede crear un nuevo workspace y asignarle un nombre el cual será usado en los próximos pasos.

Un Rol y Política de IAM son necesarios para que EKS pueda publicar las métricas a AMP, por lo tanto se crea un Rol con la siguiente política de confianza personalizada:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::{AWS_ACCOUNT_ID}:oidc-provider/{OIDC_PROVIDER}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"{OIDC_PROVIDER}:sub": "system:serviceaccount:{NAMESPACE}:{SERVICE_ACCOUNT_AMP_INGEST_NAME}"
}
}
}
]
}

Donde los siguientes valores deben ser reemplazados:

  • {AWS_ACCOUNT_ID} Es el ID de la cuenta de AWS donde los recursos se están desplegando.
  • {OIDC_PROVIDER} Es el proveedor OIDC que se creó automáticamente, la URL se encuentra en la consola de los proveedores de identidad de IAM, el formato es similar al siguiente: eks.{AWS_REGION}.amazonaws.com/id/ABC123DEF456GHI789
  • {SERVICE_ACCOUNT_AMP_INGEST_NAME} Es el nombre de la cuenta de servicio que será creada en el clúster de EKS, el valor por defecto que se asignará es: amp-iamproxy-ingest-service-account
  • {NAMESPACE} Es el namespace donde las cargas de trabajo de prometheus serán desplegadas dentro del clúster de EKS, el valor por defecto que se asignará es: prometheus

Luego al rol se le asignan los siguientes permisos de IAM:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"aps:GetSeries",
"aps:GetLabels",
"aps:GetMetricMetadata",
"aps:QueryMetrics",

"aps:RemoteWrite"
],
"Resource": "*"
}
]
}

O bien se pueden asignar las políticas administradas por AWS AmazonPrometheusQueryAccess y AmazonPrometheusRemoteWriteAccess

Finalmente se le asigna un nombre al rol, el valor por defecto que se asignará es:  amp-iamproxy-ingest-role

Ahora que la parte de permisos está completa, se realizará la instalación de Prometheus en el clúster de EKS a través de un chart de Helm y luego las métricas serán visualizadas en Amazon Managed Services for Grafana (AMG), por lo que la arquitectura se verá de la siguiente manera:

Se instala el chart de Helm ejecutando los siguientes comandos en orden:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

Luego se crea un archivo con extensión .yaml y con el siguiente contenido:

serviceAccounts:
server:
name: amp-iamproxy-ingest-service-account
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::{AWS_ACCOUNT_ID}:role/amp-iamproxy-ingest-role
server:
remoteWrite:
- url: {PROMETHEUS_REMOTE_WRITE_URL}
sigv4:
region: us-east-1
queue_config:
max_samples_per_send: 1000
max_shards: 200
capacity: 2500

Donde los siguientes valores deben ser reemplazados:

  • {AWS_ACCOUNT_ID} Es el ID de la cuenta de AWS donde los recursos se están desplegando.
  • {PROMETHEUS_REMOTE_WRITE_URL} Es el Endpoint - remote write URL que se encuentra en el Workspace de Amazon Managed Prometheus que se creó anteriormente.

[OPCIONAL] El valor de la llave serviceAccounts.server.name.annotations[].eks.amazonaws.com/role-arn corresponde al nombre del rol que se creó anteriormente, por lo tanto si se nombró de distinta manera se debe realizar el cambio.

[OPCIONAL] El valor de la llave serviceAccounts.server.name corresponde al nombre de la cuenta de servicio que se usó en la política de confianza personalizada, por lo tanto, si se nombró de distinta manera se debe realizar el cambio.

[OPCIONAL] El valor de la llave server.remoteWrite.url[].sigv4.region corresponde al nombre de la región donde se están desplegando los recursos, por lo tanto si la región es distinta a us-east-1 se debe realizar el cambio.
Luego el namespace para Prometheus debe ser creado, el nombre de este es el que se asignó en la política de confianza personalizada, esto se realiza ejecutando el siguiente comando:

kubectl create ns prometheus

Luego se instala el chart de Prometheus ejecutando el siguiente comando:

helm install prometheus prometheus-community/prometheus -n prometheus -f file.yaml

Reemplazando file.yaml con el nombre del archivo .yaml que se creó anteriormente. En caso de que el namespace para prometheus se haya creado con un nombre distinto se debe cambiar el valor del parámetro -n Si todo se realizó de manera correcta la salida debe ser similar a la siguiente:

Para obtener los recursos que el Helm Chart de Prometheus creó se debe ejecutar:

kubectl get all -n prometheus

La salida debe ser similar a la siguiente:

Como se puede observar, todas las columnas Ready muestran los valores esperados, en caso de que muestre algo distinto luego de un par de minutos se deben confirmar los valores de la política de confianza personalizada que se creó en el Rol, así mismo los valores del archivo .yaml en caso de que alguno de los valores esté erróneo se debe ajustar y reinstalar el Chart de Helm.

[OPCIONAL] Si se desea navegar a través de la interfaz de Prometheus se deben ejecutar los siguientes comandos:

export POD_NAME=$(kubectl get pods --namespace prometheus -l "app.kubernetes.io/name=prometheus,app.kubernetes.io/instance=prometheus" -o jsonpath="{.items[0].metadata.name}")

kubectl --namespace prometheus port-forward $POD_NAME 9090

Abrir en un navegador la URL http://localhost:9090 si todo se hizo de manera correcta se podrá observar la consola de Prometheus:

Ahora que Prometheus fue configurado correctamente es momento de observar las métricas, esto se realiza con Amazon Managed Grafana (AMG) y tal como Amazon Managed Prometheus (AMP) este servicio se encuentra en la consola de AWS:

Se crea un nuevo workspace:

En el proceso de creación se habilita AWS IAM Identity Center y se habilita el acceso abierto para poder acceder a la consola desde internet sin necesidad de un bastion host.

En el paso #3 se habilita todos los Data sources y SNS a manera de prueba.

Luego de crear el Workspace de AMG se debe esperar aproximadamente 10 minutos a que este se configure, luego se pueden añadir los usuarios de IAM, esto se realiza desde la consola de AMG en la pestaña Authentication.

Para poder hacer configuración de los primeros tableros se debe añadir un usuario de tipo Admin:

Luego en la consola principal de AMG se encuentra la URL para acceder a la interfaz, se abre en una nueva pestaña del navegador y se usan las credenciales de IAM Identity Center para acceder:

Allí aparecerá el icono del nuevo Workspace de AMG y se dará clic para accederlo. De hacerlo todo correctamente se podrá ver la interfaz de AMG.

Luego se añade el Data source de Prometheus que se configuró anteriormente, para ello se expande el menú izquierdo Apps > AWS Data Sources y luego se selecciona Amazon Managed Service for Prometheus :

Luego se selecciona la región donde se desplegó AMP y automáticamente se mostrará el Workspace que anteriormente se creó:

Después se selecciona y se añade dando clic en Add data sources.

Ahora que las métricas de Prometheus están enlazadas en AMG es momento de visualizarlas, para eso se importa un nuevo Dashboard. Se expande el menú izquierdo y se selecciona Dashboards luego New > Import

En el campo Import via grafana.com se usa el ID 3119 y luego se da click en Load

En la siguiente página se le asigna un nombre al nuevo Dashboard y se selecciona el workspace de AMP para usar esas métricas como datasource, finalmente se da clic en Import

Luego de algunos minutos el Dashboard mostrará la información que está obteniendo de AMP y a su vez del clúster de EKS lo cual indica que la configuración fue realizada de manera satisfactoria.

Ahora que ya es posible tener observabilidad en el clúster de EKS es posible tener aún mas detalles de las trazas de las aplicaciones desplegadas gracias a Amazon CloudWatch X-Ray.

Para habilitar X-Ray se debe crear una nueva cuenta de servicio para el daemon de X-Ray. Se seguirán usando las plantillas de Terraform, por tanto se debe editar el archivo main.tf y añadir el siguiente contenido al final del archivo:

data "aws_caller_identity" "current" {}
resource "kubernetes_service_account" "xray_service_account" {

metadata {
name      = "xray-daemon"
namespace = "default"
annotations = {
"eks.amazonaws.com/role-arn" = aws_iam_role.x-ray-role.arn
}
labels = {
"app.kubernetes.io/name"       = "xray-daemon"
"app.kubernetes.io/managed-by" = "terraform"

"app"                          = "xray-daemon"
}
}
}
data "aws_iam_policy_document" "assume_role_policy" {

statement {
actions = ["sts:AssumeRoleWithWebIdentity"]
effect  = "Allow"
condition {
test     = "StringEquals"
variable = "${replace(module.eks_blueprints.oidc_provider, "https://", "")}:sub"
values = [
"system:serviceaccount:default:xray-daemon"
]
}
condition {
test     = "StringEquals"
variable = "${replace(module.eks_blueprints.oidc_provider, "https://", "")}:aud"
values = [
"sts.amazonaws.com"
]
}
principals {
identifiers = [
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${replace(module.eks_blueprints.oidc_provider, "https://", "")}"
]
type = "Federated"
}
}
}
resource "aws_iam_role" "x-ray-role" {

name                = "x-ray-daemon-role"
assume_role_policy  = data.aws_iam_policy_document.assume_role_policy.json
managed_policy_arns = ["arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess"]
tags                = merge(local.tags)
}

Luego se aplican los cambios ejecutando terraform apply confirmando el plan de ejecución. Un nuevo rol de IAM con nombre x-ray-daemon-role ha sido creado y contiene la política AWSXRayDaemonWriteAccess la cual es necesaria para el DaemonSet de X-Ray.

También se ha creado la cuenta de servicio en el clúster con nombre xray-daemon.

Se confirma que todo haya quedado correctamente configurado ejecutando:

kubectl describe serviceaccount xray-daemon

La salida debe ser similar a la siguiente:

X-Ray debe ser desplegado como un DaemonSet en cada uno de los nodos del clúster, para demostrar como funciona se usará la aplicación del EKS Immersion Workshop. Así que se deben seguir los para desplegar la aplicación:

  • Clonar el repositorio de eks-app-mesh-polyglot-demo con el comando:
git clone https://github.com/aws-containers/eks-app-mesh-polyglot-demo.git
  • Dirigirse al directorio donde quedó clonado el repositorio con el comando:
cd eks-app-mesh-polyglot-demo
  • Instalar el chart de Helm que viene en el repositorio al namespace workshop con el comando:
helm install workshop workshop/helm-chart/
  • Verificar que todo haya quedado desplegado de manera exitosa con el comando:
kubectl get pod,svc -n workshop -o wide

La salida debe ser similar a la siguiente donde copiaremos la URL del service/frontend:

  • Luego de un par de minutos en lo que el ALB se provisione si todo se realizó de manera correcta se podrá visualizar la interfaz del FrontEnd:

Antes de hacer uso de esta e insertar productos se desplegará el DaemonSet de X-Ray, para ello se ejecuta el siguiente comando:

kubectl apply -f https://raw.githubusercontent.com/aws-containers/eks-app-mesh-polyglot-demo/master/workshop/xray-eks.yaml

Y se verifica el estado del DaemonSet ejecutando:

kubectl describe daemonset xray-daemon

La salida debe ser similar a la siguiente:

Como se ve en la sección de Eventos todo fue creado exitosamente y ya se pueden insertar productos en el FrontEnd de la aplicación, se recomienda realizar la inserción de múltiples productos para que se generen trazas en X-Ray:

Así mismo la aplicación generará algunas otras trazas cada segundo por lo tanto se verán en la consola de X-Ray desde la consola de AWS:

Por defecto mostrará las únicas aplicaciones que se encuentran instrumentalizadas y se podrán ver en el mapa de servicio que ofrece una visualización de las peticiones de los usuarios:

En la imagen anterior por ejemplo se puede ver que el Cliente realiza 14.80 transacciones por minuto al frontend y todas llegan al backend con una latencia inferior a 1 milisegundo. Luego si se accede al menú izquierdo en Traces se podrá ver algunas de las trazas que ha generado la aplicación:

Al acceder a alguna se puede ver con más detalle cada métrica de la petición:

Clean-Up X-Ray Resources:

Para eliminar los recursos desplegados para X-Ray se pueden ejecutar los siguientes comandos:

kubectl delete -f https://raw.githubusercontent.com/aws-containers/eks-app-mesh-polyglot-demo/master/workshop/xray-eks.yaml

Y para eliminar los recursos de la aplicación de prueba se debe ejecutar:

helm uninstall workshop

Amazon CloudWatch Container Insights

Finalmente se habilitará Amazon CloudWatch Container Insights para tener mayor observabilidad del clúster y la posibilidad de obtener los logs de las aplicaciones desplegadas, se desplegará la siguiente arquitectura:

Habilitar CloudWatch Container Insights consiste en pocos pasos. Lo primero que se debe hacer es comprobar que no se estén mostrando métricas en la consola de Container Insights. Luego al Rol que tienen el NodeGroup del Cluster de EKS se le debe añadir la Policy CloudWatchAgentServerPolicy. Para eso en la plantilla de terraform se debe editar el archivo main.tf. En el modulo eks_blueprints dentro del bloque managed_node_groups.mg_5 se debe añadir lo siguiente:

additional_iam_policies = ["arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"]

Quedando de ejemplo de la siguiente manera:

Luego se procede a ejecutar terraform apply donde se confirman los cambios

Y en la consola de IAM se añade el rol debe quedar con los siguientes permisos:

Luego se ejecuta el siguiente comando que instalará el Amazon CloudWatch Observability EKS add-on

aws eks create-addon --addon-name amazon-cloudwatch-observability --cluster-name eks-cluster-with-vpc -–region us-east-1

En caso de que la región sea distinta se debe cambiar el valor del parámetro region.

La salida del comando mostrará el estado de instalación del add-on y este se podrá observar en la pestaña Add-ons del clúster de EKS. Una vez esté en estado Active se podrá continuar.

Estos recursos se despliegan en el Namespace amazon-cloudwatch por lo tanto para obtener los recursos desplegados en ese namespace se ejecuta el comando:

kubectl get all -n amazon-cloudwatch

El cual debe mostrar una salida similar a la siguiente:

Luego de algunos minutos se puede actualizar la consola de Container Insights para detallar las metricas que muestra y navegar entre cada uno de los menús para observar el nivel de observabilidad que se entrega:

Uno de los principales beneficios de Amazon CloudWatch Container Insights es la posibilidad de revisar los logs de las aplicaciones en CloudWatch logs, para ello se selecciona en la izquierda el recurso Pods y en la tabla Container performance se selecciona algún pod y en el menú desplegable Actions se selecciona View application logs.

Se redireccionará a la consola de CloudWatch Logs Insights, allí se da click en Run query y mostrará los logs del pod seleccionado:


Se puede filtrar por fecha para tener un mejor detalle de algún error o comportamiento inesperado en las aplicaciones desplegadas en el clúster de EKS.

Para eliminar los recursos creados para CloudWatch Container Insights a través del add-on se debe ejecutar:

aws eks delete-addon --addon-name amazon-cloudwatch-observability --cluster-name eks-cluster-with-vpc -–region us-east-1

Limpieza de Recursos Creados:

Primero debe haberse ejecutado la limpieza de cada uno de los recursos que se crearon siguiendo las instrucciones que se encuentran al final de cada sección. Luego se debe acceder al directorio donde se ejecutó el terraform apply y ejecutar terraform destroy igualmente solicitará el nombre de la región us-east-1 y confirmar la eliminación con yes.

Igualmente el rol que se creó para la inserción de métricas a Prometheus se puede eliminar desde la consola de IAM y los Workspaces de AMP y AMG se eliminan desde la respectiva consola del servicio.

Conclusión

Se demostró de múltiples maneras como habilitar la observabilidad en el clúster de EKS para obtener visibilidad respecto al rendimiento no solamente del clúster y sus nodos si no de los recursos desplegados allí, gracias a esto las organizaciones pueden optimizar sus recursos garantizando que las cargas de trabajo siempre estén disponibles con los recursos necesarios para su funcionamiento y demandas.

 


Sobre los autores

Nicolás Santisteban es un consultor DevOps ubicado en Bogotá – Colombia con experiencia en AWS para multiples clientes corporativos en el continente implementado soluciones DevOps para automatizar el Ciclo de vida del desarrollo del software. En su lado mas personal le encantan los videojuegos musicales y ritmo, le encanta el café, la música electrónica y asistir a festivales de música

 

 

 

 

Eduardo Miranda es un Senior DevOps Consultant basado en Santiago – Chile, Eduardo tiene un conocimiento amplio sobre contenedores y le encanta trabajar con entusiasmo para poder apoyar a los clientes a mejorar sus arquitecturas día a dia.

 

 

 

 

Sebastian Ovalle Haverbeck es un Arquitecto de Soluciones ubicado en Santiago – Chile con una amplia experiencia en arquitecturas basadas en Kubernetes para eventos de alto tráfico enfocadas al comercio. aficionado al boxeo y amante de los videojuegos.