아래의 AWS서비스를 이용하여 간단한 Scalable 웹을 만들어 보려고 한다. 해당 포스트를 통해 우리가 사용하는 서비스들이 어떻게 Scalable한 형태를 유지하는지 이해하며, 자주 사용되는 AWS 서비스들도 같이 살펴보려고 한다.
======
Elastic Computer Cloud (EC2),
Application Load Balancer (ALB),
Relational Database Service (RDS),
ElastiCache,
Simple Storage Service (S3),
Identity and Access Management (IAM),
CloudWatch,
AutoScaling
Demo를 진행하기전 테스트 환경을 아래와 같이 구성했다.
VPC
1)Scalable-VPC 10.0.0.0/16 생성
Subnet
1)ap-northeast-2a - Public1생성
2)ap-northeast-2b - Public2 생성
Route tables - Scalable-rtb-public
1) 라우트 테이블에 Intetnet gateways 추가 후 서브넷에 연결
서울 리전 (ap-northeast-2)에 서비스를 운영할 VPC(가상 네트워크)를 생성하였다. 해당 VPC내에서 서비스를 운용할 2개의 서브넷(IP주소의 범위)을 만들어 준다. 인터넷 연결이 필요하기 때문에 해당 서브넷에 대한 라우트테이블에 인터넷 게이트웨이를 추가해준다.
======
Step 0 에서는 한 개의 인스턴스를 생성한 뒤 해당 인스턴스에 Web Service + DB를 한번에 설치하여 서버 하나를 이용해 서비스 운영에 필요한 모든 요소를 설치하여 서비스를 배포하는 방법을 알아본다.
$ sudo apt-get update
$ sudo apt-get install mysql-server
$ sudo mysql_secure_installation
(* mysql_secure_installation
https://mariadb.com/kb/en/mysql_secure_installation/)
$ sudo apt-get install awscli apache2
$ sudo apt-get install php libapache2-mod-php php-mysql php-curl php-xml php-memcached php-mbstring
$ sudo apt-get install git
$ cd /var
$ sudo chown -R ubuntu:ubuntu www
$ cd /var/www/html
$ git clone https://github.com/qyjohn/web-demo
$ cd web-demo
4-1. 아파치가 "uploads" 폴더에 접근 할 수 있게 권한을 아래와 같이 바꾸어준다.
$ sudo chown -R www-data:www-data uploads
4-2. 설치한 Mysql에 사용할 database 만들기
$ sudo mysql
mysql> CREATE DATABASE web_demo;
mysql> CREATE USER 'user.name'@'localhost' IDENTIFIED BY 'pass.word';
mysql> GRANT ALL PRIVILEGES ON web_demo.* TO 'user.name'@'localhost';
mysql> quit
4-3. Git을 이용해 가져온 "web-demo"의 소스코드에 web_demo.sql을 위에서 만든 web_demo db로 가져온다.
$ cd /var/www/html/web-demo
$ mysql -u test1 -p web_demo < web_demo.sql
4-4. config.php 파일에서 아래의 부분 올바르게 설정해주기
$ nano config.php
username / password에 앞에서 본인이 설정한대로 입력
// Database connection parameters
$db_hostname = "localhost";
$db_database = "web_demo";
$db_username = "user.name";
$db_password = "pass.word";
4-5. Single Server 접속
접속
http://public-ip-address-of-your-ec2-instance/web-demo/index.php
서버의 구성 형태
위와 같은 "서버의 구성 형태"에서는 많은 양의 트래픽 & 데이터 처리하기 적합하지 않다. 싱글 서버에서 서비스 동작에 필요한 모든 작업을 수행하기 때문이다. 또한 장애가 발생한다면 서비스 전체에 영향을 줄 수 있다. 이러한 부분을 보완하기 위해 다음 단계에서는 여러개의 인스턴스 및 구성 요소들을 분리하여 운영하는 방법을 알아본다.
====
이 단계에서는 LEVEL 0에서 만든 기본 단계의 서버를 확장하여 여러 서버에 배포할 예정입니다. 또한 EFS(NFS service)를 사용하여 여러개의 서버 노드끼리 공유 파일시스템을 형성할 것입니다.
1-1. AWS EFS Console 접속
https://ap-northeast-2.console.aws.amazon.com/efs/home?region=ap-northeast-2#/get-started
2-1. 인스턴스에서 생성한 EFS 마운트 해주기
$ sudo apt-get update
$ sudo apt-get install nfs-common
$ sudo mkdir /efs
$ sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 dns-name-of-your-efs-file-system:/ /efs
$ sudo chown -R ubuntu:ubuntu /efs
2-2. 마운트 확인 및 파일시스템 테이블에 마운트포인트 추가
$ df -h
$ mount
$ dns-name-of-your-efs-file-system:/ /efs nfs auto,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 0 0
2-3. EFS에 마운트한 디렉터리에 "web-deme" 소스코드 저장하기
$ cd /efs
$ git clone https://github.com/qyjohn/web-demo
$ cd web-demo
$ sudo chown -R www-data:www-data uploads
$ cd /var/www/html
$ sudo ln -s /efs/web-demo web-demo
3-1. AWS RDS Console에 접속 이후 MySql Database 생성
3-2. 인스턴스에서 생성한 Mysql에 접속 후 데이터베이스 만들기
$ mysql -h dns-name-of-rds-instance -u admin -p
mysql> CREATE DATABASE web_demo;
mysql> CREATE USER 'user.name'@'%' IDENTIFIED BY 'pass.word';
mysql> GRANT ALL PRIVILEGES ON web_demo.* TO 'user.name'@'%';
mysql> quit
3-3. 다운 받은 web_demo.sql을 web_demo DB로 import 해준다.
$ cd /var/www/html/web-demo
$ mysql -h dns-name-of-rds-instance -u username -p web_demo < web_demo.sql
3-4. /var/www/html/web-demo config.php에서 새로운 " new database server hostname, username, password, and database name" 에 대한 설정을 변경해준다.
4-1. AWS ElastiCache Console 접속 이후 Redis or Memcached Cluster 사용해서 cache node 만들어 주기
[+] Amazon ElastiCache 설명서
https://docs.aws.amazon.com/ko_kr/elasticache/index.html
4-2. PHP와 redis를 연동하기 위한 php-redis module 설치 및 apache2의 php.ini 파일 설정
$ sudo apt-get install php-redis
[+] Reference
https://github.com/phpredis/phpredis
session.save_handler = rediscluster
session.save_path = "configuration-endpoint-of-the-elasticache-redis-cluster:6379"
4-3. 웹 서비스에 정상적으로 접속 가능한지 확인 후, 해당 인스턴스를 이용하여 AMI 생성하기.
[+] 인스턴스 및 AMI - https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/ec2-instances-and-amis.html
Images -> AMI로 이동
접속확인
5-1. ALB를 통한 로드밸런싱 구성
====
트래픽이 제한된 웹 서비스에서는 EFS 를 통한 공유 파일 시스템을 사용하면 좋지만 사이트에 트래픽이 증가하거나 불규칙 할 경우 다른 형태의 스토리지를 사용 하는 것이 좋다. AutoScail을 통해 트래픽을 여러개의 서버로 분산할 수 있지만 공유 파일 시스템을 통해 같은 스토리지를 사용하는 경우 성능에 제한이 걸릴 수 있다.
$storage_option = "s3"; // hd or s3
$s3_region = "us-east-2";
$s3_bucket = "bucket_name";
$s3_prefix = "uploads";
====
수동으로 $latency 을 조절하여 웹 서비스에 과중한 워크로드가 걸린 상황을 만들 수 있다. 아래의 방법으로 진행해보자
EC2 콘솔에서 레벨 2에서 생성한 AMI와 IAM 역할을 사용하여 시작 템플릿을 생성합니다.
위 단계에서 만든 시작 템플릿을 사용하여 AutoScaling 그룹을 생성합니다.AutoScaling 그룹이 ALB 대상 그룹으로부터 트래픽을 수신하는지 확인하십시오.
$latency = 0; -> $latency = 10;
이후 TargetGroup을 확인해보면 새로운 인스턴스 3개가 더 추가된 것을 확인할 수 있다.
(성공적으로 AutoScaling이 되었다.)
또한 AWS SNS를 통해 CloudWatch Alarm이 특정 메트릭에 대한 알람이 발생하면 아래와 같이 메일로 알림을 받을 수도 있다.
위의 작업을 통해, 간단한 웹 어플리케이션을 여러 AWS 서비스들과 어떻게 엮어 Scalable 하게 구성할 수 있는지에 대해 살펴보았다. 이렇듯 서비스하려는 어플리케이션의 특성에 맞춰 서버를 유동적으로 구성한다는 것은 Cloud Computing이 가진 강력한 장점이다. 하지만 이러한 장점을 실제 서비스에 적용하는 과정은 CSP가 제공하는 서비스에 대한 기본적인 이해도를 필요로 한다.
이번 포스팅으로 맨 앞에서 언급한 여러 서비스들을 간단히 사용해보고, 사용 목적 및 적용 방법등을 살펴 볼 수 있는 좋은 기회가 되었으면 한다.