<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>RDS &#8211; Blog of Kliment Andreev &#8211; A place so I won&#039;t forget things</title>
	<atom:link href="https://blog.andreev.it/tag/rds/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.andreev.it</link>
	<description></description>
	<lastBuildDate>Sat, 05 Mar 2022 02:03:42 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>AWS: Access RDS database using PrivateLink from another account</title>
		<link>https://blog.andreev.it/2022/03/aws-access-rds-database-using-privatelink-from-another-account/</link>
					<comments>https://blog.andreev.it/2022/03/aws-access-rds-database-using-privatelink-from-another-account/#comments</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Sat, 05 Mar 2022 02:03:42 +0000</pubDate>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Endpoint]]></category>
		<category><![CDATA[PrivateLink]]></category>
		<category><![CDATA[RDS]]></category>
		<guid isPermaLink="false">https://blog.andreev.it/?p=9118</guid>

					<description><![CDATA[Here is the deal. Our vendor wants to access our Aurora database. We can&#8217;t&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>Here is the deal. Our vendor wants to access our Aurora database. We can&#8217;t do VPC peering because our CIDRs overlap. On top of that, we don&#8217;t want peering with 3rd party vendors and we don&#8217;t want to host our data in the vendor&#8217;s account. So, we have to use PrivateLink.<br />
In this post I&#8217;ll guide you through creating an RDS database in one account and accessing it from another account over <a href="https://aws.amazon.com/privatelink/" rel="noopener" target="_blank">PrivateLink</a>. In order to do this, we&#8217;ll need:</p>
<ul>
&#8211; Two AWS accounts (Provider and Customer). We are the provider, the vendor is the customer.<br />
&#8211; One VPC with 2 public/private subnets in each account. The vendor&#8217;s (customer) VPC config doesn&#8217;t really matter.<br />
&#8211; One EC2 instance in each account (public subnet) for testing access
</ul>
<p>We will create an endpoint service in the Provider VPC and an endpoint in the Customer VPC. The endpoint service requires a network load balancer as well. Here is a problem. When we create a NLB, the target of the NLB are IP addresses. The RDS database has DNS entries as endpoints. Technically, we can resolve the DNS URLs in IPs and use them as targets. But these IPs can change. So we have to put something in between the RDS and NLB. That&#8217;s the job of the RDS proxy. The DNS URLs of an RDS Proxy always resolve to the same IPs. Another problem is that RDS proxy can be deployed for MySQL and PostgreSQL databases only. So keep this in mind.   </p>
<h1>VPC</h1>
<p>I&#8217;ll create two VPCs in each account. The first VPC will have a 192.168.100.0/22 CIDR and the second VPC will have 192.168.200.0/22 CIDR with 4 x /24 private and public subnets. Here is the breakdown of the subnets. It&#8217;s a standard build with two NAT gateways and one Internet gateway.<br />
The first VPC is called <strong>vpc-Provider</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-01.png"><img fetchpriority="high" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-01.png" alt="" width="2296" height="334" class="aligncenter size-full wp-image-9121" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-01.png 2296w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-01-300x44.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-01-1024x149.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-01-768x112.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-01-1536x223.png 1536w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-01-2048x298.png 2048w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-01-1920x279.png 1920w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-01-1170x170.png 1170w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-01-585x85.png 585w" sizes="(max-width: 2296px) 100vw, 2296px" /></a><br />
The second VPC is called <strong>vpc-Consumer</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-02.png"><img decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-02.png" alt="" width="2056" height="354" class="aligncenter size-full wp-image-9123" /></a></p>
<h1>Security groups</h1>
<p>Create two security groups under <strong>vpc-Provider</strong> VPC, one called <strong>sgEC2</strong> and the other called <strong>sgRDS.</strong><br />
For the <strong>sgEC2</strong> group, allow SSH from some IP, e.g. your IP from work/home. The EC2 instance that we&#8217;ll create will be in a public subnet.<br />
For the <strong>sgRDS</strong> group, allow port 3306 (MySQL) from the actual subnet ID for <strong>sgEC2</strong> group and another rule to allow access to 3306 from itself. This is how the rules for <strong>sgRDS</strong> look like.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-03.png"><img decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-03.png" alt="" width="2796" height="434" class="aligncenter size-full wp-image-9125" /></a><br />
Now, do the same for the <strong>vpc-Consumer account, but create only the <strong>sgEC2</strong> group.</strong><a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-03.png" alt="" width="2826" height="746" class="aligncenter size-full wp-image-9127" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-03.png 2826w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-03-300x79.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-03-1024x270.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-03-768x203.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-03-1536x405.png 1536w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-03-2048x541.png 2048w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-03-1920x507.png 1920w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-03-1170x309.png 1170w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-03-585x154.png 585w" sizes="(max-width: 2826px) 100vw, 2826px" /></a> </p>
<h1>RDS</h1>
<p>For the RDS, use pretty much default settings. In my case, I used:</p>
<ul>
&#8211; Standard create<br />
&#8211; Amazon Aurora<br />
&#8211; Amazon Aurora MySQL-Compatible Edition<br />
&#8211; Capacity type: Provisioned<br />
&#8211; Aurora (MySQL 5.7) 2.07.2<br />
&#8211; Templates: Dev/Test<br />
&#8211; Name the cluster and enter your admin credentials (remember these)<br />
&#8211; Burstable db.t3.small<br />
&#8211; Don&#8217;t create an Aurora Replica<br />
&#8211; Choose the VPC that we created<br />
&#8211; Public access: No<br />
&#8211; Security group: sgRDS<br />
&#8211; Availability Zone: No preference</ul>
<p>Then click to <strong>Create database</strong>.</p>
<h1>EC2</h1>
<p>While the database is creating, go to EC2 and create an instance that we&#8217;ll use for testing. It can be any Linux and any size. I&#8217;ve used t2.micro Amazon Linux with telnet/MySQL client installed (<em>sudo yum install telnet mysql</em>) in a public subnet. I&#8217;ve named the instance ec2Provider. Create another instance in the second account with the same specs as ec2Provider and name it ec2Customer.</p>
<h1>Test 1</h1>
<p>Go to the RDS and get the DNS record for the Aurora cluster. It&#8217;s at the bottom.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-04.png" alt="" width="2792" height="1294" class="aligncenter size-full wp-image-9132" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-04.png 2792w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-04-300x139.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-04-1024x475.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-04-768x356.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-04-1536x712.png 1536w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-04-2048x949.png 2048w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-04-1920x890.png 1920w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-04-1170x542.png 1170w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-04-585x271.png 585w" sizes="(max-width: 2792px) 100vw, 2792px" /></a><br />
Log to the instance in the same account (ec2Provider) and try to telnet to that port. You should be able to. CTRL-C to get out of there and log to MySQL using the client.</p>
<pre class="brush: bash; title: ; notranslate">
mysql -h database-1.cluster-cdbzhqzxu6yp.us-east-2.rds.amazonaws.com -u admin -p
</pre>
<p>Replace the hostname with yours. This the output of my connection.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-05.png" alt="" width="1298" height="814" class="aligncenter size-full wp-image-9133" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-05.png 1298w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-05-300x188.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-05-1024x642.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-05-768x482.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-05-1170x734.png 1170w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-05-585x367.png 585w" sizes="(max-width: 1298px) 100vw, 1298px" /></a><br />
I&#8217;ll create a database while I am there.</p>
<pre class="brush: bash; title: ; notranslate">
create database test_db;
</pre>
<h1>AWS Secrets Manager</h1>
<p>In order to deploy an RDS proxy, we need a secret (user/password combo) stored in the AWS Secrets Manager. Use the same username and password that you used for the RDS database, which is <strong>admin </strong>and whatever password you used. Make sure you select the database that is listed at the bottom of the first screen.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-06.png" alt="" width="1079" height="814" class="aligncenter size-full wp-image-9135" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-06.png 1079w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-06-300x226.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-06-1024x773.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-06-768x579.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-06-585x441.png 585w" sizes="(max-width: 1079px) 100vw, 1079px" /></a><br />
Name the secret and proceed with the defaults.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-07.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-07.png" alt="" width="1071" height="322" class="aligncenter size-full wp-image-9136" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-07.png 1071w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-07-300x90.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-07-1024x308.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-07-768x231.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-07-585x176.png 585w" sizes="(max-width: 1071px) 100vw, 1071px" /></a></p>
<h1>RDS Proxy</h1>
<p>Go to the RDS menu and select and click on the database cluster. Scroll all the way down to the RDS Proxy section. Click on <strong>Create proxy</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-08.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-08.png" alt="" width="1557" height="360" class="aligncenter size-full wp-image-9137" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-08.png 1557w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-08-300x69.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-08-1024x237.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-08-768x178.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-08-1536x355.png 1536w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-08-1170x271.png 1170w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-08-585x135.png 585w" sizes="(max-width: 1557px) 100vw, 1557px" /></a></p>
<ul>
&#8211; Name the proxy (Proxy identifier)<br />
&#8211; Engine &#8211; MySQL<br />
&#8211; Choose the database<br />
&#8211; Uncheck the <strong>Add reader point</strong>.<br />
&#8211; Choose the secret that you created before and specify two private subnets<br />
&#8211; Leave AWS to create the IAM role.<br />
&#8211; Under <strong>Additional connectivity configuration</strong> make sure you assign the <strong>sgRDS </strong>security group and remove the default. </ul>
<p>Click on <strong>Create proxy</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-09.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-09.png" alt="" width="850" height="596" class="aligncenter size-full wp-image-9138" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-09.png 850w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-09-300x210.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-09-768x539.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-09-585x410.png 585w" sizes="(max-width: 850px) 100vw, 850px" /></a></p>
<h1>Test 2</h1>
<p>Let&#8217;s try to access our database through the proxy now. In the main menu for the RDS, click on the <strong>Proxies </strong>on the left.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-10.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-10.png" alt="" width="259" height="319" class="aligncenter size-full wp-image-9139" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-10.png 259w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-10-244x300.png 244w" sizes="(max-width: 259px) 100vw, 259px" /></a><br />
Click on the proxy and scroll down to see the proxy endpoint. Copy that value.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-11.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-11.png" alt="" width="1529" height="190" class="aligncenter size-full wp-image-9140" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-11.png 1529w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-11-300x37.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-11-1024x127.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-11-768x95.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-11-1170x145.png 1170w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-11-585x73.png 585w" sizes="(max-width: 1529px) 100vw, 1529px" /></a><br />
Go to the EC2 instance in the <strong>vpc-Provider</strong>, which is in the same account as the RDS and try to access the database over proxy.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-12.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-12.png" alt="" width="943" height="394" class="aligncenter size-full wp-image-9142" /></a><br />
Great job if you made it so far!</p>
<h1>Network Load Balancer (NLB)</h1>
<p>OK, so if everything works, we need to create an NLB so we can create the endpoint service. The NLB that we&#8217;ll create requires the IP targets of the RDS proxy. You got the DNS for the RDS proxy, the one that you just tested right above. Do an <strong>nslookup </strong>on it and get the IPs.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-13.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-13.png" alt="" width="937" height="189" class="aligncenter size-full wp-image-9150" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-13.png 937w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-13-300x61.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-13-768x155.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-13-585x118.png 585w" sizes="(max-width: 937px) 100vw, 937px" /></a><br />
In my case the proxy RDS returns 192.168.103.210 and 192.168.102.160, which tells me they are in the private availability zones (AZs). Good.<br />
Create an NLB, name it and make sure it&#8217;s internal.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-14.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-14.png" alt="" width="1105" height="480" class="aligncenter size-full wp-image-9152" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-14.png 1105w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-14-300x130.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-14-1024x445.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-14-768x334.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-14-585x254.png 585w" sizes="(max-width: 1105px) 100vw, 1105px" /></a><br />
Choose the VPC and the two internal subnets.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-15.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-15.png" alt="" width="846" height="634" class="aligncenter size-full wp-image-9153" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-15.png 846w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-15-300x225.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-15-768x576.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-15-585x438.png 585w" sizes="(max-width: 846px) 100vw, 846px" /></a><br />
When you reach the <strong>Listeners and routing</strong>, change the port to 3306 and click on <strong>Create target group</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-16.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-16.png" alt="" width="1117" height="339" class="aligncenter size-full wp-image-9154" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-16.png 1117w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-16-300x91.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-16-1024x311.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-16-768x233.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-16-585x178.png 585w" sizes="(max-width: 1117px) 100vw, 1117px" /></a><br />
Choose <strong>IP addresses</strong>, name the <strong>Target group name</strong> and change the <strong>port </strong>to 3306. The correct VPC should be selected.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-17.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-17.png" alt="" width="874" height="803" class="aligncenter size-full wp-image-9155" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-17.png 874w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-17-300x276.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-17-768x706.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-17-585x537.png 585w" sizes="(max-width: 874px) 100vw, 874px" /></a><br />
Leave the health checks, they are automatically populated for the right port and click <strong>Next</strong>.<br />
On the next screen below, enter the IPs that you got from the nslookup for the RDS proxy. In my case it looks like this. Make sure the port is 3306 and click on <strong>Include as pending below</strong> and finally click on <strong>Create target group</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-18.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-18.png" alt="" width="1448" height="732" class="aligncenter size-full wp-image-9157" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-18.png 1448w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-18-300x152.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-18-1024x518.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-18-768x388.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-18-1170x591.png 1170w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-18-585x296.png 585w" sizes="(max-width: 1448px) 100vw, 1448px" /></a><br />
Go back to the original browser tab where you create the NLB and click the refresh button. You&#8217;ll be able to select the target group now.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-19.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-19.png" alt="" width="1047" height="248" class="aligncenter size-full wp-image-9159" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-19.png 1047w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-19-300x71.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-19-1024x243.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-19-768x182.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-19-585x139.png 585w" sizes="(max-width: 1047px) 100vw, 1047px" /></a><br />
Click on <strong>Create load balancer</strong> at the bottom. It takes a couple of minutes to provision the NLB. Once done, click on the <strong>Listeners </strong>tab and then the <strong>target group</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-20.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-20.png" alt="" width="889" height="356" class="aligncenter size-full wp-image-9160" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-20.png 889w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-20-300x120.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-20-768x308.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-20-585x234.png 585w" sizes="(max-width: 889px) 100vw, 889px" /></a><br />
It will take another couple of minutes, but you should see that the targets are unhealthy. Why is that? Because our RDS proxy can get requests from the EC2 instances only. Thе NLB can&#8217;t access the RDS proxy. Per AWS, we have to allow the CIDRs of the NLB to access the RDS proxy. That&#8217;s easy. We created an internal NLB with 192.168.102.0/24 and 192.168.103.0/24 subnets, so we have to modify the <strong>sgRDS </strong>security group. Do the same. This is how my security group <strong>sgRDS </strong>looks like now.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-21.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-21.png" alt="" width="1444" height="280" class="aligncenter size-full wp-image-9161" /></a><br />
And if you check the target group, you should see both RDS proxy instance as healthy.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-22.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-22.png" alt="" width="1488" height="749" class="aligncenter size-full wp-image-9171" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-22.png 1488w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-22-300x151.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-22-1024x515.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-22-768x387.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-22-1170x589.png 1170w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-22-585x294.png 585w" sizes="(max-width: 1488px) 100vw, 1488px" /></a></p>
<h1>Test 3</h1>
<p>Let&#8217;s check the access on the NLB. Get the DNS name. In my case it&#8217;s rds-nlb-40d1b9bfc867b2fb.elb.us-east-2.amazonaws.com.<br />
Go back to the EC2 instance in the same account and try to access the database.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-24.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-24.png" alt="" width="903" height="405" class="aligncenter size-full wp-image-9173" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-24.png 903w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-24-300x135.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-24-768x344.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-24-585x262.png 585w" sizes="(max-width: 903px) 100vw, 903px" /></a><br />
Yep, we are doing great. Let&#8217;s recap. We can&#8217;t access the RDS directly from another account because &#8211; well, it&#8217;s another account that we don&#8217;t trust and our RDS DB is in a private subnet. So, we have to create an endpoint service that requires a network load balancer. But, the NLB requires IP targets and our RDS endpoints are DNS names. Which means that the DNS names can change its IPs, so we used an RDS proxy DNS names converted to IPs which AWS claims that they won&#8217;t change. </p>
<h1>Endpoint service</h1>
<p>The Provider (we) creates an Endpoint service, the Customer (the vendor) creates the Endpoint. Simple as that. It doesn&#8217;t have to be a vendor. Maybe the proper term is the Consumer. So, we (the provider) expose some service as Endpoint Service and someone else tries to access it.<br />
An Endpoint service requires a network load balancer. We did that. So let&#8217;s create the endpoint service. It&#8217;s under the VPC menu.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-25.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-25.png" alt="" width="175" height="395" class="aligncenter size-full wp-image-9175" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-25.png 175w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-25-133x300.png 133w" sizes="(max-width: 175px) 100vw, 175px" /></a><br />
Click on <strong>Endpoint Services</strong> and then <strong>Create endpoint service</strong>.<br />
Name the endpoint service and check the network load balancer. Make sure that the <strong>Acceptance required</strong> is checked.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-26.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-26.png" alt="" width="855" height="666" class="aligncenter size-full wp-image-9176" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-26.png 855w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-26-300x234.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-26-768x598.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-26-585x456.png 585w" sizes="(max-width: 855px) 100vw, 855px" /></a><br />
Once created (in a second), get the service name. Copy that URL highlighted.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-27.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-27.png" alt="" width="1308" height="671" class="aligncenter size-full wp-image-9179" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-27.png 1308w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-27-300x154.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-27-1024x525.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-27-768x394.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-27-1170x600.png 1170w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-27-585x300.png 585w" sizes="(max-width: 1308px) 100vw, 1308px" /></a><br />
Select the endpoint service and from the Actions menu, choose <strong>Allow principals</strong>.  Add * for ARN which means everyone. Now this is really bad. For the sake of simplicity, I&#8217;ve added * (everyone) but you want to add an ARN role from the other account.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-28.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-28.png" alt="" width="917" height="608" class="aligncenter size-full wp-image-9181" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-28.png 917w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-28-300x199.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-28-768x509.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-28-780x516.png 780w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-28-585x388.png 585w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-28-263x175.png 263w" sizes="(max-width: 917px) 100vw, 917px" /></a></p>
<h1>Endpoint</h1>
<p>The endpoint is the Consumer, the vendor or some other VPC. Go to that account. We are no longer working on the original account, log to the second account and go to the <strong>Endpoint </strong>under VPC menu. Click on <strong>Create endpoint</strong>. Enter the name for endpoint, click on <strong>Other endpoint services</strong> and paste the endpoint that you got in the previous step. Click on <strong>Verify service</strong> and you should see that it&#8217;s OK.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-29.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-29.png" alt="" width="842" height="668" class="aligncenter size-full wp-image-9183" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-29.png 842w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-29-300x238.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-29-768x609.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-29-585x464.png 585w" sizes="(max-width: 842px) 100vw, 842px" /></a><br />
Scroll down and choose the VPC where you want to create the endpoint. In our case, we want to use the EC2 instance that&#8217;s in the public subnet. Add the two public subnets.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-31.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-31.png" alt="" width="891" height="745" class="aligncenter size-full wp-image-9188" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-31.png 891w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-31-300x251.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-31-768x642.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-31-585x489.png 585w" sizes="(max-width: 891px) 100vw, 891px" /></a><br />
And for the security group, add the EC2 security group.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-32.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-32.png" alt="" width="909" height="285" class="aligncenter size-full wp-image-9189" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-32.png 909w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-32-300x94.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-32-768x241.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-32-585x183.png 585w" sizes="(max-width: 909px) 100vw, 909px" /></a><br />
NOTE: If you go to the <strong>Interfaces </strong>section under EC2, you&#8217;ll see three NICs. One is for the EC2 instance that we&#8217;ve created, the other two are the endpoints.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-30.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-30.png" alt="" width="1414" height="293" class="aligncenter size-full wp-image-9186" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-30.png 1414w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-30-300x62.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-30-1024x212.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-30-768x159.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-30-1170x242.png 1170w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-30-585x121.png 585w" sizes="(max-width: 1414px) 100vw, 1414px" /></a><br />
Anyway, once you create the endpoint, you&#8217;ll see this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-33.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-33.png" alt="" width="719" height="294" class="aligncenter size-full wp-image-9192" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-33.png 719w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-33-300x123.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-33-585x239.png 585w" sizes="(max-width: 719px) 100vw, 719px" /></a><br />
Go to the other account (Provider) and under the endpoint services (VPC menu, Endpoint connections tab), you&#8217;ll see a request for the connection. That&#8217;s what <strong>Accepance required</strong> means when we created the <strong>Endpoint Service</strong>. Accept the connection. It takes about 30 seconds to complete the acceptance. </p>
<h1>Test 4</h1>
<p>Go to the Consumer account and click on <strong>Endpoint </strong>and then select the endpoint. Under the <strong>Details </strong>tab you&#8217;ll see three DNS entries.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-34.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-34.png" alt="" width="691" height="883" class="aligncenter size-full wp-image-9194" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-34.png 691w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-34-235x300.png 235w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-34-585x748.png 585w" sizes="(max-width: 691px) 100vw, 691px" /></a><br />
Copy one of them and log to the EC2 instance in that account and try to access the RDS. </p>
<pre class="brush: bash; title: ; notranslate">
mysql -h vpce-08e3fbbe49e5f241b-q4e8rrlt.vpce-svc-01cc20f911a4789ff.us-east-2.vpce.amazonaws.com -u admin -p
</pre>
<p>You won&#8217;t be able to do so. Finally, edit the security group sgEC2 that we assigned to the endpoint and add a reference to itself for port 3306. It looks like this.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-35.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-35.png" alt="" width="1677" height="762" class="aligncenter size-full wp-image-9195" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-35.png 1677w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-35-300x136.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-35-1024x465.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-35-768x349.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-35-1536x698.png 1536w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-35-1170x532.png 1170w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-35-585x266.png 585w" sizes="(max-width: 1677px) 100vw, 1677px" /></a><br />
And if you try to access the RDS now, you&#8217;ll be able to do so.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-36.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-36.png" alt="" width="888" height="283" class="aligncenter size-full wp-image-9196" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-36.png 888w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-36-300x96.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-36-768x245.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-36-585x186.png 585w" sizes="(max-width: 888px) 100vw, 888px" /></a></p>
<h1>Endpoint service</h1>
<p>You can also go the the Provider account and delete the principal under <strong>Allowed principals</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2022/03/P159-37.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2022/03/P159-37.png" alt="" width="1836" height="822" class="aligncenter size-full wp-image-9198" srcset="https://blog.andreev.it/wp-content/uploads/2022/03/P159-37.png 1836w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-37-300x134.png 300w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-37-1024x458.png 1024w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-37-768x344.png 768w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-37-1536x688.png 1536w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-37-1170x524.png 1170w, https://blog.andreev.it/wp-content/uploads/2022/03/P159-37-585x262.png 585w" sizes="(max-width: 1836px) 100vw, 1836px" /></a><br />
It&#8217;s not needed anymore.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2022/03/aws-access-rds-database-using-privatelink-from-another-account/feed/</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
			</item>
		<item>
		<title>AWS, WordPress: Deploy WordPress on AWS Linux using Terraform, EC2, RDS and EFS</title>
		<link>https://blog.andreev.it/2018/08/136-terraform-deploy-wordpress-on-aws-linux-using-terraform-ec2-rds-and-efs/</link>
					<comments>https://blog.andreev.it/2018/08/136-terraform-deploy-wordpress-on-aws-linux-using-terraform-ec2-rds-and-efs/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Sat, 11 Aug 2018 16:18:35 +0000</pubDate>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[EC2]]></category>
		<category><![CDATA[EFS]]></category>
		<category><![CDATA[RDS]]></category>
		<category><![CDATA[Terraform]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=4060</guid>

					<description><![CDATA[I&#8217;ve started playing with Terraform in order to automate some server builds and found&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>I&#8217;ve started playing with Terraform in order to automate some server builds and found it to be very useful. It has its own quirks, strange JSON-like syntax and it takes some time to get fully on-board. I&#8217;ve noticed several bugs but there is always a workaround if you google it. At the time of this writing, Terraform is version 0.11.7 so it&#8217;s still some kind of beta. The team behind it are making a lot of changes so expect some things to break. The book that I was using to study was already out of date and some commands were deprecated.<br />
I won&#8217;t explain how to install it and configure it. It&#8217;s very <a href="https://www.terraform.io/intro/getting-started/install.html" rel="noopener noreferrer" target="_blank">easy </a>to get it up and running. In order for the following script to work, make sure that you have Terraform and <a href="https://blog.andreev.it/?p=1905" rel="noopener noreferrer" target="_blank">AWS CLI</a> installed and configured.<br />
Create a separate folder/directory for this project and create three files. The first file is <strong>vars.tf</strong>. That&#8217;s where we define the variables. </p>
<pre class="brush: bash; title: ; notranslate">
variable &quot;region&quot; {
	description = &quot;The region for the deployment&quot;
	default = &quot;us-west-2&quot;
}
	
variable &quot;vpc_id&quot; {
	description = &quot;The VPC ID where WordPress will reside&quot;
	default = &quot;vpc-a36ga9zd&quot;
}

variable &quot;ami_id&quot; {
	description = &quot;The AMI ID for AWS Linux 2 in us-west-2. In other regions, the ID is different&quot;
	default = &quot;ami-a9d09ed1&quot;

}

variable &quot;instance_type&quot; {
	description = &quot;AWS Instance type to be used for the WordPress instance&quot;
	default = &quot;t2.small&quot;
}

variable &quot;volume_size&quot; {
	description = &quot;EBS volume size in GBs for the instance&quot;
	default = 8
}

variable &quot;key_name&quot; {
	description = &quot;The key pair that will be used to log to the server using SSH&quot;
	default = &quot;MyKeyPair-Oregon&quot;
}

variable &quot;ssh_port&quot; {
	description = &quot;The SSH port for the server&quot;
	default = 22
}

variable &quot;http_port&quot; {
	description = &quot;The HTTP port for the server&quot;
	default = 80
}

variable &quot;mysql_port&quot; {
	description = &quot;The MySQL port for the database&quot;
	default = 3306
}

variable &quot;nfs_port&quot; {
	description = &quot;The NFS port for the shared filesystem&quot;
	default = 2049
}

variable &quot;allocated_storage&quot; {
	description = &quot;The size in GBs of the SQL database&quot;
	default = 10
}

variable &quot;instance_class&quot; {
	description = &quot;The size/type of the SQL instance&quot;
	default = &quot;db.t2.micro&quot;
}

variable &quot;db_admin&quot; {
	description = &quot;The dbadmin username&quot;
	default = &quot;dbadmin&quot;
}

variable &quot;db_password&quot; {
	description = &quot;The dbadmin password&quot;
	default = &quot;SuperSecret&quot;
}

variable &quot;db_name&quot; {
	description = &quot;The database name&quot;
	default = &quot;dbwordpress&quot;
}
</pre>
<p>Make sure you specify your region, your VPC ID and the key name. That&#8217;s how you will login to your instance. You can find your key name if you go to <strong>Key Pairs</strong> menu in AWS console.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/08/P113-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/08/P113-01.png" alt="" width="544" height="227" class="aligncenter size-full wp-image-8274" /></a><br />
I tried to test the same setup on CentOS 7.x but for some reason the user data boot script was never executed, thus making this script unusable. It might work with Ubuntu or some other flavor of Linux, if you can make the user data script execute on boot and make some modifications, e.g. apt-get instead of yum etc&#8230;<br />
The next file is <strong>outputs.tf</strong>. These are the variables that are needed at the end of the run of the script. BTW, the script takes around 4 minutes to complete. </p>
<pre class="brush: bash; title: ; notranslate">
output &quot;efs_dns_name&quot; {
	value = &quot;${aws_efs_file_system.efsWordPress.dns_name}&quot;
}

output &quot;ip_address&quot; {
    value = &quot;${aws_instance.wordpress.public_ip}&quot;
}

output &quot;sql_hostname&quot; {
    value = &quot;${aws_db_instance.dbWordPress.address}&quot;
}
</pre>
<p>At the end of the script, we&#8217;ll get the DNS name of the EFS filesystem, the external IP address of the instance and the MySQL hostname. We&#8217;ll need the last two.<br />
And finally, the main script (<strong>main.tf</strong>) is where all the resources that are needed are specified.</p>
<pre class="brush: bash; highlight: [13,61,62,63,64,65,66,68,83,87]; title: ; notranslate">
provider &quot;aws&quot; {
	region = &quot;${var.region}&quot;
}

resource &quot;aws_security_group&quot; &quot;sgWordPress&quot; {
	name = &quot;sgWordPress&quot;
	vpc_id      = &quot;${var.vpc_id}&quot;

	ingress {
		from_port = &quot;${var.ssh_port}&quot;
		to_port = &quot;${var.ssh_port}&quot;
		protocol = &quot;tcp&quot;
		cidr_blocks =&#x5B;&quot;0.0.0.0/0&quot;]
	}

	ingress {
		from_port = &quot;${var.http_port}&quot;
		to_port = &quot;${var.http_port}&quot;
		protocol = &quot;tcp&quot;
		cidr_blocks = &#x5B;&quot;0.0.0.0/0&quot;]
	}

	ingress {
		from_port = &quot;${var.mysql_port}&quot;
		to_port = &quot;${var.mysql_port}&quot;
		protocol = &quot;tcp&quot;
		self = true
	}

	ingress {
		from_port = &quot;${var.nfs_port}&quot;
		to_port = &quot;${var.nfs_port}&quot;
		protocol = &quot;tcp&quot;
		self = true
	}

	egress {
		from_port = 0
		to_port = 0
		protocol = &quot;-1&quot;
		cidr_blocks = &#x5B;&quot;0.0.0.0/0&quot;]
	}

	tags {
		Name = &quot;sgWordPress&quot;
	}
}

resource &quot;aws_efs_file_system&quot; &quot;efsWordPress&quot; {
  creation_token = &quot;EFS for WordPress&quot;

  tags {
    Name = &quot;EFS for WordPress&quot;
  }
}

data &quot;aws_subnet_ids&quot; &quot;suballIDs&quot; {
	vpc_id = &quot;${var.vpc_id}&quot;
}

resource &quot;aws_efs_mount_target&quot; &quot;mtWordPress&quot; {
  count = &quot;${length(data.aws_subnet_ids.suballIDs.ids)}&quot;
  file_system_id = &quot;${aws_efs_file_system.efsWordPress.id}&quot;
  subnet_id      = &quot;${element(data.aws_subnet_ids.suballIDs.ids, count.index)}&quot;
  security_groups = &#x5B;&quot;${aws_security_group.sgWordPress.id}&quot;]
}

resource &quot;aws_instance&quot; &quot;wordpress&quot; {
	ami = &quot;${var.ami_id}&quot;
	instance_type = &quot;${var.instance_type}&quot;
	vpc_security_group_ids = &#x5B;&quot;${aws_security_group.sgWordPress.id}&quot;]
	key_name = &quot;${var.key_name}&quot; 
	ebs_block_device {
		device_name = &quot;/dev/sdb&quot;
    	volume_size = &quot;${var.volume_size}&quot;
    	delete_on_termination = &quot;true&quot;
  	}

	tags {
		Name = &quot;WordPress Server&quot;
	}

	user_data = &lt;&lt;EOF
		#!/bin/bash
		echo &quot;${aws_efs_file_system.efsWordPress.dns_name}:/ /var/www/html nfs defaults,vers=4.1 0 0&quot; &gt;&gt; /etc/fstab
		yum install -y php php-dom php-gd php-mysql
		for z in {0..120}; do
			echo -n .
			host &quot;${aws_efs_file_system.efsWordPress.dns_name}&quot; &amp;&amp; break
		  	sleep 1
		done
		cd /tmp
		wget https://www.wordpress.org/latest.tar.gz
		mount -a
		tar xzvf /tmp/latest.tar.gz --strip 1 -C /var/www/html
		rm /tmp/latest.tar.gz
		chown -R apache:apache /var/www/html
		systemctl enable httpd
		sed -i 's/#ServerName www.example.com:80/ServerName www.myblog.com:80/' /etc/httpd/conf/httpd.conf
		sed -i 's/ServerAdmin root@localhost/ServerAdmin admin@myblog.com/' /etc/httpd/conf/httpd.conf
		#setsebool -P httpd_can_network_connect 1
		#setsebool -P httpd_can_network_connect_db 1
		systemctl start httpd
		#firewall-cmd --zone=public --permanent --add-service=http
		#firewall-cmd --reload
		#iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
		#iptables -A OUTPUT -p tcp --sport 80 -m conntrack --ctstate ESTABLISHED -j ACCEPT
	EOF

}

resource &quot;aws_db_instance&quot; &quot;dbWordPress&quot; {
	identifier = &quot;dbwordpress&quot;
	engine = &quot;mysql&quot;
	engine_version = &quot;5.7&quot;
	allocated_storage = &quot;${var.allocated_storage}&quot;
	instance_class = &quot;${var.instance_class}&quot;
	vpc_security_group_ids = &#x5B;&quot;${aws_security_group.sgWordPress.id}&quot;]
	name = &quot;${var.db_name}&quot;
	username = &quot;${var.db_admin}&quot;
	password = &quot;${var.db_password}&quot;
	parameter_group_name = &quot;default.mysql5.7&quot;
	skip_final_snapshot = true
	tags {
		Name = &quot;WordPress DB&quot;
	}
}
</pre>
<p>The script starts with the name of the provided that will be used (AWS), then a security group is being defined with ports 22 and 80 open to the world. Opening port 22 to the world is not a good idea, so you can restrict the access. In line 13, you can change the subnets allowed, e.g. instead of [&#8220;0.0.0.0/0&#8221;], you can restrict the SSH to a couple of IPs, e.g. [&#8220;1.2.3.4/32&#8243;,&#8221;12.13.14.15/32&#8221;]. Then, we define the ports for NFS and MySQL. If you can see these ports are open to themselves only. That means that only the resources having assigned that security group can talk between themselves on these two ports. And finally, we allow all outgoing traffic.<br />
Further, we have an EFS file system created and mount targets. The mounts targets define in what availability zones the EFS system will be available. Since each region has different numbers of availability zones, we don&#8217;t know that number, so we have to enumerate the AZs for each region. If you look at lines 61 to 66 you&#8217;ll see how we do that. It&#8217;s pretty much a <a href="https://blog.gruntwork.io/terraform-tips-tricks-loops-if-statements-and-gotchas-f739bbae55f9" rel="noopener noreferrer" target="_blank">for..next loop</a> in Terraform.<br />
At line 68, we have our main resource defined, the instance. You&#8217;ll see that each resource has a lot of input parameters. Some of these are mandatory and some are optional. For each resource, you can find a detailed explanation on the Terraform site. For example, if you google <a href="https://www.google.com/search?q=terraform+aws_instance" rel="noopener noreferrer" target="_blank">&#8220;terraform aws_instance&#8221;</a> the first link that shows up on terraform.io website will be about that.<br />
At line 83 the custom script begins. It will add the EFS mount point to <strong>/etc/fstab</strong> so the NFS system is mounted on each reboot. At line 87 there is a short delay until EFS filesystem becomes available. Because the resources are created in parallel, it takes up to 90 seconds for the EFS DNS name to get propagated. If we don&#8217;t have the delay, the instance will boot up, try to mount the EFS system and fail, because the DNS mount point won&#8217;t be accessible. AWS Linux 2 comes with SELinux disabled and no firewalls, but if you have some other instance, you can uncomment the lines at the end of the user data script. Otherwise, SELinux will prevent Apache and MySQL to work with PHP. Lines 106 and 107 are if you use <strong>iptables </strong>instead of <strong>firewalld</strong>. Tailor to your needs. Finally, at line 112, the MySQL DB is defined.<br />
Once you have all these three files <strong>(vars.tf, outputs.tf and main.tf)</strong> modified and saved in the same folder/directory, you can star the provisioning. First, initialize the script so Terraform can download the plugin for AWS.</p>
<pre class="brush: bash; title: ; notranslate">
terraform init
</pre>
<p>Then, check if everything is OK with the script.</p>
<pre class="brush: bash; title: ; notranslate">
terraform plan
</pre>
<p>And finally, execute the script.</p>
<pre class="brush: bash; title: ; notranslate">
terraform apply
</pre>
<p>It will prompt you to say &#8220;<strong>yes</strong>&#8221; and after the script completes, you&#8217;ll have something like this at the end.</p>
<pre class="brush: bash; title: ; notranslate">
Apply complete! Resources: 7 added, 0 changed, 0 destroyed.

Outputs:

efs_dns_name = fs-64307acd.efs.us-west-2.amazonaws.com
ip_address = 34.220.235.222
sql_hostname = dbwordpress.cbh9gck8kp6s.us-west-2.rds.amazonaws.com
</pre>
<p>Go to <strong>http://your_ip</strong> and you should have the welcome WordPress screen. Use the database name, username and the password for the database defined in <strong>vars.tf</strong> (dbwordpress, dbadmin, SuperSecret) and for the hostname use the SQL DB output variable (<strong>sql_hostname</strong>) above.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/08/P113-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/08/P113-02.png" alt="" width="732" height="409" class="aligncenter size-full wp-image-8275" /></a><br />
And that&#8217;s it! You have your WordPress up and running on RDS and EFS filesystem without even logging to AWS console or your Linux instance.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2018/08/P113-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2018/08/P113-03.png" alt="" width="931" height="559" class="aligncenter size-full wp-image-8276" /></a><br />
Once you are done playing you can destroy all of the resources with one command.</p>
<pre class="brush: bash; title: ; notranslate">
terraform destroy
</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2018/08/136-terraform-deploy-wordpress-on-aws-linux-using-terraform-ec2-rds-and-efs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AWS: Restore MS SQL database to RDS</title>
		<link>https://blog.andreev.it/2017/08/109-aws-restore-ms-sql-database-rds/</link>
					<comments>https://blog.andreev.it/2017/08/109-aws-restore-ms-sql-database-rds/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Sat, 05 Aug 2017 22:32:25 +0000</pubDate>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[MS SQL]]></category>
		<category><![CDATA[RDS]]></category>
		<category><![CDATA[restore]]></category>
		<guid isPermaLink="false">http://blog.iandreev.com/?p=3099</guid>

					<description><![CDATA[I had to migrate a SQL 2014 database from our on-prem environment to AWS.&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>I had to migrate a SQL 2014 database from our on-prem environment to AWS. The requirement was to use RDS. So, these are the steps that I&#8217;ve taken in order to successfully migrate the database. You can also check the official AWS link <a href="http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/SQLServer.Procedural.Importing.html" target="_blank" rel="noopener noreferrer">here</a>. </p>
<p>First, take a backup of the existing database in <strong>BAK </strong>format. In my case for the purpose of this blog, I&#8217;ve backed up my vCenter database called <strong>VCDB </strong>in a file called <strong>VCDB.BAK</strong>. Once you have the file, create a S3 bucket in AWS with the default settings and upload the BAK file there. In my case the S3 bucket was named <strong>restoremybackup</strong>.<br />
Next, make sure you have access to a Windows server with SQL Management Studio installed, either in AWS or on-prem, but this server will need to talk to the RDS database over port 1433 TCP. I built a server in AWS and installed the SQL Management Studio, which is a free download. Make sure that you have a security group in place that allows port 1433. We will use this security group to assign it to the RDS instance. I&#8217;ve created a new security group called <strong>sgAllowSQLAccess</strong>. For the source, type the IP of the server with SQL Management Studio or the security group itself. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2017/08/P087-01.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/08/P087-01.png" alt="" width="681" height="375" class="aligncenter size-full wp-image-7650" srcset="https://blog.andreev.it/wp-content/uploads/2017/08/P087-01.png 681w, https://blog.andreev.it/wp-content/uploads/2017/08/P087-01-300x165.png 300w, https://blog.andreev.it/wp-content/uploads/2017/08/P087-01-585x322.png 585w" sizes="(max-width: 681px) 100vw, 681px" /></a><br />
Then, go to RDS and create an <strong>Option Group</strong>. Name the <strong>Option Group</strong>, in my case it&#8217;s <strong>ogSQL2014Restore</strong>, choose the engine and the version. I am using <strong>sqlserver-se</strong> which is <strong>SQL Standard Edition</strong> and the version is <strong>12.00</strong> which is <strong>MS SQL 2014</strong>. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2017/08/P087-02.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/08/P087-02.png" alt="" width="684" height="282" class="aligncenter size-full wp-image-7651" srcset="https://blog.andreev.it/wp-content/uploads/2017/08/P087-02.png 684w, https://blog.andreev.it/wp-content/uploads/2017/08/P087-02-300x124.png 300w, https://blog.andreev.it/wp-content/uploads/2017/08/P087-02-585x241.png 585w" sizes="(max-width: 684px) 100vw, 684px" /></a><br />
Once created, select your <strong>Option Group</strong> and click on <strong>Add Option</strong>. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2017/08/P087-03.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/08/P087-03.png" alt="" width="672" height="288" class="aligncenter size-full wp-image-7652" srcset="https://blog.andreev.it/wp-content/uploads/2017/08/P087-03.png 672w, https://blog.andreev.it/wp-content/uploads/2017/08/P087-03-300x129.png 300w, https://blog.andreev.it/wp-content/uploads/2017/08/P087-03-585x251.png 585w" sizes="(max-width: 672px) 100vw, 672px" /></a><br />
Choose <strong>SQLSERVER_BACKUP_RESTORE</strong>, then click on <strong>Create a New Role</strong>. For the role, use a name, in my case it&#8217;s <strong>iamRestoreSQLBackup</strong>. Then type the name of the S3 bucket that you just created and make sure that you select <strong>Apply Immediately &#8211; yes</strong>.<br />
Then click on <strong>Add Option</strong>.<br />
<a href="https://blog.andreev.it/wp-content/uploads/2017/08/P087-04.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/08/P087-04.png" alt="" width="636" height="316" class="aligncenter size-full wp-image-7653" srcset="https://blog.andreev.it/wp-content/uploads/2017/08/P087-04.png 636w, https://blog.andreev.it/wp-content/uploads/2017/08/P087-04-300x149.png 300w, https://blog.andreev.it/wp-content/uploads/2017/08/P087-04-585x291.png 585w" sizes="(max-width: 636px) 100vw, 636px" /></a><br />
Now, it&#8217;s time to create the RDS database. Launch a new RDS instance and use the parameters that suit your needs. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2017/08/P087-05.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/08/P087-05.png" alt="" width="647" height="566" class="aligncenter size-full wp-image-7654" srcset="https://blog.andreev.it/wp-content/uploads/2017/08/P087-05.png 647w, https://blog.andreev.it/wp-content/uploads/2017/08/P087-05-300x262.png 300w, https://blog.andreev.it/wp-content/uploads/2017/08/P087-05-585x512.png 585w" sizes="(max-width: 647px) 100vw, 647px" /></a><br />
For the next set of options, choose your preferred settings, but make sure that you assign the <strong>Security Group</strong> that we just created and the <strong>Option Group</strong> that we also created. In my case it looks like this. </p>
<p><a href="https://blog.andreev.it/wp-content/uploads/2017/08/P087-06.png"><img loading="lazy" decoding="async" src="https://blog.andreev.it/wp-content/uploads/2017/08/P087-06.png" alt="" width="571" height="706" class="aligncenter size-full wp-image-7655" srcset="https://blog.andreev.it/wp-content/uploads/2017/08/P087-06.png 571w, https://blog.andreev.it/wp-content/uploads/2017/08/P087-06-243x300.png 243w" sizes="(max-width: 571px) 100vw, 571px" /></a><br />
Once the RDS it&#8217;s in available state, try to telnet to port 1433 to the RDS endpoint from the Windows server where you have the SQL Management Studio installed. If everything is OK, you are ready to restore the database. In SQL Management Studio, select a <strong>New Query</strong> and type the following. </p>
<pre class="brush: sql; title: ; notranslate">
exec msdb.dbo.rds_restore_database 
        @restore_db_name='database_name', 
        @s3_arn_to_restore_from='arn:aws:s3:::bucket_name/file_name_and_extension';
</pre>
<p>Replace <strong>&#8216;database_name&#8217;</strong> and <strong>&#8216;bucket_name/file_name_and_extenstion&#8217;</strong> with your values. In my case, they were <strong>VCDB </strong>and <strong>restoremybackup/VCDB.BAK</strong>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2017/08/109-aws-restore-ms-sql-database-rds/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
