새소식

Welcome to the tech blog of Junior Backend Developer Seulbin Kang!

Infra

(BE 개발자 4개월차) 현업에서 경험한 AWS 이사하기 (1차)

  • -

👀 들어가기 전에

얼마 전 우리 팀에서는 드디어 제대로된 새 계정으로의 AWS 이동이 필요해졌다. 

여태까지 임시로 쓰고 있던 임시계정이 아닌 제대로된 계정으로 새롭게 구축한 AWS를 대상으로 옮겨가게 되었다.

지금까지는 간단한 테스트 벤치용 AWS정도로 가벼운 사용을 하고 있었지만, 이 정도로는 앞으로 있을 트래픽 및 장기 운영을 고려한 안정성 요구로 새로이 회사 팀 계정을 파서 제대로 Cloud를 구축하기로 하게된 것이다.

이 과정에서 현재 사용중인 S3와 MySQL DB 서버는 그대로 데이터를 이전해야만 했다. 

여기서 이 모든 작업을 내가 맡게 되었다.

그래서 이 작업을 진행하면서 느낀점도 많고 배워간 점도 많았기에 이에 대해 정리해보려 한다. 

이 글이 1차인 이유는, 지금은 DEV 계정으로 DEV 서버만 옮겨갔고 이제 곧 Prod계정으로 Prod 서버 모든 것을 다시 옮겨가야하기에 1차로 지었다. 2차는 아마 유사하긴 하겠지만, 1차에서 테스트 해본 결과를 토대로 판단이 날 것이라, 그때의 느낀 상황들은 또 그 때가서 정리해보려한다.


👀 본론

AWS 마이그레이션? 어떻게 하는데요?

한 번도 해본 적이 없기에 할 줄을 몰랐다.

그냥 프로젝트에서 여태 해오듯이 계정 파서 RDS 만들고 모든 VPC 오픈해버릴 수도 없는 노릇이었다.

회사 서버다. 프로젝트 서버가 아니다. 보안이 그 무엇보다도 중요하고 그렇기에 지켜야할 것들이 많았다.

우선 AWS 마이그레이션 날짜는 1/22 저녁~ 1/23 아침 까지를 목표로 잡고 그 전까지 어떻게 할지에 대한 계획과 일정을 수립했다.

처음 해보는 것이기에 공부가 좀 많이 필요했다.

우선 우리 회사의 Dev 서버 쪽 클라우드 아키텍처 일부를 그려본다면 아래와 같다.

대략적인 DEV 아키텍처

 

우선 아키텍처를 보며 어디서 어디로 옮겨갈지 어떻게 옮겨갈지 순서를 하나하나 확립해나가기 시작했다.

아래와 같이 순서를 확립했다.

 

1. S3 이전

2. RDS 이전

3. EC2 환경 수립 (Test Tool & Service)

4. CI /CD 배포 경로 변경

5. Route53 경로 라우팅 전환


S3 이전 시작 : "데이터는 꼭 그대로 옮겨 주세요!"

가장 먼저 고민한 건 S3였다.

RDS보다 S3를 먼저 옮겨야겠다는 생각이 들었던 것은, S3는 파일 기반 저장소이기 때문에 어플리케이션과의 관계가 상대적으로 느슨하고 반대로 한 번 참조가 어긋나면 서비스 전반에 영향을 줄 수 있기 때문이다. DB데이터는 마이그레이션 과정에서 일시적으로 읽기 전용 전환이나 점검을 통해 정합성을 맞출 수 있지만, S3의 경우 URL, 객체 키, 권한 정책이 어긋나면 이미 배포된 어플리케이션에서 즉시 장애로 이어질 수 있다. (물론, 새 EC2에 서비스가 배포되어있는 것은 아니었지만, 이전에 사용하고 있던 EC2에 서비스는 이미 배포되어있기에 기존 S3가 조금이라도 틀어질 경우 발생할 문제를 최소화하고 싶었다.)

 

문제는 계정이 다른 곳으로 옮겨보는 것이 처음이라는 것이다. 

처음에는 단순히

A계정에서 B계정으로 복사 권한만 열어주면 끝날 문제가 아닌가?

라고 생각했다.

 

근데 조금만 생각해보면 보안적으로 하면 안될 선택이었다.

그래서 선택한 방식은 다음과 같다.

중간에 옮기는 것을 도와줄 EC2를 하나 두고,

해당 EC2에서  A계정 자격증명으로 기존 S3를 Read, B계정 자격증명으로 신규 S3 Write를 할 수 있도록 한다.

S3 마이그레이션 아키텍처

aws s3 sync를 사용해 단방향으로 복사시킨다.

aws s3 sync s3://old-bucket s3://new-bucket \
  --source-profile old-account \
  --profile new-account

 

이 방식으로 진행하게 되면서 두 계정은 서로 직접적인 권한을 열어줄 필요가 없다.

