-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add EKS integration testing for APM Traces #327
Changes from 2 commits
53295cc
88a63c1
ff6e726
099d960
1af68f8
e942c2c
ddfaa4f
11e2a50
df63334
31f005d
0aabd78
f92f866
ee1a465
e309dab
da2f6e7
f0b6d7c
9f55f2e
74a90ae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -56,7 +56,8 @@ resource "aws_eks_node_group" "this" { | |||||||||||||||||
aws_iam_role_policy_attachment.node_AmazonEC2ContainerRegistryReadOnly, | ||||||||||||||||||
aws_iam_role_policy_attachment.node_AmazonEKS_CNI_Policy, | ||||||||||||||||||
aws_iam_role_policy_attachment.node_AmazonEKSWorkerNodePolicy, | ||||||||||||||||||
aws_iam_role_policy_attachment.node_CloudWatchAgentServerPolicy | ||||||||||||||||||
aws_iam_role_policy_attachment.node_CloudWatchAgentServerPolicy, | ||||||||||||||||||
aws_iam_role_policy_attachment.node_AWSXRayDaemonWriteAccess | ||||||||||||||||||
] | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
|
@@ -99,6 +100,10 @@ resource "aws_iam_role_policy_attachment" "node_CloudWatchAgentServerPolicy" { | |||||||||||||||||
policy_arn = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy" | ||||||||||||||||||
role = aws_iam_role.node_role.name | ||||||||||||||||||
} | ||||||||||||||||||
resource "aws_iam_role_policy_attachment" "node_AWSXRayDaemonWriteAccess" { | ||||||||||||||||||
policy_arn = "arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess" | ||||||||||||||||||
role = aws_iam_role.node_role.name | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
# TODO: these security groups be created once and then reused | ||||||||||||||||||
# EKS Cluster Security Group | ||||||||||||||||||
|
@@ -321,22 +326,22 @@ resource "kubernetes_daemonset" "service" { | |||||||||||||||||
|
||||||||||||||||||
container { | ||||||||||||||||||
name = "apm-client" | ||||||||||||||||||
image = "public.ecr.aws/amazonlinux/amazonlinux:latest" | ||||||||||||||||||
image = "public.ecr.aws/docker/library/golang:latest" | ||||||||||||||||||
image_pull_policy = "Always" | ||||||||||||||||||
resources { | ||||||||||||||||||
limits = { | ||||||||||||||||||
"cpu" : "50m", | ||||||||||||||||||
"memory" : "50Mi" | ||||||||||||||||||
"memory" : "300Mi" | ||||||||||||||||||
} | ||||||||||||||||||
requests = { | ||||||||||||||||||
"cpu" : "50m", | ||||||||||||||||||
"memory" : "50Mi" | ||||||||||||||||||
"memory" : "300Mi" | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
command = [ | ||||||||||||||||||
"/bin/sh", | ||||||||||||||||||
"-c", | ||||||||||||||||||
"while true; do echo '${data.template_file.server_consumer.rendered}' | sed -e \"s/START_TIME/$(date +%s%N)/\" > server_consumer.json; curl -H 'Content-Type: application/json' -d @server_consumer.json -i http://127.0.0.1:4318/v1/metrics --verbose --http0.9; echo '${data.template_file.client_producer.rendered}' | sed -e \"s/START_TIME/$(date +%s%N)/\" > client_producer.json; curl -H 'Content-Type: application/json' -d @client_producer.json -i http://127.0.0.1:4318/v1/metrics --verbose --http0.9; sleep 1; done" | ||||||||||||||||||
"while true; echo '${data.template_file.traceid_generator.rendered}' > traceid_generator.go && chmod +x traceid_generator.go; export START_TIME=$(date +%s%N); export TRACE_ID=$(go run ./traceid_generator.go); do echo '${data.template_file.server_consumer.rendered}' | sed -e \"s/START_TIME/$START_TIME/\" > server_consumer.json; curl -H 'Content-Type: application/json' -d @server_consumer.json -i http://127.0.0.1:4318/v1/metrics --verbose; echo '${data.template_file.client_producer.rendered}' | sed -e \"s/START_TIME/$START_TIME/\" > client_producer.json; curl -H 'Content-Type: application/json' -d @client_producer.json -i http://127.0.0.1:4318/v1/metrics --verbose; echo '${data.template_file.traces.rendered}' | sed -e \"s/START_TIME/$START_TIME/\" | sed -e \"s/TRACE_ID/$TRACE_ID/\" > traces.json; curl -H 'Content-Type: application/json' -d @traces.json -i http://127.0.0.1:4318/v1/traces --verbose; sleep 1; done" | ||||||||||||||||||
] | ||||||||||||||||||
env { | ||||||||||||||||||
name = "HOST_IP" | ||||||||||||||||||
|
@@ -378,9 +383,11 @@ resource "kubernetes_daemonset" "service" { | |||||||||||||||||
# Template Files | ||||||||||||||||||
########################################## | ||||||||||||||||||
locals { | ||||||||||||||||||
cwagent_config = "../../../../${var.test_dir}/resources/config.json" | ||||||||||||||||||
server_consumer = "../../../../${var.test_dir}/resources/server_consumer.json" | ||||||||||||||||||
client_producer = "../../../../${var.test_dir}/resources/client_producer.json" | ||||||||||||||||||
cwagent_config = "../../../../${var.test_dir}/resources/config.json" | ||||||||||||||||||
server_consumer = "../../../../${var.test_dir}/resources/metrics/server_consumer.json" | ||||||||||||||||||
client_producer = "../../../../${var.test_dir}/resources/metrics/client_producer.json" | ||||||||||||||||||
traces = "../../../../${var.test_dir}/resources/traces/traces.json" | ||||||||||||||||||
traceid_generator = "../../../../${var.test_dir}/resources/traceid_generator.go" | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
data "template_file" "cwagent_config" { | ||||||||||||||||||
|
@@ -415,6 +422,18 @@ data "template_file" "client_producer" { | |||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
data "template_file" "traces" { | ||||||||||||||||||
template = file(local.traces) | ||||||||||||||||||
vars = { | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
Comment on lines
+425
to
+429
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Use local_file instead of template_file if it isn't templating anything.
Suggested change
|
||||||||||||||||||
|
||||||||||||||||||
data "template_file" "traceid_generator" { | ||||||||||||||||||
template = file(local.traceid_generator) | ||||||||||||||||||
vars = { | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
resource "kubernetes_service_account" "cwagentservice" { | ||||||||||||||||||
depends_on = [kubernetes_namespace.namespace] | ||||||||||||||||||
metadata { | ||||||||||||||||||
|
@@ -487,9 +506,9 @@ resource "null_resource" "validator" { | |||||||||||||||||
] | ||||||||||||||||||
provisioner "local-exec" { | ||||||||||||||||||
command = <<-EOT | ||||||||||||||||||
echo "Validating EKS metrics/logs for AMF" | ||||||||||||||||||
echo "Validating EKS metrics/traces for APM" | ||||||||||||||||||
cd ../../../.. | ||||||||||||||||||
go test ${var.test_dir} -eksClusterName=${aws_eks_cluster.this.name} -computeType=EKS -v -eksDeploymentStrategy=DAEMON | ||||||||||||||||||
go test ${var.test_dir} -timeout 1h -eksClusterName=${aws_eks_cluster.this.name} -computeType=EKS -v -eksDeploymentStrategy=DAEMON | ||||||||||||||||||
EOT | ||||||||||||||||||
} | ||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package main | ||
|
||
import ( | ||
"crypto/rand" | ||
"encoding/binary" | ||
"encoding/hex" | ||
"fmt" | ||
"time" | ||
) | ||
|
||
func main() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand that this is probably to avoid dependencies, but https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/propagators/aws/xray provides an ID generator, which is what customers would be using as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh nice! I can look into this |
||
var r [16]byte | ||
epochNow := time.Now().Unix() | ||
binary.BigEndian.PutUint32(r[0:4], uint32(epochNow)) | ||
rand.Read(r[4:]) | ||
fmt.Printf("%s", hex.EncodeToString(r[:])) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
{ | ||
"resourceSpans": [ | ||
{ | ||
"resource": { | ||
"attributes": [ | ||
{ | ||
"key": "k8s.namespace.name", | ||
"value": { | ||
"stringValue": "default" | ||
} | ||
}, | ||
{ | ||
"key": "k8s.pod.name", | ||
"value": { | ||
"stringValue": "pod-name" | ||
} | ||
}, | ||
{ | ||
"key": "aws.deployment.name", | ||
"value": { | ||
"stringValue": "deployment-name" | ||
} | ||
}, | ||
{ | ||
"key": "host.id", | ||
"value": { | ||
"stringValue": "i-00000000000000000" | ||
} | ||
} | ||
] | ||
}, | ||
"scopeSpans": [ | ||
{ | ||
"scope": { | ||
"name": "apm-integration-test" | ||
}, | ||
"spans": [ | ||
{ | ||
"traceId": "TRACE_ID", | ||
"spanId": "EEE19B7EC3C1B174", | ||
"parentSpanId": "EEE19B7EC3C1B173", | ||
"name": "apm-integration-test-traces", | ||
"startTimeUnixNano": START_TIME, | ||
"endTimeUnixNano": START_TIME, | ||
"kind": 2, | ||
"attributes": [ | ||
{ | ||
"key": "aws.span.kind", | ||
"value": { | ||
"stringValue": "CLIENT" | ||
} | ||
}, | ||
{ | ||
"key": "aws.local.operation", | ||
"value": { | ||
"stringValue": "operation" | ||
} | ||
}, | ||
{ | ||
"key": "aws.local.service", | ||
"value": { | ||
"stringValue": "service-name" | ||
} | ||
}, | ||
{ | ||
"key": "aws.remote.operation", | ||
"value": { | ||
"stringValue": "remote-operation" | ||
} | ||
}, | ||
{ | ||
"key": "aws.remote.service", | ||
"value": { | ||
"stringValue": "service-name-remote" | ||
} | ||
}, | ||
{ | ||
"key": "aws.remote.target", | ||
"value": { | ||
"stringValue": "remote-target" | ||
} | ||
} | ||
] | ||
} | ||
] | ||
} | ||
] | ||
} | ||
] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand what this is doing, but I think it's still hard to follow. Can we build the generator?
nit: There has to be a better way to mount the files you need to run in this container instead of the template rendering.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah ideally we can build the generator bin, and mount it on a volume along with the other json files. The templating comes from the metric tests which I've borrowed.
I could try to spend some time to make this cleaner and easier to follow