Skip to main content

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
Basic information

이미지 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

  1. Go to KakaoCloud Console > VPC and select Security Group.

  2. Click the [Create security group] button by referring to the followings.

    Security Group: tutorial-bastion-sg
    1. Enter the name and description of the security group as follows:

      NameDescription (Optional)
      tutorial-bastion-sgSecurity policy for bastion host
    2. Click the [Add] button at the bottom, set the inbound conditions as follows, and click the [Apply] button.

      Check my public IP

      Click the button below to check your current public IP.

      Inbound policy to addItemSetting value
      bastion inbound policy 1ProtocolTCP
      Source{Your public IP}/32
      Port number10000-10010
      Description (Optional)Bastion inbound policy 1
      bastion inbound policy 2ProtocolTCP
      Source{Your public IP}/32
      Port number81
      Description (Optional)Bastion inbound policy 2
      bastion inbound policy 3ProtocolTCP
      Source{Your public IP}/32
      Port number22
      Description (Optional)Bastion inbound policy 3
    Security Group: tutorial-web-sg
    1. Enter the name and description of the security group as follows:

      NameDescription (Optional)
      tutorial-web-sgSecurity policy for web server
    2. Click the [Add] button at the bottom, set the inbound conditions as follows, and click the [Apply] button.

      Inbound policy to addItemSetting value
      Web inbound policyProtocolTCP
      Source10.0.0.0/20
      Port number80
      Description (Optional)Web inbound
    Security Group: tutorial-app-sg
    1. Enter the name and description of the security group as follows:

      NameDescription (Optional)
      tutorial-app-sgSecurity policy for application server
    2. Click the [Add] button at the bottom, set the inbound conditions as follows, and click the [Apply] button.

      Inbound policy to addItemSetting value
      App inbound policyProtocolTCP
      Source10.0.32.0/20
      Port number8080
      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:

  1. Go to KakaoCloud Console > Beyond Compute Service > Virtual Machine.

  2. In the Instance menu, click the [Create instance] button and create a VM instance as follows:

    CategoryItemSetting/Entry valueDescription
    Basic informationNametutorial-bastion
    Count1
    ImageUbuntu 20.04
    Instance typem2a.large
    VolumeRoot Volume20
    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.
    NetworkVpctutorial
    Subnetmain (10.0.0.0/20)
    Security grouptutorial-bastion-sg

Web instance

To prepare the foundation for building the web service, create a VM instance.

  1. Go to KakaoCloud Console > Beyond Compute Service > Virtual Machine.

  2. 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.
    CategoryItemSetting/Entry valueDescription
    Basic informationNametutorial-web
    Count2
    ImageUbuntu 20.04
    Instance typem2a.large
    VolumeRoot Volume20
    Key pair{USER_KEYPAIR}Select the key pair created or used above
    NetworkVpctutorial
    Subnet{VPC_ID}_sn_2 (10.0.16.0/20)
    Security grouptutorial-web-sg

App server instance

To prepare the foundation for the application layer where business logic is executed, create a VM instance.

  1. Go to KakaoCloud Console > Beyond Compute Service > Virtual Machine.

  2. In the Instance menu, click the [Create instance] button and create a VM server instance as follows:

    CategoryItemSetting/Entry valueDescription
    Basic informationNametutorial-app
    Count2
    ImageUbuntu 20.04
    Instance typem2a.large
    VolumeRoot Volume20
    Key pair{USER_KEYPAIR}Select the key pair created or used above
    NetworkVpctutorial
    Subnet{VPC_ID}_sn_4 (10.0.48.0/20)
    Security grouptutorial-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.

info

