VM-based web service
This document introduces how to configure a web service in the cloud based on a 3-tier architecture. In particular, it will explore how to design a more secure and efficient web service architecture using a bastion host. A 3-tier architecture divides the web application into three logical layers, typically composed of the following:
- Web layer: The part that directly interacts with the user, accessed through a web browser.
- App layer: The part where business logic is executed, processing user requests and interacting with the database.
- Database layer: The part that stores and manages data, providing necessary data to the application layer.
About this scenario
This scenario, we will create a website called "KakaoCloud Library" using a 3-tier architecture. The key features are as follows:
- Configuration of a computing environment for web hosting using a 3-tier architecture
- Designing a secure and efficient web service architecture using a bastion server
- Ensuring high availability with KakaoCloud Load Balancer
- Configuring a database using KakaoCloud MySQL
- Estimated time: 60 minutes
- Recommended OS: MacOS, Ubuntu
- Region: kr-central-2
- Prerequisites
Scenario architecture
Prework
In the prerequisite stage, we will create the resources needed to configure a web service based on a 3-tier architecture. First, we will set up the KakaoCloud network environment necessary to deploy the 3-tier architecture. Next, we will configure web server instances and app server instances on VMs, and also set up a bastion server instance as an intermediary to access servers located in a private network that cannot be directly accessed externally for security reasons.
Network setup
Before configuring the computing environment on KakaoCloud, you first need to set up the network environment. Refer to Building network using NAT instances in multi-availability zone to configure the network environment for the 3-tier architecture.
This document explains how to create NAT instances to securely connect to the internet even in a private subnet. The network settings explained in this document are based on the values defined in the Building network using NAT instances in multi-availability zone document.
Configure security group
-
Go to KakaoCloud Console > VPC and select Security Group.
-
Click the [Create security group] button by referring to the followings.
Security Group: tutorial-bastion-sg
-
Enter the name and description of the security group as follows:
Name Description (Optional) tutorial-bastion-sg Security policy for bastion host -
Click the [Add] button at the bottom, set the inbound conditions as follows, and click the [Apply] button.
Check my public IPClick the button below to check your current public IP.
Inbound policy to add Item Setting value bastion inbound policy 1 Protocol TCP
Source {Your public IP}/32
Port number 10000-10010 Description (Optional) Bastion inbound policy 1 bastion inbound policy 2 Protocol TCP
Source {Your public IP}/32
Port number 81 Description (Optional) Bastion inbound policy 2 bastion inbound policy 3 Protocol TCP
Source {Your public IP}/32
Port number 22 Description (Optional) Bastion inbound policy 3
Security Group: tutorial-web-sg
-
Enter the name and description of the security group as follows:
Name Description (Optional) tutorial-web-sg Security policy for web server -
Click the [Add] button at the bottom, set the inbound conditions as follows, and click the [Apply] button.
Inbound policy to add Item Setting value Web inbound policy Protocol TCP
Source 10.0.0.0/20
Port number 80 Description (Optional) Web inbound
Security Group: tutorial-app-sg
-
Enter the name and description of the security group as follows:
Name Description (Optional) tutorial-app-sg Security policy for application server -
Click the [Add] button at the bottom, set the inbound conditions as follows, and click the [Apply] button.
Inbound policy to add Item Setting value App inbound policy Protocol TCP
Source 10.0.32.0/20 Port number 8080 Description (Optional) app inbound
-
Bastion instance
Combining a bastion host with a 3-tier architecture allows you to operate and manage cloud-based web services securely and efficiently.
The bastion server acts as an essential gateway component for remotely accessing cloud instances, strengthening security by preventing direct access to the web and application layers when accessing the cloud environment.
It also helps facilitate efficient remote access and management of cloud instances, coordinating communication between each layer.
To create a bastion
instance on a VM, follow these steps:
-
Go to KakaoCloud Console > Beyond Compute Service > Virtual Machine.
-
In the Instance menu, click the [Create instance] button and create a VM instance as follows:
Category Item Setting/Entry value Description Basic information Name tutorial-bastion Count 1 Image Ubuntu 20.04 Instance type m2a.large Volume Root Volume 20 Key pair {USER_KEYPAIR}
⚠️ The key pair must be securely stored when created for the first time.
Lost keys cannot be recovered and will need to be reissued.Network Vpc tutorial Subnet main (10.0.0.0/20) Security group tutorial-bastion-sg
Web instance
To prepare the foundation for building the web service, create a VM instance.
-
Go to KakaoCloud Console > Beyond Compute Service > Virtual Machine.
-
In the Instance menu, click the [Create instance] button and create a VM instance as follows:
caution- The Key Pair should be created once and stored securely. Lost keys cannot be recovered.
- Security Group is created with the default settings. The security group will be changed to match the detailed conditions later.
Category Item Setting/Entry value Description Basic information Name tutorial-web Count 2 Image Ubuntu 20.04 Instance type m2a.large Volume Root Volume 20 Key pair {USER_KEYPAIR}
Select the key pair created or used above Network Vpc tutorial Subnet {VPC_ID}
_sn_2 (10.0.16.0/20)Security group tutorial-web-sg
App server instance
To prepare the foundation for the application layer where business logic is executed, create a VM instance.
-
Go to KakaoCloud Console > Beyond Compute Service > Virtual Machine.
-
In the Instance menu, click the [Create instance] button and create a VM server instance as follows:
Category Item Setting/Entry value Description Basic information Name tutorial-app Count 2 Image Ubuntu 20.04 Instance type m2a.large Volume Root Volume 20 Key pair {USER_KEYPAIR}
Select the key pair created or used above Network Vpc tutorial Subnet {VPC_ID}
_sn_4 (10.0.48.0/20)Security group tutorial-app-sg
Step-by-step process
The detailed tasks for configuring the web service are as follows:
Step 1. Set up Bastion host
The bastion server serves as a gateway to access the web server and app server, and a public IP must be associated to allow external access.
If a bad permissions
error occurs due to key pair file permission issues, you can resolve it by adding the sudo
command.
-
In the Virtual Machine > Instance menu, select the
bastion
instance created earlier and click the [Associate public IP] button on the right.- The associated public IP can be checked in the Network tab.
-
Run the terminal in your local environment and use the
cd
command to navigate to the folder where you downloaded the key pair file.- If you created and used the key file for the first time, it is typically stored in the Downloads folder (
cd ~/Downloads
).
- If you created and used the key file for the first time, it is typically stored in the Downloads folder (
-
Execute the following command to access the instance via SSH.
chmod 400 ${PRIVATE_KEY}.pem # Grant read permissions
ssh -i ${PRIVATE_KEY}.pem ubuntu@${BASTION_PUBLIC_IP}Environment Variable Description PRIVATE_KEY🖌︎ Key file name BASTION_PUBLIC_IP🖌︎ In Virtual Machine > Instance menu, select the created `bastion` instance and check in the Network tab -
To run Nginx Proxy Manager, first configure the bastion host. Execute the provisioning with the following command.
sudo curl -o /tmp/install-bastion.sh https://raw.githubusercontent.com/kakaoenterprise/kakaocloud-tutorials/bastion-host/install-bastion.sh
bash /tmp/install-bastion.shWhat is Nginx Proxy Manager (NPM)?Nginx Proxy Manager (NPM) is an open-source project that helps you easily set up and manage a web server based on Nginx. Using this tool, users can effectively configure web servers and manage multiple domains.
-
Open a browser in your local environment, enter the following address, and access the management page.
-
http://${BASTION_PUBLIC_IP}:81/login
-
ID :
admin@example.com
-
Password :
changeme
Item Description {BASTION_PUBLIC_IP}
Check this information by going to Virtual Machine > Instance menu > clicking the 'Bastion' instance > Network tab.
-
-
Go to Dashboard > Streams.
-
Enter the information for the web and app hosts as follows.
Category Item Setting value tutorial-web-1 Incoming Port 10000 Forward Host Private IP of the tutorial-web-1
instance
- Check this information by going to Virtual Machine > Instance menu > clickingtutorial-web-1
instance > Network tab.Forward Port 22 tutorial-web-2 Incoming Port 10001 Forward Host Private IP of the tutorial-web-2
instance
- Check this information by going to Virtual Machine > Instance menu > clickingtutorial-web-2
instance > Network tab.Forward Port 22 tutorial-app-1 Incoming Port 10002 Forward Host Private IP of the tutorial-app-1
instance
- Check this information by going to Virtual Machine > Instance menu > clickingtutorial-app-1
instance > Network tab.Forward Port 22 tutorial-app-2 Incoming Port 10003 Forward Host Private IP of the tutorial-app-2
instance
- Check this information by going to Virtual Machine > Instance menu > clickingtutorial-app-2
instance > Network tab.Forward Port 22 -
Incoming traffic to the internal hosts will be routed through the bastion. Therefore, configure the security group as follows so that the web and app hosts can receive traffic sent from the bastion.
Web Instance
-
Go to the Virtual Machine > Instance menu and select the created
Web
instance. -
In the Security tab, click the hyperlink tutorial-web-sg↗️ and select Manage inbound policies.
-
Click the [Add] button, add an inbound policy as follows, and click the [Apply] button.
cautionThe changes will not be saved unless you click the [Apply] button.
Category Item Setting value Web Protocol TCP
Source {BASTION_PRIVATE_IP}/32
- Check the Network tab after selecting theBastion
instance created in the Virtual Machine > Instance menu.Port number 22 Description (Optional) Web inbound policy
App instance
-
Go to the Virtual Machine > Instance menu and select the created
App
instance. -
In the Security tab, click the hyperlink tutorial-app-sg↗️ and select Manage inbound policies.
-
Click the [Add] button, add an inbound policy as follows, and click the [Apply] button.
cautionThe changes will not be saved unless you click the [Apply] button.
Category Item Setting value App Protocol TCP
Source {BASTION_PRIVATE_IP}/32
- Check the Network tab after selecting theBastion
instance created in the Virtual Machine > Instance menuPort number 22 Description (Optional) App inbound policy
-
-
Verify that you can access each host from your local environment. Based on the forwarding information provided earlier, connect to the internal hosts mapped to the appropriate ports. Navigate to the folder containing the key pair file and run the following commands.
*tutorial-web-1
ssh -i ${PRIVATE_KEY}.pem ubuntu@${BASTION_PUBLIC_IP} -p 10000
\*tutorial-web-2
ssh -i ${PRIVATE_KEY}.pem ubuntu@${BASTION_PUBLIC_IP} -p 10001
\*tutorial-app-1
ssh -i ${PRIVATE_KEY}.pem ubuntu@${BASTION_PUBLIC_IP} -p 10002
\*tutorial-app-2
ssh -i ${PRIVATE_KEY}.pem ubuntu@${BASTION_PUBLIC_IP} -p 10003Environment Variable Description PRIVATE_KEY🖌︎ Key file name BASTION_PUBLIC_IP🖌︎ Check this information by going to Virtual Machine > Instance menu > clicking the Bastion instance > Network tab.
Step 2. Create managed MySQL database
KakaoCloud's MySQL is a fully managed database service provided in a VPC environment. This service allows you to easily provision MySQL instances through the console without complex installation processes, and use them securely in a logically separated network.
-
Go to the KakaoCloud Console > Data Store > MySQL menu.
-
In the Instance Group tab, click the [Create instance group] button by referring to the followings.
Category Item Setting/Entry value Basic settings Instance group name tutorial-mysql Description Optional MySQL settings Engine version Use the specified value MySQL username admin MySQL password root1234 Instance availability/Count Single (Primary instance) Instance type m2a.large Storage type/size 100 Log storage type/size 100 Network settings VPC tutorial Subnet {VPC_ID}_sn_5 (10.0.64.0/20)
Automatic backup Automatic backup options Disabled
Step 3. Create application server
The WAS (Web Application Server) connects to the DB and provides services such as user registration, login, and comments.
-
Connect to the VM mapped to the port set in nginx-proxy-manager.
# tutorial-app-1
ssh -i ${PRIVATE_KEY}.pem ubuntu@${BASTION_PUBLIC_IP} -p 10002
# tutorial-app-2
ssh -i ${PRIVATE_KEY}.pem ubuntu@${BASTION_PUBLIC_IP} -p 10003Environment Variables Description PRIVATE_KEY🖌︎ Key file name BASTION_PUBLIC_IP🖌︎ Virtual Machine > Instance menu > click on the `Bastion` instance > Network tab. -
Install the example project.
git clone -b kakaocloud-library https://github.com/kakaoenterprise/kakaocloud-tutorials
-
Go to the folder where the example project is located.
cd kakaocloud-tutorials
-
Install the packages required to build and run the example project.
bash install-requirements.sh
-
Enter the environment variables and run the example application.
sudo docker run -it \
-e MYSQL_HOST=${MYSQL_HOST} \
-e DB_USERNAME=${DB_USERNAME} \
-e DB_PASSWORD=${DB_PASSWORD} \
-p 8080:8080 \
--name kakaocloud-library-server -d \
$(sudo docker build -q -f ./server/deploy/Dockerfile ./server)Environment variables Setting values Description MYSQL_HOST🖌︎ MYSQL_ENDPOINT n MySQL > Instance group, select tutorial-mysql and check the endpoint at the top. DB_USERNAME🖌︎ admin DB user name DB_PASSWORD🖌︎ root1234 DB user password
Step 4. Create load balancer on application server
-
Go to KakaoCloud Console > Load Balancing menu, and click the [Create load balancer] button.
-
Enter the name and description of the load balancer to be created, and set the VPC and Subnet to be mapped. Refer to the information below, and proceed with the listener settings under the conditions below, and click the [Create] button.
Category Item Setting/Input value Type Network Load Balancer (L4) Basic information Load Balancer Name tutorial-app-lb Network VPC tutorial Subnet {VPC_ID}_sn_3
(10.0.32.0/20)Listener Protocol TCP
Port 8080 -
Wait until the Provisioning status of the created Load Balancer becomes
Active
.- It takes about 1~3 minutes.
-
Click Target Group on the left sidebar, then click the [Create target group] button.
-
Set the information by referring to the following, and then click the [Next] button.
Category Item Setting/Input value Load Balancer Available Zone kr-central-2-a Load Balancer tutorial-app-lb Listener TCP:8080 Basic information Target Group Name tutorial-app-target-group Protocol TCP
Algorithm Round Robin
Sticky Session Unused Health Check Used
Type TCP
Check Cycle 10
Timeout 5
State transition criteria (Success) 3
State transition criteria (Failure) 3
-
Select the App instance to add to the target group from the list.
-
Enter the port information as follows, click the [Add target] button, and then click the [Next] button.
Target Instance Port tutorial-app-1 8080 tutorial-app-2 8080 -
Check the information you created and click the [Create] button.
-
The load balancer and health check must be able to access the connected target, the Application server. To do this, add the following inbound policy to the security group of the Application server,
tutorial-app-sg
.-
Go to VPC > Security Group and select
tutorial-app-sg
. -
Click the [Manage inbound policy] button and add the following policy. You must add all the Health Check IPs that are confirmed. This example assumes that there are 2 Health Check IPs.
Inbound Policy Description Protocol Packet Source Port Number app inbound policy 1 Access to load balancer and host
performing health check 1TCP {healthcheck-ip1}/32
- Go to Load Balancing > Target Group menu > Target tab >
Health check IP by subnet.8080 app inbound policy 2 Access to load balancer and host
performing health check 2TCP {healthcheck-ip2}/32
- Go to Load Balancing > Target Group menu > Target tab >
Health check IP by subnet.8080
-
Step 5. Create web server
A Web server uses the HTTP protocol on the Internet network to transmit static information such as HTML, CSS, and Javascript code to a web browser.
Install the web server application nginx to provide static data, and set the example react project to be provided as static data when accessing the web server. Requests coming in under the /api path are forwarded to the app server.
-
Access the VM mapped to the port set in the Nginx Proxy Manager. Move to the folder where the key pair file exists and run it.
# tutorial-web-1
ssh -i ${PRIVATE_KEY}.pem ubuntu@${BASTION_PUBLIC_IP} -p 10000
# tutorial-web-2
ssh -i ${PRIVATE_KEY}.pem ubuntu@${BASTION_PUBLIC_IP} -p 10001Environment variables Description PRIVATE_KEY🖌︎ Key file name BASTION_PUBLIC_IP🖌︎ In Virtual Machine > Instance, select Bastion instance and check the Network tab. -
Install the example project.
git clone -b kakaocloud-library https://github.com/kakaoenterprise/kakaocloud-tutorials
-
Move to the folder where the example project is located.
cd kakaocloud-tutorials
-
Install the packages required to build and run the example project.
bash install-requirements.sh
-
Enter the environment variables and run the web server.
sudo docker run -it \
-e SERVER_ENDPOINT=${SERVER_ENDPOINT} \
-p 80:80 -p 443:443 \
--name kakaocloud-library-client -d \
$(sudo docker build -q -f ./client/deploy/Dockerfile ./client)Environment variables Setting values Description SERVER_ENDPOINT🖌︎ http://{APP_LB_PRIVATE_IP}:8080 The private IP of the created Application load balancer in `{APP_LB_PRIVATE_IP}`.
Step 6. Create load balancer on the web server
In this step, you will create a load balancer that receives client requests on the web server and distributes the incoming traffic to multiple servers.
-
Click Load Balancing > [Create load balancer] button in the console.
-
Enter the name and description of the load balancer to be created, and set the VPC and Subnet to be mapped. Refer to the information below and proceed with the listener settings under the following conditions and click the [Create] button.
Category Item Setting/Input value Select Type Application Load Balancer
Basic information Load Balancer Name tutorial-web-lb Network VPC tutorial Subnet main Listener Protocol HTTP Port 80 -
Wait until the Provisioning status of the created Load Balancer becomes
Active
.- It takes about 1 to 3 minutes.
-
Select Target Group on the left sidebar and click the [Create target group] button.
-
After setting the following, click the [Next] button.
Category Item Setting/Input value Load Balancer Available Zone kr-central-2-a Load Balancer tutorial-web-lb Listener TCP::80 Basic information Target Group Name tutorial-web-target-group Protocol HTTP Algorithm Round Robin Sticky Session Not Used Health Check Used
Type HTTP
HTTP Method GET
HTTP Version 1.1
HTTP Status Code 200
Check Path /
Check Cycle 10
Timeout 5
Status Transition Criteria (Success) 3
Status Transition Criteria (Failure) 3
-
Select the instance to add to the target group from the list.
-
Enter the following information in the port input field and click the [Add target] button and the [Next] button in sequence.
Target instance Port tutorial-web-1 80 tutorial-web-2 80 -
Check the information you created and click the [Create] button.
-
The load balancer and health check must be able to access the connected target, the web server. To do this, add the following inbound policy to the web server's security group,
tutorial-web-sg
.-
Go to VPC > Security Group and select app-sg.
-
Click the [Manage inbound policy] button and add the following policy. You must add all the Health Check IPs that are confirmed. This example assumes that there are 2 Health Check IPs.
Inbound Policy Description Protocol Packet Source Port Number Web inbound policy 1 Access to load balancer and host
performing health check 1TCP {healthcheck-ip1}/32
- Go to Load Balancing > Target Group menu > Target tab >
Health check IP by subnet.80 Web inbound policy 2 Access to load balancer and host
performing health check 2TCP {healthcheck-ip2}/32
- Go to Load Balancing > Target Group menu > Target tab >
Health check IP by subnet.80
-
Step 7. Associate public IP to web server load balancer
- Go to Load Balancing > Load Balancer menu and select the web server load balancer you created.
- Click [Associate public IP].
- Check the public IP in the Details tab.
Step 8. Check service access
Check the service by accessing the registered Public IP in the browser. If connected normally, you can see the following 'KakaoCloud Library' service screen.