코드스테이츠 백엔드 부트캠프 77일차 - [Cloud] 운영 전략

wish17·2023년 4월 4일
0
post-thumbnail

[Cloud] 운영 전략

Proxy Server

프록시 서버

  • 클라이언트가 서버와 소통할 때, 서버에 바로 접근하지 않고 자신을 통해 서버에 접근할 수 있도록 해주는 일종의 대리 서버

  • 보통 지역이 제한되어있는 서비스를 이용하기 위해 우회하거나, 캐시를 통해 더 빠른 이용을 하기 위해 프록시 서버를 사용한다.

프록시 서버의 종류

1. Forward Proxy

  • 클라이언트에 가까이 위치한 프록시 서버

  • 캐싱을 통해 빠른 서비스 이용 가능

    • 여러 클라이언트가 동일한 요청을 할 경우 프록시 서버 캐시에 데이터를 저장해 놓고, 서버에 재요청을 보내지 않아도 다른 클라이언트에게 빠르게 전달할 수 있다.
  • 보안

    • 서버가 응답받은 IP는 프록시 서버의 IP이기 때문에 서버에게 클라이언트를 숨길 수 있다.

2. Reverse Proxy

  • 서버에 가까이 위치한 프록시 서버

  • 분산처리

    • 프록시 서버로 요청이 들어오면 여러대의 서버로 요청을 나누어 전달 후 처리 (과부하 방지)
  • 보안

    • 클라이언트에게 서버를 숨길 수 있다.

결국 위 두가지 프록시 서버 모두 사용자 - 프록시서버 - 서버 구조로 비슷해 보일 수 있지만 Forward Proxy의 경우 서버에게 받은 응답들을 캐싱해 가지고 있으면서 사용자에게 나눠주는거고 Reverse Proxy의 경우 사용자의 요청을 여러 서버에게 나눠준다고 생각하면 될 것 같다.


수평확장

클라이언트의 요청 증가에 따라 서버를 업그레이드 하는 두가지 방법

  • Scale-Up

    • 물리적으로 서버의 사양을 높이는 하드웨어적인 방법
    • 프로그램 구현 변화 없어도 됨
    • but 일정 수준 이상부터는 가성비가 급격히 안좋아짐, 한계점 있음
  • Scale-Out

    • 서버의 갯수를 늘려 부하를 분산시키는 방법
    • 비교적 저렴

로드밸런서

Scale-Out방법으로 여러대의 서버로 부하를 나눠 처리할 때 교통정리 역할을 해주는 기술

로드 밸런서의 종류

로드 밸런서는 클라이언트의 요청을 어떤 것을 기준으로 분산시키냐에 따라 네 가지의 종류로 나뉜다.

로드 밸런서의 종류로드밸런싱의 기준
L2데이터 전송 계층에서 Mac 주소를 바탕으로 로드 밸런싱
L3네트워크 계층에서 IP 주소를 바탕으로 로드 밸런싱
L4전송 계층에서 IP주소와 Port를 바탕으로 로드 밸런싱
L7응용 계층에서 클라이언트의 요청을 바탕으로 로드 밸런싱 (ex. 엔드포인트)

오토스케일링

aws에서 제공하는 자동 서버 증설(Auto Scaling) 기능

  • 서버의 처리 요구량이 증가하면 새 리소스를 자동으로 추가
  • 처리 요구량이 줄어들면 리소스를 감소시켜 적절한 분산 환경을 만들어줌
  • 클라우드 서비스 종류마다 기능의 이름이나 방식이 조금 다름

Auto Scaling의 장점

동적 스케일링

  • 사용자의 요구 수준에 따라 리소스를 동적으로 스케일링
  • 스케일 업 할 수 있는 서버의 수에는 제한 X

로드 밸런싱

  • 로드밸런서와 함께 사용하면, 다수의 EC2 인스턴스에게 워크로드를 효과적으로 분배할 수 있다.
    (사용자가 정의한 규칙에 따라 워크로드 처리)

타겟 트래킹

  • 특정 타겟에 대해서만 Auto Scaling을 할 수 있다.
    (사용자가 설정한 타겟에 맞춰 EC2 인스턴스의 수를 조정)

헬스 체크

  • EC2 인스턴스의 상태를 주기적으로 감시하고 문제가 발생하면 해당 인스턴스를 자동으로 교체하는 기능

서버 플릿 관리

