💻주제 : AWS를 이용한 HA(High Availability) wordpress 서비스 배포
✍️작성자 : nayoungs
📅진행 기간: 2022.04.06 ~ 2022.04.08
📌목차
1. 프로젝트 개요
1-1. 프로젝트 주제 선정 동기 및 목표
1-2. 프로젝트 특징
1-3. 프로젝트 환경
2. 프로젝트 과정
2-1. VPC 구성
2-2. 키 페어 생성
2-3. Bastion Host 구성
2-4. RDS 구성
2-5. EC2 인스턴스 생성
2-6. EC2에서 WordPress 구성
2-7. EC2 AMI 생성
2-8. Load Balancing 및 Auto Scaling 구성
2-9. CloudFront 배포
3. 프로젝트 최종 결과
1. 프로젝트 개요
1-1. 프로젝트 주제 선정 동기 및 목표
아키텍처를 직접 설계해보는 것과 더불어 클라우드 및 AWS 서비스에 대한 이해도를 높이기 위해 미니 프로젝트를 진행하게 되었습니다. 해당 프로젝트에서는 AWS를 이용하여 고가용성 wordpress를 구현하는 것이 목표입니다.
1-2. 프로젝트 특징
WAS(Web Application Server)와 데이터베이스 서버를 프라이빗 서브넷(Private Subnet)에 구성함으로써 보안성을 향상시키고, Auto Scaling과 Application Load Balancer를 활용하여 높은 가용성을 확보하는 것이 핵심입니다.
1-3. 프로젝트 환경
1-3-1. 사용 기술
목록 | 설명 |
활성화된 AWS 계정 | AWS 프리티어가 유지된 계정으로 프로젝트 진행 |
Chrome | 프로젝트 구축 후 브라우저로 사용 |
Amazon VPC(Virtual Private Cloud) | 격리된 네트워크 구성 |
Amazon EC2(Elastic ComputeCloud) | Bastion Host, WAS Server 구성 |
Amazon RDS(Relational Database Service) | MySQL 데이터베이스 서버 구성 |
Amazon ELB(Elastic Load Balancing) | 서버로의 네트워크 트래픽 분산 |
Amazon Auto Scaling | EC2 인스턴스의 개수를 자동으로 조정 |
Amazon CloudFront | 짧은 지연 시간과 빠른 전송속도를 위한 CDN 서비스 |
- 프로젝트 시스템 아키텍쳐(Architechture)
2. 프로젝트 과정
🌎리전(Region) : 버지니아 북부(us-east-1)
2-1. VPC 구성
1) VPC 마법사로 VPC 및 서브넷 생성
- 먼저 VPC 대시보드로 이동해서 VPC 마법사를 시작합니다.
- VPC의 이름을 wordpressvpc로 지정하고, CIDR 블록을 확인합니다.
- 가용영역(AZ) 2개를 선택하고 2개의 퍼블릭 서브넷과 4개의 프라이빗 서브넷을 생성합니다.
- 프라이빗 서브넷을 4개 생성하는 이유는 이후 DB 서브넷 그룹에 사용하기 위함입니다.
- NAT 게이트웨이는 속도의 향상을 위해 [AZ 당 1개]를 선택하고, 엔트포인트는 [없음], DNS 호스트 이름은 활성화합니다
- VPC 구성을 전체적으로 확인(미리보기)하면 다음과 같습니다.
- 서브넷의 CIDR 블록
public | private1 | private2 | |
us-east-1a | 10.0.0.0/20 | 10.0.128.0/20 | 10.0.160.0/20 |
us-east-1b | 10.0.16.0/20 | 10.0.144.0/20 | 10.0.176.0/20 |
2-2. 키 페어 생성
- Windows Terminal에서 ssh-keygen 명령을 통해 키를 생성합니다.
- 키(key)를 사용하여 인스턴스에 SSH를 통해 액세스하면 서버에서 명령을 실행할 수 있게 됩니다.
PS C:\Users\USER> ssh-keygen
- ls 명령어를 사용하여 .ssh 하위에 키가 생성 되었는지 확인합니다
PS C:\Users\USER> ls .ssh
디렉터리: C:\Users\USER\.ssh
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2022-04-07 오후 10:01 2610 id_rsa
-a---- 2022-04-07 오후 10:01 575 id_rsa.pub
-a---- 2022-04-06 오후 3:30 4188 known_hosts
-a---- 2022-01-30 오후 3:26 95 known_hosts.old
- EC2 [키 페어] - [키 페어 가져오기]를 선택합니다.
- 키의 이름을 mysshkey로 지정하고 [찾아보기]를 클릭하여 생성한 키 페어를 가져옵니다.
- 키 페어가 생성된 것을 확인합니다.
2-3. Bastion Host 구성
1) 보안 그룹 생성
- [보안 그룹] - [보안 그룹 생성] 을 클릭하고 세부 정보를 입력합니다.
- SSH 프로토콜을 사용하여 Bastion Host에 로그인하고 구성할 수 있도록 현재 IP 주소(내 IP)에서 들어오는 SSH 트래픽을 허용합니다
2) Bastion Host EC2 생성
- Bastion Host로 사용할 EC2 인스턴스를 생성합니다.
- AMI 선택 뷰에서 Amazon Linux 2 AMI(HVM)를 선택합니다.
- 청구 요금이 발생하지 않도록 AWS 프리 티어로 제공되는 t2.micro 옵션을 선택합니다.
- 네트워크를 좀 전에 생성한 wordpressvpc로 선택하고, 서브넷은 가용영역 us-east-1a의 public subnet을 선택합니다.
- 외부에서 SSH로 접속할 수 있도록 퍼블릭 IP를 자동으로 할당합니다.
- [기존 보안 그룹 선택] 체크 후, 좀 전에 생성한 ssh_to_bastion 보안 그룹을 선택합니다.
- [기존 키 페어 선택] 체크 후, 이전에 생성한 mysshkey를 선택합니다.
- Windows Terminal을 통해 Bastion Host 접속을 확인합니다.
PS C:\Users\USER> ssh ec2-user@54.166.12.160
The authenticity of host '54.166.12.160 (54.166.12.160)' can't be established.
ECDSA key fingerprint is SHA256:
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '54.166.12.160' (ECDSA) to the list of known hosts.
__| __|_ )
_| ( / Amazon Linux 2 AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-2/
2-4. RDS 구성
1) DB 서브넷 그룹 생성
- RDS를 private 서브넷에 생성할 때는 최소 2개의 가용 영역(AZ) 또는 서브넷이 선택되어야합니다.
- RDS 데이터베이스 생성 시 필요한 서브넷 그룹을 미리 생성해둡니다.
- RDS에서 [서브넷 그룹] - [DB 서브넷 그룹 생성]을 선택합니다.
- 서브넷 그룹 세부 정보를 입력합니다
- 가용 영역 us-east-1a와 us-east-1에서 프라이빗 1개씩, 총 2개의 서브넷 그룹을 선택합니다.
- 서브넷 그룹이 생성된 것을 확인합니다.
2) RDS 생성
- RDS에서 [RDS 대시보드] - [데이터 베이스 생성] 을 클릭합니다.
- MySQL 엔진을 선택합니다.
- DB 인스턴스 식별자를 입력하고, 자격 증명 설정을 진행합니다
- VPC로 wordpressvpc를 선택하고, 좀 전에 생성한 DB 서브넷 그룹 wordpress-rds-group을 선택합니다.
- 데이터베이스는 private subnet에 구성되는 것으로, 외부에 노출되면 안되므로 퍼블릭 액세스를 허용하지 않습니다.
- 데이터베이스가 위치할 가용 영역을 us-east-1a로 선택합니다.
- 추가 구성에서 초기 데이터베이스 이름을 wordpress로 설정합니다.
- wordpress 데이터베이스가 생성된 것을 확인합니다.
2-5. EC2 인스턴스 생성
1) webserver EC2 인스턴스 생성
- 시작 템플릿에 사용할 AMI 를 위한 EC2 인스턴스를 생성합니다.
- AMI 선택 뷰에서 Amazon Linux 2 AMI(HVM)를 선택합니다.
- 청구 요금이 발생하지 않도록 AWS 프리 티어로 제공되는 t2.micro 옵션을 선택합니다.
- 네트워크를 wordpressvpc로 선택하고, 서브넷은 가용영역 us-east-1a의 private subnet을 선택합니다.
- 외부에서 접속이 불가능해야하므로, 퍼블릭 IP를 비활성화합니다.
- wordpress EC2에 앞으로 사용할 새 보안 그룹 wordpress_security를 생성합니다.
- Bastion Host에서 SSH 프로토콜을 통해 접속하고 구성할 수 있도록 Bastion Host에서 들어오는 SSH 트래픽을 허용해줍니다.
- 기존 키페어 mysshkey를 사용하여 인스턴스를 시작합니다.
- 이전에 Windows Terminal에서 Bastion 호스트에 접속된 상태로 다음을 진행합니다.
- 내 컴퓨터 C드라이브에서 .ssh 하위의 키 파일(id_rsa)의 내용을 복사하여 vim 에디터를 이용해 Bastion Host에 동일하게 생성합니다.
[ec2-user@ip-10-0-15-33 ~]$ cd .ssh
[ec2-user@ip-10-0-15-33 .ssh]$ vim id_rsa
- 키 파일(id_rsa)은 읽기만 가능하도록 권한을 변경합니다.
[ec2-user@ip-10-0-15-33 .ssh]$ chmod 400 id_rsa
- Bastion Host에서 ssh을 통해 Web Server 접속을 확인합니다.
[ec2-user@ip-10-0-15-33 ~]$ ssh ec2-user@10.0.138.153
The authenticity of host '10.0.138.153 (10.0.138.153)' can't be established.
ECDSA key fingerprint is SHA256:
ECDSA key fingerprint is MD5:15:
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.0.138.153' (ECDSA) to the list of known hosts.
__| __|_ )
_| ( / Amazon Linux 2 AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-2/
16 package(s) needed for security, out of 19 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-10-0-138-153 ~]$
2) EC2 인스턴스가 RDS 데이터 베이스에 액세스하도록 허용
- 먼저 RDS 데이터베이스를 수정하여 EC2 인스턴스에서의 네트워크 액세스를 허용합니다.
- AWS 콘솔에서 RDS 데이터베이스로 이동한 후 앞서 생성한 MySQL 데이터베이스 wordpress 를 클릭합니다.
- [연결 & 보안] 탭에서 wordpress의 VPC 보안 그룹을 클릭합니다.
- [인바운드] 탭을 클릭한 다음, [편집] 버튼을 클릭하여 보안 그룹에 대한 규칙을 변경합니다.
- [유형] 속성을 [MYSQL/Aurora]로 변경하고 EC2인스턴스에 사용한 wordpress_security 보안 그룹을 선택하여 EC2가 RDS에 액세스할 권한을 부여합니다.
2-6. EC2에서 WordPress 구성
1) 데이터베이스 사용자 생성
- Windows Terminal에서 EC2 인스턴스에 연결된 상태로 다음을 진행합니다.
- 먼저 데이터베이스와 상호작용할 MySQL 클라이언트를 설치합니다.
[ec2-user@ip-10-0-138-153 ~]$ sudo yum install -y mysql
- RDS 데이터베이스 wordpress의 [연결 & 보안] 탭에서에서 엔드포인트를 복사합니다.
- MySQL 호스트에 대한 환경 변수 MYSQL_HOST를 복사한 엔드포인트로 설정해줍니다.
[ec2-user@ip-10-0-138-153 ~]$ export MYSQL_HOST=[엔드포인트]
- mysql 데이터베이스 wordpress에 연결합니다.
[ec2-user@ip-10-0-138-153 ~]$ mysql -u admin -p wordpress
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 21
Server version: 8.0.27 Source distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [wordpress]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| wordpress |
+--------------------+
5 rows in set (0.00 sec)
- 사용자를 생성하고 wordpress 데이터베이스에 액세스할 권한을 부여합니다.
MySQL [wordpress]> CREATE USER wordpress IDENTIFIED BY '[암호]';
Query OK, 0 rows affected (0.01 sec)
MySQL [wordpress]> GRANT ALL PRIVILEGES ON wordpress.* TO wordpress;
Query OK, 0 rows affected (0.01 sec)
MySQL [wordpress]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
MySQL [wordpress]> Exit
Bye
2) WordPress 설치 및 구성
- WordPress를 실행하려면 EC2 인스턴스에서 웹 서버를 실행해야 합니다.
- EC2 인스턴스에 웹 데몬(apache)를 설치합니다.
[ec2-user@ip-10-0-138-153 ~]$ sudo yum install -y httpd
- apache 웹 서버를 시작 및 활성화합니다.
[ec2-user@ip-10-0-138-153 ~]$ sudo service httpd start
[ec2-user@ip-10-0-138-153 ~]$ sudo systemctl enable httpd.service
- wget을 이용하여 url로 wordpress 파일을 설치합니다.
[ec2-user@ip-10-0-138-153 ~]$ wget https://wordpress.org/latest.tar.gz
- -C 옵션을 통해 위치를 /var/www/html로 지정하여 아카이브를 해제합니다.
[ec2-user@ip-10-0-138-153 ~]$ sudo tar -xvzf latest.tar.gz -C /var/www/html
- 아카이브 해제를 확인하고 편의를 위해 wordpress 디렉토리로 이동합니다.
[ec2-user@ip-10-0-138-153 ~]$ ls /var/www/html
wordpress
[ec2-user@ip-10-0-138-153 ~]$ cd /var/www/html/wordpress/
- sample 파일 wp-config-sample.php를 복제합니다.
[ec2-user@ip-10-0-137-118 wordpress]$ sudo cp wp-config-sample.php wp-config.php
- 압축해제된 wordpress 디렉토리와 그 하위 디렉토리의 소유자,소유그룹을 apache로 변경합니다.
[ec2-user@ip-10-0-137-118 wordpress]$ sudo chown -R apache:apache /var/www/html/wordpress
- vim 에디터를 사용하여 wp-config 파일을 수정합니다.
// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'wordpress' );
/** Database username */
define( 'DB_USER', 'wordpress' );
/** Database password */
define( 'DB_PASSWORD', '[암호]' );
/** Database hostname */
define( 'DB_HOST', '[엔드포인트]' );
/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8' );
/** The database collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );
- apache 설정 파일 /etc/httpd/conf/httpd.conf에서 DocumentRoot를 /var/www/html/wordpress로 변경하고, DirectoryIndex를 index.php로 변경합니다.
[ec2-user@ip-10-0-137-118 wordpress]$ sudo vim /etc/httpd/conf/httpd.conf
- wordpress에 필요한 애플리케이션 종속성 설치
[ec2-user@ip-10-0-137-118 wordpress]$ sudo amazon-linux-extras install -y lamp-mariadb10.2-php7.2 php7.2
- 변경사항이 적용되도록 Apache 웹 서버를 다시 시작합니다.
[ec2-user@ip-10-0-137-118 wordpress]$ sudo service httpd restart
Redirecting to /bin/systemctl restart httpd.service
2-7. EC2 인스턴스 AMI 생성
- 설정 완료된 EC2 인스턴스 Web Server로 시작 템플릿에 사용할 AMI를 생성합니다.
- 인스턴스 선택 후 [작업] - [이미지 및 템플릿] - [이미지 생성] 을 클릭합니다.
- AMI가 생성된 것을 확인합니다.
2-8. Load Balancing 및 Auto Scaling 구성
1) 시작 템플릿 생성
- Auto Scaling Group에 사용할 시작 템플릿을 생성합니다.
- EC2에서 [시작 템플릿] - [시작 템플릿 생성]을 클릭합니다.
- 시작 템플릿 이름과 템플릿 버전 설명을 작성하고 EC2 Auto Scaling 지침을 체크합니다.
- [내 AMI] 탭에서 좀 전에 생성한 wordpress web server AMI를 선택합니다.
- 인스턴스 유형을 프리티어로 사용할 수 있는 t1.micro를 선택하고, 키 페어는 mysshkey를 선택합니다.
2) auto scaling group 생성
- 가용성을 향상시켜주기 위한, Auto Scaling 그룹을 생성합니다.
- [Auto Scaling 그룹] - [Auto Scaling 그룹 생성]을 클릭합니다.
- Auto Scaling 그룹 이름을 입력하고, 좀 전에 생성한 시작 템플릿 wordpress-template을 선택합니다.
- 네트워크 설정에서 VPC는 wordpressvpc를 선택하고, EC2 인스턴스(WordPress)를 구성할 프라이빗 서브넷을 가용 영역 us-east-1a, us-east-1b에서 각각 1개씩 선택합니다.
- 외부 사용자들이 Load Balancer를 통해 WordPress 서비스에 접속하게 할 예정이므로 새로운 로드밸런서를 생성합니다.
- 웹 서비스이기 때문에 Application Load Balancer를 선택하고, 인터넷 연결용이므로 Internet-facing을 선택합니다.
- 로드밸런서 가용영역을 퍼블릿(public) 서브넷으로 선택하고, 대상 그룹을 생성해줍니다.
✔️관련 오류 해결
처음에 로드밸런서 가용 영역을 프라이빗(private)으로 설정하여 타임아웃 오류가 발생하였습니다.
로드 밸런싱 시킬 대상(EC2)이 프라이빗 서브넷에 위치하므로 로드밸런서도 프라이빗 서브넷에 구성하여야 된다고 생각했으나,
로드밸런서 가용영역은 일반적인 우리가 알고 있는 AZ가 아닌 로드밸런서가 접근할 수 있는 subnet을 의미한다는 것을 알게되었습니다.
private subnet은 igw와 연결되어있지 않으며, 로드밸런싱 대상은 public ip 또는 탄력적 ip가 할당되어 있지 않기 때문에
외부 트래픽을 다룰 수 없게 됩니다. 따라서 로드밸런서의 활성화된 가용영역(서브넷)을 public subnet으로 설정해줍니다.
결론적으로 로드 밸런서의 가용영역을 퍼블릭(public) 서브넷으로 변경함으로써 문제를 해결할 수 있었습니다.
- 상태 확인 유형에서 ELB를 체크해주고, CloudWatch 내에서 그룹 지표 수집을 활성화(모니터링)할 수 있도록 체크해줍니다.
- 그룹 크기(원하는 용량, 최소 용량, 최대 용량)을 선택해줍니다.
- 마지막으로 Auto Scaling 그룹의 인스턴스를 시작하거나 종료하도록 수행하는 조정 정책을 설정해주고 Auto Scaling 그룹 생성을 완료합니다.
- Auto Scaling 그룹이 생성되고 설정했던 원하는 용량(2)에 맞에 가용 영역 us-east-1a, us-east-1b각각에 인스턴스가 1개씩 생성된 것을 확인할 수 있습니다.
3) 보안 그룹 생성
- 외부 사용자가 HTTP 프로토콜을 통해 로드밸런서에 접속할 수 있도록 보안 그룹을 생성해줍니다.
- [보안 그룹] - [보안 그룹 생성] 을 클릭하고 세부 정보를 입력합니다.
- HTTP에 대한 모든 트래픽을 허용해줍니다.
4) 로드 밸런서 보안 그룹 편집
- [로드 밸런서] - [설명 탭] - [보안 그룹 편집]을 선택합니다.
- 좀 전에 생성한 보안 그룹 allow http를 연결해줌으로써 외부 사용자들이 HTTP로 로드밸런서에 접속할 수 있도록 설정합니다.
5) EC2 보안 그룹 수정
- EC2에 로드 밸런서로부터의 접근이 허용 되도록 EC2 보안그룹 wordpress_security를 수정합니다.
- [보안 그룹] - [wordpress_security 체크] - [작업] - [인바운드 규칙 편집] 선택
- 로드 밸런서로부터 HTTP 프로토콜을 사용하여 EC2에 접속할 수 있도록 로드밸런서의 보안그룹 allow http의 ID를 등록해줍니다.
6) Load Balancer DNS로 접속
- 로드 밸런서의 DNS를 복사합니다.
- 복사한 DNS로 시크릿 모드 Chrome에 접속합니다.
- 정상적으로 접속되는 것을 확인할 수 있습니다.
7) wordpress 로그인
- 워드프레스 설정을 진행합니다.
- 이후 CloudFront 배포 후와의 속도를 비교하기 위해 속도를 확인해둡니다.
8) DB 반영 확인
- Windows Terminal을 통해 Bastion Host > EC2 에서 RDS에 연결했을 때, 데이터베이스에 정상적으로 반영된 것을 확인할 수 있습니다.
MySQL [wordpress]> show tables;
+-----------------------+
| Tables_in_wordpress |
+-----------------------+
| wp_commentmeta |
| wp_comments |
| wp_links |
| wp_options |
| wp_postmeta |
| wp_posts |
| wp_term_relationships |
| wp_term_taxonomy |
| wp_termmeta |
| wp_terms |
| wp_usermeta |
| wp_users |
+-----------------------+
12 rows in set (0.00 sec)
2-9. CloudFront 배포
- AWS 콘솔을 통해 CloudFront 접속 후 [CloudFront 배포 생성] 을 클릭합니다.
- 원본 도메인으로 로드 밸런서 wordpress-autoscaling-1을 선택합니다.
- 프로토콜로 HTTP를 선택합니다.
- CloudFront가 배포된 것을 확인할 수 있습니다.
- CloudFront 배포 도메인 이름을 복사합니다.
3. 프로젝트 결과
- CloudFront 배포 도메인으로 접속합니다
- CloudFront로 배포하기 전(663ms)과 비교했을 때, 결과적으로 426ms로 속도가 빨라진 것을 확인할 수 있습니다.
- 프리티어 내에서 진행하기 위해 단일 데이터베이스를 사용하였으나, 데이터베이스를 Multi-AZ에 배포한다면 더 높은 가용성을 확보할 수 있습니다. Multi-AZ로 구성하였을 때의 아키텍쳐(Architecture)는 다음과 같습니다.