[2023 기능대회 준비] 10. 1과제 예상문제 만들어 풀어보기

Yohan_05·2023년 3월 22일
1
post-thumbnail

기능경기대회에서 클라우드 종목은 아키텍처만 알려주고 세부적인 문제는 알려주지 않는다. 그러기에 아키텍처를 보고 문제를 예상하고, 그 예상한 문제를 풀어보려고한다. 문제를 풀다가 조금이라도 정확하게 모르는 개념들이 나온다면 추후 글을 작성해 정리할 예정이다.

예상문제

  1. 네트워크
  • 10.10.0.0/16 대역대를 사용하는 VPC를 생성하고 이름은 ws-vpc로 합니다.
  • 고가용성을 고려해서 3개의 가용영역에 각각 프라이빗 서브넷, 퍼블릭 서브넷을 1개씩 생성합니다.
  • 프라이빗 서브넷에서 생성되는 인스턴스들은 NAT 게이트웨이를 통해서 아웃 바운드 인터넷 통신이 가능해야합니다.
  • 서브넷 마스크는 24비트를 사용하고 대역대는 자유입니다.
  • 서브넷 이름은 public/private-(가용영역 코드 a,b,c,d)를 포함합니다.
  1. Bastion
  • 퍼블릭 서브넷에 bastion으로 사용한 Ec2 인스턴스를 생성
  • ssh 접속이 가능하도록 키페어 및 보안그룹 설정
  • bastion에서 도커 이미지를 생성해서 Ecr에 이미지를 업로드, 권한 알잘딱 부여
  1. ECR
  • webapp 이라는 이름으로 Ecr 리포지토리 생성
  • 해당 Ecr 리포지토리는 IAM을 통해 인증 및 인가를 받은 사용자만 접근 가능
  1. 컨테이너 이미지 생성
  • 첨부파일을 통해서 제공된 Flask 웹 애플리케이션을 구동하는 Dockerfile을 생성
  • 컨테이너 이미지 실행시 애플리케이션이 정상적으로 구동되면 Ok
  • 생성한 컨테이너 이미지를 ECR 리포지토리에 업로드하여야함.
  1. ECS 클러스터
  • webapp-cluster 이라는 이름으로 Ecs 클러스터를 생성해야함.
  • 해당 ecs 클러스터에서 생성되는 task는 위에서 생성한 vpc에 있는 프라이빗 서브넷에서 실행되야함.
  • 오토스케일링 그룹을 통해서 용량 공급자를 추가하고 용량 공급자를 통해서 생성되는 ecs 인스턴스는 최소 0개에서 최대 5개까지 늘릴 수 있어야함.
  • ECS 인스턴스의 AMI는 amazon linux를 사용해야하고 인스턴스 타입은 t3.mideum으로.
  • ssh 접속을 할 필요는 없음.
  1. ECS 작업 정의
  • ECR 리포지토리에 업로드한 컨테이너 이미지를 구동하는 작업정의를 생성
  • 이름은 webapp-taskdefinition으로 하고 256CPU 와 2gb 메모리를 할당.
  1. Ecs 서비스
  • 위에서 생성한 Ecs taskdefinition을 사용하는 서비스를 생성.
  • Ecs 클러스터를 생성할 때 설정한 용량 공급자를 통해서 생성되는 Ecs 인스턴스에 task가 실행되어야함.
  • 최소 2개의 Task가 동시에 실행되어야함.
  • ALB 및 대상그룹의 이름은 webapp-alb, webapp-targetgroup 으로 지정하고 alb에는 Http:80을 수신하는 리스너를 추가
  • 대상그룹은 애플리케이션의 /healthz 경로를 호출해서 상태검사를 하여야함.
  • ALB 에서만 해당 task 로 접근이 가능해야함.
  1. CloudFront
  • 위에서 생성한 ALB를 오리진으로 하는 CloudFront 배포판을 생성
  • /api 경로는 동적 컨텐츠를 제공 -> 캐시를 하면 안됨.
  • 웹 브라우저에서 생성된 CloudFront 배포판의 DNS 주소로 접속해서 / 경로는 캐시가 되고, /api 는 캐시가 되지 않는걸 검증
  • ALB 보안 그룹의 인바운드 규칙을 수정/추가해서 CloudFront를 통해서만 접속이 가능하도록.

네트워크

순서대로 네트워크 먼저 생성을 해주자. VPC 생성을 눌러준다.

VPC와 서브넷, 라우팅 테이블의 이름들이 모두 지정되어있다면 자동 생성 옵션을 꺼주고, 일일히 하나하나 입력해주자. 하지만 이번 예상 문제에선 그게 아니기때문에 자동생성을 눌러준다. 이후 명시된대로 CIDR 블록에 10.10.0.0/16을 기입해준다.

문제에 나와있는대로 가용영역은 3개, 퍼블릭 서브넷과 프라이빗 서브넷은 각 가용영역마다 하나씩(3개), 이후 NAT 게이트웨이도 하나 설정해주고 VPC 엔드포인트는 사용하지 않을 것이기 때문에 없음으로 해두었다.

