AWS 배포 완벽 가이드 | Section 5, 6

김민지·2024년 12월 18일

Section 5 | Github Actions를 이용한 배포 자동화

CI/CD 단계

  1. 로컬에서 코드 수정사항 발생
  2. 수정 후 dev 등 다른 branch에서 commit, push (not main!)
  3. github에서 pull request 확인 후 merge confilct가 없고 문제없는 요청이라면,
    (만약 문제가 있다면 로컬에서 git pull 후 다시 code update하고 1 ~ 3 반복)
  4. Github Actions에서 test 실행 및 build
  5. 성공 시, merge
  6. deploy
  7. 배포 성공 시 완료

CI: 배포 준비를 위한 Github Workflow 생성하기

  1. git branch 생성
    git branch로 현재 브랜치들 확인 후, git branch dev<or your branch name>으로 새 브랜치 생성
  2. commit 후 push
    이 때, push할 위치를 찾기 위해 git remote로 확인 가능. git push <git remote 결과> <현재 브랜치 명>

  3. github에서 merge... ← 이 때 github actions에서 어떤 동작을 하도록 만들고 싶음!
  • 로컬에서(Express 폴더) .github라는 이름의 폴더 생성 (+ 해당 강의에서 사용되는 UI extention은 Material Icon Theme)
  • .github 안에 workflows 폴더도 생성
  • workflows 폴더 안에 test.yml 파일 생성 (+ GitHub Actions extention도 설치)
    github action은 여러가지 trigger를 가지고 있고, 각 trigger들이 발동되었을 때 실행될 action을 정의해주는 것이라고 이해할 수 있음.
name: test

on: pull_request

jobs: 
    test: 
        runs-on: ubuntu-22.04
        steps: 
            - name: Checkout repository
              uses: actions/checkout@v3
            - name: Node.js setup
              uses: actions/setup-node@v3
              with: 
                node-version: "22"
            - name: Install npm packages
              run: npm ci
            - name: Install and run redis-server
              run: 
                sudo apt-get update
                sudo apt-get install -y redis-server
                redis-server --daemonize yes --requirepass test_env --port 6380
            - name: Run test
              run: npm run test
            - name: Build test
              run: npm run build

💥 이 때, error: failed to push some refs to 'https://github.com/<username>/<reponame>.git' 오류 이슈 발생

  • 이유: GitHub는 .github/workflows 디렉터리에 포함된 파일의 보안성을 보장하기 위해 추가적인 권한이 필요한데, 사용하는 인증 방법(OAuth 앱 또는 퍼스널 액세스 토큰)에 이 권한이 없다면 push가 거부된다고 함

해결방법

  1. 아래와 같이 workflow를 체크한 새로운 토큰을 발급받은 후 token 코드 복사
  2. Window 상태바에서 자격 증명 관리자를 검색한 후 github 관련 자격들을 모두 삭제
  3. 다시 push 시도 후 로그인 요청창이 뜨면 token으로 로그인하기 선택 후 새로 발급받은 토큰 입력 → push 성공

  • 완성된 내용을 push, pull request만 하면 바로 지금 작성한 action들이 trigger될 것임
  • pull request

💥 이 때, Install and run redis-server 단계에서 아래와 같은 오류 발생

  • 버전 18이 아니라 22로 해서 그런가..?
  • 수정해서 해결한 코드:
name: test

on: pull_request

jobs: 
    test: 
        runs-on: ubuntu-22.04
        steps: 
            - name: Checkout repository
              uses: actions/checkout@v3
            - name: Node.js setup
              uses: actions/setup-node@v3
              with: 
                node-version: "22"
            - name: Install npm packages
              run: npm ci
            - name: Install and configure redis-server
              run: |
                sudo apt-get update
                sudo apt-get install -y redis-server
                # Configure Redis to run as a daemon
                sudo sed -i 's/^# daemonize no/daemonize yes/' /etc/redis/redis.conf
                # Set Redis password
                echo "requirepass test_env" | sudo tee -a /etc/redis/redis.conf
                # Set Redis port
                sudo sed -i 's/^port 6379/port 6380/' /etc/redis/redis.conf
                # Restart Redis to apply configurations
                sudo systemctl restart redis-server
                # Verify Redis is running
                redis-cli -p 6380 -a test_env ping
            - name: Run test
              run: npm run test
            - name: Build test
              run: npm run build