서버 플릿

  • 일련의 EC2 서버 집합
  • 여러 대의 서버 인스턴스를 관리하기 위한 그룹
  • 서버 플릿을 사용하면 여러 인스턴스를 일괄적으로 관리할 수 있다.
  • (서버 플릿이라는 그룹을 기준으로) 인스턴스를 자동으로 교체하거나 확장하는 등의 작업을 효율적으로 수행할 수 있다.
    • ex. 하나의 서버 플릿 그룹이 5개의 EC2서버에서 실행되도록 설정 했을 때 2대가 고장나면 자동으로 2대를 추가해서 다시 5개로 유지하는 등

EC2 Auto Scaling 활용

Auto Scaling은 EC2 인스턴스 뿐만 아니라 다른 인스턴스와도 결합 가능하다.
EC2 Auto Scaling은 오직 EC2 서버라는 리소스만 대상으로 한다.

시작 템플릿(Launch Configuration)

Auto Scaling으로 인스턴스를 확장 또는 축소하려면 어떤 서버를 사용할지 결정해야 한다. 이걸 시작 템플릿을 통해 결정한다.

  • 시작 템플릿은 AMI 상세 정보, 인스턴스 타입, 키 페어, 시큐리티 그룹 등 인스턴스에 대한 모든 정보를 담고 있다.

  • 만약 시작 템플릿을 사용하고 있지 않고 시작 템플릿을 생성하지 않으려는 경우에는 시작 템플릿(Launch Configuration) 대신 시작 구성을 생성할 수 있다.

    • 시작 구성은 사용할 AMI의 ID, 인스턴스 유형, 키 페어, 보안 그룹 등의 정보를 포함시켜서 생성한다.
    • 시작 구성은 EC2 Auto Scaling이 사용자를 위해 생성하는 EC2 인스턴스 유형을 지정한다는 점에서 시작 템플릿과 비슷하다.

Auto Scaling 그룹 생성

Auto Scaling 그룹

  • 스케일업 및 스케인 다운 규칙의 모음
  • EC2 인스턴스 시작부터 삭제까지의 모든 동작에 대한 규칙과 정책을 담고 있다.

Scaling 유형

  • 인스턴스 레벨 유지

    • 기본 스케일링 계획으로도 부르며, 항상 실행 상태를 유지하고자 하는 인스턴스의 수를 지정할 수 있는 방식
    • 일정한 수의 인스턴스가 필요한 경우 최소, 최대 및 원하는 용량에 동일한 값을 설정할 수 있다.
  • 수동 스케일링

    • 기존 Auto Scaling 그룹의 크기를 수동으로 변경할 수 있는 방식
    • 수동 스케일링을 선택하면 사용자가 직접 콘솔이나, API, CLI 등을 이용해 수동으로 인스턴스를 추가 또는 삭제 해야 한다.
    • 보통 쓰지 않으며, 안쓰는게 좋다.
  • 일정별 스케일링

    • 예측 가능한(시간을 기준으로 한) 규칙을 기반으로 스케일링을 적용하는 방식
    • ex) 낮 시간대에는 트래픽이 최고치에 이르고 밤 시간대에는 트래픽이 거의 없다면 낮 시간대에 서버를 증설하고 밤 시간대에 스케일 다운 하는 규칙을 추가하면 된다.
  • 동적 스케일링

    • 수요 변화에 대응하여 Auto Scaling 그룹의 용량을 조정하는 방식
    • CloudWatch가 모니터링 하는 지표를 추적하여 경보 상태일 때 수행할 스케일링 규칙을 정한다.
    • 스케일 업과 스케일 다운 두 가지의 정책을 작성해야 한다.
    • ex) CPU 처리 용량의 80% 수준까지 급등한 상태가 5분 이상 지속될 경우 Auto Scaling이 작동돼 새 서버를 추가하는 방식으로 스케일링 정책을 정의한다.

웹 서버

TOMCAT

Apache사에서 개발한 서블릿 컨테이너만 있는 오픈소스 웹 애플리케이션 서버

Tomcat 특징

  • 자바 애플리케이션을 위한 대표적인 오픈소스 WAS(Web Application Server)
  • 오픈소스이기 때문에 라이선스 비용 부담 없이 사용할 수 있다.
  • 독립적으로도 사용 가능하며 Apache 같은 다른 웹 서버와 연동하여 함께 사용할 수 있다.
  • Tomcat은 자바 서블릿 컨테이너에 대한 공식 구현체로, Spring Boot에 내장되어있어 별도의 설치 과정이 필요 하지 않다.


Jetty

이클립스 재단의 HTTP 서버이자 자바 서블릿 컨테이너

  • Tomcat과 마찬가지로 자바 서블릿 컨테이너이자 서버로 사용할 수 있기 때문에 개발자는 원하는 서버(Tomcat or Jetty)를 선택하여 프로젝트를 구성할 수 있다.

