Tuesday, August 12, 2025

Accessing Services from a VPC Lambda

We reached the point where I claim that we have all the code we need in order to have our stock watcher update from the lambda. But nothing is working because there is no connectivity between the lambda and the API Gateway (in that direction; there is connectivity between the Gateway and the lambda which enables it to be invoked).

There are a number of solutions to this problem:
  • There are some services (such as cloudwatch, which we are successfully using; also neptune and dynamodb) which "just work";
  • There are some services (such as SSM, the secrets manager) which have custom endpoints you can identify in your lambda code;
  • It is possible to define a NAT gateway;
  • It is possible to use AWS PrivateLink;
  • It is possible to use IPv6 and an egress-only gateway.
Each of these has issues. The first two are simply not solutions for the API Gateway. The third and fourth both cost money, not only when you use them, but whenever you have them defined. For me, this goes against the whole principle of serverless, and seems like a rip-off: AWS makes you put certain lambdas in VPCs, and then doesn't allow you to mix that with other AWS services, and then charges you a standing fee to solve the problem. The fifth solution, then, is what we're left with, but that requires us to mess with IPv6.

It took AWS forever to implement IPv6. I forget why I first wanted to use IPv6 on AWS, but it was back in 2012 or 2013. I was amazed that it wasn't an option. I was even more amazed that it wasn't on their roadmap. If I read the histories correctly, it was only introduced in 2023.

I don't fully understand these things, but the reason you need a NAT gateway from a VPC is because you are using "local" IPv4 addresses. There are no "local" IPv6 addresses - they are all unique. As such, it is not necessary to translate them to global addresses, and hence no NAT gateway is needed. Instead, there is a component called an "egress-only" gateway which supports IPv6 only and has the significant advantage that it is completely free.

All of my VPC setup is off-camera, so I can just tell you that I created an egress only internet gateway and then enabled IPv6 on all the subnets in my VPC.

That's a good start, but it's not enough. In order for any of this to work, both the lambda and the API gateway also need to support IPv6. Each of them has an option to enable "dual stack" processing - that is, both IPv4 and IPv6. For the lambda, it is part of the VpcConfig setting:
            VpcConfig <= aws.VPC.Config
                DualStack <- true
                Subnets <- vpc->subnets
                SecurityGroups <- vpc->securityGroups

NEPTUNE_WATCH_LAMBDA:neptune/dply/infrastructure.dply

And for the API Gateway, we need to specify the IpAddressType at the top level:
        api.gatewayV2 "stock-watch"
            @teardown delete
            Protocol <- "websocket"
            IpAddressType <- "dualstack"
            RouteSelectionExpression <- "$request.body.action"

NEPTUNE_WATCH_LAMBDA:neptune/dply/infrastructure.dply

It may not be obvious why we need this in the API Gateway, but the IpAddressType property is really there to enable the gateway to provide its web services to IPv6 clients. We are not really doing that, but the mechanism is the same: you make an HTTP request to the gateway from within the lambda. Since that request is travelling "over" IPv6, we need the gateway to be listening to IPv6 traffic.

I'm going to admit that much of this still confuses me. I think I understand IPv6 addressing reasonably enough, but I have always been confused by "multi-homed" machines with multiple network cards. How does it know which to choose? Particularly when there are so many (at least 6 - two protocols for each of three subnets). But it does, somehow, and it works. And doesn't require me to pay for a NAT gateway.

Conclusion

The new networking options in AWS make it possible to use IPv6 to have a free route from within a VPC to the wider internet, including AWS services. It's a little complicated, but hopefully this article makes it clear what needs to be done for this case at least.

No comments:

Post a Comment