💥 이후, Run test 단계에서 멈춰있음

→ 이유 : test 자체는 모두 성공적으로 완료함. 그러나 다음 단계로 넘어가지 않는 이유는 로컬에서 테스트코드를 수정할 때 프로세스가 종료되지 않고 계속 실행되도록 하기 위해 jest --watchAll 로 설정해둠. 이를 통해 코드를 수정하고 저장할 때마다 테스트가 다시 실행됨. 그러나 CI 환경에서는 테스트가 끝나면 해당 프로세스가 멈춰야 함.

  • package.json 수정: "scripts"에 "test:ci": "jest" 추가 후 로컬에서 npm run test:ci로 실행하고 멈추는 것 확인
  • test.yml 수정:
            - name: Run test
              run: npm run test:ci

  • 아래와 같이 성공적으로 pull request 생성
  • 실제 협업 환경에서는 branch를 기능별로 생성할 경우 여러개의 branch가 존재할 수록 혼잡할 수 있으므로 merge가 완료된 branch는 delete해주는 것이 권장됨

SSH 터널링으로 Lightsail VM 접속하기: Github action으로 자동화 배포

  1. 로컬 터미널에서 SSH key 생성: ssh-keygen -t rsa -b 4096 -C "github_action" -f ~/.ssh/github_id_rsa
  2. 로컬 터미널에서 SSH key 조회: cd ~/.sshls로 조회 후, cat ~/.ssh/github_id_rsa.pub로 생성된 SSH key 복사해두기
  3. AWS Ubuntu 터미널에서 현재 등록되어있는 SSH key 조회
  4. AWS Ubuntu 터미널에서 새로 생성한 SSH키 추가: vim ~/.ssh/authorized_keys에 들어가서 엔터치고 새로운 키 붙여넣기
  5. 로컬 터미널에서 SSH로 접속 시도: ssh -i ~/.ssh/github_id_rsa ubuntu@43.201.5.12

VM에 Static Public IP 부착

  • Networking에 들어가서 attatch static IP로 부착하기

  • static IP로 바꿔서 다시 로컬 터미널에서 접속해보자
    ssh -i ~/.ssh/github_id_rsa ubuntu@<publicIP>

Github Action이 필요한 SSH 관련 보안 정보 안전하게 제공

  • 제공해야 하는 SSH 보안 정보: SSH secret key, Ubuntu userName (ubuntu), Public IP(static public ip), host
  1. Github repository의 settings > secretes and variables 로 가서, New repository secret에 SSH_PRIVATE_KEY를 추가하기

    로컬 터미널에서 cat ~/.ssh/github_id_rsa (뒤에 pub이 붙지 않는 것이 private key이다)를 조회해서 복사한 후 추가 (-----END OPENSSH PRIVATE KEY----- 등도 다같이 추가)
  2. 동일하게 SSH_USERNAME를 추가하기
  3. 동일하게 SSH_PUBLIC_IP를 추가하기
  4. ssh-keyscan <publicIP>로 로컬에서 구한 내용으로 SSH_KNOWN_HOSTS를 추가하기
    복사할 때에는 항상 처음부터 끝까지

배포용 Workflow

  • deploy.yml이라는 파일명으로 deploy를 위한 github actions 테스트 생성
name: deploy

on: 
    push: 
        branches:
            - main