Jetty 특징

  • 2009년 이클립스 재단으로 이전하며 오픈소스 프로젝트로 개발되었다.
  • Jetty는 타 웹 애플리케이션 대비 적은 메모리를 사용하여 가볍고 빠르다.
  • 애플리케이션에 내장 가능하다.
  • 경량 웹 애플리케이션으로 소형 장비, 소규모 프로그램에 더 적합하다.

Spring Boot 서버 Jetty로 변경하는 방법

아래와 같이 build.gradle 파일에서 Tomcat을 제외시키고 Jetty를 추가해주면 된다.

dependencies {
	implementation ('org.springframework.boot:spring-boot-starter-web') {
		exclude module: 'spring-boot-starter-tomcat' // Tomcat 제외시키기
	}
	implementation ('org.springframework.boot:spring-boot-starter-jetty') // Jetty 적용
	testImplementation 'org.springframework.boot:spring-boot-starter-test'

}


같은 방식으로 Tomcat, Jetty를 제외하고도 Netty, Undertow등 다양한 서버로 변경할 수 있다.


NginX - Proxy Server

NginX

  • 가볍고 높은 성능을 보이는 오픈소스 웹 서버 소프트웨어

Nginx는 클라이언트에게 정적 리소스를 빠르게 응답하기 위한 웹 서버로 사용할 수 있다.
(Tomcat과 Jetty는 자바 서블릿 컨테이너 혹은 웹 애플리케이션 서버다.)

Nginx 특징

  • 트래픽이 많은 웹 사이트의 확장성을 위해 개발된 고성능 웹 서버다.
  • 비동기 이벤트 기반으로 적은 자원으로 높은 성능과, 높은 동시성을 위해 개발되었다.
  • 다수의 클라이언트 연결을 효율적으로 처리할 수 있다.
  • 클라이언트와 서버 사이에 존재하는 리버스 프록시 서버로 사용할 수 있다.
  • Nginx를 클라이언트와 서버 사이에 배치하여 무중단 배포를 할 수 있다.

Spring Boot와 Nginx 연동 방법

웹 브라우저에서 http://localhost를 입력하면 기본적으로 80 포트로 접속된다.
nginx를 사용하여 80 포트에서 들어오는 요청을 가로채서 8080 포트로 전달해 보았다.

  1. 다운로드

  1. nginx.exe 실행 -> 추가 정보 -> 실행

  1. http://localhost/ 접속해서 실행 확인
    (포트번호 생략 가능)

4.Nginx 설정 파일 수정

nginx-1.22.1\nginx-1.22.1\conf 경로에서 nginx.conf 파일 확인 가능
(압축해제한 폴더 확인)

설정에서 포트 번호를 80으로 변경하고 리버스 프록시 서버로서 Spring Boot 프로젝트에 연동

server {
		listen       80; # (Mac OS의 경우) 8080 포트에서 80번 포트로 변경합니다.
...
		location / {
				...
				proxy_pass http://localhost:8080; # 요청을 8080 포트로 넘긴다.
				proxy_set_header X-Real-IP $remote_addr;
				proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
				proxy_set_header Host $http_host;
		}
}

  1. Nginx 재시작

Nginx 실행 파일이 있는 폴더(압축 해제한 폴더)로 이동하여 다음 명령어를 실행

nginx -s reload

그런데 nginx: [error] invalid PID number "" in "D:\AAWonJong\Program File\nginx-1.22.1\nginx-1.22.1/logs/nginx.pid"와 같이 잘못된 PID 번호라고 오류가 발생했다. (nginx 종료가 제대로 안되는 것 같다.)

아래와 같이 80 포트를 사용하는 프로세스를 찾아 중지시키고 다시 실행시켰다.

D:\AAWonJong\Program File\nginx-1.22.1\nginx-1.22.1>netstat -aon | findstr ":80"
  TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       20952
  TCP    192.168.0.177:57096    211.47.61.158:80       TIME_WAIT       0
  TCP    192.168.0.177:57097    104.76.70.102:80       TIME_WAIT       0
  TCP    192.168.0.177:57098    104.76.70.102:80       TIME_WAIT       0
  TCP    192.168.0.177:57099    23.67.53.11:80         TIME_WAIT       0
  TCP    [::]:80                [::]:0                 LISTENING       20952

D:\AAWonJong\Program File\nginx-1.22.1\nginx-1.22.1>tasklist /fi "pid eq 20952"

