Terraform-Driven Observability Stack for AWS EKS: Datadog and PagerDuty Integration
Terraform-Driven Observability Stack for AWS EKS: Datadog and PagerDuty Integration
In the dynamic landscape of cloud-native applications, maintaining robust observability is paramount for ensuring high availability and optimal performance. For organizations leveraging AWS EKS (Elastic Kubernetes Service), a powerful and scalable Kubernetes platform, integrating a comprehensive observability stack is non-negotiable. This technical guide will walk you through building a Terraform-driven observability solution for your AWS EKS clusters, combining the deep monitoring capabilities of Datadog with the critical incident management prowess of PagerDuty.
Architecture Pro-Tip: Always treat your observability stack as infrastructure-as-code (IaC). This approach ensures consistency, version control, and auditability for your monitoring and alerting configurations, just like your core application infrastructure. Decouple environment-specific variables (API keys, region) into a separate terraform.tfvars or environment variables for secure and flexible deployments across dev, staging, and production.
Why Terraform for Observability?
Terraform, HashiCorp's popular infrastructure-as-code tool, allows you to define and provision cloud and on-prem resources in human-readable configuration files that you can version, reuse, and share. Applying Terraform to your observability stack offers several compelling advantages:
- Automation: Automate the deployment and configuration of Datadog agents, monitors, dashboards, PagerDuty services, escalation policies, and integrations.
- Consistency: Ensure uniform monitoring and alerting configurations across multiple EKS clusters and environments.
- Version Control: Track changes to your observability setup in Git, enabling easy rollbacks and collaboration.
- Auditability: Maintain a clear, auditable record of who changed what and when in your monitoring infrastructure.
- Scalability: Effortlessly scale your observability components as your EKS footprint grows.
Prerequisites
Before diving into the configuration, ensure you have the following:
- An active AWS account with an existing EKS cluster.
- Terraform installed (version 1.0+ recommended).
- AWS CLI configured with appropriate permissions to interact with EKS and IAM.
- A Datadog account with API and Application Keys.
- A PagerDuty account with an API Key.
- Familiarity with Kubernetes concepts (Pods, Deployments, Services, Helm).
Core Components: Datadog and PagerDuty
Datadog: Comprehensive EKS Monitoring
Datadog provides end-to-end visibility across your entire EKS environment. It collects metrics, logs, and traces from your cluster nodes, containers, applications, and AWS services, offering unified dashboards, advanced analytics, and powerful alerting capabilities. Key features for EKS include:
- Kubernetes integration for cluster and pod metrics.
- APM for distributed tracing of microservices.
- Log management and analytics.
- Real User Monitoring (RUM) and Synthetic Monitoring.
- Powerful anomaly detection and forecasting.
PagerDuty: Incident Management and On-Call Automation
PagerDuty is a leading incident management platform that transforms Datadog alerts into actionable incidents. It streamlines the entire incident lifecycle, from initial notification to resolution, ensuring that critical issues are addressed promptly by the right team members. Benefits include:
- Automated incident creation and routing.
- On-call scheduling and escalation policies.
- Real-time alerting via multiple channels (SMS, phone, email, push notifications).
- Post-incident analysis and reporting.
Architectural Overview
Our architecture involves:
- AWS EKS Cluster: The foundation hosting our containerized applications.
- Datadog Agent: Deployed as a DaemonSet and Cluster Agent within EKS, collecting metrics, logs, and traces.
- Datadog Monitors: Terraform-defined rules that trigger alerts based on specific EKS or application metrics thresholds.
- PagerDuty Service: A dedicated service in PagerDuty, managed by Terraform, which receives incidents from Datadog.
- PagerDuty Escalation Policy: Defines the on-call rotation and escalation path for incidents related to the EKS cluster.
- Terraform: Orchestrates the deployment of Datadog Agents via Helm, configures Datadog monitors, and sets up PagerDuty services and integrations.
Step-by-Step Implementation with Terraform
1. AWS EKS Cluster Setup
For this guide, we assume you have an existing AWS EKS cluster. If not, you can use Terraform to provision one. The output of your EKS cluster module (e.g., cluster_id, kubeconfig_filepath) will be crucial for the Kubernetes provider.
2. Datadog API and Application Key Setup
Log into your Datadog account and navigate to Organization Settings > API Keys to retrieve or generate:
- Datadog API Key: Used by the Datadog Agent to send data.
- Datadog Application Key: Used by the Terraform Datadog provider to manage resources.
Store these securely, preferably as environment variables or using a secrets manager like AWS Secrets Manager.
3. PagerDuty Service and Integration Key Setup
Log into your PagerDuty account:
- Navigate to Integrations > API Keys to generate a PagerDuty API Key.
- Note your PagerDuty Subdomain (e.g.,
yourcompanyfromyourcompany.pagerduty.com).
These will be used by the Terraform PagerDuty provider.
4. Terraform Project Structure
A recommended project structure for clarity:
.
├── main.tf
├── variables.tf
├── providers.tf
├── datadog.tf
├── pagerduty.tf
└── outputs.tf
5. Terraform Configuration for Datadog
5.1. Datadog Provider Configuration
Configure the Datadog provider using your API and Application keys. It's best practice to use environment variables for sensitive credentials.
# providers.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = "~> 2.23"
}
helm = {
source = "hashicorp/helm"
version = "~> 2.11"
}
datadog = {
source = "DataDog/datadog"
version = "~> 3.0"
}
pagerduty = {
source = "PagerDuty/pagerduty"
version = "~> 2.0"
}
}
}
provider aws {
region = "us-east-1" # Replace with your AWS region
}
data aws_eks_cluster example {
name = "your-eks-cluster-name" # Replace with your EKS cluster name
}
data aws_eks_cluster_auth example {
name = "your-eks-cluster-name"
}
provider kubernetes {
host = data.aws_eks_cluster.example.endpoint
token = data.aws_eks_cluster_auth.example.token
cluster_ca_certificate = base64decode(data.aws_eks_cluster.example.certificate_authority.0.data)
}
provider helm {
kubernetes {
host = data.aws_eks_cluster.example.endpoint
token = data.aws_eks_cluster_auth.example.token
cluster_ca_certificate = base64decode(data.aws_eks_cluster.example.certificate_authority.0.data)
}
}
provider datadog {
# Configure DATADOG_API_KEY and DATADOG_APP_KEY as environment variables
# api_key = var.datadog_api_key
# app_key = var.datadog_app_key
}
5.2. Deploying Datadog Agent to EKS
The Datadog Agent is best deployed using its official Helm chart. This Terraform configuration ensures the agent is installed and configured with your Datadog API key.
# datadog.tf
resource helm_release datadog_agent {
name = "datadog"
repository = "https://helm.datadoghq.com"
chart = "datadog"
namespace = "datadog"
create_namespace = true
version = "3.x.x" # Use the latest stable version
set {
name = "datadog.apiKey"
value = var.datadog_api_key
sensitive = true
}
set {
name = "datadog.appKey"
value = var.datadog_app_key
sensitive = true
}
set {
name = "datadog.site"
value = "datadoghq.com" # Or datadog.eu, etc.
}
set {
name = "clusterAgent.enabled"
value = "true"
}
set {
name = "clusterChecksRunner.enabled"
value = "true"
}
set {
name = "kubeStateMetrics.enabled"
value = "true"
}
set {
name = "logCollection.enabled"
value = "true"
}
set {
name = "apm.enabled"
value = "true"
}
set {
name = "processAgent.enabled"
value = "true"
}
set {
name = "systemProbe.enabled"
value = "true"
}
set {
name = "securityAgent.runtime.enabled"
value = "true"
}
}
5.3. Configuring Datadog Monitors
Define Datadog monitors as Terraform resources. Here’s an example for CPU utilization for EKS nodes.
# datadog.tf
resource datadog_monitor eks_node_cpu_utilization {
name = "[EKS] High Node CPU Utilization on {{host.name}}"
type = "metric alert"
query = "avg(last_5m):avg:system.cpu.idle{kubernetes_cluster_name:your-eks-cluster-name} by {host} < 10"
message = "CPU utilization on EKS node {{host.name}} is {{value}}% idle, which is too high. Investigate immediately."
tags = ["environment:production", "service:eks", "team:devops"]
escalation_message = "CPU remains high on {{host.name}}. Escalating to on-call."
priority = 1
monitor_thresholds {
critical = 10 # Less than 10% idle means >90% utilization
warning = 20 # Less than 20% idle means >80% utilization
}
notify_no_data = false
notify_audit = false
timeout_h = 0
require_full_window = false
}
resource datadog_monitor eks_pod_restarts {
name = "[EKS] High Pod Restarts in {{kube_container_name}} in namespace {{kube_namespace}}"
type = "metric alert"
query = "sum(last_5m):sum:kubernetes.container.restarts{kubernetes_cluster_name:your-eks-cluster-name} by {kube_container_name,kube_namespace} > 3"
message = "Pod restarts detected for {{kube_container_name}} in {{kube_namespace}}. Investigate application stability."
tags = ["environment:production", "service:eks", "team:devops"]
priority = 2
monitor_thresholds {
critical = 3
}
}
Remember to replace your-eks-cluster-name with your actual cluster name and adjust queries/thresholds as needed.
6. Terraform Configuration for PagerDuty
6.1. PagerDuty Provider Configuration
Configure the PagerDuty provider using your API key and subdomain.
# providers.tf (continued)
provider pagerduty {
# Configure PAGERDUTY_TOKEN as an environment variable
# token = var.pagerduty_api_key
subdomain = var.pagerduty_subdomain
}
6.2. Creating PagerDuty Service and Integration
Define a PagerDuty service, an escalation policy, and a Datadog integration for that service. This ensures that alerts from Datadog are routed correctly.
# pagerduty.tf
resource pagerduty_escalation_policy eks_ops_policy {
name = "EKS Operations Escalation Policy"
num_loops = 2
rule {
delay_in_minutes = 5
target {
type = "user"
id = "PXXXXXXXX" # Replace with your PagerDuty User ID or Team ID
}
}
# Add more rules for escalation if needed (e.g., another user, a team, or a schedule)
}
resource pagerduty_service eks_monitoring_service {
name = "AWS EKS Cluster Monitoring"
auto_resolve_timeout = 14400 # 4 hours
acknowledgement_timeout = 600 # 10 minutes
escalation_policy = pagerduty_escalation_policy.eks_ops_policy.id
}
resource pagerduty_service_integration datadog_integration {
name = "Datadog Integration"
service = pagerduty_service.eks_monitoring_service.id
type = "datadog_api_inbound_integration"
}
Make sure to replace PXXXXXXXX with a valid PagerDuty user ID. You can find this in the PagerDuty UI under a user's profile URL or by using the PagerDuty API.
7. Connecting Datadog Monitors to PagerDuty
To send alerts from Datadog to PagerDuty, update your Datadog monitor resources to include the PagerDuty service integration. You will need the integration_key from the PagerDuty service integration created above.
# datadog.tf (continued)
resource datadog_monitor eks_node_cpu_utilization {
name = "[EKS] High Node CPU Utilization on {{host.name}}"
type = "metric alert"
query = "avg(last_5m):avg:system.cpu.idle{kubernetes_cluster_name:your-eks-cluster-name} by {host} < 10"
message = "CPU utilization on EKS node {{host.name}} is {{value}}% idle, which is too high. Investigate immediately. @pagerduty-eks-monitoring" # Integration syntax
tags = ["environment:production", "service:eks", "team:devops"]
escalation_message = "CPU remains high on {{host.name}}. Escalating to on-call. @pagerduty-eks-monitoring"
priority = 1
monitor_thresholds {
critical = 10
warning = 20
}
notify_no_data = false
notify_audit = false
timeout_h = 0
require_full_window = false
# This block is crucial for PagerDuty integration via the API key
renotify_interval = 30 # Minutes
renotify_occurrences = 2
renotify_statuses = ["alert", "no data"]
# The actual Datadog-PagerDuty integration happens via this syntax in the message.
# The pagerduty_service_integration resource does not directly link to datadog_monitor in Terraform.
# Instead, Datadog resolves the "@pagerduty-eks-monitoring" string to the configured integration.
# You need to manually configure the integration name in Datadog UI under Integrations -> PagerDuty,
# matching the integration_key from the PagerDuty service integration resource.
# You would give it a "Custom Name" like "eks-monitoring".
Important: The @pagerduty-eks-monitoring tag in the Datadog monitor message refers to a named PagerDuty integration configured within Datadog itself. You must create this integration in the Datadog UI (Integrations -> PagerDuty) and use the integration_key output from your pagerduty_service_integration resource. The name you give it in the Datadog UI (e.g., "eks-monitoring") is what you use after @pagerduty- in the monitor message.
8. Deploying the Stack
With your Terraform configuration complete, initialize your backend, review the plan, and apply your changes.
export DATADOG_API_KEY="<YOUR_DATADOG_API_KEY>"
export DATADOG_APP_KEY="<YOUR_DATADOG_APPLICATION_KEY>"
export PAGERDUTY_TOKEN="<YOUR_PAGERDUTY_API_KEY>"
export TF_VAR_datadog_api_key="<YOUR_DATADOG_API_KEY>"
export TF_VAR_datadog_app_key="<YOUR_DATADOG_APPLICATION_KEY>"
export TF_VAR_pagerduty_api_key="<YOUR_PAGERDUTY_API_KEY>"
export TF_VAR_pagerduty_subdomain="<YOUR_PAGERDUTY_SUBDOMAIN>"
terraform init
terraform plan
terraform apply
Testing and Validation
After applying your Terraform configuration:
- Datadog Agent: Verify the Datadog Agent pods are running correctly in your EKS cluster (
kubectl get pods -n datadog). Check the Datadog UI under Infrastructure > Host Map to see your EKS nodes and containers. - Datadog Monitors: Navigate to Monitors > Manage Monitors in Datadog to ensure your Terraform-defined monitors are listed and active.
- PagerDuty Service: In PagerDuty, confirm that the "AWS EKS Cluster Monitoring" service and its Datadog integration exist.
- Trigger an Alert: For testing, you can temporarily lower a monitor's threshold or intentionally create a condition that triggers an alert (e.g., scale down a deployment to cause high CPU on remaining pods). Observe if an incident is created in PagerDuty.
Best Practices and Advanced Considerations
- Secrets Management: Avoid hardcoding API keys. Use a secrets manager like AWS Secrets Manager or HashiCorp Vault, and fetch values dynamically in Terraform.
- Module Reusability: Encapsulate common Datadog monitor patterns and PagerDuty service definitions into reusable Terraform modules.
- Custom Dashboards: While not covered here, Terraform can also define Datadog dashboards for a comprehensive IaC approach to observability.
- Service Discovery: Leverage Datadog's autodiscovery for Kubernetes to automatically collect metrics and logs from new services deployed to EKS.
- Advanced Alerting: Explore Datadog's composite monitors, anomaly detection, and forecasting for more sophisticated alerting logic.
- Incident Response Playbooks: For each PagerDuty service, attach detailed runbooks or playbooks to guide responders through incident resolution.
- Cost Management: Monitor your Datadog usage, especially for logs and custom metrics, to manage costs effectively.
Conclusion
By adopting a Terraform-driven approach, you can establish a robust, automated, and auditable observability stack for your AWS EKS environment using Datadog and PagerDuty. This integration ensures that your EKS clusters are not only meticulously monitored but that critical incidents are also promptly triaged and resolved, significantly enhancing your operational resilience and allowing your DevOps teams to focus on innovation rather than manual configurations. Embrace Infrastructure as Code for your observability, and empower your teams with predictable, reliable insights.
Comments
Post a Comment