jobs:
    deploy: 
        runs-on: ubuntu-latest
        steps: 
            - name: Set up SSH
              run: 
                mkdir -p ~/.ssh/
                echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
                chmod 600 ~/.ssh/id_rsa
            
            - name: Set up known hosts
              run: 
                echo "${{ secrets.SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
                chmod 644 ~/.ssh/known_hosts
            
            - name: SSH and deploy
              run: 
                ssh ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_PUBLIC_IP }} "
                  cd express
                  git pull || exit 1
                  npm install || exit 1
                  npm run build || exit 1
                  sudo pkill node || exit 1
                  sudo npm run start & npx wait-on http://localhost
                  exit
                "

main branch 보호

  • 지금은 .yml의 테스트들이 완전히 완료되거나 성공하지 않아도 merge는 가능함
    Require status checks to pass before merging: 테스트 미통과 merge 방지
  • 로컬에서 그냥 바로 git push origin master 등으로 곧바로 push해버릴수도 있음
    Require a pull request before merging: 강제 push 방지
  • 위의 기능들은 team이나 enterprise repository에서만 사용 가능! (사실상 개인 개발자에게는 크게 필요하지 않으므로)

Section 6 | 견고한 서버 구축하기: High Availability & Zero Down Time

좋은 서버란?

  • 가용성이 높은 서버 (High available): 서버가 계속 꺼지지 않고 유지될 뿐 아니라 traffic이 많이 몰려도 낮은 response time 유지하는 서버
  • zero down time: 배포 시 종종 발생하는 down time을 없앤 서버
  • 부하 테스트를 위해 artillery 라는 도구 사용 예정

Artillery 사용해서 부하 테스트 하기

  1. Artillery 설치: npm을 사용해서 설치하게 됨. 이 때, 설치에는 관리자 권한이 필요하므로 sudo 명령어를 앞에 붙인 후 웹사이트에 안내되어있는 설치 명령어대로 설치하기 (단, window에서는 powershell을 관리자 권한으로 실행하는 것으로 충분히 설치 가능)
  2. load-test.yml 테스트파일 생성
    config: 어떤 url을 대상으로 테스트할 것인지(target), 몇 명의 유저들이 몇번의 부하를 주게 할 건지에 대한 내용(phases)
    scenario: 어떤 종류의 요청을 날릴 건지 (GET, POST, ...)
config: 
  target: http://localhost:4000
  phases: 
    - duration: 5 # 5초동안 지속
      arrivalRate: 1000 # 1초당 1000개의 가상유저가 아래의 시나리오대로 요청을 보내는 것을 가정

scenarios: 
  - flow: 
    - get: 
        url: "/messages" # tab 키 안 누르면 오류남 ,, 
  1. npm run dev로 로컬에서 서버를 돌려줌 (우선은 로컬 URL로 테스트중이므로!)
  2. 다른 터미널 창을 동시에 열어서 artillery run load-test.yml으로 테스트 실행
  3. 지금까지는 부하가 갈 확률이 낮은 API였으니까 (단순히 messages라는 배열에 GET 요청을 받는게 전부인 간단한 API) app.ts에 코드를 약간 추가해서 더 복잡하게 만들어보자
  // recursion: 부하를 늘리기 위한 재귀함수(피보나치) 및 API endpoint 추가
  function fibo (n:number):number{
    if (n <= 1) return n;
    return fibo(n-1) + fibo(n-2);
  }

  app.get("/fibo/:n", (req, res) => {
    const n = parseInt(req.params.n, 10); // 10진수로 표현
    const result = fibo(n); // 재귀함수 적용
    res.send(`Recursion function Fibonacci(${n}) => ${result}`); // 요청 보내기
  });
  1. Postman으로 먼저 테스트해보자: 요청 시 제공하는 숫자를 늘릴 수록 요청 처리 시간이 빠르게 증가한다는 것을 알 수 있음!
  2. 현재 수정된 코드(.yml, ts) git으로 push해주기
  3. AWS 터미널에서 pull, build 후 서버 시작 후 도메인으로 들어가서 fibo 테스트

    ✨ 주의: AWS 터미널에서 서버를 시작할 때에는 반드시 관리자 권한으로 sudo npm run start를 해줘야 함!!
  4. url을 배포 url로 변경한 후 테스트
    n = 10

    n = 35: 아예 timeout된 요청도 있고, 수행에 성공한 요청들도 비교적 긴 시간이 소요되며 완료된 것을 확인할 수 있음
  • 어떻게 개선할 수 있을까? node는 single thread runner라서 여러개의 CPU가 있더라도 이를 활용하지 못함.. 그래서 다른 서버의 경우도 그렇지만(서버가 다운되고 회복되는 시간에 서버다운시간이 발생하는 것을 방지하기 위해) 특히나 node의 경우에는 CPU의 개수만큼 여러개의 포트에서 서버를 여러개 띄워주는게 중요함

