목적: 부하 분산 장치 생성을 위한 로드 밸런서 설정
해당 그룹에서는 HTTP(80), HTTP(443) 트래픽을 허용한다.
해당 톰캣 포트는 8080이고 ELB에서 들어오는 트래픽만 받아줄거기에 앞서 설정한 ELB SG을 설정한다.
ALB에서 보낸 트래픽이 8080을 통해 흘러 들어온다.
해당 백엔드는 Memcache, RabbitMQ, MySQL 총 3개의 서비스가 포함된다.
어플리케이션 보안그룹에 속한 Tomcat은 해당 포트를 통해 백엔드와 통신 가능
단, 백엔드 서버는 서로간에 통신이 가능해야 하므로 인바운드 그룹에 backend SG을 추가한다.
[ App Server]
해당 서버마다 운영자가 접근할 수 있도록 22번 포트를 각각 모두 열여준다.
또한 외부에서 퍼블릭ip + 8080포트로 접근할 수 있도록 8080포트에 내 ip를 허용한다.
p.s: 공용ip가 변경되면 해당 인바운드 규칙도 변경해줘야함.
[ Backend Server]
각각의 서버에서 트래픽을 허용하는 인바운드 규칙을 해주는 것은 허용 측면에서 설정이고 해당 서버에 필요한 리소스를 얻기 위해서 인터넷에 접근하기 위해서는 아웃바운드를 설정해줘야한다. (EX: apt-get...)
[backend server]
[App server]
데이터베이스 서버부터 생성해보자
DB 인스턴스 생성
네트워크 설정부분에서 보안그룹은 기존에 생성한 bakcend SG로 설정한다.
EC2가 실행되고 해당 스크립트가 자동 실행된다.
#!/bin/bash
DATABASE_PASS='admin123'
sudo yum update -y
sudo yum install epel-release -y
sudo yum install git zip unzip -y
sudo yum install mariadb-server -y
# starting & enabling mariadb-server
sudo systemctl start mariadb
sudo systemctl enable mariadb
cd /tmp/
git clone -b main https://github.com/hkhcoder/vprofile-project.git
#restore the dump file for the application
sudo mysqladmin -u root password "$DATABASE_PASS"
sudo mysql -u root -p"$DATABASE_PASS" -e "UPDATE mysql.user SET Password=PASSWORD('$DATABASE_PASS') WHERE User='root'"
sudo mysql -u root -p"$DATABASE_PASS" -e "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1')"
sudo mysql -u root -p"$DATABASE_PASS" -e "DELETE FROM mysql.user WHERE User=''"
sudo mysql -u root -p"$DATABASE_PASS" -e "DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%'"
sudo mysql -u root -p"$DATABASE_PASS" -e "FLUSH PRIVILEGES"
sudo mysql -u root -p"$DATABASE_PASS" -e "create database accounts"
sudo mysql -u root -p"$DATABASE_PASS" -e "grant all privileges on accounts.* TO 'admin'@'localhost' identified by 'admin123'"
sudo mysql -u root -p"$DATABASE_PASS" -e "grant all privileges on accounts.* TO 'admin'@'%' identified by 'admin123'"
sudo mysql -u root -p"$DATABASE_PASS" accounts < /tmp/vprofile-project/src/main/resources/db_backup.sql
sudo mysql -u root -p"$DATABASE_PASS" -e "FLUSH PRIVILEGES"
# Restart mariadb-server
sudo systemctl restart mariadb
#starting the firewall and allowing the mariadb to access from port no. 3306
sudo systemctl start firewalld
sudo systemctl enable firewalld
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --zone=public --add-port=3306/tcp --permanent
sudo firewall-cmd --reload
sudo systemctl restart mariadb
Memcache 인스턴스 생성
그 외의 과정은 위에서 설정한 DB 인스턴스 생성 과정과 모두 일치.
#!/bin/bash
sudo dnf install epel-release -y
sudo dnf install memcached -y
sudo systemctl start memcached
sudo systemctl enable memcached
sudo systemctl status memcached
sed -i 's/127.0.0.1/0.0.0.0/g' /etc/sysconfig/memcached
sudo systemctl restart memcached
firewall-cmd --add-port=11211/tcp
firewall-cmd --runtime-to-permanent
firewall-cmd --add-port=11111/udp
firewall-cmd --runtime-to-permanent
sudo memcached -p 11211 -U 11111 -u memcached -d
참고로 사용자 데이터 입력 시 #!/bin/bash가 첫 문단에 기입이 되도록 해야한다.
RabbitMQ 인스턴스 생성
이하 동일
App 인스턴스 생성
연결을 시도하려면 ssh 연결 시 아래처럼 ec2-user로 나오는데 centos로 AMI를 설정했기에 username을 'centos'로 변경 후 시도해야 한다!
그러면 다음과 같이 shell script로 설정한 mariadb가 실행된 걸 확인 가능하다.
추가적으로 인터넷에 접근하기 위해 아웃바운드 설정을 위해서 해주었으니 아래처럼 curl로 요청을 외부에 보냈을 떄 응답을 받을 수 있다 (200)
데이터베이스 접속
서버 접속 후 상태 확인하기
상태 확인 또 다른 명령어 (ps -ef | grep)
네트워크 관점에서 해당 포트 상태 확인 ( ss -tnulp | grep {해당포트번호}
tomcat service 실행 상태 확인
도메인 이름과 유형을 선택한다
- 유형 선택 시 프라이빗을 선택하는데, 인터넷 연결이 아닌 공통 리젼 내 해당 VPC 내에서 인스턴스 간 통신을 지원하기에 프라이빗으로 설정한다.
생성 완료
레코드 생성
Memcached, RabbitMQ 서버에도 동일하게 레코드 생성
소스코드 파일을 S3에 보관하기 위해 해당 서비스를 이용하기 위한 권한을 부여해주자.
cli를 활용한 버킷 생성
aws s3 mb s3://{bucket name}
참고로 버킷 네임은 유일한 이름이어한다.
WAR파일 버킷에 밀어넣기
위에서 생성한 버킷에 내 소스코드 파일을 넣어주자.
aws s3 cp vprofile-v2.war s3://jincheol-vprofile-bucket/
IAM 역할 생성
이제 위에서 생성한 app01 서버에 접속해 s3버킷에 넣는 소스코드를 다운로드 받아야 하는데 위에서 s3버킷 생성 및 소스코드를 집어넣어준 권한을 받아야한다.
유저 자체를 생성해주는 것보다 우리는 역할을 부여해 해당 행위를 할 수 있는 자격을 부여해보도록 하자.ㄴ
Ec2로 돌아가 생성한 역할을 부여해주도록 하자.
즉, 우리는 AccessKey로 접근하는 방식 대신 인스턴스에 '역할'을 부여해줌으로써 권한 설정을 준 것이다.
1. aws-cli 설치
apt install awscli -y
2. aws s3 버킷 리스트 확인
3. vprofile-v2.war 파일 tmp폴더에 복사
aws s3 cp s3://jincheol-vprofile-bucket/vprofile-v2.war /tmp/
유효성 검사
root@ip-10-0-9-180:~# systemctl stop tomcat9
rm -rf /var/lib/tomcat9/webapps/ROOT
cp /tmp/vprofile-v2.war /var/lib/tomcat9/webapps/ROOT.war
systemctl start tomcat9
ls /var/lib/tomcat9/webapps/
레코드 설정 ( in application.properties)
#JDBC Configutation for Database Connection
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://db01.vprofile.in:3306/accounts?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
jdbc.username=admin
jdbc.password=admin123
#Memcached Configuration For Active and StandBy Host
#For Active Host
memcached.active.host=mc01.vprofile.in
memcached.active.port=11211
#For StandBy Host
memcached.standBy.host=127.0.0.2
memcached.standBy.port=11211
#RabbitMq Configuration
rabbitmq.address=rmq01.vprofile.in
rabbitmq.port=5672
rabbitmq.username=test
rabbitmq.password=test
#Elasticesearch Configuration
elasticsearch.host =192.168.1.85
elasticsearch.port =9300
elasticsearch.cluster=vprofile
elasticsearch.node=vprofilenode
위에서 ROUTE53을 활용해 생성한 레코드 주소를 해당 property 파일에 동일하게 입력한다.
대상그룹 생성
대상그룹은 요청 트래픽을 경유하는 인스턴스 그룹이다.
로드밸런서가 해당 대상(목표)그룹으로 트래픽을 분산한다.
해당 로드밸런서는 톰캣 서버로 트래픽을 분산시켜 주고 톰캣 서버의 창구는 8080포트이기에 해당 포트번호를 8080으로 맞춰준다!
http의 기본 포트는 80번이며 우리는 80번 포트가 아닌 8080포트로의 트래픽을 허용하기에 (http프토콜을 사용하지만 문 번호가 다름) 해당 사용중인 문 번호로 override 한다.
위에서 생성한 타겟 그룹으로 트래픽을 실제로 분산시켜 줄 로드밸런서를 생성하자!
443 로드밸런서는 인증서나 도메인을 구입하지 않았다면, 제거해야 한다.
나같은 경우엔 app 서버로 허용되는 인바운드 규칙 중 8080포트로 들어오는 트래픽에 대해서 내 ip만 허용해주었는데, 해당 ip를 허용해줄 때 집에서 설정해주고 실제 접속은 외부 카페에서 시도해서 한 번 실패를 해주었기에 카페 Ip로 다시 인바운드 규칙을 수정해주었다.
결과
준비물
1. AMI
2. 시작 템플릿
3. AutoScailing Group
시작템플릿의 역할은 오토 스케일링 시, 시작할 인스턴스 이미지 및 보안그룹 등에 대한 일종의 시작점을 제공한다.
톰캣 인스턴스를 증감/증대 시키기에 보안그룹은 해당 보안그룹과 동일하게 맞춘다.
해당 인스턴스 생성 시, 기존 부모 인스턴스에게 부여된 역할을 동일하게 부여한다.
ASG가 동작되면 생성된 인스턴스를 아래 대상그룹에 포함시켜 로드밸런싱 그룹에 포함되도록 한다.
오토 스케일링 그룹을 생성하였다면, 아래처럼 인스턴스가 새로 생성된 걸 확인할 수 있다.
또한 대상그룹에도 포함된 걸 확인 할 수 있다.
Sticky Session 이란 ?
Application Load Balancer (ALB)에서의 Sticky Session은 클라이언트가 특정 인스턴스에 대한 연결을 계속 유지하도록 하는 기능입니다. 일반적으로 로드 밸런서는 요청이 들어올 때마다 서버 또는 인스턴스 간에 부하를 분산하는 역할을 합니다. 그러나 Sticky Session이 활성화되면 로드 밸런서는 특정 클라이언트의 모든 요청을 동일한 서버 또는 인스턴스로 보냅니다.
이 기능은 세션 기반의 어플리케이션에서 유용하게 사용됩니다. 일반적으로 클라이언트와 서버 간의 세션 정보가 유지되어야 하는 경우, 예를 들어 사용자 로그인 정보나 장바구니 정보 등이 있는 경우가 그 예입니다. 이때 하나의 인스턴스에 대한 클라이언트의 모든 요청이 동일한 서버로 전송되면, 세션 정보가 그대로 유지되면서 일관된 경험을 제공할 수 있습니다.
Sticky Session은 다양한 방법으로 구현될 수 있습니다. 일반적으로는 클라이언트의 세션 쿠키에 의존하거나, 클라이언트의 IP 주소에 의존하여 특정 서버로 유지되도록 설정할 수 있습니다. Sticky Session을 사용하면 세션 정보를 서버 간에 공유하지 않고도 특정 클라이언트에 대한 지속적인 연결을 유지할 수 있습니다.
하지만 Sticky Session을 사용할 때 주의해야 할 점도 있습니다. 특히 로드 밸런서와 백엔드 서버 간의 부하 분산이 저하될 수 있으며, 특정 서버에 장애가 발생할 경우 해당 서버에 연결된 클라이언트는 영향을 받을 수 있습니다. 따라서 Sticky Session을 사용하는 경우 이러한 측면을 고려하여 설계해야 합니다.
유저가 특정 Url로 접속
ALB(Application Load Balancer)에 접촉
ALB는 포트8080을 가진 톰캣 서버 인스턴스에 요청을 전달한다.
-> 톰캣 서버는 다른 보안그룹에 존재 (Security Group)
톰캣 서버는 해당 요청을 백엔드 서버로 보낸다
-> 이때 Route53으로 개인(private) DNS 서버를 설정해 백엔드와의 통신이 가능하게 한다. (db01,rmq01,mc01)
-> 백엔드 서버는 같은 보안그룹을 유지한다.
-> 각각의 포트번호를 열어주고 서로간에 통신이 필요하기에 해당 보안그룹 역시 등록한다.
S3에 업로드한 소스파일을 변경 될 때 마다 톰캣 서버에 업로드 할 수 있다. (이때 CI/CD를 적용하는 것이 효율적)