이대로 생성을 눌러주고 다음 파트로 넘어가자.

Bastion

가장 간단한 파트다. 인스턴스 시작을 눌러주자. 이름은 bastion, OS 이미지는 아마존 리눅스 2를 선택해주었다. 새로나온 2023도 있긴한데 원래 쓰던 익숙한걸 쓰는게 에러가 났을때 대응하기도 쉽고 그래서 2를 계속 쓰고있다.

인스턴스 유형은 t3.medium, 키페어는 기존에 쓰고 있던거를 계속 쓰겠다.(새로 생성하는게 더 좋을 듯 싶긴하다)

새로만든 vpc와 public subnet을 선택해주고 퍼블릭 IP 자동할당을 활성화해준다. 보안그룹은 이름을 잘 지어주고 22번 포트만 anywhere 로 열어준다.

이대로 생성을 눌러주고 다음파트로 넘어가주자.

ECR

생성하는거는 제일 간단하다. 리포지토리 생성 -> 이름 지정해주고 생성을 눌러준다.

이후 해당 Ecr 리포지토리는 IAM을 통해 인증 및 인가를 받은 사용자만 접근 가능 이 조건을 만족시키기 위해 IAM 유저를 만들러가자.

IAM

사용자의 이름을 알잘딱 입력해주고, ecr에 대한 접근 자체는 콘솔에서 하는것이 아니기 때문에 console에 대한 사용자 액세스 권한은 제공하지 않는다.

이후 뭐 연결하는 정책은 없고 그냥 생성을 눌러준다. 이후 인스턴스->bastion->보안->IAM 역할 수정에 들어가준다.

IAM 역할 생성을 클릭.

역할 만들기

aws 서비스 중 Ec2(인스턴스)와 연결할 정책이기 때문에 아래와 같이 선택해주고

ECR에 접근할 권한을 얻기 위해 AmazonEC2ContainerRegistryFullAccess 를 부여.

역할 이름과 설명을 알잘딱 정해주고 생성해준다.

이후 bastion에 IAM 역할에 방금 만든 역할을 골라주고, IAM 역할을 업데이트해준다.

이대로 업데이트하고 다음파트로 넘어가자.

컨테이너 이미지 생성

bastion내에서 하는 작업이다. bastion내에서 플라스크 세팅을 해주고 Dockerfile 을 만들고, app.py 를 띄우고 ECR로 푸쉬하면된다.

우선 bastion에 ssh 접속을 해준다.

아래와 같은 명령어를 입력하여 세팅을 해준다.

$ python3 --version	# 파이썬이 있는지 확인해준다.
$ python3 -m venv venv	# 가상환경을 세팅해준다.
$ cd venv/bin	# 경로 이동하고
$ source activate	# 가상환경을 실행?시켜준다
$ pip3 install -U Flask	# 플라스크를 설치해준다.
# sudo yum install docker	# 도커를 설치해준다.
# sudo systemctl start docker # 도커를 실행시켜준다.

vi app.py 로 아래의 코드를 복사, 붙여넣기 해주고

# app.py

from flask import Flask, request
import random

app = Flask(__name__)


@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"


@app.route("/healthz")
def health():
    return "OK"


@app.route("/api")
def api():
    return {
        "value": random.randint(0, 100)
    }


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8080)

Dockerfile 도 생성하여서 아래와 같은 스크립트를 복사, 붙여넣기 해준다.

# Dockerfile
FROM python:3.8-slim

COPY . /app

RUN pip3 install flask 

WORKDIR /app

CMD ["python3", "-m", "flask", "run", "--host=0.0.0.0"]

이후 빌드를 하여 이미지가 잘 생성되는지 확인을 해보고

테스트로 한번 실행도 시켜본다. 잘 실행되는것을 볼 수있다.

이제 aws configure 를 통해 iam user 의 accessKey를 등록시켜줘야한다. AccessKey를 발급받기 위해 IAM -> 사용자 -> 발급받고자하는 사용자 이름을 클릭

보안 자격증명 -> 액세스키 -> 액세스 키 만들기를 눌러주고

aws cli를 사용할때 쓰는 액세스 키를 발급받기 때문에 Command Line Interface를 선택해주고 발급받아준다. 이때 발급받은 키는 절대 분실하지 말고 알잘딱 메모장에 복사 붙여넣기를 하든 .csv 파일로 저장하든 하자.

이후 $ aws configure로 자신의 액세스키와 시크릿 액세스키, 리전, 아웃풋 포멧을 입력해준다.

이후 다시 ECR로 돌아와 자신이 만든 리포지토리의 푸시 명령 보기를 클릭하여 푸시 명령을 본다.

1.인증 토큰을 검색하고 레지스트리에 대해 Docker 클라이언트를 인증합니다.

  • 명령어를 입력했을때 LoginSucceded가 떠야함.

2.다음 명령을 사용하여 도커 이미지를 빌드합니다.

  • successfully 가 떠야함.

3.빌드가 완료되면 이미지에 태그를 지정하여 이 리포지토리에 푸시할 수 있습니다.

  • 태그만 지정하는거라 뭐 뜨는건 없을겁니다.