이 과정에서 중간 AWS CLI를 통해서 중계작업을 진행했다.

IAM Role 기반 Architecture

 

 

자격증명은 위 사진과 같이, Account A에서는 Put은 불가했으며, Account B에서의 Get은 불가하도록 구성하였다.

작업이 끝나면 Relay EC2 자격증명만 정리해주면 된다. 또한, 로그로 이전 결과 검증이 가능했다.

 

정상적으로 이전 완료한 S3

 

이후 정상적으로 이전 완료한 S3를 새 계정에서 확인할 수 있었다.

이전 계정과 동일한 루트로 접근하도록 두어 S3 버킷명만 다르게 하면 정상적으로 어플리케이션에서의 접근이 가능하도록 구성되었다.


RDS 이전 : 버전? 문자셋? 락?

하나의 산을 넘어오니 다른 산이 나왔다. RDS다.

기존 RDS는 MySQL 8.0버전을 사용 중에 있었다. 허나, MySQL 8.0버전은 곧 aws에서 서비스 종료가 되기에

신규 RDS는 더 높은 버전으로 옮겨야했다. 그래서 선택한 버전이 MySQL 8.4였다. 리스크가 없었다. 버전간 큰 차이가 있지 않았기에 이전하는데에 문제가 없을 것이라 판단했던 것이다.

이전을 하는 과정에서는 아래 세가지 사항을 고려했다.

  • 데이터 정합성
  • 다운타임 최소화
  • 버전 차이로 인한 문제 여부

결론적으로 선택한 방식은 기존 RDS에서 Dump뜬 후 신규 RDS에서 Restore하는 방식을 선택하게 되었다.

mysqldump -h old-rds ... > dump.sql
mysql -h new-rds ... < dump.sql

 

기존에 사용하고 있던 RDS가 테스트로 밖에 사용이 안되었기에 안에 들어있는 용량이 그렇게 크지 않았기에 Dump해서 이전하는 것 만으로도 충분히 가능할 것이라 생각했다.


실제 진행하면서 부딪힌 문제들

1. 접근 경로 : Basition을 거쳐야만 접속이 가능하다.

RDS dump의 과정

 

신규 계정 B의 RDS는 보안 정책상 외부에서 직접 접근할 수 없도록 구성되어 있었다.

즉, 로컬 PC나 IntelliJ 와 같은 클라이언트에서 바로 RDS에 접속해 덤프를 뜨는 방식은 불가능했다.

Basition EC2에 접속한 뒤 해당 서버를 경유해 RDS 작업을 수행

 

그리하여 작업 흐름은 아래와 같이 정리되었다.

  1. Basition EC2에 SSH 접속
  2. Basition에서 기존 RDS로 접속해 mysqldump 수행
  3. 생성된 dump 파일을 이용해 신규 RDS에 restore

번거롭긴 하지만, RDS를 외부에 노출하지 않아도 되며, 접근 경로가 명확히 통제되며 보안 측면에서 가장 안전한 구조였다.


2. 락 때문에 서비스가 멈출 수도 있지 않을까?

DB이전 방식을 dump → restore로 정한 순간 가장 먼저 들었던 고민은 락에 대한 부분이었다.

Dump 뜨는 동안 테이블에 락이 걸리면 결국 서비스에 영향이 생길수 밖에 없지 않을까?

 

이번 작업은 안정적으로 전체 데이터를 정확히 복사해내는게 가장 중요하기에 아래와 같은 판단을 내렸다.

다운타임을 없애기보다는 짧은 시간 동안의 서비스 중단을 감수하고 정합성을 최우선으로 안정적으로 이전하자

 

그래서 우선, 최대한 사람들이 서비스를 사용하지 않는 저녁 8시에 해당 작업이 진행되었다.

이 방향으로 팀원들과 공유했고, 타 팀과도 협의하여 해당 시간 동안 프론트엔드에서는 아예 점검 중 화면을 노출하도록 조치하였다.

 

덕분에 락으로 인한 중간 데이터 불일치나 예외 상황 없이 한 번에 깔끔하게 이전을 마무리할 수 있었다.


3. 문자셋 및 타 설정

DB 이전에서 의외로 신경 쓰였던 부분은 버전 차이도 버전차이지만, 문자셋과 파라미터 설정이었다.

DB는 문자셋이나 collation 설정 하나만 달라도 restore 과정에서 오류가 발생하거나 이전 후 어플리케이션 동작에 문제가 생길 수 있다.

그래서 실제로 restore를 진행하기 전에 아래 사항들을 먼저 점검했다.

  • 기존 DB와 신규 DB의 문자셋 및 collation 확인
  • 신규 RDS의 파라미터 그룹 설정이 과도하게 변경되지 않았는지 확인
  • MySQL 8.0 → 8.4 버전 차이로 인해 문제가 될 만한 설정 여부 점검

확인한 과정들

두 RDS에서 아래 명령어를 통해 확인해보았다.

