Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
This change includes a ton of improvements to the docs in preparation of
1.3

* Add a limitations page (Fixes #39)
* Update CloudFormation deployment to use Launch Templates (Fixes #57)
* Add a page detailing bandwidth limits for various instance types
  (Fixes #60)
* Add documentation for new 1.3 features (Fixes #64)
  • Loading branch information
AndrewGuenther committed Jan 25, 2024
1 parent c887089 commit f1130da
Show file tree
Hide file tree
Showing 11 changed files with 4,483 additions and 45 deletions.
1 change: 1 addition & 0 deletions FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ko_fi: codebrewed
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Welcome to fck-nat. The (f)easible (c)ost (k)onfigurable NAT!

Full documentation is available at https://fck-nat.dev

fck-nat offers a ready-to-use ARM and x86 based AMIs built on Amazon Linux 2 which can support up to 5Gbps burst NAT
fck-nat offers a ready-to-use ARM and x86 based AMIs built on Amazon Linux 2023 which can support up to 5Gbps burst NAT
traffic on a t4g.nano instance. How does that compare to a Managed NAT Gateway?

Hourly rates:
Expand Down
102 changes: 102 additions & 0 deletions docs/choosing_an_instance_size.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Choosing an Instance Size

It can be a bit difficult to understand what instance size is best for your needs when considering a fck-nat instance,
but if you keep in mind a few key rules, the decision should be relatively straightforward. We also include some
baseline recommendations below.

The rules of EC2 to internet networking:

1. Most instances offer bandwidth "Up to" a certain amount. This is their burst capacity. Their baseline is
**signigicantly** smaller. The baseline value is available via the EC2 `describe-instance-types` API.
2. Instances with fewer than 32 vCPUs are limited to a maximum of 5Gbps egress to the internet.
3. Instances with >=32 vCPUs are allowed 50% their baseline bandwidth out to the internet.

Alright, now that we have those rules down, what's the best option for you? It's suggested that you read all of the
sections below before jumping to the one you need because there's a lot of good information spread throughout that
could help in your decision making, but here's a summary table:

| Bandwidth | Instance type | Price per Month |
| --------- | ------------- | --------------- |
| 3.2Mbps | t4g.nano | $3.06 |
| 6.4Mbps | t3.micro | $7.59 |
| 1.6Gbps | c6gn.medium | $32.81 |
| 3.125Gbps | c7gn.medium | $48.25 |
| 5Gbps | c7gn.large | $132.20 |
| 25Gbps | r6in.8xlarge | $1074.56 |
| 50Gbps | c7gn.8xlarge | $1457.66 |

Yes, there's some big jumps there. No, there's not really any sensible option in between.

### I want to spend less than $10 per month on a NAT solution

For you my friend, we have the `t4g.nano`. Not only is the `t4g.nano` the least expensive option out of all instance
types, it also has the highest Gbps/dollar ratio of all the options under $10! The `t4g.nano` supports a burst
bandwidth of up to 5Gbps and a sustained bandwidth of 3.2Mbps for $3.06/month.

If you're looking for an option that's a little more expensive but has a higher sustained bandwidth, the `t3.micro` is
$7.59/month and supports a sustained bandwidth of 6.4Mbps.

### I need at least 1Gbps sustained egress

You have two really good options here. The `c6gn.medium` offers a sustained bandwidth of 1.6 Gbps for $32.81/month
which is the lowest price available for any instance supporting >1Gbps egress.

If you're willing to spend a little more, you can get the Rolls Royce of NAT instances, the `c7gn.medium`. The
`c7gn.medium` supports a whopping 3.125Gbps sustained bandwidth and boasts **the highest Gbps/dollar ration out of
any instance type in AWS** for $48.25/month

### How about 5Gbps sustained egress?

If you want to hit the max (at <32vCPUs) sustained capacity of 5Gbps out to the internet then your best option is the
`c7gn.large` which offers 5Gbps sustained for $132.20/month.

### I need **more**

Remember, once you're looking to top 5Gbps, you have to look at instance types with at least 32 vCPUs. This means that
you're looking at a significant price jump. At this point, it is worthwhile considering sticking to NAT Gateway, but
there's definitely high total throughput cases which warrant rolling your own NAT at this scale.

The lowest priced instance offering more than 5Gbps egress is the `c6g.8xlarge` for $794.42/month and offering...6Gbps.
Once you start getting to this level though, the scaling function actually becomes really straightforward because AWS
offers dedicated networking at known increments: 12Gbps (like the `c6g.8xlarge` up there), 25Gbps, 50Gbps, and 100Gbps.
Remember, at >=32vCPUs you're only getting 50% egress bandwidth so the effective values are really 6Gbps, 12.5Gbps,
25Gbps, and 50Gbps

Here's the instance types offering the best value at each of those additional levels:

| Bandwidth | Instance type | Price per Month |
| --------- | ------------- | --------------- |
| 6Gbps | c6g.8xlarge | $794.42 |
| 12.5Gbps | m5n.8xlarge | $1510.37 |
| 25Gbps | r6in.8xlarge | $1074.56 |
| 50Gbps | c7gn.8xlarge | $1457.66 |

As you can see, 6Gbps and 12.5Gbps are simply not economical options when compared to the best 5Gbps and 25Gbps
options. So you're effectively looking at jumping straight from 5Gbps to 25Gbps if you need higher sustained
bandwidth.

??? note "How were these values calculated?"
Through some pain, effort, and a lot of `jq` you can produce the source data on your own and perform your own
analysis on instance types. The scripts below will pull network bandwidth information from the EC2 API and pricing
information from the pricing API then combine them along with a `max_egress` value that takes into account the
rules above and a `ratio` value which is effectively Gbps per dollar and is used as a measurement of "value"

```shell
aws ec2 describe-instance-types \
--output json \
| jq '.InstanceTypes[] | { (.InstanceType): { vcpus: .VCpuInfo.DefaultVCpus, baseline: .NetworkInfo.NetworkCards[0].BaselineBandwidthInGbps, burst: .NetworkInfo.NetworkPerformance}}' \
| jq -s add > instance-networking.json


aws pricing get-products \
--service-code AmazonEC2 \
--filters "Type=TERM_MATCH,Field=location,Value=US East (N. Virginia)" \
--region us-east-1 \
| jq -rc '.PriceList[]' \
| jq -r '{ (.product.attributes.instanceType): { price: (.terms.OnDemand[].priceDimensions[].pricePerUnit.USD | tonumber) }}' \
| jq -s add > instance-pricing.json

jq -s '.[0] * .[1]' instance-pricing.json instance-networking.json \
| jq 'with_entries(select(.value | has("baseline") and has("price") and .price > 0.0))' \
| jq 'to_entries | map(.value |= . + {max_egress: (if .vcpus < 32 then ([.baseline, 5.0] | min) else .baseline / 2 end) }) | map(.value |= . + {ratio: (.max_egress / (.price | tonumber)), price_monthly: (.price * 730)}) | sort_by(.value.ratio) | from_entries' > instance-merged.json
```
19 changes: 16 additions & 3 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
# fck-nat Configuration

## Configuration file
## Configuration File

Upon starting, fck-nat evaluates a configuration file describing how the instance should behave as well as what features
shall be enabled. To configure fck-nat, ensure a file `/etc/fck-nat.conf` exists with your configuration. fck-nat
requires the service to be restarted by running `service fck-nat-resart`. In most implementations this configuration is
requires the service to be restarted by running `systemctl restart fck-nat.service`. In most implementations this configuration is
passed only once via EC2's user data.

The following describes available options:
| name | description |

| Name | Description |
| ----------------------- | ----------- |
| `eni_id` | The ID of the Elastic Network Interface to attach to the instance and use as a consistent endpoint to send traffic to fck nat. This is required when using high-availability mode. |
| `eip_id` | The ID of an Elastic IP to be attached to the public network interface. This ensures the NAT gateway public traffic is always routed through the same public IP address. |
| `cwagent_enabled` | If set, enables Cloudwatch agent and forward instance metrics to Cloudwatch. Requires `cwagent_cfg_param_name` to be set. |
| `cwagent_cfg_param_name` | The name of the SSM Parameter holding the Cloudwatch agent configuration and which the agent shall pull from. Requires `cwagent_enabled` to be set. |

## IAM Requirements

Certain features of fck-nat require the role attached to the instance to have permissions for certain AWS API
operations. The table below details the current permission requirements for various features:

| Feature | Required Permissions |
| ------- | -------------------- |
| HA-mode (`eni_id`) | `ec2:AttachNetworkInterface, ec2:ModifyNetworkInterfaceAttribute` |
| Static IP (`eip_id`) | `ec2:AssociateAddress, ec2:DisassociateAddress` |
| Cloudwatch Agent (`cwagent_enabled`) | Managed Policy: `CloudWatchAgentServerPolicy` *and* `ssm:GetParameter` |
| SSM Agent (installed by default, IAM role required to use) | Managed Policy: `AmazonSSMManagedEC2InstanceDefaultPolicy` |
55 changes: 29 additions & 26 deletions docs/deploying.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ The most well-supported way to deploy fck-nat with all of its features available
using another Infrastructure-as-code provider, you can still deploy a basic NAT instance with fck-nat, but it is more
intensive to support some of fck-nat's additional features.

Notably missing at the moment is a Terraform module. If you're using Terraform and would like to leverage fck-nat,
please +1 this issue: [Create a fck-nat Terraform module](https://github.com/AndrewGuenther/fck-nat/issues/4)

## CDK

fck-nat provides an official CDK module which supports all of fck-nat's features (namely high-availability mode)
Expand Down Expand Up @@ -111,6 +108,10 @@ resource "aws_instance" "fck-nat" {

## Cloudformation

!!! note
If you'd be interested in seeing fck-nat published on the Cloudformation registry,
[give this issue a +1](https://github.com/AndrewGuenther/cdk-fck-nat/issues/295)

For brevity, this document assumes you already have a VPC with public and private subnets defined in your
Cloudformation template. This example template provisions the minimum resources required to connect fck-nat in your
VPC. This is a good option for those that have an existing VPC and NAT Gateway and are looking to switch over.
Expand Down Expand Up @@ -161,28 +162,30 @@ Resources:
Roles:
- Ref: NatRole

FckNatAsgLaunchConfig:
Type: AWS::AutoScaling::LaunchConfiguration
FckNatLaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
ImageId: ami-05b6d5a2e26f13c93
InstanceType: t4g.nano
IamInstanceProfile:
Ref: FckNatAsgInstanceProfile
SecurityGroups:
- Fn::GetAtt:
- NatSecurityGroup
- GroupId
UserData:
Fn::Base64:
Fn::Join:
- ""
- - |-
#!/bin/bash
echo "eni_id=
- Ref: FckNatInterface
- |-
" >> /etc/fck-nat.conf
service fck-nat restart
LaunchTemplateName: FckNatLaunchTemplate
LaunchTemplateData:
ImageId: ami-05b6d5a2e26f13c93
InstanceType: t4g.nano
IamInstanceProfile:
Ref: FckNatAsgInstanceProfile
SecurityGroups:
- Fn::GetAtt:
- NatSecurityGroup
- GroupId
UserData:
Fn::Base64:
Fn::Join:
- ""
- - |-
#!/bin/bash
echo "eni_id=
- Ref: FckNatInterface
- |-
" >> /etc/fck-nat.conf
service fck-nat restart
DependsOn:
- NatRole

Expand All @@ -192,8 +195,8 @@ Resources:
MaxSize: "1"
MinSize: "1"
DesiredCapacity: "1"
LaunchConfigurationName:
Ref: FckNatAsgLaunchConfig
LaunchTemplateId:
Ref: FckNatLaunchTemplate
VPCZoneIdentifier:
- !Sub "${subnet}"
UpdatePolicy:
Expand Down
37 changes: 27 additions & 10 deletions docs/features.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
# fck-nat Features

!!! info "Heads up!"
The easiest way to get all of the features below is to use the official [CDK](deploying.md#cdk) or
[Terraform](deploying.md#terraform) modules!

## High-availability Mode

fck-nat can operate on a single instance, or withing an autoscaling group for improved availability. When running in an
fck-nat can operate on a single instance, or within an autoscaling group for improved availability. When running in an
autoscaling group, fck-nat can be configured to always attach a specific ENI at start-up, allowing fck-nat to maintain
a consistent internal-facing IP address. Additionally, it is also possible to configure an already allocated EIP address
that would be carried through instance refreshs.
a static internal-facing IP address. (For information on static external IPs, see: [Static IP](#static-ip))

This feature is controlled via the `eni_id` directive in the [configuration file](configuration.md#configuration-file)
and also requires additional IAM permissions to function, see: [IAM Requirements](configuration.md#iam-requirements)

## Static IP

If you wish for your NAT instance to maintain a consistent external facing IP, fck-nat supports automatically
association of an Elastic IP (EIP) addresss at launch.

This feature is controlled via the `eip_id` directive in the [configuration file](configuration.md#configuration-file)
and also requires additional IAM permissions to function, see: [IAM Requirements](configuration.md#iam-requirements)

Those features are controlled by `eni_id` and `eip_id` directive in the configuration file.
## SSM Agent

**IAM requirements**: `ec2:AttachNetworkInterface`, `ec2:ModifyNetworkInterfaceAttribute` on `*` for ha-mode, plus
`ec2:AssociateAddress`, `ec2:DisassociateAddress` on `*` when using a static EIP.
The Amazon SSM Agent is installed in the fck-nat AMI by default to allow SSH-less access to instances as well as
automated patching capabilities if you so choose (The fck-nat AMI also has kernel live patching modules enabled). To
enable access via SSM, you just need to make sure that your fck-nat instance has the requisite
[IAM permissions attached](configuration.md#iam-requirements)

## Metrics

Expand All @@ -33,7 +49,7 @@ provided in the managed NAT Gateway:
"namespace": "fck-nat",
"metrics_collected": {
"net": {
"resources": ["eth0", "eth1"],
"resources": ["ens5", "ens6"],
"measurement": [
{ "name": "bytes_recv", "rename": "BytesIn", "unit": "Bytes" },
{ "name": "bytes_sent", "rename": "BytesOut", "unit": "Bytes" },
Expand All @@ -51,7 +67,7 @@ provided in the managed NAT Gateway:
]
},
"ethtool": {
"interface_include": ["eth0", "eth1"],
"interface_include": ["ens5", "ens6"],
"metrics_include": [
"bw_in_allowance_exceeded",
"bw_out_allowance_exceeded",
Expand All @@ -66,7 +82,8 @@ provided in the managed NAT Gateway:
}
},
"append_dimensions": {
"InstanceId": "$${aws:InstanceId}"
"InstanceId": "${aws:InstanceId}",
"AutoScalingGroupNam": "${aws:AutoScalingGroupName}",
}
}
}
Expand All @@ -75,4 +92,4 @@ provided in the managed NAT Gateway:
Ensure you are aware of Cloudwatch metrics costs before enabling Cloudwatch agent. The above configuration would
cost you about $17/monthly, excluding free tier.

**IAM requirements**: `ssm:GetParameter` on the SSM Parameter ARN, and `cloudwatch:PutMetricData` on `*`.
**IAM requirements**: `ssm:GetParameter` on the SSM Parameter ARN, and `cloudwatch:PutMetricData` on `*`.
11 changes: 6 additions & 5 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Welcome to fck-nat. The (f)easible (c)ost (k)onfigurable NAT!
* Want to use NAT instances and stay up-to-date with the latest security patches? fck-nat.
* Want to reuse your Bastion hosts as a NAT? fck-nat.

fck-nat offers a ready-to-use ARM and x86 based AMIs built on Amazon Linux 2 which can support up to 5Gbps burst NAT
fck-nat offers a ready-to-use ARM and x86 based AMIs built on Amazon Linux 2023 which can support up to 5Gbps burst NAT
traffic on a t4g.nano instance. How does that compare to a Managed NAT Gateway?

Hourly rates:
Expand Down Expand Up @@ -50,17 +50,18 @@ swappable" philosophy.

### Getting a fck-nat AMI

fck-nat provides public AMIs in both arm64 and x86_64 flavors built on top of Amazon Linux 2. If you would rather use a
fck-nat provides public AMIs in both arm64 and x86_64 flavors built on top of Amazon Linux 2023. If you would rather use a
different base image or host the AMI yourself, you can build your own AMI.

#### The public fck-nat AMIs

fck-nat currently provides public AMIs in most regions. You can see the full list in
`packer/fck-nat-public-all-regions.pkrvars.hcl`. While arm64 images are the most cost effective, x86_64 images are also
[`packer/fck-nat-public-all-regions.pkrvars.hcl`](https://github.com/AndrewGuenther/fck-nat/blob/main/packer/fck-nat-public-all-regions.pkrvars.hcl).
While arm64 images are the most cost effective, x86_64 images are also
available. You can get view the available fck-nat AMIs with the following query:

```
# Amazon Linux 2 based AMIs
# Amazon Linux 2023 based AMIs
aws ec2 describe-images --owners 568608671756 --filters 'Name=name,Values=fck-nat-al2023-*'
```

Expand Down Expand Up @@ -89,5 +90,5 @@ configured in order to route traffic to your NAT. Namely, you must:
1. Disable source/destination checks
1. Update your VPC route table

Some tools can accomplish this for you, others cannot. Check the ["Deploying"](deploying.md) section for more
Some tools can accomplish this for you, others cannot. Check the [Deployment page](deploying.md) for more
information about deploying fck-nat with your favorite infrastructure-as-code tool.

0 comments on commit f1130da

Please sign in to comment.