이미지 이름                    PID 세션 이름              세션#  메모리 사용
========================= ======== ================ =========== ============
httpd.exe                    20952 Services                   0      8,212 K

D:\AAWonJong\Program File\nginx-1.22.1\nginx-1.22.1>taskkill /pid 20952 /f
성공: 프로세스(PID 20952)가 종료되었습니다.

D:\AAWonJong\Program File\nginx-1.22.1\nginx-1.22.1>nginx -s reload
nginx: [error] invalid PID number "" in "D:\AAWonJong\Program File\nginx-1.22.1\nginx-1.22.1/logs/nginx.pid"

D:\AAWonJong\Program File\nginx-1.22.1\nginx-1.22.1>nginx.exe
  1. 로컬 재접속

Nginx 재시작 후 localhost (80번 포트는 생략 가능)에 접속하면 아래와 같이 에러문을 확인할 수 있다. (8080번 포트를 사용하지 않았기 때문)

애플리케이션 실행 후 다시 localhost에 접속하면 정상적으로 화면이 출력된다.


nginx -s stop 이 명령어로 nginx 종료 가능


Nginx - Load Balancer

NGINX를 이용하여 로컬 환경에서 로드밸런싱을 구성해 봤다.

  1. 두 개의 스프링부트 서버 실행

빌드 후 아래 두 명령어를 이용해 하나는 8080번 포트, 다른 하나는 8081번 포트를 사용해서 실행

java -jar sample-0.0.1-SNAPSHOT.jar
java -Dserver.port=8081 -jar sample-0.0.1-SNAPSHOT.jar //8081 포트에서 실행

빌드방법은 링크 참조

@RestController
public class HelloController {

  @GetMapping("/")
  public String hello() {
    long pid = ProcessHandle.current().pid();
    return String.format("Hello World, Hello BE Bootcamp! @PID : %d", pid);
  }
}

위와 같이 PID(프로세스 식별자=Process Identifier)를 확인하기 편하게 코드를 짜뒀다.

  1. NGINX 설정파일 수정
http {
	~~~
	upstream backend {
		server localhost:8080;
		server localhost:8081;
	}
    server{
    	~~~
		location / {
			proxy_pass http://backend;
		}
    }    
}

  • 위의 코드는 backend라는 서버 그룹을 만든 뒤 그룹 자체로 전달을 하는 구조다. 서버 그룹의 이름은 다른 이름으로 변경 가능하다.

    • 이 때 그룹에 속한 각 서버의 값은 위에서 실행한 두 개의 스프링부트 프로젝트 접속 URL을 작성한다.
    • 로컬환경에서 8080번 포트와 8081번 포트로 실행했기 때문에 각각 포트 번호까지 함께 작성했다.
  • location의 proxy_pass 값을 위에서 만든 서버 그룹으로 설정했다.

NGINX의 포트는 80번으로 설정되어있기 때문에 포트를 생략한 localhost 로 접속시 8080번 포트와 8081번 포트가 번갈아 연결된다.

  1. 로드밸런싱 결과

NGINX 실행 후 http://localhost/에 접속시 아래와 같이 두 프로세스가 번갈아 나오는걸 확인 가능했다.


VPC

VPC(Virtual Private Cloud 서비스)

  • 클라우드 내 프라이빗 공간을 제공함으로써, 클라우드를 퍼블릭과 프라이빗 영역으로 논리적으로 분리할 수 있게 하는 기능
  • VPC를 통해 클라우드에 있는 리소스를 격리해 각 리소스별 의존도를 낮춰 확장성을 가질 수 있다.

VPC구성 요소, 주요 용어

IP Address

IP는 컴퓨터 네트워크에서 장치들이 서로를 인식하고 통신을 하기 위해서 사용하는 특수한 번호로, IPv4, IPv6로 나뉘어 있으며 혼용하여 사용하고 있다.

IPv4를 기준으로 예를 들면, 아래와 같은 형식인 172.16.0.0 의 모습으로 이루어져 있다.

172.16.0.0
10101100.00010000.00000000.00000000

하지만 표에서 보이는 십진수의 형태는 보기 편하도록 변형한 것이고, 실제의 형태는 2진수 8자리의 형태, 즉 각 8bit(비트)씩 총 32bit로 구성되어 있다. 이때 각 8bit를 Octet이라고 부르며, . 으로 구분한다. 그러므로 IPv4는 4개의 Octet(옥텟)으로 이루어져 있다고 할 수 있다.

IP Address Class