If a bad permissions error occurs due to key pair file permission issues, you can resolve it by adding the sudo command.

  1. 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.
  2. 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).
  3. 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 VariableDescription
    PRIVATE_KEY🖌Key file name
    BASTION_PUBLIC_IP🖌In Virtual Machine > Instance menu, select the created `bastion` instance and check in the Network tab
  4. 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.sh
    What 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.

  5. 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

      ItemDescription
      {BASTION_PUBLIC_IP}Check this information by going to Virtual Machine > Instance menu > clicking the 'Bastion' instance > Network tab.
  6. Go to Dashboard > Streams.

  7. Enter the information for the web and app hosts as follows.

    CategoryItemSetting value
    tutorial-web-1Incoming Port10000
    Forward HostPrivate IP of the tutorial-web-1 instance
    - Check this information by going to Virtual Machine > Instance menu > clicking tutorial-web-1 instance > Network tab.
    Forward Port22
    tutorial-web-2Incoming Port10001
    Forward HostPrivate IP of the tutorial-web-2 instance
    - Check this information by going to Virtual Machine > Instance menu > clicking tutorial-web-2 instance > Network tab.
    Forward Port22
    tutorial-app-1Incoming Port10002
    Forward HostPrivate IP of the tutorial-app-1 instance
    - Check this information by going to Virtual Machine > Instance menu > clicking tutorial-app-1 instance > Network tab.
    Forward Port22
    tutorial-app-2Incoming Port10003
    Forward HostPrivate IP of the tutorial-app-2 instance
    - Check this information by going to Virtual Machine > Instance menu > clicking tutorial-app-2 instance > Network tab.
    Forward Port22
  8. 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
    1. Go to the Virtual Machine > Instance menu and select the created Web instance.

    2. In the Security tab, click the hyperlink tutorial-web-sg↗️ and select Manage inbound policies.

    3. Click the [Add] button, add an inbound policy as follows, and click the [Apply] button.

      caution

      The changes will not be saved unless you click the [Apply] button.

      CategoryItemSetting value
      WebProtocolTCP
      Source{BASTION_PRIVATE_IP}/32
      - Check the Network tab after selecting the Bastion instance created in the Virtual Machine > Instance menu.
      Port number22
      Description (Optional)Web inbound policy
    App instance
    1. Go to the Virtual Machine > Instance menu and select the created App instance.

    2. In the Security tab, click the hyperlink tutorial-app-sg↗️ and select Manage inbound policies.

    3. Click the [Add] button, add an inbound policy as follows, and click the [Apply] button.

      caution

      The changes will not be saved unless you click the [Apply] button.

      CategoryItemSetting value
      AppProtocolTCP
      Source{BASTION_PRIVATE_IP}/32
      - Check the Network tab after selecting the Bastion instance created in the Virtual Machine > Instance menu
      Port number22
      Description (Optional)App inbound policy
  9. 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 10003

    Environment VariableDescription
    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.

  1. Go to the KakaoCloud Console > Data Store > MySQL menu.

  2. In the Instance Group tab, click the [Create instance group] button by referring to the followings.

    CategoryItemSetting/Entry value
    Basic settingsInstance group nametutorial-mysql
    DescriptionOptional
    MySQL settingsEngine versionUse the specified value
    MySQL usernameadmin
    MySQL passwordroot1234
    Instance availability/CountSingle (Primary instance)
    Instance typem2a.large
    Storage type/size100
    Log storage type/size100
    Network settingsVPCtutorial
    Subnet{VPC_ID}_sn_5 (10.0.64.0/20)
    Automatic backupAutomatic backup optionsDisabled

Step 3. Create application server

The WAS (Web Application Server) connects to the DB and provides services such as user registration, login, and comments.

  1. 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 10003
    Environment VariablesDescription
    PRIVATE_KEY🖌Key file name
    BASTION_PUBLIC_IP🖌 Virtual Machine > Instance menu > click on the `Bastion` instance > Network tab.
  2. Install the example project.

    git clone -b kakaocloud-library https://github.com/kakaoenterprise/kakaocloud-tutorials
  3. Go to the folder where the example project is located.

    cd kakaocloud-tutorials
  4. Install the packages required to build and run the example project.

    bash install-requirements.sh
  5. 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_ENDPOINTn MySQL > Instance group, select tutorial-mysql and check the endpoint at the top.
    DB_USERNAME🖌adminDB user name
    DB_PASSWORD🖌root1234DB user password