Process Manager: 여러 process 띄우고 LoadBalancing하기

  • PM2 : 원래는 개발자가 여러개의 PORT를 관리하며 각각 child process를 돌려줘야 하지만, PM2의 경우는 개발자가 기본 포트 (80)에만 실행하면 나머지는 proxy로 자체적으로 처리해줌.
  • pm2 start build/index.js -i 3 --time: i 옵션은 몇개의 프로세스를 띄울 지 정하는 옵션임
  • pm2 list로 현재 실행중인 프로세스 확인 가능
  • pm2 kill로 현재 실행중인 프로세스 중지 가능
  • 코드 수정 후 새로운 버전으로 프로세스를 실행하고자 할 때, 프로세스를 죽일 필요 없이 pm2 reload all로 수행 가능
  • pm2 활용 시 무중단 배포 가능: 코드 수정시에도 다음과 같이 무중단으로 실행하므로!
    (1) 수정된 코드로 새 프로세스 하나 띄우기
    (2) 잘 돌아가는 거 확인
    (3) 기존 코드의 프로세스 하나 죽이기
  • pm2 logs --watch로 실시간 로그 확인 가능: 코드 수정을 실시간으로 반영하므로, pm2 logs --watch 실행 후 app.ts 파일을 수정해보면 확인 가능

VM에 Process Manager 적용

  • 앞서 로컬에서 테스트해본 것을 바탕으로 VM에 적용하는 순서를 알아보자.
  1. 로컬 터미널에서 ssh -i ~/.ssh/github_id_rsa ubuntu@<publicIP> 입력 후 SSH 터미널로 접속
  2. VM에 들어가서 pm2 설치: sudo npm i -g pm2
  3. sudo pkill node: node processor 죽이기
  4. cd express 후, sudo pm2 start build/index.js -i max --time 실행 (여기까지는 한번만 실행하면 되는 내용이므로 .yml 파일에 넣기에는 적절하지 않음)
    -i 옵션의 숫자는 상수에서 max로 수정해주면 PM2가 자체적으로 해당 서버의 CPU 개수에 맞춰서 프로세스 개수를 설정해서 띄워줌. 로컬에서 실행하면 각 로컬 기기의 코어 수만큼의 프로세스가 띄워짐 (내 로컬은 8코어이므로 8개의 프로세스가 실행됨)
  5. deploy.yml 파일 다음과 같이 수정: sudo pkill node || exit 1, sudo npm run start & npx wait-on http://localhost를 삭제하고 sudo pm2 reload로 대체하기
name: deploy

on: 
    push: 
        branches:
            - main

jobs:
    deploy: 
        runs-on: ubuntu-latest
        steps: 
            - name: Set up SSH
              run: 
                mkdir -p ~/.ssh/
                echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
                chmod 600 ~/.ssh/id_rsa
            
            - name: Set up known hosts
              run: 
                echo "${{ secrets.SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
                chmod 644 ~/.ssh/known_hosts
            
            - name: SSH and deploy
              run: 
                ssh ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_PUBLIC_IP }} "
                  cd express
                  git pull || exit 1
                  npm install || exit 1
                  npm run build || exit 1
                  sudo pm2 reload all
                  exit
                "

