diff --git a/modules/add-ons/adot-collector-nginx/README.md b/modules/add-ons/adot-collector-nginx/README.md new file mode 100644 index 0000000..f2aac70 --- /dev/null +++ b/modules/add-ons/adot-collector-nginx/README.md @@ -0,0 +1,49 @@ +# Observability Pattern for Nginx + +This module provides an automated experience around Observability for Nginx workloads. +It provides the following resources: + +- AWS Distro For OpenTelemetry Operator and Collector +- AWS Managed Grafana Dashboard and data source +- Alerts and recording rules with AWS Managed Service for Prometheus + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [aws](#requirement\_aws) | >= 3.72 | +| [kubernetes](#requirement\_kubernetes) | >= 2.10 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 3.72 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [helm\_addon](#module\_helm\_addon) | ../helm-addon | n/a | + +## Resources + +| Name | Type | +|------|------| +| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [addon\_context](#input\_addon\_context) | Input configuration for the addon |
object({
aws_caller_identity_account_id = string
aws_caller_identity_arn = string
aws_eks_cluster_endpoint = string
aws_partition_id = string
aws_region_name = string
eks_cluster_id = string
eks_oidc_issuer_url = string
eks_oidc_provider_arn = string
irsa_iam_permissions_boundary = string
irsa_iam_role_path = string
tags = map(string)
}) | n/a | yes |
+| [amazon\_prometheus\_workspace\_endpoint](#input\_amazon\_prometheus\_workspace\_endpoint) | Amazon Managed Prometheus Workspace Endpoint | `string` | `null` | no |
+| [amazon\_prometheus\_workspace\_region](#input\_amazon\_prometheus\_workspace\_region) | Amazon Managed Prometheus Workspace's Region | `string` | `null` | no |
+| [helm\_config](#input\_helm\_config) | Helm Config for Prometheus | `any` | `{}` | no |
+
+## Outputs
+
+No outputs.
+
diff --git a/modules/add-ons/adot-collector-nginx/main.tf b/modules/add-ons/adot-collector-nginx/main.tf
new file mode 100644
index 0000000..d9f1ff6
--- /dev/null
+++ b/modules/add-ons/adot-collector-nginx/main.tf
@@ -0,0 +1,62 @@
+locals {
+ name = "adot-collector-nginx"
+ namespace = try(var.helm_config.namespace, local.name)
+}
+
+data "aws_partition" "current" {}
+
+module "helm_addon" {
+ source = "../helm-addon"
+
+ helm_config = merge(
+ {
+ name = local.name
+ chart = "${path.module}/otel-config"
+ version = "0.2.0"
+ namespace = local.namespace
+ description = "ADOT helm Chart deployment configuration"
+ },
+ var.helm_config
+ )
+
+ set_values = [
+ {
+ name = "ampurl"
+ value = "${var.amazon_prometheus_workspace_endpoint}api/v1/remote_write"
+ },
+ {
+ name = "region"
+ value = var.amazon_prometheus_workspace_region
+ },
+ {
+ name = "prometheusMetricsEndpoint"
+ value = "metrics"
+ },
+ {
+ name = "prometheusMetricsPort"
+ value = 8888
+ },
+ {
+ name = "scrapeInterval"
+ value = "15s"
+ },
+ {
+ name = "scrapeTimeout"
+ value = "10s"
+ },
+ {
+ name = "scrapeSampleLimit"
+ value = 1000
+ }
+ ]
+
+ irsa_config = {
+ create_kubernetes_namespace = try(var.helm_config["create_namespace"], true)
+ kubernetes_namespace = local.namespace
+ create_kubernetes_service_account = true
+ kubernetes_service_account = try(var.helm_config.service_account, local.name)
+ irsa_iam_policies = ["arn:${data.aws_partition.current.partition}:iam::aws:policy/AmazonPrometheusRemoteWriteAccess"]
+ }
+
+ addon_context = var.addon_context
+}
diff --git a/modules/add-ons/adot-collector-nginx/outputs.tf b/modules/add-ons/adot-collector-nginx/outputs.tf
new file mode 100644
index 0000000..e69de29
diff --git a/modules/add-ons/adot-collector-nginx/variables.tf b/modules/add-ons/adot-collector-nginx/variables.tf
new file mode 100644
index 0000000..b7d13c3
--- /dev/null
+++ b/modules/add-ons/adot-collector-nginx/variables.tf
@@ -0,0 +1,34 @@
+variable "helm_config" {
+ description = "Helm Config for Prometheus"
+ type = any
+ default = {}
+}
+
+variable "amazon_prometheus_workspace_endpoint" {
+ description = "Amazon Managed Prometheus Workspace Endpoint"
+ type = string
+ default = null
+}
+
+variable "amazon_prometheus_workspace_region" {
+ description = "Amazon Managed Prometheus Workspace's Region"
+ type = string
+ default = null
+}
+
+variable "addon_context" {
+ description = "Input configuration for the addon"
+ type = object({
+ aws_caller_identity_account_id = string
+ aws_caller_identity_arn = string
+ aws_eks_cluster_endpoint = string
+ aws_partition_id = string
+ aws_region_name = string
+ eks_cluster_id = string
+ eks_oidc_issuer_url = string
+ eks_oidc_provider_arn = string
+ irsa_iam_permissions_boundary = string
+ irsa_iam_role_path = string
+ tags = map(string)
+ })
+}
diff --git a/modules/add-ons/adot-collector-nginx/versions.tf b/modules/add-ons/adot-collector-nginx/versions.tf
new file mode 100644
index 0000000..d2ddf87
--- /dev/null
+++ b/modules/add-ons/adot-collector-nginx/versions.tf
@@ -0,0 +1,14 @@
+terraform {
+ required_version = ">= 1.0.0"
+
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 3.72"
+ }
+ kubernetes = {
+ source = "hashicorp/kubernetes"
+ version = ">= 2.10"
+ }
+ }
+}
diff --git a/modules/workloads/nginx/otel-config/Chart.yaml b/modules/workloads/nginx/otel-config/Chart.yaml
new file mode 100644
index 0000000..94c1fbd
--- /dev/null
+++ b/modules/workloads/nginx/otel-config/Chart.yaml
@@ -0,0 +1,6 @@
+apiVersion: v2
+name: opentelemetry
+description: A Helm chart to install otel operator
+type: application
+version: 0.2.0
+appVersion: v0.1.0
diff --git a/modules/workloads/nginx/otel-config/templates/clusterrole.yaml b/modules/workloads/nginx/otel-config/templates/clusterrole.yaml
new file mode 100644
index 0000000..4bb1fb7
--- /dev/null
+++ b/modules/workloads/nginx/otel-config/templates/clusterrole.yaml
@@ -0,0 +1,29 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: otel-prometheus-role
+rules:
+ - apiGroups:
+ - ""
+ resources:
+ - nodes
+ - nodes/proxy
+ - services
+ - endpoints
+ - pods
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - extensions
+ resources:
+ - ingresses
+ verbs:
+ - get
+ - list
+ - watch
+ - nonResourceURLs:
+ - /metrics
+ verbs:
+ - get
diff --git a/modules/workloads/nginx/otel-config/templates/clusterrolebinding.yaml b/modules/workloads/nginx/otel-config/templates/clusterrolebinding.yaml
new file mode 100644
index 0000000..7bd8168
--- /dev/null
+++ b/modules/workloads/nginx/otel-config/templates/clusterrolebinding.yaml
@@ -0,0 +1,12 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: otel-prometheus-role-binding
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: otel-prometheus-role
+subjects:
+ - kind: ServiceAccount
+ name: adot-collector-nginx
+ namespace: adot-collector-nginx
diff --git a/modules/workloads/nginx/otel-config/templates/opentelemetrycollector.yaml b/modules/workloads/nginx/otel-config/templates/opentelemetrycollector.yaml
new file mode 100644
index 0000000..aaefbdd
--- /dev/null
+++ b/modules/workloads/nginx/otel-config/templates/opentelemetrycollector.yaml
@@ -0,0 +1,67 @@
+apiVersion: opentelemetry.io/v1alpha1
+kind: OpenTelemetryCollector
+metadata:
+ name: adot
+spec:
+ image: public.ecr.aws/aws-observability/aws-otel-collector:latest
+ mode: deployment
+ serviceAccount: adot-collector-nginx
+ config: |
+ receivers:
+ prometheus:
+ config:
+ global:
+ scrape_interval: {{ .Values.scrapeInterval }}
+ scrape_timeout: {{ .Values.scrapeTimeout }}
+
+ scrape_configs:
+ - job_name: 'kubernetes-pod-nginx'
+ sample_limit: {{ .Values.scrapeSampleLimit }}
+ metrics_path: /{{ .Values.prometheusMetricsEndpoint }}
+ kubernetes_sd_configs:
+ - role: pod
+ relabel_configs:
+ - source_labels: [ __address__ ]
+ action: keep
+ regex: '.*:9404$'
+ - action: labelmap
+ regex: __meta_kubernetes_pod_label_(.+)
+ - action: replace
+ source_labels: [ __meta_kubernetes_namespace ]
+ target_label: Namespace
+ - source_labels: [ __meta_kubernetes_pod_name ]
+ action: replace
+ target_label: pod_name
+ - action: replace
+ source_labels: [ __meta_kubernetes_pod_container_name ]
+ target_label: container_name
+ - action: replace
+ source_labels: [ __meta_kubernetes_pod_controller_kind ]
+ target_label: pod_controller_kind
+ - action: replace
+ source_labels: [ __meta_kubernetes_pod_phase ]
+ target_label: pod_controller_phase
+ metric_relabel_configs:
+ - source_labels: [ __name__ ]
+ regex: 'jvm_gc_collection_seconds.*'
+ action: drop
+ exporters:
+ awsprometheusremotewrite:
+ endpoint: {{ .Values.ampurl }}
+ aws_auth:
+ region: {{ .Values.region }}
+ service: "aps"
+ logging:
+ loglevel: info
+ extensions:
+ health_check:
+ pprof:
+ endpoint: :1888
+ zpages:
+ endpoint: :55679
+ service:
+ extensions: [pprof, zpages, health_check]
+ pipelines:
+ metrics:
+ receivers: [prometheus]
+ exporters: [logging, awsprometheusremotewrite]
diff --git a/modules/workloads/nginx/otel-config/values.yaml b/modules/workloads/nginx/otel-config/values.yaml
new file mode 100644
index 0000000..f3517b2
--- /dev/null
+++ b/modules/workloads/nginx/otel-config/values.yaml
@@ -0,0 +1,7 @@
+ampurl: ${amp_url}
+region: ${region}
+prometheusMetricsEndpoint: ${prometheus_metrics_endpoint}
+prometheusMetricsPort: ${prometheus_metrics_port}
+scrapeInterval: ${scrape_interval}
+scrapeTimeout: ${scrape_timeout}
+scrapeSampleLimit: ${scrape_sample_limit}