Step 4. Create load balancer on application server

  1. Go to KakaoCloud Console > Load Balancing menu, and click the [Create load balancer] button.

  2. 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.

    CategoryItemSetting/Input value
    TypeNetwork Load Balancer (L4)
    Basic informationLoad Balancer Nametutorial-app-lb
    NetworkVPCtutorial
    Subnet{VPC_ID}_sn_3 (10.0.32.0/20)
    ListenerProtocolTCP
    Port8080
  3. Wait until the Provisioning status of the created Load Balancer becomes Active.

    • It takes about 1~3 minutes.
  4. Click Target Group on the left sidebar, then click the [Create target group] button.

  5. Set the information by referring to the following, and then click the [Next] button.

    CategoryItemSetting/Input value
    Load BalancerAvailable Zonekr-central-2-a
    Load Balancertutorial-app-lb
    ListenerTCP:8080
    Basic informationTarget Group Nametutorial-app-target-group
    ProtocolTCP
    AlgorithmRound Robin
    Sticky SessionUnused
    Health CheckUsed
    TypeTCP
    Check Cycle10
    Timeout5
    State transition criteria (Success)3
    State transition criteria (Failure)3
  6. Select the App instance to add to the target group from the list.

  7. Enter the port information as follows, click the [Add target] button, and then click the [Next] button.

    Target InstancePort
    tutorial-app-18080
    tutorial-app-28080
  8. Check the information you created and click the [Create] button.

  9. 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.

    1. Go to VPC > Security Group and select tutorial-app-sg.

    2. 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 PolicyDescriptionProtocolPacket SourcePort Number
      app inbound policy 1Access to load balancer and host
      performing health check 1
      TCP{healthcheck-ip1}/32
      - Go to Load Balancing > Target Group menu > Target tab >
      Health check IP by subnet
      .
      8080
      app inbound policy 2Access to load balancer and host
      performing health check 2
      TCP{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.

  1. 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 10001
    Environment variables Description
    PRIVATE_KEY🖌Key file name
    BASTION_PUBLIC_IP🖌In Virtual Machine > Instance, select Bastion instance and check the Network tab.
  2. Install the example project.

    git clone -b kakaocloud-library https://github.com/kakaoenterprise/kakaocloud-tutorials
  3. Move to the folder where the example project is located.

    cd kakaocloud-tutorials
  4. Install the packages required to build and run the example project.

    bash install-requirements.sh
  5. 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}:8080The 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.

  1. Click Load Balancing > [Create load balancer] button in the console.

  2. 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.

    CategoryItemSetting/Input value
    Select TypeApplication Load Balancer
    Basic informationLoad Balancer Nametutorial-web-lb
    NetworkVPCtutorial
    Subnetmain
    ListenerProtocolHTTP
    Port80
  3. Wait until the Provisioning status of the created Load Balancer becomes Active.

    • It takes about 1 to 3 minutes.
  4. Select Target Group on the left sidebar and click the [Create target group] button.

  5. After setting the following, click the [Next] button.

    CategoryItemSetting/Input value
    Load BalancerAvailable Zonekr-central-2-a
    Load Balancertutorial-web-lb
    ListenerTCP::80
    Basic informationTarget Group Nametutorial-web-target-group
    ProtocolHTTP
    AlgorithmRound Robin
    Sticky SessionNot Used
    Health CheckUsed
    TypeHTTP
    HTTP MethodGET
    HTTP Version 1.1
    HTTP Status Code200
    Check Path/
    Check Cycle10
    Timeout5
    Status Transition Criteria (Success)3
    Status Transition Criteria (Failure)3
  6. Select the instance to add to the target group from the list.

  7. Enter the following information in the port input field and click the [Add target] button and the [Next] button in sequence.

    Target instancePort
    tutorial-web-180
    tutorial-web-280
  8. Check the information you created and click the [Create] button.

  9. 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.

    1. Go to VPC > Security Group and select app-sg.

    2. 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 PolicyDescriptionProtocolPacket SourcePort Number
      Web inbound policy 1Access to load balancer and host
      performing health check 1
      TCP{healthcheck-ip1}/32
      - Go to Load Balancing > Target Group menu > Target tab >
      Health check IP by subnet
      .
      80
      Web inbound policy 2Access to load balancer and host
      performing health check 2
      TCP{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

  1. Go to Load Balancing > Load Balancer menu and select the web server load balancer you created.
  2. Click [Associate public IP].
  3. 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.
KakaoCloud Library