수직 vs 수평 확장: Vertical vs Horizontal Scaling

  • artillery run load-test.yml로 부하를 점진적으로 주면서 sudo pm2 list --watch로 관찰하기
  • fibo에 n으로 35 정도 주면 그때무터는 CPU 사용량이 100%에 달하기 시작한다.
  • 실전에서 만약 이렇게 CPU에 부담을 주는 코드가 있다면, 첫번째로 해야 할 일은 코드를 수정하는 것일 것이다. 그러나 만약 최선을 다해 최적화했는데도 여전히 CPU 사용량 등의 문제로 time out이 나온다면...?
  1. 수직 확장: 현재 가지고 있는 한 대의 기기의 스펙을 업그레이드 하는 것
    그러나 이런 문제가 발생할 때마다 CPU를 더 사다가 달거나 더 성능이 좋은 기기로 기기를 바꿀 수는 없을 것임..
  2. 수평 확장: 저 성능의 기기를 여러개 사다가 개수를 늘려서 문제 해결하기
    AWS의 경우도 수평확장이 대체적으로 금액적으로도 더 저렴함
    서버 여러개를 띄우는 식으로 이 문제를 해결하면 만약 자주 있는 일은 아니지만 VM 서버가 죽을 때의 공백도 자연히 매울 수 있음
  • 순간적으로 메모리가 많이 드는 build 과정을 서버에서 빼기 위해서 필요한 개념: docker

Snapshot을 이용해서 비교적 간편하게 수평확장하기: Horizontal Scaling 방법

  • 이제 우리가 선택한 방법인 수평 확장을 위해서는 결국 새로운 VM 서버들을 추가해야하는데, 생각해보면 우리가 앞서 VM 서버 하나를 시작하는데에도 Redis, PM 등등 여러가지 설정들을 해주느라 시간이 많이 소요되었음. 이걸 서버 하나 추가할 때마다 처음부터 한다고 생각하면 너무 시간도 오래 걸리고 균일하게 복사하기도 어려울 수 있음.
  • 해결책: snapshot을 따서 hard storage를 그대로 복사해버리자!

    배포와는 무관하게 Redis, PM2 등 서버 설정하는 작업을 수행해서 서버가 바뀔 때마다 snapshot은 백업용으로 따두는게 좋음
  • create new instance를 선택해서 새로운 서버 생성!
  • 다른 옵션들은 그대로 두고 instance plan만 들어가서 체크해주기
  • 생성된 모습
  • Networking에 들어가서 연결해주자

  • 생성된 express-2 의 SSH 터미널에 들어가서 설정할 부분들 설정해주기
  • 아래와 같이 처음부터 express도 있는 걸 알 수 있음
  • 이 시점에서 Health check 를 확인하면 아래와 같이 failed로 뜰 것임
  • SSH 창에서 cd express, redis-server --daemonize yes, sudo pm2 start build/index.js -i max --time 를 실행하고 체크하면 pass로 뜸!

    추가로 경고를 해결하기 위해 sudo sysctl vm.overcommit_memory=1도 실행해줌
  • express-2의 public ip로 접근해보기
  • 여기까지 설정하고 다시 로컬에서 동일하게 35로 테스트를 돌려가며 부하를 체크하자!
    response time이 확연히 개선된 것을 확인할 수 있음. 이보다 더 단축하기 위해서는 서버를 추가로 연결해야 하는데 우선은 테스트 삼아 해보는 중이므로 여기까지만 진행할 것.