4.다음 명령을 실행하여 이 이미지를 새로 생성한 AWS 리포지토리로 푸시합니다.

  • 이런 화면이 뜬다면 푸쉬가 완료된거임.

리포지토리 안에 들어가면 잘 푸쉬가 된 것을 확인할 수 있다.

ECS 클러스터

클러스터 생성을해보자.

클러스터 이름은 webapp-cluster로 지어주고 문제와 동일하게 옵션을 설정해준다.

만들었던 VPC를 선택, 그리고 private subnet을 골라준다. 보안그룹은 기본적인 인바운트 트래픽만 허용하기 위해서 새 보안 그룹 생성. - 0.0.0.0/0, 80번 포트.

기본적인 IAM 역할, 네임 태그를 설정해주고 생성해준다.

ECS 작업 정의

방금 만든 클러스터의 새 작업 정의를 생성해주도록하자.

Fargate가 아닌 Ec2 형식이니까 ec2 선택.

이름은 문제에 나와있는대로 만들어주고, 나머지는 유동적으로 알잘딱 진행하였다.

문제에 나와있는대로 작업 크기를 설정, IAM 역할은 기본 역할로 설정하였다.

컨테이너를 추가한다. 컨테이너 이름은 알아서 지어주고, 이미지는 우리가 만든 ECR에 푸쉬한 Image의 URL을 복사, 붙여넣기 해준다. 포트는 Flask application이기에 5천번으로 매핑. 이대로 컨테이너를 생성해준다.

그 다음 쭉쭉 내려서 작업정의를 생성해준다.

ALB

문제에 언급된대로 Application Load Balancer 를 생성.

문제에 언급된대로 이름을 설정, 체계는 인터넷 경계로.

우리가 만든 VPC 설정, Public subnet들을 선택.

보안그룹은 80번포트를 열어준다음 연결해주고

대상그룹은 아래와 같이 진행해주자.

대상그룹

당연히 유형은 인스턴스, 이름은 문제에 언급된대로 작성해준다.

이후 클러스터로 인해 생성된 EC2 인스턴스 2개를 선택해주고 5천번 포트로 아래에 보류 중인 것으로 포함을 클릭하여 대상 그룹을 생성해준다.

대상그룹을 만들어 ALB랑 연결시켜주었다면 ALB생성.

ALB를 생성해주었다면 기존의 ECS 클러스터 인스터스들의 보안그룹을 이런식으로 ALB의 보안그룹을 등록시켜두자.

ECS 서비스

클러스터를 클릭하여 서비스를 생성해준다.

형식은 Ec2, 아까 만들어준 작업정의와 개정을 선택해주고 서비스 이름은 알아서 지어준다. 작업 개수는 문제에서 '최소 2개의 Task'가 실행되어야한다고 했으므로 2개로 설정해준다.

로드 밸런서 유형은 ALB, 방금 만든 로드밸런서를 골라준다.

이후 컨테이너 연결을 해준다.

문제대로 오토 스케일링을 설정하여 최소 작업개수를 2, 최대 작업 개수를 5로 설정해준다.

자동 작업 조정 정책은 알잘딱 이름을 지어주고, 대상값은 80으로 하여서 CPU가 80퍼센트 이상으로 높아지면 알잘딱 조정되게 해준다. 그리고 생성.

기다리면 RUNNING 으로 실행되고있는 작업들을 볼 수 있다.

ALB로 접속했을때 Hello,World! 가 잘 출력되는것을 볼 수 있다.

CloudFront

마지막 파트다. CloudFront를 생성하자.

  1. CloudFront

    원본 경로는 모든 경로를 사용할 것이기 때문에 지정하지 않고, 이름은 알아서 추가되어있을 것이다. 이것보다 아래의 내용들은 문제에 적혀있지 않으므로 알잘딱 골라준다.

무효화

배포한 클라우드 프론트의 특정 경로를 캐시에서 제거하는 옵션? 입니다. 무효화 생성 버튼을 눌러줍시다.

/api 경로는 동적 컨텐츠를 제공 -> 캐시를 하면 안됨. 라는 제약사항이 있기 때문에 /api 경로를 추가해준다. 이후 무효화 생성.

보안그룹


ALB 보안 그룹의 인바운드 규칙을 수정/추가해서 CloudFront를 통해서만 접속이 가능하도록. 이란 제약사항이 있기 때문에 아래와 같이 ALB의 보안그룹을 수정해줘야한다.

이때 클라우드 프론트의 ID는 VPC-관리형접두사목록-com.amazonaws.global.cloudfront.origin-fancing에서 확인할 수 있다.

설정을 해주고 나면 기존의 alb 주소는 로딩이 지속되다가 타임아웃이 뜨게된다.

반면에 클라우드 프론트의 주소는 접속이 잘 되는 것을 볼 수 있다.

마치며

생각보다 그리 어렵지 않았던 예상 문제였다. 이번 실습을 하면서 잘 몰랐던 부분, 용어들을 정리해서 업로드할 예정이다.

profile
안녕하세요 DevOps 엔지니어로 현업에서 활동중인 요한이라고 합니다.

0개의 댓글