Amazon EKS Monitoring and Logging
Last Updated: July 3, 2026
Effective monitoring and logging are essential for maintaining the reliability, availability, and performance of Amazon EKS clusters. This document covers various tools, techniques, and best practices for implementing monitoring and logging in EKS clusters.
Table of Contents
- Monitoring and Logging Overview
- EKS Control Plane Logging
- Container Logging
- Cluster Monitoring
- Alerting and Event Management
- Log Analysis and Visualization
- Monitoring and Logging Best Practices
- Troubleshooting and Debugging
Monitoring and Logging Overview
Importance of Monitoring and Logging
Monitoring and logging in Amazon EKS clusters are important for the following reasons:
- Visibility: Provides visibility into cluster status, performance, and behavior
- Issue Detection: Detects issues early before they become critical
- Trend Analysis: Identifies performance and resource usage trends over time
- Capacity Planning: Forecasts and plans for resource requirements
- Security and Auditing: Detects security events and meets compliance requirements
- Troubleshooting: Enables rapid diagnosis and resolution when issues occur
Monitoring and Logging Architecture
A comprehensive monitoring and logging architecture for an EKS cluster consists of the following components:
Monitoring and Logging Strategy
Follow these steps to develop an effective monitoring and logging strategy:
- Define Objectives: Define monitoring and logging objectives and requirements
- Identify Metrics and Logs: Identify key metrics and logs to collect
- Select Tools: Select monitoring and logging tools that meet requirements
- Establish Baselines: Establish baselines for normal behavior
- Configure Alerts: Configure alerts for important events and thresholds
- Automate: Automate monitoring and logging processes as much as possible
- Regular Review: Regularly review and improve monitoring and logging strategy
EKS Control Plane Logging
Amazon EKS provides the ability to send cluster control plane logs to Amazon CloudWatch Logs. This provides visibility into the cluster's control components.
Control Plane Log Types
EKS supports the following control plane log types:
- API Server (api): Kubernetes API server logs
- Audit (audit): Kubernetes audit logs
- Authenticator (authenticator): AWS IAM authenticator logs
- Controller Manager (controllerManager): Controller manager logs
- Scheduler (scheduler): Kubernetes scheduler logs
Enabling Control Plane Logging
You can enable control plane logging using the AWS Management Console, AWS CLI, or eksctl:
Using AWS CLI
aws eks update-cluster-config \
--region us-west-2 \
--name my-cluster \
--logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'Using eksctl
eksctl utils update-cluster-logging \
--region us-west-2 \
--cluster my-cluster \
--enable-types api,audit,authenticator,controllerManager,schedulerQuerying Control Plane Logs
You can query control plane logs using CloudWatch Logs Insights:
API Server Error Query
fields @timestamp, @message
| filter @message like /Error/
| sort @timestamp desc
| limit 20Authentication Failure Query
fields @timestamp, @message
| filter @message like /authentication failed/
| sort @timestamp desc
| limit 20Audit Log Query
fields @timestamp, @message
| filter @message like /responseStatus.code="403"/
| sort @timestamp desc
| limit 20Control Plane Log Retention and Cost Management
You can configure log retention periods in CloudWatch Logs to manage costs:
aws logs put-retention-policy \
--log-group-name /aws/eks/my-cluster/cluster \
--retention-in-days 30EKS Capabilities Logging (GitOps, ACK, kro)
EKS Capabilities runs Argo CD, AWS Controllers for Kubernetes (ACK), and kro as managed controllers on the EKS control plane. Their controller logs can now be delivered directly to CloudWatch Logs, S3, or Kinesis Data Firehose, the same delivery options used for control plane logging, without running a separate log collector in the cluster to scrape the controller pods.
This closes a visibility gap that previously required inspecting controller pods directly:
- GitOps sync errors from Argo CD
- Failed resource reconciliation from ACK
- Workflow state transitions from kro
Enable log delivery for the capabilities you run alongside standard control plane logging, then query the results with CloudWatch Logs Insights the same way you would query API server or audit logs. See the announcement (June 4, 2026) for the current list of supported capability log types.
Container Logging
Container logs provide important information for diagnosing and resolving application issues. In EKS, you can collect and manage container logs in various ways.
Logging Architecture
A typical container logging architecture in EKS looks like this:
Log Collection with Fluent Bit
Fluent Bit is a lightweight log collector widely used for collecting container logs in EKS clusters:
Fluent Bit Installation
Install Fluent Bit using Helm:
helm repo add aws-for-fluent-bit https://aws.github.io/eks-charts
helm repo update
helm install aws-for-fluent-bit aws-for-fluent-bit/aws-for-fluent-bit \
--namespace kube-system \
--set cloudWatch.region=us-west-2 \
--set cloudWatch.logGroupName=/aws/eks/my-cluster/fluentbitFluent Bit Configuration
ConfigMap for custom configuration:
apiVersion: v1
kind: ConfigMap
metadata:
name: fluent-bit-config
namespace: kube-system
data:
fluent-bit.conf: |
[SERVICE]
Flush 5
Log_Level info
Daemon off
Parsers_File parsers.conf
[INPUT]
Name tail
Tag kube.*
Path /var/log/containers/*.log
Parser docker
DB /var/log/flb_kube.db
Mem_Buf_Limit 5MB
Skip_Long_Lines On
Refresh_Interval 10
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc:443
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
Merge_Log On
K8S-Logging.Parser On
K8S-Logging.Exclude Off
[OUTPUT]
Name cloudwatch
Match kube.*
region us-west-2
log_group_name /aws/eks/my-cluster/fluentbit
log_stream_prefix container-
auto_create_group true
[OUTPUT]
Name es
Match kube.*
Host search-my-es-domain.us-west-2.es.amazonaws.com
Port 443
TLS On
AWS_Auth On
AWS_Region us-west-2
Index eks-logs
Suppress_Type_Name OnCloudWatch Container Insights
CloudWatch Container Insights collects, aggregates, and summarizes metrics and logs from containerized applications and microservices:
Installing Container Insights
ClusterName=my-cluster
RegionName=us-west-2
FluentBitHttpPort='2020'
FluentBitReadFromHead='Off'
[[ ${FluentBitReadFromHead} = 'On' ]] && FluentBitReadFromTail='Off'|| FluentBitReadFromTail='On'
[[ -z ${FluentBitHttpPort} ]] && FluentBitHttpServer='Off' || FluentBitHttpServer='On'
kubectl apply -f https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/quickstart/cwagent-fluent-bit-quickstart.yamlContainer Insights Dashboard
Access the Container Insights dashboard in the CloudWatch console to monitor:
- Node, pod, and container-level CPU and memory usage
- Network and disk I/O
- Pod and container status
- Cluster failures and events
Custom Logging Solutions
You can implement custom logging solutions for specific requirements:
EFK (Elasticsearch, Fluentd, Kibana) Stack
# Install Elasticsearch
helm repo add elastic https://helm.elastic.co
helm repo update
helm install elasticsearch elastic/elasticsearch \
--namespace logging \
--create-namespace \
--set replicas=3
# Install Fluentd
helm install fluentd stable/fluentd \
--namespace logging \
--set output.host=elasticsearch-master.logging.svc.cluster.local
# Install Kibana
helm install kibana elastic/kibana \
--namespace logging \
--set service.type=LoadBalancerPLG (Promtail, Loki, Grafana) Stack
# Install Loki and Promtail
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
helm install loki grafana/loki-stack \
--namespace logging \
--create-namespace \
--set grafana.enabled=true \
--set promtail.enabled=true \
--set loki.persistence.enabled=true \
--set loki.persistence.size=10GiLog Structuring and Parsing
It's recommended to use structured log formats for effective log analysis:
JSON Log Format
Output logs in JSON format from your application:
{
"timestamp": "2025-07-11T13:00:00Z",
"level": "INFO",
"message": "Request processed successfully",
"request_id": "12345",
"user_id": "user-789",
"duration_ms": 45,
"status_code": 200
}Log Parser Configuration
Configuration for log parsing in Fluent Bit:
[PARSER]
Name json
Format json
Time_Key timestamp
Time_Format %Y-%m-%dT%H:%M:%S%zCluster Monitoring
Effective cluster monitoring is essential for tracking the status, performance, and resource usage of your EKS cluster. This section explores various tools and techniques for monitoring EKS clusters.
CloudWatch Container Insights
Amazon CloudWatch Container Insights collects, aggregates, and summarizes metrics, logs, and events from containerized applications and microservices:
Enabling Container Insights
Enable Container Insights using the CloudWatch agent:
ClusterName=my-cluster
RegionName=us-west-2
FluentBitHttpPort='2020'
FluentBitReadFromHead='Off'
[[ ${FluentBitReadFromHead} = 'On' ]] && FluentBitReadFromTail='Off'|| FluentBitReadFromTail='On'
[[ -z ${FluentBitHttpPort} ]] && FluentBitHttpServer='Off' || FluentBitHttpServer='On'
curl https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/quickstart/cwagent-fluent-bit-quickstart.yaml | sed 's/{{cluster_name}}/'${ClusterName}'/;s/{{region_name}}/'${RegionName}'/;s/{{http_server_toggle}}/"'${FluentBitHttpServer}'"/;s/{{http_server_port}}/"'${FluentBitHttpPort}'"/;s/{{read_from_head}}/"'${FluentBitReadFromHead}'"/;s/{{read_from_tail}}/"'${FluentBitReadFromTail}'"/' | kubectl apply -f -Container Insights Metrics
Container Insights collects the following metrics:
- Cluster level: Node count, pod count, failed pod count
- Node level: CPU usage, memory usage, network I/O, disk I/O
- Pod level: CPU usage, memory usage, network I/O
- Service level: Pod count, CPU usage, memory usage
Container Insights Dashboard
Access the Container Insights dashboard in the CloudWatch console to visualize cluster performance:
- Log in to AWS Management Console
- Navigate to CloudWatch service
- Select "Insights" > "Container Insights" from the left navigation pane
- Select cluster, node, pod, or service view
Container Insights Alerts
Set up CloudWatch alarms to receive notifications when metrics exceed specific thresholds:
aws cloudwatch put-metric-alarm \
--alarm-name "High-CPU-Cluster" \
--alarm-description "Alarm when cluster CPU exceeds 80%" \
--metric-name pod_cpu_utilization \
--namespace ContainerInsights \
--statistic Average \
--period 300 \
--threshold 80 \
--comparison-operator GreaterThanThreshold \
--dimensions Name=ClusterName,Value=my-cluster \
--evaluation-periods 2 \
--alarm-actions arn:aws:sns:us-west-2:123456789012:my-topicCloudWatch Observability Add-on 5.0.0
Starting with version 5.0.0 (February 2026) of the amazon-cloudwatch-observability EKS add-on, Application Signals (APM) ships enabled by default instead of requiring manual opt-in. The add-on now bundles Enhanced Container Insights, Container Logs, and Application Signals into a single package, and instruments workloads for traces, metrics, and logs without requiring pod annotations:
aws eks update-addon \
--cluster-name my-cluster \
--addon-name amazon-cloudwatch-observability \
--addon-version v5.0.0-eksbuild.1See the release notes (February 26, 2026) for upgrade guidance if you're moving from an add-on version where Application Signals was opt-in. For the newer OTel-based evolution of Container Insights metric collection, see CloudWatch Metrics.
EKS Node Monitoring Agent
The EKS Node Monitoring Agent watches worker nodes for system, storage, network, and accelerator (GPU) issues and publishes them as Kubernetes Node Conditions, which the EKS auto node repair feature can act on automatically. As of February 2026, the agent's source is public on GitHub, so it can be customized or extended beyond the built-in checks.
The agent is included by default in EKS Auto Mode and is also available as a standalone add-on for standard managed node groups:
aws eks create-addon \
--cluster-name my-cluster \
--addon-name eks-node-monitoring-agentCheck the conditions it reports with:
kubectl get nodes -o custom-columns='NAME:.metadata.name,CONDITIONS:.status.conditions[*].type'
kubectl describe node <node-name>See the announcement (February 24, 2026) for the GitHub repository and supported condition types.
Prometheus and Grafana
Prometheus is a time-series database and monitoring system, and Grafana is a dashboard tool for visualizing metrics. You can use these two tools together for comprehensive monitoring of your EKS cluster.
Amazon Managed Service for Prometheus and Grafana
AWS provides managed services for Prometheus and Grafana:
- Amazon Managed Service for Prometheus (AMP) setup:
# Create AMP workspace
aws amp create-workspace --alias my-amp-workspace
# Install Prometheus server and configure remote write to AMP
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus prometheus-community/prometheus \
--namespace prometheus \
--create-namespace \
--set server.remoteWrite[0].url=https://aps-workspaces.us-west-2.amazonaws.com/workspaces/ws-12345678-1234-1234-1234-123456789012/api/v1/remote_write \
--set server.remoteWrite[0].sigv4.region=us-west-2- Amazon Managed Grafana (AMG) setup:
# Create AMG workspace
aws grafana create-workspace \
--name my-grafana-workspace \
--authentication-providers AWS_SSO \
--permission-type SERVICE_MANAGED
# Add AMP data source
aws grafana create-workspace-service-account \
--workspace-id g-12345678 \
--name amp-datasource \
--service-account-role ADMINSelf-Managed Prometheus and Grafana
You can also deploy self-managed Prometheus and Grafana to your EKS cluster:
- Install kube-prometheus-stack:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install monitoring prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace \
--set grafana.service.type=LoadBalancer- Access Grafana:
# Get Grafana service URL
kubectl get svc -n monitoring monitoring-grafana -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
# Get default username and password
kubectl get secret -n monitoring monitoring-grafana -o jsonpath='{.data.admin-user}' | base64 --decode
kubectl get secret -n monitoring monitoring-grafana -o jsonpath='{.data.admin-password}' | base64 --decodeKey Prometheus Metrics
Prometheus collects the following important Kubernetes metrics:
- Node metrics: CPU, memory, disk, network usage
- Pod metrics: CPU, memory usage, restart count
- Container metrics: CPU, memory usage, filesystem usage
- API server metrics: Request latency, request count, error rate
- etcd metrics: Latency, disk I/O, leader changes
Useful Grafana Dashboards
You can import the following useful dashboards in Grafana:
- Kubernetes Cluster Monitoring (ID: 15661)
- Node Exporter Full (ID: 1860)
- Kubernetes Pod Monitoring (ID: 6417)
- Kubernetes API Server (ID: 12006)
- Kubernetes Resource Requests/Limits (ID: 13770)
PromQL Query Examples
You can write useful queries using Prometheus Query Language (PromQL):
# CPU usage by node
sum(rate(node_cpu_seconds_total{mode!="idle"}[5m])) by (instance) / count(node_cpu_seconds_total{mode="idle"}) by (instance) * 100
# Memory usage by pod (top 10)
topk(10, sum(container_memory_usage_bytes{container!=""}) by (pod))
# Container restart count
sum(kube_pod_container_status_restarts_total) by (pod)
# Disk usage percentage by node
100 - ((node_filesystem_avail_bytes{mountpoint="/"} * 100) / node_filesystem_size_bytes{mountpoint="/"})Distributed Tracing with AWS X-Ray
AWS X-Ray collects data about the requests that your application processes and uses this to identify application issues and optimization opportunities.
X-Ray Setup
- Install X-Ray daemon:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: xray-daemon
namespace: default
spec:
selector:
matchLabels:
app: xray-daemon
template:
metadata:
labels:
app: xray-daemon
spec:
containers:
- name: xray-daemon
image: amazon/aws-xray-daemon:latest
ports:
- containerPort: 2000
hostPort: 2000
protocol: UDP
resources:
limits:
memory: 256Mi
requests:
memory: 256Mi
env:
- name: AWS_REGION
value: us-west-2
serviceAccountName: xray-daemon
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: xray-daemon
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: xray-daemon
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: xray-daemon
namespace: default- Integrate X-Ray SDK into your application:
Java application example:
import com.amazonaws.xray.AWSXRay;
import com.amazonaws.xray.AWSXRayRecorderBuilder;
import com.amazonaws.xray.plugins.EKSPlugin;
public class Application {
static {
AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard().withPlugin(new EKSPlugin());
AWSXRay.setGlobalRecorder(builder.build());
}
// Application code
}X-Ray Service Map
Use the X-Ray service map to visualize relationships and communication between components in your microservices architecture:
- Log in to AWS Management Console
- Navigate to X-Ray service
- Select "Service Map" from the left navigation pane
- Check latency, errors, and fault points between services
X-Ray Analysis and Insights
Use X-Ray Analytics to analyze trace data and identify performance bottlenecks:
- Navigate to X-Ray service in AWS Management Console
- Select "Analytics" from the left navigation pane
- Analyze response time distribution, error rate, and fault points
Kubernetes Dashboard
The Kubernetes Dashboard provides a web-based UI for managing cluster resources and troubleshooting issues:
Installing Kubernetes Dashboard
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
# Create service account and cluster role binding for dashboard access
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
EOF
# Generate access token
kubectl -n kubernetes-dashboard create token admin-userAccessing the Dashboard
# Start dashboard proxy
kubectl proxy
# Access the following URL in browser
# http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/Custom Metrics and Monitoring
You can implement custom solutions for collecting and monitoring application-specific metrics:
Prometheus Client Library Integration
Integrate Prometheus client libraries into your application to expose custom metrics:
Java application example:
import io.prometheus.client.Counter;
import io.prometheus.client.Histogram;
import io.prometheus.client.exporter.HTTPServer;
public class Application {
static final Counter requests = Counter.build()
.name("app_requests_total")
.help("Total requests.")
.register();
static final Histogram requestLatency = Histogram.build()
.name("app_request_latency_seconds")
.help("Request latency in seconds.")
.register();
public static void main(String[] args) throws IOException {
HTTPServer server = new HTTPServer(8080);
// Application code
}
public void processRequest() {
requests.inc();
Histogram.Timer timer = requestLatency.startTimer();
try {
// Process request
} finally {
timer.observeDuration();
}
}
}Collecting Custom Metrics
Use Prometheus ServiceMonitor to collect custom metrics:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: app-monitor
namespace: monitoring
spec:
selector:
matchLabels:
app: my-app
endpoints:
- port: metrics
interval: 15s
path: /metricsCustom Dashboards
Create custom dashboards in Grafana to visualize application metrics:
- Log in to Grafana
- Click the "+" icon and select "Dashboard"
- Click "Add panel"
- Select "Prometheus" as the data source
- Write a PromQL query (e.g.,
rate(app_requests_total[5m])) - Configure panel title, description, and visualization type
- Click "Save"
Alerting and Event Management
Effective alerting and event management are essential for rapidly detecting and responding to issues in your EKS cluster. This section explores various tools and techniques for managing alerts and events in EKS clusters.
CloudWatch Alarms
Use Amazon CloudWatch alarms to receive notifications when metrics exceed specific thresholds:
Cluster CPU Usage Alarm
aws cloudwatch put-metric-alarm \
--alarm-name "EKS-Cluster-High-CPU" \
--alarm-description "Alarm when cluster CPU exceeds 80%" \
--metric-name pod_cpu_utilization \
--namespace ContainerInsights \
--statistic Average \
--period 300 \
--threshold 80 \
--comparison-operator GreaterThanThreshold \
--dimensions Name=ClusterName,Value=my-cluster \
--evaluation-periods 2 \
--alarm-actions arn:aws:sns:us-west-2:123456789012:my-topicMemory Usage Alarm
aws cloudwatch put-metric-alarm \
--alarm-name "EKS-Cluster-High-Memory" \
--alarm-description "Alarm when cluster memory exceeds 80%" \
--metric-name pod_memory_utilization \
--namespace ContainerInsights \
--statistic Average \
--period 300 \
--threshold 80 \
--comparison-operator GreaterThanThreshold \
--dimensions Name=ClusterName,Value=my-cluster \
--evaluation-periods 2 \
--alarm-actions arn:aws:sns:us-west-2:123456789012:my-topicDisk Usage Alarm
aws cloudwatch put-metric-alarm \
--alarm-name "EKS-Node-High-Disk" \
--alarm-description "Alarm when node disk usage exceeds 85%" \
--metric-name node_filesystem_utilization \
--namespace ContainerInsights \
--statistic Maximum \
--period 300 \
--threshold 85 \
--comparison-operator GreaterThanThreshold \
--dimensions Name=ClusterName,Value=my-cluster \
--evaluation-periods 2 \
--alarm-actions arn:aws:sns:us-west-2:123456789012:my-topicPrometheus Alertmanager
Prometheus Alertmanager handles alerts generated by Prometheus and routes them to appropriate notification channels:
Alertmanager Configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: alertmanager-config
namespace: monitoring
data:
alertmanager.yml: |
global:
resolve_timeout: 5m
slack_api_url: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
route:
group_by: ['alertname', 'job']
group_wait: 30s
group_interval: 5m
repeat_interval: 12h
receiver: 'slack-notifications'
routes:
- match:
severity: critical
receiver: 'slack-notifications'
continue: true
receivers:
- name: 'slack-notifications'
slack_configs:
- channel: '#eks-alerts'
send_resolved: true
title: '[{{ .Status | toUpper }}] {{ .CommonLabels.alertname }}'
text: >-
{{ range .Alerts }}
*Alert:* {{ .Annotations.summary }}
*Description:* {{ .Annotations.description }}
*Severity:* {{ .Labels.severity }}
*Details:*
{{ range .Labels.SortedPairs }} • *{{ .Name }}:* `{{ .Value }}`
{{ end }}
{{ end }}Alert Rules Configuration
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: kubernetes-alerts
namespace: monitoring
spec:
groups:
- name: kubernetes
rules:
- alert: KubernetesPodCrashLooping
expr: rate(kube_pod_container_status_restarts_total[5m]) * 60 * 5 > 5
for: 5m
labels:
severity: critical
annotations:
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} is crash looping"
description: "Pod {{ $labels.namespace }}/{{ $labels.pod }} is restarting {{ $value }} times / 5 minutes"
- alert: KubernetesNodeMemoryPressure
expr: kube_node_status_condition{condition="MemoryPressure", status="true"} == 1
for: 5m
labels:
severity: warning
annotations:
summary: "Node {{ $labels.node }} is under memory pressure"
description: "Node {{ $labels.node }} has been under memory pressure for more than 5 minutes"
- alert: KubernetesNodeDiskPressure
expr: kube_node_status_condition{condition="DiskPressure", status="true"} == 1
for: 5m
labels:
severity: warning
annotations:
summary: "Node {{ $labels.node }} is under disk pressure"
description: "Node {{ $labels.node }} has been under disk pressure for more than 5 minutes"EventBridge Event Rules
Use Amazon EventBridge to create rules that respond to events in your EKS cluster:
EKS Cluster State Change Event Rule
aws events put-rule \
--name "EKS-Cluster-State-Change" \
--event-pattern '{
"source": ["aws.eks"],
"detail-type": ["EKS Cluster State Change"],
"detail": {
"clusterName": ["my-cluster"]
}
}'
aws events put-targets \
--rule "EKS-Cluster-State-Change" \
--targets '[
{
"Id": "1",
"Arn": "arn:aws:sns:us-west-2:123456789012:my-topic"
}
]'EKS Node Group Event Rule
aws events put-rule \
--name "EKS-NodeGroup-Events" \
--event-pattern '{
"source": ["aws.eks"],
"detail-type": ["EKS Node Group State Change"],
"detail": {
"clusterName": ["my-cluster"]
}
}'
aws events put-targets \
--rule "EKS-NodeGroup-Events" \
--targets '[
{
"Id": "1",
"Arn": "arn:aws:sns:us-west-2:123456789012:my-topic"
}
]'Kubernetes Event Monitoring
Kubernetes events provide information about important activities occurring in the cluster:
Installing Event Monitoring Tools
# Install event-exporter
kubectl apply -f https://raw.githubusercontent.com/opsgenie/kubernetes-event-exporter/master/deploy/01-cluster-role.yaml
kubectl apply -f https://raw.githubusercontent.com/opsgenie/kubernetes-event-exporter/master/deploy/02-service-account.yaml
kubectl apply -f https://raw.githubusercontent.com/opsgenie/kubernetes-event-exporter/master/deploy/03-cluster-role-binding.yamlEvent Exporter Configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: event-exporter-config
namespace: default
data:
config.yaml: |
logLevel: info
logFormat: json
route:
routes:
- match:
- type: "Warning"
receivers:
- webhook:
endpoint: "http://alertmanager:9093/api/v1/alerts"
headers:
Content-Type: application/json
- match:
- type: "Normal"
reason: "Created|Started|Killing|Scheduled|Pulled"
receivers:
- file:
path: "/tmp/normal-events.log"
receivers:
- name: "dump"
file:
path: "/tmp/all-events.log"
- name: "slack"
slack:
channel: "#kubernetes-events"
token: "xoxb-1234-1234-1234"Event Exporter Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: event-exporter
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: event-exporter
template:
metadata:
labels:
app: event-exporter
spec:
serviceAccountName: event-exporter
containers:
- name: event-exporter
image: opsgenie/kubernetes-event-exporter:latest
args:
- -conf=/etc/config/config.yaml
volumeMounts:
- name: config
mountPath: /etc/config
volumes:
- name: config
configMap:
name: event-exporter-configNotification Channel Integration
You can integrate various notification channels to deliver alerts to your team:
Slack Integration
apiVersion: v1
kind: Secret
metadata:
name: slack-webhook
namespace: monitoring
type: Opaque
stringData:
url: https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
---
apiVersion: notification.toolkit.fluxcd.io/v1beta1
kind: Provider
metadata:
name: slack
namespace: monitoring
spec:
type: slack
channel: eks-alerts
secretRef:
name: slack-webhookPagerDuty Integration
apiVersion: v1
kind: Secret
metadata:
name: pagerduty-api-key
namespace: monitoring
type: Opaque
stringData:
token: your-pagerduty-api-key
---
apiVersion: notification.toolkit.fluxcd.io/v1beta1
kind: Provider
metadata:
name: pagerduty
namespace: monitoring
spec:
type: pagerduty
serviceKey: your-pagerduty-service-key
secretRef:
name: pagerduty-api-keyEmail Integration
apiVersion: v1
kind: Secret
metadata:
name: smtp-credentials
namespace: monitoring
type: Opaque
stringData:
username: your-smtp-username
password: your-smtp-password
---
apiVersion: notification.toolkit.fluxcd.io/v1beta1
kind: Provider
metadata:
name: email
namespace: monitoring
spec:
type: smtp
server: smtp.example.com
port: "587"
from: eks-alerts@example.com
to:
- team@example.com
secretRef:
name: smtp-credentialsAlert Management and Escalation
Implement strategies for effectively managing and escalating alerts:
Alert Severity Levels
Classify alerts into the following severity levels:
- Critical: Severe issues requiring immediate action
- Warning: Issues requiring attention but not immediate action
- Info: Informational alerts
Alert Escalation Policy
Implement alert escalation policies using tools like PagerDuty:
- First Response: Alert on-call engineer
- Escalation 1: Alert backup engineer if no response after 15 minutes
- Escalation 2: Alert team lead if no response after 30 minutes
- Escalation 3: Alert manager if no response after 45 minutes
Reducing Alert Fatigue
Implement strategies to reduce alert fatigue:
- Alert Grouping: Group related alerts to reduce duplicate notifications
- Alert Filtering: Filter to deliver only important alerts
- Alert Throttling: Limit frequency of repeated alerts
- Alert Time Windows: Deliver non-business-critical alerts only during business hours
Log Analysis and Visualization
Log analysis and visualization play an important role in diagnosing and resolving issues occurring in your EKS cluster. This section explores various tools and techniques for analyzing and visualizing logs in EKS clusters.
CloudWatch Logs Insights
Use CloudWatch Logs Insights to query and analyze logs from your EKS cluster:
Container Log Query
fields @timestamp, kubernetes.pod_name, log
| filter kubernetes.namespace_name = "default"
| filter kubernetes.container_name = "app"
| filter log like /ERROR/
| sort @timestamp desc
| limit 20API Server Error Query
fields @timestamp, @message
| filter @logStream like /kube-apiserver/
| filter @message like /Error/
| sort @timestamp desc
| limit 20Authentication Failure Query
fields @timestamp, @message
| filter @logStream like /authenticator/
| filter @message like /authentication failed/
| sort @timestamp desc
| limit 20Log Pattern Analysis
fields @timestamp, @message
| parse @message "* * * [*] *" as date, time, level, component, message
| stats count(*) as count by level, component
| sort count descAmazon OpenSearch Service
Use Amazon OpenSearch Service (formerly Amazon Elasticsearch Service) to store, analyze, and visualize logs from your EKS cluster:
Creating OpenSearch Domain
aws opensearch create-domain \
--domain-name eks-logs \
--engine-version OpenSearch_1.3 \
--cluster-config InstanceType=r6g.large.search,InstanceCount=2 \
--ebs-options EBSEnabled=true,VolumeType=gp3,VolumeSize=100 \
--node-to-node-encryption-options Enabled=true \
--encryption-at-rest-options Enabled=true \
--domain-endpoint-options EnforceHTTPS=true \
--advanced-security-options Enabled=true,InternalUserDatabaseEnabled=true,MasterUserOptions='{MasterUserName=admin,MasterUserPassword=Admin123!}' \
--access-policies '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"*"},"Action":"es:*","Resource":"arn:aws:es:us-west-2:123456789012:domain/eks-logs/*"}]}'Sending Logs to OpenSearch Using Fluent Bit
apiVersion: v1
kind: ConfigMap
metadata:
name: fluent-bit-config
namespace: kube-system
data:
fluent-bit.conf: |
[SERVICE]
Flush 5
Log_Level info
Daemon off
Parsers_File parsers.conf
[INPUT]
Name tail
Tag kube.*
Path /var/log/containers/*.log
Parser docker
DB /var/log/flb_kube.db
Mem_Buf_Limit 5MB
Skip_Long_Lines On
Refresh_Interval 10
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc:443
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
Merge_Log On
K8S-Logging.Parser On
K8S-Logging.Exclude Off
[OUTPUT]
Name es
Match kube.*
Host search-eks-logs-abcdefghijklmnopqrstuvwxyz.us-west-2.es.amazonaws.com
Port 443
TLS On
AWS_Auth On
AWS_Region us-west-2
Index eks-logs
Suppress_Type_Name OnLog Visualization with OpenSearch Dashboards
Create the following visualizations in OpenSearch Dashboards:
- Log Explorer: Log search and filtering
- Dashboards: Create dashboards based on log data
- Visualizations: Create charts and graphs based on log data
- Alerts: Configure alerts based on log patterns
Grafana Loki
Grafana Loki is a log aggregation system that uses a label-based approach similar to Prometheus:
Installing Loki
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
helm install loki grafana/loki-stack \
--namespace logging \
--create-namespace \
--set grafana.enabled=true \
--set promtail.enabled=true \
--set loki.persistence.enabled=true \
--set loki.persistence.size=10GiLogQL Query Examples
# Search error logs in a specific namespace
{namespace="default"} |= "ERROR"
# Search logs for a specific pod
{namespace="default", pod=~"app-.*"} | json
# Count logs by log level
sum by (level) (count_over_time({namespace="default"} | json | level=~"info|warn|error" [5m]))Creating Grafana Dashboards
Create log dashboards in Grafana using the Loki data source:
- Log in to Grafana
- Click the "+" icon and select "Dashboard"
- Click "Add panel"
- Select "Loki" as the data source
- Write a LogQL query
- Configure panel title, description, and visualization type
- Click "Save"
AWS CloudTrail
Use AWS CloudTrail to log and analyze AWS API calls related to your EKS cluster:
Creating CloudTrail Trail
aws cloudtrail create-trail \
--name eks-api-trail \
--s3-bucket-name my-cloudtrail-bucket \
--is-multi-region-trail \
--include-global-service-events
aws cloudtrail start-logging --name eks-api-trailFiltering CloudTrail Events
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventSource,AttributeValue=eks.amazonaws.comCloudTrail Lake Query
SELECT eventTime, eventName, userIdentity.arn, requestParameters
FROM eks_events
WHERE eventSource = 'eks.amazonaws.com'
AND eventName LIKE '%Cluster%'
AND eventTime >= '2025-07-01T00:00:00Z'
AND eventTime <= '2025-07-11T23:59:59Z'
ORDER BY eventTime DESCLog Analysis Best Practices
Best practices for effectively analyzing logs from your EKS cluster:
Structured Logging
Use structured log formats (e.g., JSON) in your applications:
{
"timestamp": "2025-07-11T13:00:00Z",
"level": "INFO",
"message": "Request processed successfully",
"request_id": "12345",
"user_id": "user-789",
"duration_ms": 45,
"status_code": 200
}Correlation IDs
Use correlation IDs to track requests across distributed systems:
import org.slf4j.MDC;
public class RequestHandler {
public void handleRequest(Request request) {
String correlationId = request.getHeader("X-Correlation-ID");
if (correlationId == null) {
correlationId = UUID.randomUUID().toString();
}
MDC.put("correlation_id", correlationId);
try {
// Process request
} finally {
MDC.remove("correlation_id");
}
}
}Using Log Levels
Use appropriate log levels to indicate the importance of logs:
- ERROR: Application errors and exceptions
- WARN: Potential problems or unexpected situations
- INFO: General application events
- DEBUG: Detailed information useful for debugging
- TRACE: Very detailed debugging information
Log Retention Policy
Set log retention policies based on cost and compliance requirements:
# Set CloudWatch Logs log group retention period
aws logs put-retention-policy \
--log-group-name /aws/eks/my-cluster/cluster \
--retention-in-days 30
# Set S3 bucket lifecycle policy
aws s3api put-bucket-lifecycle-configuration \
--bucket my-logs-bucket \
--lifecycle-configuration file://lifecycle-config.jsonlifecycle-config.json:
{
"Rules": [
{
"ID": "Delete old logs",
"Status": "Enabled",
"Prefix": "logs/",
"Expiration": {
"Days": 90
}
},
{
"ID": "Archive old logs",
"Status": "Enabled",
"Prefix": "logs/",
"Transitions": [
{
"Days": 30,
"StorageClass": "STANDARD_IA"
},
{
"Days": 60,
"StorageClass": "GLACIER"
}
]
}
]
}Monitoring and Logging Best Practices
Let's explore best practices for effectively implementing monitoring and logging in EKS clusters.
Monitoring Best Practices
Multi-Layer Monitoring
Monitor all layers of your EKS cluster:
- Infrastructure Layer: EC2 instances, VPC, subnets, security groups
- Cluster Layer: Control plane, nodes, pods, services
- Application Layer: Application performance, user experience
Golden Signals Monitoring
Focus on the "4 Golden Signals" suggested in Google's SRE book:
- Latency: Time taken to process requests
- Traffic: Number of requests to the system
- Errors: Rate of failed requests
- Saturation: How "full" the system is (e.g., memory usage)
Proactive Monitoring
Implement proactive monitoring to detect issues before they occur:
- Trend Analysis: Analyze resource usage trends over time
- Anomaly Detection: Detect abnormal patterns
- Predictive Analysis: Forecast future resource requirements
Automated Scaling
Implement automated scaling based on monitoring data:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80Business Metrics Monitoring
Monitor business metrics in addition to technical metrics:
- User Activity: Number of active users, session length
- Transactions: Transaction count, transaction value
- Conversion Rate: User conversion rate, churn rate
- SLA Compliance: Whether Service Level Objectives (SLOs) are being met
Logging Best Practices
Centralized Logging
Aggregate all logs in a central location:
- Consistent Format: Use consistent log format across all applications
- Central Repository: Use central log repository like CloudWatch Logs, OpenSearch, or Loki
- Log Forwarding: Use log forwarding agents like Fluent Bit or Fluentd
Include Context Information
Include sufficient context information in logs:
- Timestamp: Accurate timestamp (ISO 8601 format recommended)
- Request ID: Unique ID for request tracking in distributed systems
- User Information: User ID or session ID (excluding personally identifiable information)
- Service Information: Service name, version, instance ID
- Error Details: Error code, error message, stack trace
Log Level Filtering
Set appropriate log levels based on environment:
- Development Environment: DEBUG or TRACE level
- Staging Environment: INFO level
- Production Environment: INFO or WARN level (DEBUG can be enabled as needed)
Protecting Sensitive Information
Protect sensitive information in logs:
- PII Masking: Mask personally identifiable information (PII)
- Exclude Credentials: Exclude credentials like passwords, tokens, API keys
- Encryption: Encrypt logs at rest and in transit
Alerting Best Practices
Alert Priority
Prioritize alerts to reduce alert fatigue:
- P1 (Critical): Severe issues requiring immediate action
- P2 (High): Important issues requiring action within business hours
- P3 (Medium): Issues requiring action during scheduled maintenance
- P4 (Low): Informational alerts
Alert Grouping
Group related alerts to reduce duplicate notifications:
route:
group_by: ['alertname', 'job', 'instance']
group_wait: 30s
group_interval: 5m
repeat_interval: 4hActionable Alerts
Include sufficient information in alerts for troubleshooting:
- Clear Title: Title that clearly describes the issue
- Detailed Description: Detailed description of the cause and impact
- Troubleshooting Steps: Steps or links for troubleshooting
- Related Metrics and Logs: Links to metrics and logs useful for diagnosis
Alert Testing
Regularly test your alerting system:
- Alert Simulation: Generate test alerts
- Escalation Testing: Test escalation paths
- Fault Injection: Inject faults in controlled environments
Cost Optimization Best Practices
Log Volume Optimization
Optimize log volume to reduce costs:
- Sampling: Sample high-volume logs
- Filtering: Filter unnecessary logs
- Compression: Compress logs
Metric Cardinality Management
Manage metric cardinality to reduce costs:
- Label Limits: Limit the number of labels used in metrics
- Aggregation: Aggregate detailed metrics to higher levels
- Sampling: Sample high-resolution metrics
Storage Tiering
Implement cost-effective storage tiering:
- Hot Storage: Recent logs and frequently accessed logs
- Warm Storage: Less frequently accessed logs
- Cold Storage: Archived logs
Troubleshooting and Debugging
Let's explore various techniques for troubleshooting and debugging issues in EKS clusters.
Cluster Troubleshooting
Checking Cluster Status
# Check cluster status
aws eks describe-cluster --name my-cluster --query "cluster.status"
# Check cluster endpoint
aws eks describe-cluster --name my-cluster --query "cluster.endpoint"
# Check cluster logs
aws eks update-cluster-config \
--name my-cluster \
--logging '{"clusterLogging":[{"types":["api","audit","authenticator","controllerManager","scheduler"],"enabled":true}]}'
# Check cluster logs in CloudWatch Logs
aws logs get-log-events \
--log-group-name /aws/eks/my-cluster/cluster \
--log-stream-name kube-apiserver-12345abcde \
--limit 10Node Troubleshooting
# Check node status
kubectl get nodes
kubectl describe node <node-name>
# Check node group status
aws eks describe-nodegroup \
--cluster-name my-cluster \
--nodegroup-name my-nodegroup
# Check node logs
aws ec2 get-console-output \
--instance-id i-1234567890abcdef0
# Access node via SSH
ssh -i ~/.ssh/my-key.pem ec2-user@<node-ip>Pod Troubleshooting
# Check pod status
kubectl get pods -A
kubectl describe pod <pod-name> -n <namespace>
# Check pod logs
kubectl logs <pod-name> -n <namespace>
kubectl logs <pod-name> -n <namespace> --previous # Logs from previous container
# Check pod events
kubectl get events -n <namespace> --sort-by='.lastTimestamp'
# Access pod shell
kubectl exec -it <pod-name> -n <namespace> -- /bin/bashNetworking Troubleshooting
Service Troubleshooting
# Check service status
kubectl get svc -A
kubectl describe svc <service-name> -n <namespace>
# Check endpoints
kubectl get endpoints <service-name> -n <namespace>
# DNS check
kubectl run -it --rm --restart=Never busybox --image=busybox:1.28 -- nslookup <service-name>.<namespace>.svc.cluster.local
# Port forwarding
kubectl port-forward svc/<service-name> 8080:80 -n <namespace>Network Policy Troubleshooting
# Check network policies
kubectl get networkpolicies -A
kubectl describe networkpolicy <policy-name> -n <namespace>
# Test network connectivity
kubectl run -it --rm --restart=Never busybox --image=busybox:1.28 -- wget -O- <service-name>.<namespace>.svc.cluster.local
# Packet capture
kubectl debug node/<node-name> -it --image=nicolaka/netshoot -- tcpdump -i any port 80Logging and Monitoring Troubleshooting
Fluent Bit Troubleshooting
# Check Fluent Bit pod status
kubectl get pods -n kube-system -l app=aws-for-fluent-bit
# Check Fluent Bit logs
kubectl logs -n kube-system -l app=aws-for-fluent-bit
# Check Fluent Bit configuration
kubectl get cm -n kube-system fluent-bit-config -o yamlPrometheus Troubleshooting
# Check Prometheus pod status
kubectl get pods -n monitoring -l app=prometheus
# Check Prometheus logs
kubectl logs -n monitoring -l app=prometheus-server
# Check Prometheus targets
kubectl port-forward -n monitoring svc/prometheus-server 9090:80
# Access http://localhost:9090/targets in browserGrafana Troubleshooting
# Check Grafana pod status
kubectl get pods -n monitoring -l app=grafana
# Check Grafana logs
kubectl logs -n monitoring -l app=grafana
# Check Grafana data sources
kubectl port-forward -n monitoring svc/grafana 3000:80
# Access http://localhost:3000/datasources in browserCommon Issues and Solutions
ImagePullBackOff Error
Issue: Pod stuck in ImagePullBackOff state
Solutions:
- Verify image name and tag are correct
- Check image pull secret for private registries
- Verify node has internet access
# Create image pull secret
kubectl create secret docker-registry regcred \
--docker-server=<registry-server> \
--docker-username=<username> \
--docker-password=<password> \
--docker-email=<email>
# Apply secret to pod
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "regcred"}]}'CrashLoopBackOff Error
Issue: Pod repeatedly restarting in CrashLoopBackOff state
Solutions:
- Check pod logs
- Check resource limits
- Check application configuration
# Check pod logs
kubectl logs <pod-name> -n <namespace>
# Check pod events
kubectl describe pod <pod-name> -n <namespace>
# Add debug container
kubectl debug <pod-name> -n <namespace> --image=busybox:1.28 --target=<container-name>Node NotReady State
Issue: Node displayed as NotReady state
Solutions:
- Check node status and events
- Check kubelet logs
- Check node resource usage
# Check node status
kubectl describe node <node-name>
# Access node via SSH
ssh -i ~/.ssh/my-key.pem ec2-user@<node-ip>
# Check kubelet logs
sudo journalctl -u kubelet
# Check node resource usage
top
df -hService Connection Issues
Issue: Unable to connect to service
Solutions:
- Check service and endpoints
- Check pod labels and selectors
- Check network policies
# Check service and endpoints
kubectl get svc <service-name> -n <namespace>
kubectl get endpoints <service-name> -n <namespace>
# Check pod labels
kubectl get pods -n <namespace> --show-labels
# Check service selector
kubectl get svc <service-name> -n <namespace> -o jsonpath='{.spec.selector}'
# Check network policies
kubectl get networkpolicies -n <namespace>Debugging Tools
kubectl Debugging Tools
# Pod debugging
kubectl debug <pod-name> -n <namespace> --image=busybox:1.28 --target=<container-name>
# Node debugging
kubectl debug node/<node-name> -it --image=busybox:1.28
# Create temporary debugging pod
kubectl run debug --rm -it --image=nicolaka/netshoot -- /bin/bashAWS CLI Debugging Tools
# Describe EKS cluster
aws eks describe-cluster --name my-cluster
# Describe EKS node group
aws eks describe-nodegroup --cluster-name my-cluster --nodegroup-name my-nodegroup
# CloudWatch Logs query
aws logs start-query \
--log-group-name /aws/eks/my-cluster/cluster \
--start-time $(date -u -v-1H +%s) \
--end-time $(date -u +%s) \
--query-string 'fields @timestamp, @message | filter @message like /Error/'Network Debugging Tools
# Create network debugging pod
kubectl run netshoot --rm -it --image=nicolaka/netshoot -- /bin/bash
# Test network connectivity
nc -zv <service-name> <port>
curl -v <service-name>:<port>
# DNS check
dig <service-name>.<namespace>.svc.cluster.local
# Packet capture
tcpdump -i any port <port> -w capture.pcapConclusion
In this document, we explored various tools, techniques, and best practices for monitoring and logging in Amazon EKS clusters. Implementing an effective monitoring and logging strategy allows you to continuously understand the state of your cluster, detect issues early, and respond quickly when problems occur.
Key topics covered:
- Monitoring and Logging Overview: Importance and architecture of monitoring and logging
- EKS Control Plane Logging: Control plane log types and how to enable them
- Container Logging: Container log collection using Fluent Bit and CloudWatch Container Insights
- Cluster Monitoring: Cluster monitoring using CloudWatch, Prometheus, and Grafana
- Alerting and Event Management: Alert configuration using CloudWatch alarms and Prometheus Alertmanager
- Log Analysis and Visualization: Log analysis using CloudWatch Logs Insights, OpenSearch, and Grafana Loki
- Monitoring and Logging Best Practices: Best practices for effective monitoring and logging
- Troubleshooting and Debugging: Common issues and solutions
Monitoring and logging in EKS clusters is an ongoing process that should be continuously improved to meet the requirements of your cluster and applications.
References
- Amazon EKS Monitoring Best Practices
- Amazon EKS Logging Best Practices
- Kubernetes Monitoring Architecture
- Prometheus Documentation
- Grafana Documentation
- Fluent Bit Documentation
- Amazon CloudWatch Documentation
- Amazon OpenSearch Service Documentation
Quiz
To test what you learned in this chapter, try the topic quiz.