Availability Zones (AZ)

  • Create instance 시 확인해보면 Region 별로 Zone이 여러개 있음. 이 때, Region은 우리가 위치한 지역을 말하고, Zone은 해당 지역 내에서 서버가 분리된 기준을 뜻함. 즉, 만약 Seoul Region에 Zone이 4개가 있다면 분리된 데이터 센터가 4개 있다고 이해해도 무방함. 이 Zone들은 분리되어있으므로 자연재해, 전쟁 등의 만일의 사태에도 모든 센터가 동시 다운되지 않도록 설정됨. 따라서, 수평 확장으로 VM 서버를 여러개 설정했다면 이 서버들의 Zone을 모두 다르게 설정해주는게 더 안정적임!
  • 예: 이전 카카오 서버 다운 사태와 같은 사태를 대비하기 위한 대비책임
    데이터센터 하나에 몰빵해두면 다운 시에 위험할테니까
  • 추가로, Load Balancer는 확인해보면 All zones 라고 되어있음. 모든 요청은 Load Balancer를 통해서 들어오므로 개발자가 아무리 각 VM 서버를 적절히 zone별로 분할하더라도 Load Balancer가 다운되어버리면 아예 요청 자체를 받지 못해서 critical한 문제가 된다. 따라서 처음 생성될 때 여러개의 instance를 가지고 생성되고, 각 instance는 모든 AZ에 분산되어있다.

Redis data inconsistency 문제 정의

  • POST로 데이터를 저장한 후 조회하려고 하는데 다시 빈 배열이 돌아옴

  • GET 요청을 3번 정도 보내고 나서야 겨우 앞서 보낸 내용이 들어가있음 ..
  • 여러개의 요청을 더 보내보자! redis, are u ok..?, hello 를 보냄!
  • 조회해본 결과, 아래의 조합끼리만 계속 나옴. 원래는 세개가 동시에 나와야 하는데..? 이유가 뭘까?

  • 결론적으로, 이유는 각각의 GET, POST 요청이 각각 별도의 VM 서버로 Load Balancer에 의해 routing 된 것이 문제임.
  • POST 요청에서 redis, hello 가 하나의 서버로 들어가고 are u ok..?가 또 하나의 서버로 들어가서 각각 저장된 후 GET 요청을 보낼 때마다 두 서버 중 하나씩을 가져오니까 묶음으로 해서 계속 위의 두 조합의 화면만이 나오는 것임. 결국 Redis 서버가 여러개라서 발생하는 문제이다.
  • 이런 이유로 별도의 DB를 두고 각 서버와 DB를 연결해서 하나로 통일하는 것임!
  • 우선 우리는 간단히 이 문제를 해결하기 위해 Redis 서버를 분리해서 하나의 Redis 서버에 각각의 Node.js App이 연결될 수 있도록 아키텍처를 수정할 것임.

Private Network 사용해서 VM to VM 안전하게 통신

  1. 새로운 instance 만들기 (Redis를 분리할 instance가 필요하므로)



    (AWS 정책 상 CPU를 하나의 계정 당 디폴트로 20까지만 사용할 수 있는데 이미 전부 사용했고 요청 수용에 시간이 걸리는 관계로 여기부터는 강의 내용 필기만 진행)
  2. 새로 생성한 instance의 SSH 터미널로 들어가서 redis 동일하게 다시 설치 후 SET foo bar, GET foo 등으로 설치된 거 체크하기
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
sudo chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt-get update
sudo apt-get install redis
  1. 6379번 PORT를 AWS 새로 생성한 Instance에 추가하기
  2. (선택) SSH 터미널에서 sudo systemctl status redis-server로 들어가고, 다시 그 안의 redis-server.service라는 파일에 접근하기 위해 cat /lib/systemd/system/redis-server.service로 들어가서 확인해본 후 그 안에 기재되어있는 redis.conf 파일을 또 확인하기 위해 sudo cat /etc/redis/redis.conf로 들어가보면 정말 많은 설정들이 있음. 우선 여기서 우리는 인프라 엔지니어가 되려는게 아니므로 좀 더 간단한 버전으로 해서 해결해보자.
  3. redis 서버를 꺼주기 위해 sudo systemctl stop redis-server로 강제종료하기
    shutdown으로 아무리 꺼도 기본 설정이 다시 켜는거로 되어있으므로 꺼지지 않음
    꺼진 걸 확인하기 위해 sudo systemctl status redis-server로 조회해보면 inactive(dead)라고 나옴
  4. redis-server --daemonize yes --requirepass prod1234 로 설정해서 임시로 비밀번호까지 걸어서 켜주자
    그 후 안내문에 나오는대로 sudo sysctl vm.overcommit_memory=1도 실행 후 다시 실행 redis-server --daemonize yes --requirepass prod1234
    이후 접속을 위해서는 set foo bar, get foo 등을 체크하기 전에 auth prod1234로 비밀번호를 입력해줘야 함
  5. 로컬에서 접속 시도: redis-cli -h <새instance의publicIP>
    auth prod1234로 비밀번호를 입력하기
    get foo로 연결 확인
  6. 다른 VM에서도 동일하게 접속 시도 및 연결 확인
  • 보안적 허점 개선
  1. PORT 6379번 삭제: 이제부터 로컬에서는 접속 불가
  2. 새로 생성한 redis-1 instance의 private IP를 가지고 다른 VM에서 다음과 같이 접속
    redis-cli -h <새instance의privateIP>