이전에는 IPv4 주소에서 호스트가 연결되어 있는 특정 네트워크를 가리키는 8비트의 네트워크 영역(Network Address)과 해당 네트워크 내에서 호스트의 주소(Host Address)를 가리키는 나머지 영역을 구분하기 위해서 클래스(Class)를 사용했다. 클래스는 총 5가지(A, B, C, D, E) 클래스로 나누어져 있다. 하지만 D와 E 클래스는 멀티캐스트용, 연구 개발을 위한 예약 IP이므로 보통 사용되지 않는다.

  • A 클래스
Network AddressHost AddressHost AddressHost Address
0-1270-2550-2550-255

단, 0.0.0.0 의 경우는 자체 네트워크를 의미하기 때문에 제외되고, 127.0.0.0 ~ 127.255.255.255는 자기 자신을 가리키기 위한 목적으로 예약된 IP주소이기 때문에 사용할 수 없다.

  • B 클래스
Network AddressNetwork AddressHost AddressHost Address
128-1910-2550-2550-255
  • C 클래스
Network AddressNetwork AddressNetwork AddressHost Address
192-2230-2550-2550-255

CIDR(Classless inter-domain routing)

CIDR은 사이더라고 불리며, 클래스 없는 도메인 간 라우팅 기법으로 1993년 도입되기 시작한 국제 표준의 IP주소 할당 방법이며, 위의 IP 클래스 방식을 대체한 방식이다.

기존에는 클래스에 따라 정해진 Network Address와 Host Address를 사용해야 했다면, CIDR은 원하는 블록만큼 Network Address를 지정하여 운용할 수 있다.

위의 예시에 따르면, /16 은 첫 16bit를 Network Address로 사용한다는 의미로, 총 2^16인 65,536개의 IP주소를 사용할 수 있는 커다란 네트워크 블록을 이러한 방식으로 표시한다.

CIDR 블록IP 주소의 수
/2816
/24254
/204094
/1816,382
/1665,536

서브넷(Subnet)

서브넷 서브네트워크(Subnetwork)

  • IP 네트워크의 논리적인 하위 부분을 가리킨다.

서브넷을 통해 하나의 네트워크를 여러 개로 나눌 수 있다.
VPC를 사용하면 퍼블릭 서브넷, 프라이빗 서브넷, VPN only 서브넷 등, 필요에 따라 다양한 서브넷을 생성할 수 있다.

  • 퍼블릭 서브넷 : 인터넷을 통해 연결 할 수 있는 서브넷
  • 프라이빗 서브넷 : 인터넷을 연결하지 않고, 보안을 유지하는 배타적인 서브넷
  • VPN only 서브넷 : 기업 데이터 센터와 VPC를 연결하는 서브넷

서브넷은 VPC의 CIDR 블록을 이용해 정의되며, 최소 크기의 서브넷은 /28 다. 이때 주의 할 점은 서브넷은 AZ당 최소 하나를 사용할 수 있고, 여러 개의 AZ에 연결되는 서브넷은 만들 수 없다.

Tips ) AWS가 확보한 서브넷 중 처음 네 개의 IP주소와 마지막 IP주소는 인터넷 네트워킹을 위해 예약되어 있다. 서브넷에서 가용 IP주소를 계산할 때는 항상 이 부분을 기억하고 있어야 한다. 예를 들어, 10.0.0.0/24 체계의 CIDR 블록이 있는 서브넷에서 10.0.0.0, 10.0.0.1, 10.0.02, 10.0.0.3, 10.0.0.255 등 5개의 IP주소는 예약 되어 있다.

라우팅 테이블(Routing Table)

라우팅 테이블

  • 하나의 지점에서 또 다른 지점으로 가기 위한 모든 정보를 제공하기 위한 테이블
  • 트래픽의 전송 방향을 결정하는 라우트와 관련된 규칙을 담은 테이블로 목적지를 향한 최적의 경로로 데이터 패킷을 전송하기 위한 모든 정보를 담고 있다.

모든 서브넷은 라우팅 테이블을 갖고 있다.

예를 들어 아래의 캡처본과 같이 특정 VPC의 서브넷이 라우팅 테이블에 인터넷 게이트웨이(VPC와 인터넷 간 통신을 가능하게 하는 구성요소)를 포함하고 있다면, 해당 서브넷은 인터넷 액세스 권한 및 정보를 가진다.

각각의 서브넷은 항상 라우팅 테이블을 가지고 있어야 하며, 하나의 라우팅 테이블 규칙을 여러 개의 서브넷에 연결하는 것도 가능하다. 서브넷을 생성하고 별도의 라우팅 테이블을 생성하지 않으면 클라우드가 자동으로 VPC의 메인 라우팅 테이블을 연결한다.

0개의 댓글