SELECT 
  SCHEMA_NAME,
  DEFAULT_CHARACTER_SET_NAME,
  DEFAULT_COLLATION_NAME
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME = 'DB_NAME';

 

MySQL 서버 자체의 문자셋과 Collation은 아래와 같은 방식으로 확인해보았다.

SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

 

이외에 다른 파라미터들은 sql_mode, innodb_default_row_format, explicit_defaults_for_timestamp 이 세가지 값을 확인해보았다.

SHOW VARIABLES LIKE 'sql_mode';
SHOW VARIABLES LIKE 'innodb_default_row_format';
SHOW VARIABLES LIKE 'explicit_defaults_for_timestamp';

 

다행히 결론적으로 큰 차이는 없었고, 해당 부분에서도 문제 없이 Restore가 정상적으로 완료되었다.


EC2 환경 수립

기존 서비스는 이미 다음과 같은 방식으로 운영되고 있었다.

  • 어플리케이션은 Docker 이미지로 빌드
  • Docker Hub에 이미지 Push
  • EC2에서는 해당 이미지를 pull하여 컨테이너 실행
  • 배포 자동화는 GitHub Actions + Self-hosted Runner

즉, EC2에 직접 Java를 설치해서 jar를 실행하는 방식이 아니라 EC2는 컨테이너를 실행하기 위한 런타임 환경 역할만 수행하면 되었다.

이 기준에 따라 EC2 환경 수립의 방향을 정했다.


Service EC2 환경 구성

Service EC2의 역할은 아래와 같다.

  • 실제 Spring Boot 어플리케이션 실행
  • RDS (MySQL)/ S3연동
  • CI/CD를 통한 자동 배포 대상

따라서 Service EC2에는 최소한 다음 두가지가 필요했다.

  • Docker 설치
    : 컨테이너 실행
  • GitHub Actions Self-Hosted Runner 설치
    : GitHub Actions에서 빌드가 끝난 이미지를 직접 EC2에서 Pull하여 run하기 위하여 필요

Test Tool EC2 환경 구성

Test Tool EC2는 서비스 자체를  실행하지 않으며 운영 및 모니터링을 위한 도구들을 담당했다.

구성해야할 대상은 Grafana, Prometheus, Loki, InfluxDB 였고, 이 서버 역시 Docker 기반으로 구성되어 있었기 때문에 docker-compose 파일을 통해 컨테이너로 띄웠다. 각 서비스 포트가 정상적으로 열려있는지 확인하는 것도 잊지 않고 진행해주었다.


수동 배포를 통한 1차 검증

CI/CD 파이프라인을 변경하기 전에 신규 환경에서 서비스가 정상적으로 기동되는지를 수동 배포로 먼저 검증했다.

인프라 환경이 크게 변경된 상황에서 곧바로 CI/CD를 연결하기 보다는 어플리케이션과 인프라 자체가 정상 동작하는지를 사전에 확인하는 것이 필요하다고 판단했기 때문이다.

진행한 과정들

 

이 과정에서 아래 사항들을 중점적으로 확인했다.

  • Docker Hub에서 이미지를 정상적으로 pull받아 오는지
  • 컨테이너 실행 시 환경 변수 주입은 정상적으로 되는지
  • Spring Boot 어플리케이션은 잘 기동되는지
  • 신규 RDS(MySQL 8.4)와의 연결은 정상적으로 되는지
  • 신규 S3 버킷 접근은 정상적으로 되는지

위 항목들이 모두 문제없이 동작하는 것을 확인한 이후에야 비로소 EC2 환경 수립이 완료되었다고 판단할 수 있었다.

이제 남아있는 작업은 다음 두 가지였다.

1) CI/CD 파이프라인 재구성

2) Route53 도메인 라우팅 전환

남은 작업


👀 마무리하며

CI/CD 파이프라인을 구성하는 과정에서, 기존 GitHub Actions Self-Hosted Runner의 태그 설정 문제로 인해 Organization 단 설정 변경이 필요하다는 점을 확인했고 해당 작업은 현재 담당 매니저님께 요청을 드린 상태이다. 다만, 이미 신규 환경에서의 수동 배포 및 서비스 기동까지는 모두 검증이 완료된 상태이기 때문에, 러너 설정만 정리되면 CI/CD 파이프라인을 다시 연결하고 Route 53 도메인 라우팅을 전환하는 작업만 진행하면 된다. (참고로 HTTPS 전환을 위한 ACM 인증서는 Route53 전환에 앞서 미리 신청해둔 상태이다.🙆🏻‍♂️)

이제 자동화된 배포 흐름을 복구하고 트래픽을 신규 환경으로 안전하게 전환하는 일만 남았다.

이번 Dev 서버 마이그레이션 작업을 진행하며 배운점들, 공부했던 점들을 토대로 Prod서버까지 무사히 마이그레이션 할 수 있기를 바란다.

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.