Peer VPCs to enable traffic across VPCs

Datacoral recommends that you create a dedicated VPC for Datacoral services in order to provide isolation, auditing, and network access management. However, sometimes our services will need to communicate across different VPCs. There are a few situations when this might be needed:

  • When a customer is installing Datacoral in a new VPC, but they wish to use an existing Redshift cluster that is an older VPC.
  • When a customer has installed Datacoral in its own VPC, and they would like Datacoral services to communicate with services/databases in a separate VPC.

In such cases, VPC Peering will have to be performed. We should make sure that the two VPCs don't have an overlapping CIDR Block.

There are three parts -- Sending a peering request, accepting it and configuring it.

Creating and sending a peering request

From the AWS account that involves the VPC that is running Datacoral, a connection request needs to be sent to the other VPC.

Step 1: Go to the VPC Console.

Step 2: Click on Create Peering Connections button

Step 3: Enter Requesting and Accepting VPC information

You can choose whether the receiving VPC is in the same or different account (account number will be needed). Press the Create Peering Connection button in the bottom-right.

After this, a success message will be shown.

For more info, and details on using the AWS CLI, see here if the VPC is in the same AWS account or here if the VPC is in a different AWS account.

AWS CLI: create-vpc-peering-connection

aws ec2 create-vpc-peering-connection \
--vpc-id <The ID of the requester VPC> \
--region <The Region code for the requester VPC> \
--peer-owner-id <The AWS account ID of the owner of the accepter VPC> \
--peer-vpc-id <The ID of the VPC with which you are creating the VPC peering connection> \
--peer-region <The Region code for the accepter VPC>

if requester VPC is in same account you can ignore peer-owner-id or pass your own account ID for more info, for more info see here.

Example Command:

aws ec2 create-vpc-peering-connection \
--vpc-id vpc-1a2b3c4d \
--region us-west-2 \
--peer-owner-id 123456789012 \
--peer-vpc-id vpc-11122233 \
--peer-region us-east-1

Output:

{
"VpcPeeringConnection": {
"Status": {
"Message": "Initiating Request to 123456789012",
"Code": "initiating-request"
},
"Tags": [],
"RequesterVpcInfo": {
"PeeringOptions": {
"AllowEgressFromLocalVpcToRemoteClassicLink": false,
"AllowDnsResolutionFromRemoteVpc": false,
"AllowEgressFromLocalClassicLinkToRemoteVpc": false
},
"VpcId": "vpc-1a2b3c4d",
"Region": "us-west-2",
"OwnerId": "098765432109",
"CidrBlockSet": [
{
"CidrBlock": "10.0.0.0/16"
}
],
"CidrBlock": "10.0.0.0/16"
},
"VpcPeeringConnectionId": "pcx-1234567890asdfghj",
"ExpirationTime": "2020-02-07T08:54:24.000Z",
"AccepterVpcInfo": {
"OwnerId": "123456789012",
"Region": "us-east-1",
"VpcId": "vpc-11122233"
}
}
}

Accepting a Peering Request

Now navigate to the AWS account to which a peering request has been sent. The request will have to be accepted here.

Step 1: Go to the VPC Console.

Here in the VPC console, you'll see the peering connection will show up with a yellow circle which means that the connection is pending.

Step 2: Click on Actions for Pending Peering Request and Accept.

Click on the pending Peering Request, and then click on Actions in the panel above it. This will open a drop-down as seen below. Click on "Accept Request".

Step 3: Accept Peering Request.

In the modal that opens, click on "Yes, Accept".

After a few seconds, we will be able to see that the peering connection is successful.

AWS CLI: accept-vpc-peering-connection

Accept a VPC peering connection request. To accept a request, the VPC peering connection must be in the pending-acceptance state, and you must be the owner of the peer VPC. Use DescribeVpcPeeringConnections to view your outstanding VPC peering connection requests.

For an inter-Region VPC peering connection request, you must accept the VPC peering connection in the Region of the accepter VPC, for more info see here.

aws ec2 accept-vpc-peering-connection \
--vpc-peering-connection-id <The ID of the VPC peering connection> \
--region <The Region code for the accepter VPC>

Example Command: Using the output command from the create-vpc-peering-connection get VpcPeeringConnectionId

aws ec2 accept-vpc-peering-connection \
--vpc-peering-connection-id pcx-1234567890asdfghj \
--region us-east-1

Output:

{
"VpcPeeringConnection": {
"Status": {
"Message": "Provisioning",
"Code": "provisioning"
},
"Tags": [],
"AccepterVpcInfo": {
"PeeringOptions": {
"AllowEgressFromLocalVpcToRemoteClassicLink": false,
"AllowDnsResolutionFromRemoteVpc": false,
"AllowEgressFromLocalClassicLinkToRemoteVpc": false
},
"VpcId": "vpc-11122233",
"Region": "us-east-1",
"OwnerId": "123456789012",
"CidrBlockSet": [
{
"CidrBlock": "172.31.0.0/16"
}
],
"CidrBlock": "172.31.0.0/16"
},
"VpcPeeringConnectionId": "pcx-1234567890asdfghj",
"RequesterVpcInfo": {
"PeeringOptions": {
"AllowEgressFromLocalVpcToRemoteClassicLink": false,
"AllowDnsResolutionFromRemoteVpc": false,
"AllowEgressFromLocalClassicLinkToRemoteVpc": false
},
"VpcId": "vpc-1a2b3c4d",
"Region": "us-west-2",
"OwnerId": "098765432109",
"CidrBlockSet": [
{
"CidrBlock": "10.0.0.0/16"
}
],
"CidrBlock": "10.0.0.0/16"
}
}
}

VPC Peering Configurations

