지즘까지 학습한 Serverless내용을 바탕으로 Serverless의 아키텍처를 구성해보겠습니다.
모바일 애플리케이션 예제
지금 우리는 아래와 같은 요구 사항을 가진 모바일 애플리케이션을 만들고자 합니다.
• HTTPS로 REST API로 노출
• 서버리스 아키텍처
• 사용자는 S3에서 자신의 폴더와 직접 상호 작용할 수 있어야 합니다.
• 사용자는 관리형 서버리스 서비스를 통해 인증해야 합니다.
• 사용자는 할 일을 쓰고 읽을 수 있지만 대부분 읽는다.
• 데이터베이스는 확장되어야 하고 읽기 처리량이 높아야 합니다.
- 모바일 클라이언트
- REST HTTPS 연결을 위해 Amazon API Gateway로 HTTP Endpoint설정
일반적인 서버리스 API 방식으로 API Gateway가 람다 함수를 호출하여 확장을 허용하고 서버리스 인프라를 쓰도록 합니다.
- 서버리스이면서 확장이 잘 되는 DynamoDB를 벡엔드로 둡니다.
- 인증 계층이 있어야 하기 때문에, Amazon Cognito 서버리스 기술을 사용할 것입니다.
모바일 클라이언트가 Cognito에연결하고 인증하면 API Gateway는 Cognito와 함께 인증을 확인해 줄 겁니다.
여기까지가 기본적인 서버리스 API입니다
위에 요구 조건에 따라 아키텍처를 조금 더 확장해나가보겠습니다.
Amazon S3 버킷에 사용자 액세스 권한을 주려면 어떻게 해야 할까요?
- Amazon Cognito에 인증을 요청하는 모바일 클라이언트가 있을 때, Cognito는 AWS STS를 통해 임시 자격 증명을 제공할 수 있습니다.
- 이 자격 증명을 모바일 클라이언트에게 반환하면, 클라이언트가 자격증명을 통해 Amazon S3에서 파일을 저장하고 회수하며 S3에서 전용 공간에 액세스하도록 허용할 수 있습니다.
Amazon S3를 임시 자격 증명에 사용해야 한다는 것이 핵심입니다.
- 사용자가 늘어나기 시작하고 읽기 처리량이 점점 높아진다면,
RCU가 늘어날 것입니다. 읽기 처리량을 늘리면서 전체 비용을 줄이려면 캐싱 계층으로 DAX
를 사용하면 됩니다.
DynamoDB 이전에 DynamoDB DAX를 사용해 캐싱 계층을 갖추는 겁니다.
- 캐싱에는 다른 방법도 있습니다. DAX도 사용 가능하지만 캐시에 응답을 저장할 때, Amazon API Gateway 레벨에서 이 경우는 진행할 수도 있는데 답이 거의 바뀌지 않으면서 API 라우트에 대한 응답을 캐시에 저장하는 경우에 해당됩니다.
서버리스 웹사이트 예제
아래와 같은 요구 사항을 가진 서버리스 웹사이트를 만들고자 합니다.
• 이 웹사이트는 전 세계적으로 확장되어야 합니다.
• 블로그는 거의 쓰지 않지만 자주 읽습니다.
• 일부 웹사이트는 순전히 정적 파일이고 나머지는 동적 REST API입니다.
• 가능한 경우 캐싱을 구현해야 합니다.
• 구독하는 모든 신규 사용자는 환영 이메일을 받아야 합니다.
• 블로그에 업로드된 모든 사진에는 미리보기 이미지가 생성되어 있어야 합니다.
- 일단 콘텐츠를 서빙해야 하는데요, 콘텐츠는 정적이고 글로벌을 대상으로 서빙해야 합니다.
- 클라이언트가 있고 우리의 콘텐츠는 읽기 동작이 많기 때문에 대부분 Amazon S3에 저장돼 있을 겁니다.
- Amazon S3는 특정 리전에 있는데, 글로벌을 대상으로 노출시키려면, 전 세계를 대상으로 서비스되는 CDN 서비스인 Amazon CloudFront를 이용하면 됩니다.
- 그렇게 클라이언트는 Amazon CloudFront의 엣지 로케이션과 통신을 하게 되고, Amazon S3에게 받은 데이터를 캐시로 저장하게 됩니다.
이 모든 작업을 안전하게 진행하려면 어떻게 할 수 있을까요?
이 질문은 매우 당연한 질문입니다.
- 클라이언트는 글로벌 배포를 위한 CloudFront와 인터랙트합니다. 이제 오리진 액세스를 제한해서 CloudFront로만 Amazon S3 버킷에 접근할 수 있도록 할 겁니다.
- CloudFront만 인가할 수 있도록 S3 버킷 정책을 추가합니다. Amazon S3에 바로 접근하는 사용자는 인가를 받지 못하고 Amazon S3 버킷은 보호됩니다.
- 퍼블릭 서버리스 REST API는 위에서 어플리케이션을 만들었던 방식과 동일하게 추가할 수 있습니다.
글로벌로 서빙할 때 지역에 따라 발생하는 지연을 줄이기 위해 Dynamo DB Global Table 데이터베이스를 사용하는 것도 좋습니다.
- 이제 신규 방문자에게 보낼 환영 이메일을 보내려고합니다.
2.이걸 위해 Dynamo DB에서 변경사항을 전송하기 위해 Dynamo DB 스트림을 이용하고 스트림은 람다 함수를 호출합니다.
3.이 람다 함수는 좀 특별한데, IAM 역할을 부여 받아 Amazon SES를 사용할 수 있게 도와줍니다.
Amazon SES(Simple Email Service)는 이메일을 발송해 주는 서비스입니다.
- Amazon 람다 함수가 AWS SDK를 이용해 Amazon SES가 이메일을 발송하게 합니다.
또한 요구사항 중에 이미지를 업로드하면 섬네일을 생성한다는 게 있었습니다.
1.여기서는 클라이언트에서 S3 버킷으로 바로 업로드
를 할 수도 있고 아니면 CloudFront OAI를 이용
할 수도 있습니다.
OAI 방식이라면 클라이언트는 사진을 CloudFront에 업로드하고 CloudFront는 사진을 Amazon S3 버킷으로 전달하게 됩니다
이런 방식을 S3 Transfer Acceleration이라고 합니다
사진은 바로 S3로 올리거나 S3 Transfer Acceleration을 이용하거나이고요
- S3에 파일이 추가되면 람다 함수를 호출하게 합니다. S3가 람다를 호출할 수 있고, 람다는 섬네일을 생성하고 섬네일을 S3 버킷에 넣는데, 다른 버킷에 넣을 수도 있습니다.
3.Amazon S3는 SQS와 SNS를 호출할 수도 있습니다. 이건 선택사항인데, SQS나 SNS로 원하는 작업을 하시면 됩니다.
Micro Services architecture
마이크로 서비스 아키텍처를 구성해보도록 하겠습니다.
- MSA는 많은 서비스가 REST API를 사용하여 서로 직접 상호 작용합니다.
- 각 마이크로 서비스에 대한 각 아키텍처는 형태와 모양이 다를 수 있습니다.
- 우리는 마이크로 서비스 아키텍처를 원하므로 각 서비스에 대해 더 간결한 개발 수명 주기를 가질 수 있습니다.
- 첫 번째 서비스를 구성할 것인데, 사용자는 첫 마이크로서비스와 HTTPS를 통해 통신하게 될 겁니다.
- 맨 위에 있는 줄을 보면, 일래스틱 로드 밸런서가 ECS와 통신하고 난 뒤에 DynamoDB와 통신하도록 배치하였습니다.
- 마이크로서비스는 보통 DNS 이름이나 URL을 가지고 있습니다.
첫번째 아키텍쳐의 DNS인 service1.example.com을 예시로 들어
보면, 정보를 얻으려면 DNS 쿼리를 Route 53에 보내 별칭 레코드를
받고 나서 서비스와 상호작용이 가능합니다.
- 두 번째 서비스를 구성할 것인데, 전형적인 서버리스용 아키텍처를 사용할 것입니다. 하지만 DynamoDB 대신 일래스티 캐시가 있는데요.
- 그냥 재미 삼아 이것저것 섞어서 사용하려면 Lambda의 백엔드로 일래스티 캐시를 써도 괜찮습니다. 전부 잘 작동할 텐데 두 번째 마이크로서비스는 첫 번째 서비스와 상호작용 할 수도 있습니다.
일래스틱 로드 밸런서에 람다 함수가 호출을 보내
첫 마이크로서비스에서 정보를 얻고 응답을 생성합니다.
- 그리고 역시 ELB를 사용하는 세 번째 마이크로서비스를 마련할 수도 있는데 이건 서버리스가 아니라 Amazon EC2 오토 스케일링과 Amazon RDS 데이터베이스를 사용하는 거라 전에 배웠던 전형적인 아키텍처에 해당합니다.
- EC2 인스턴스가 결정을 내리기 전에 여기 점선으로 표시된 것처럼두 번째 마이크로서비스를 호출해야 합니다. URL은 service3.example.com입니다
마이크로 서비스에 대한 토론
- 원하는 방식으로 각 마이크로 서비스를 자유롭게 설계할 수 있습니다.
- 동기 패턴: API 게이트웨이, 로드 밸런서
- 비동기 패턴:
SQS, Kinesis, SNS, Lambda 트리거(S3)
- 마이크로 서비스의 과제:
• 각각의 새로운 마이크로서비스 생성에 대한 반복되는 오버헤드,
• 서버 밀도/활용 최적화 문제
• 여러 마이크로서비스의 여러 버전을 동시에 실행하는 복잡성
• 많은 개별 서비스와 통합하기 위한 클라이언트측 코드 요구 사항의 확산.
- 일부 문제는 서버리스 패턴으로 해결됩니다.
• API 게이트웨이, Lambda는 자동으로 확장되며 사용량에 따라 비용을 지불합니다.
• 손쉽게 API 복제, 환경 재현 가능
• API Gateway용 Swagger 연동을 통한 클라이언트 SDK 생성
소프트웨어 업데이트 오프로딩
- 때때로 소프트웨어 업데이트를 배포하는 EC2에서 실행되는 애플리케이션이 있습니다.
- 새로운 소프트웨어 업데이트가 나오면 많은 요청을 받고 콘텐츠는 네트워크를 통해 대량으로 배포됩니다. 비용이 많이 듭니다
- 우리는 애플리케이션을 변경하고 싶지 않지만 비용과 CPU를 최적화하고 싶습니다. 어떻게 할 수 있습니까?
CloudFront를 통한 빠른 해결
- 아키텍처 변경 없음
- 에지에서 소프트웨어 업데이트 파일을 캐시합니다.
- 소프트웨어 업데이트 파일은 동적이지 않고 정적입니다(절대 변경되지 않음).
- EC2 인스턴스는 서버리스가 아닙니다.
- 그러나 CloudFront는 우리를 위해 확장되고 확장될 것입니다.
- 우리의 ASG는 그다지 확장되지 않고 EC2에서 엄청나게 절약할 것입니다.
- 가용성, 네트워크 대역폭 비용 등도 절약할 것입니다.
- 기존 애플리케이션을 보다 확장 가능하고 저렴하게 만드는 쉬운 방법입니다!
AWS Certified Solutions Architect Associate 시험합격!