Swapping ALB Request IDs for Nginx

April 4, 2018
ops kubernetes aws

I’ve recently been making a switch from using Amazon’s Application Load Balancers (ALBs), to using their new Network Load Balancers (NLBs). There are many reasons for this switch (that are not the subject of this post), but there was one glaring short fall: We heavily rely on request log data centered around the ALB provided X-Amzn-Trace-Id Request ID value.

When switching to the NLB (which is L4, vs the ALBs’ L7), this HTTP header is not added for us. Luckily nginx provides similar functionality through the $request_id variable, however we have the following constraints:

  • If a request came from the ALB, we need to maintance the original Request ID
  • If a request did not come through the ALB, we need to append a new Request ID

Using an Nginx map, we can get this behaviour as follows:

First, in the http context, we add the following:

map $http_x_amzn_trace_id $processed_request_id {
    default  "$http_x_amzn_trace_id";
    ''       "$request_id";
}

Here we are defining a new variable, $processed_request_id, based off the value of an existing variable, $http_x_amzn_trace_id. This original variable is the Nginx exposed version of the X-Amzn-Trace-Id HTTP Header (that may have been previously added to the request by the ALB). If it matches an empty string (ie, is not present), then we return the nginx $request_id variable. Otherwise, we return the original $http_x_amzn_trace_id value. This allows us to use the original value as a default, and only provide a new value in the event that it did not exist.

Now, in the location context, you can use the new $processed_request_id variable to provide the new Request ID value to the upstream services.

location / {
    ...
    proxy_set_header X-Amzn-Trace-Id $processed_request_id;
    ...
}

Note that here we are continuing to use the X-Amzn-Trace-Id header name, however you could also set the value to multiple headers (such as X-Request-ID) in order to support different versions of your backend, that could be expecting the Request ID in different ways.