You need to configure VPC peering connections so that your route tables have access to the entire CIDR block of the peer VPC. For more info, and details on the VPC Peering Configurations, see here

Step 1: Enable DNS resolution on VPC.

Enable a VPC to resolve public IPv4 DNS hostnames to private IPv4 addresses when queried from instances in the peer VPC. Both VPCs (Accepter and Requester) must be enabled for DNS hostnames and DNS resolution.

i. To edit DNS hostnames and DNS resolution go to VPC dashboard. ii. Click on edit DNS hostnames and make sure the enable is checked and save. iii. Click on edit DNS resolution and make sure the enable is checked and save.

AWS CLI: modify-vpc-attribute

Modifies the specified attribute of the specified VPC, for more info see here.

aws ec2 modify-vpc-attribute \
--enable-dns-hostnames \
--vpc-id <The ID of the VPC> \
--region <The Region code for the VPC>
aws ec2 modify-vpc-attribute \
--enable-dns-support \
--vpc-id <The ID of the VPC> \
--region <The Region code for the VPC>

Example Command: Run these commands for both Accepter VPC and Requester VPC

aws ec2 modify-vpc-attribute \
--enable-dns-hostnames \
--vpc-id vpc-1a2b3c4d \
--region us-west-2
aws ec2 modify-vpc-attribute \
--enable-dns-support \
--vpc-id vpc-1a2b3c4d \
--region us-west-2

Step 2: Enable DNS resolution on Peering Connection.

To enable a VPC to resolve public IPv4 DNS hostnames to private IPv4 addresses when queried from instances in the peer VPC, you must modify the peering connection.

i. To Edit DNS settings on peering connection choose Peering Connections, in the navigation pane.

ii. To ensure that queries from the peer VPC resolve to private IP addresses in your local VPC, choose the option to enable DNS resolution for queries from the peer VPC. This option is Requester DNS resolution or Accepter DNS resolution, depending on whether the VPC is the requester or accepter VPC.

Accepter AWS account

Requester AWS account

iii. If the peer VPC is in the same AWS account, you can enable DNS resolution for both VPCs in the peering connection.

Once the DNS resolution is setup, you will have a screen that looks like below on the the acceptor AWS Account.

AWS CLI: modify-vpc-peering-connection-options

Modifies the VPC peering connection options on one side of a VPC peering connection, for more info see here.

aws ec2 modify-vpc-peering-connection-options \
--accepter-peering-connection-options <value> \
--requester-peering-connection-options <value> \
--vpc-peering-connection-id <value>

Example Commands:

Run from accepter account/region

aws ec2 modify-vpc-peering-connection-options \
--vpc-peering-connection-id "pcx-1234567890asdfghj" \
--accepter-peering-connection-options '{"AllowDnsResolutionFromRemoteVpc":true}' \
--region us-east-1

Run from requester account/region

aws ec2 modify-vpc-peering-connection-options \
--vpc-peering-connection-id "pcx-1234567890asdfghj" \
--requester-peering-connection-options '{"AllowDnsResolutionFromRemoteVpc":true}' \
--region us-west-2

If both the VPC's are in same account and same region, you can run single command

aws ec2 modify-vpc-peering-connection-options \
--vpc-peering-connection-id "pcx-1234567890asdfghj" \
--requester-peering-connection-options '{"AllowDnsResolutionFromRemoteVpc":true}' \
--accepter-peering-connection-options '{"AllowDnsResolutionFromRemoteVpc":true}' \
--region us-west-2

iv. Choose Save.

  • If the peer VPC is in a different AWS account or a different region, the owner of the peer VPC must sign into the VPC console, perform Step 4, and choose Save.

Step 3: Updating Your Route Tables for a VPC Peering Connection

To send private IPv4 traffic from your instance to an instance in a peer VPC, you must add a route to the route table that's associated with your subnet in which your instance resides. The route points to the CIDR block (or portion of the CIDR block) of the peer VPC in the VPC peering connection, and specifies the VPC peering connection as the target. for more info see here.

In VPC dashboard, click on route tables and search with VPC Resource Attributes and edit all route tables to add a route. Add a route with destination as accepter CIDR block if you are requester, and vice versa. In Target add peering connection id and click save routes.

  • Repeat the above step for all the route tables in the VPC.
  • Do the same in the Accepter VPC.

AWS CLI: create-route

Creates a route in a route table within a VPC, for more info see here.

aws ec2 create-route \
--route-table-id <The ID of the route table for the route> \
--destination-cidr-block <The IPv4 CIDR address block used for the destination match> \
--vpc-peering-connection-id <The ID of a VPC peering connection>

Example Command:

To get all route table ids in a VPC, for more info see here.

aws ec2 describe-route-tables \
--filters Name=vpc-id,Values=vpc-1a2b3c4d \
| jq -r '.RouteTables[].RouteTableId'

Add route in requester VPC route table

aws ec2 create-route \
--route-table-id rtb-r1234da \
--destination-cidr-block 172.31.0.0/16 \
--vpc-peering-connection-id pcx-1234567890asdfghj

Add route in accepter VPC route table

aws ec2 create-route \
--route-table-id rtb-a1234da \
--destination-cidr-block 10.0.0.0/16 \
--vpc-peering-connection-id pcx-1234567890asdfghj

Output:

{
"Return": true
}

Step 4: Verify VPC Peering connection

In order to test whether VPC Peering has been successful or not, the best way is to spin up an EC2 machine inside a private subnet in the account that houses the Datacoral installation and connect to the Redshift/Postgres/MySQL/MongoDB instance (dbhostname) using the telnet command.

telnet dbhostname dbport

dbport can be different for different database types. Defaults for different databases are:

  1. Redshift - 5439
  2. Postgres - 5432
  3. MySQL - 3306
  4. MongoDB - 27017