VM to VM connection

  • 각 VM (Ubuntu-1, Ubuntu-2)에 다음의 내용들을 차례대로 각각 적용해줘야 함
  1. 기본적으로 돌아가고 있는 Redis 서버 끄기: sudo systemctl stop redis-server
  2. cd express로 들어가서 vim .env로 env 파일 수정 후 cat .env로 수정한 내용이 반영되었는지 확인
  • 기존 .env 파일의 코드:
PORT=80
REDIS_URL: redis://localhost:6379
  • 수정된 .env 파일의 코드:
PORT=80
REDIS_URL: redis://:prod1234@<새로만든redis-1서버의PrivateIP>:6379
  1. sudo pm2 reload all
  • 다시 https://backend-ec2.com/messages URL로 postman에서 요청 보내가면서 테스트해보기
    이번에는 올바르게 POST된 요청들이 전부 나옴!

⭐ DB 같은 stateful한 서비스들은 가급적이면 Managed Service를 사용

전통적인 VM 관리에서 어려웠던 점 복기

  • 하나하나 볼 때는 그렇게 어렵지 않은데? 라고 생각할 수 있겠지만 사실상 프로젝트마다 이런 설정들을 step by step으로 외워서 오류 없이 진행하는 건 매우 번거로울 것임. 그리고 만약 그러는 도중에 실수가 발생한다면 프로젝트에 critical할 수 있음.
  1. Node.js, Redis 등을 모든 VM에 각각 설치해줘야 함
  2. vim이라는 번거로운 에디터를 사용해야 함
    insert 모드는 i, command 모드로 돌아오려면 ESC, 저장 후 종료는 :wq 등등 vim 명령어를 숙지해야 함
  3. Horizontal, vertical scaling을 수작업으로 진행해야 함
  4. Snapshot의 버전관리도 해야 함
  5. 이런 과정에서 개발자가 VM에 직접적으로 접근하며 발생하는 불가피한 human error들..
  6. VM에서는 기본적으로 각 VM마다 OS가 차지하는 메모리와 CPU가 있음.. 만약 Horizontal scaling을 진행하던 중에도 너무 작은 단위의 VM들을 연결한다면 내가 원하는 프로그램을 돌릴 공간도 없이 OS만 여러개 설치하는 꼴이 될 수도 있음.
  7. 모든 VM에는 static ip가 필요함
  8. CI/CD를 위해 SSH key 설정 등을 해줘야 함
  9. systemd에 대한 이해가 필요함
  10. auto scaling이 복잡함
  11. HA를 Process 수준과 VM 수준에서 각각 관리해줘야 함
  12. Rollback이 복잡함

AWS Lightsail resorces 정리

  • instance 전부 삭제, snapshot도 삭제
  • networking 전부 삭제
  • domain은 ECS 실습 후 삭제

0개의 댓글