
: 높은 가용성과 확장성이 뛰어난 클라우드 DNS 웹 서비스
최종 사용자를 인터넷 애플리케이션으로 라우팅할 수 있는 매우 안정적이고 비용 효율적인 방법을 개발자와 기업에 제공하기 위해 설계하였다.
리전 수준의 장애 조치 서비스를 지원한다.
사용자의 요청을 EC2 인스턴스, ELB, S3 버킷 등 AWs에서 실행되는 인프라에 효과적으로 연결한다.
사용자를 AWS 외부의 인프라로 라우팅하는 데도 Route 53을 사용한다.
트래픽을 정상적인 엔드포인트로 라우팅하거나 애플리케이션 및 해당 엔드포인트의 상태를 개별적으로 모니터링하도록 DNS 상태 확인을 구성할 수 있다.
1) 사용자 입력 → www.example.com
2) ISP가 관리하는 DNS resolver로 라우팅
3) Resolver를 통해 DNS root name server로 전달
4) .com 도메인의 TLD 이름 서버 중 하나에 다시 전달
5) Route 53의 name serve 중 하나로 전달
6) Www.example.com 레코드를 찾아 웹 서버의 IP주소 192.0.2.44 등 연관된 값을 받고 이 IP 주소를DNS resolver로 반환
7) resolver는 이 값을 웹 브라우저로 반환
8) IP 주소로 www.example.com에 대한 요청을 전송
9) 192.0.2.44에 있는 웹 서버 또는 그 밖의 리소스는 www.example.com의 웹 페이지를 웹 브라우저로 반환하고, 웹 브라우저는 이 페이지를 표시
단순 라우팅 정책
: 도메인에 대해 특정 기능을 수행하는 하나의 리소스만 있는 경우(예: example.com 웹 사이트의 콘텐츠를 제공하는 하나의 웹 서버)에 사용합니다.
장애 조치 라우팅 정책
: 액티브-패시브 장애 조치를 구성하려는 경우에 사용합니다.
지리 위치 라우팅 정책
: 사용자의 위치에 기반하여 트래픽 라우팅하려는 경우에 사용합니다.
지리 근접 라우팅 정책
: 리소스의 위치를 기반으로 트래픽을 라우팅하고 필요에 따라 한 위치의 리소스에서 다른 위치의 리소스로 트래픽을 보내려는 경우에 사용합니다.
지연 시간 라우팅 정책
: 여러 AWS Region에 리소스가 있고 최상의 지연 시간을 제공하는 Region으로 트래픽을 라우팅하려는 경우에 사용합니다.
다중 응답 라우팅 정책
: Route 53이 DNS 쿼리에 무작위로 선택된 최대 8개의 정상 레코드로 응답하게 하려는 경우에 사용합니다.
가중치 기반 라우팅 정책
: 사용자가 지정하는 비율에 따라 여러 리소스로 트래픽을 라우팅하려는 경우에 사용합니다.
: 기존의 Server to Application, EC2 to Application 등의 네트워크 연결 방식 대신, Application을 API를 통해 통신하는 독립적 서비스 집합으로 구성하는 것이다.
기존의 방식(Monolithic Application)은 각 서비스 간의 긴밀한 결합을 통해 동작한다. 이는 한 요소에 장애가 발생할 경우 전체 Application에 영향을 줄 수 있다는 의미이다.

모든 서비스가 각각의 Application 단위(container of lambda)로 구성되고, API를 통해 통신한다.
-> 유연한 확장성, 디버깅 용이(CI/CD), 서비스 단위 업무 분리
단, 서비스 연결을 위한 API 설계 개발이 복잡할 수 있다.
: 컨테이너 애플리케이션을 실행하는데 필요한 인프라 환경 구성이 전혀 없는 독립된 환경
반복 가능하고 배포 가능한 프로세스를 제공하는 것
## update
[ec2-user@ip-172-31-2-53 ~]$ sudo yum update -y
## docker 설치
[ec2-user@ip-172-31-2-53 ~]$ sudo amazon-linux-extras install docker -y
## docker service 시작
[ec2-user@ip-172-31-2-53 ~]$ sudo service docker start
## docker에서 sudo 없애기
[ec2-user@ip-172-31-2-53 ~]$ sudo setfacl -m user:ec2-user:rw /var/run/docker.sock
## 잘 설치되었는지 확인
[ec2-user@ip-172-31-2-53 ~]$ docker info
[ec2-user@ip-172-31-2-53 ~]$ docker version
...
Server:
Engine:
Version: 20.10.17
## 이미지 pull
[ec2-user@ip-172-31-2-53 ~]$ docker pull nginx:1.23.1-alpine
## run
[ec2-user@ip-172-31-2-53 ~]$ docker run -d --name=myweb -p 8001:80 nginx:1.23.1-alpine
## 접속
[ec2-user@ip-172-31-2-53 ~]$ curl localhost:8001










: 외부 연결이 가능한 2개의 퍼블릭 서브넷과 외부 연결이 차단되는 프라이빗 서브넷을 ecs-vpc에 생성한다.








: VPC 내부의 인스턴스가 인터넷과 통신할 수 있도록 인터넷 게이트웨이 생성






: private 서브넷에 있는 인스턴스가 인터넷과 통신할 수 있도록 NAT Gateway를 생성한다.






: VPC 내부에 있는 인스턴스의 인터넷 연결 요청이 인터넷 게이트웨이와 NAT 게이트웨이로 전달될 수 있도록 라우팅 테이블을 생성한다.
퍼블릿 서브넷은 인터넷 게이트웨이와 프라이빗 서브넷은 NAT 게이트웨이와 연결한다.














: VPC 내부의 인스턴스 보안을 위해 보안그룹을 생성한다. 각 보안 그룹에 속한 인스턴스는 인바운드 규칙으로 허용된 트래픽만 접근할 수 있다.
ALB가 외부의 HTTP 요청을 수신하기 위한 보안그룹과 ECS에서 생성한 웹 서비스 인스턴스가 ALB로부터 오는 트래픽은 수신하기 위한 보안 그룹을 생성한다.







: 외부로부터 오는 요청을 분배하고 배포된 웹 서비스에 전달하기 위해 ALB를 생성한다.







다음은 구성한 프로토콜과 포트를 사용하여 연결 요청을 확인하는 과정이다. 리스너가 수신한 트래픽은 대상 그룹으로 라우팅된다.







: 배포될 웹 서비스의 도커 컨테이너 이미지를 빌드하고 업로드하기 위해 AWS에서 제공하는 개발 환경인 Cloud9 환경을 생성한다.






: AWS 커맨드 라인 인터페이스 등의 AWS 서비스를 활용하기 위한 환경이 구성되어 있고, IAM 역할을 부여하여 ECR 등의 AWS 서비스에 접근이 용이하다.






ec2-user:~/environment $ rm -vf ${HOME}/.aws/credentials
ec2-user:~/environment $ aws sts get-caller-identity --query Arn | grep ecs-workshop
"arn:aws:sts::132520104923:assumed-role/ecs-workshop-ECRFullAccessRole/i-0fbb8a5ad393d2acd"
ec2-user:~/environment $ aws configure set default.region ap-northeast-2
ec2-user:~/environment $ aws configure get default.region
ap-northeast-2
: 컨테이너 이미지를 저장하기 위한 이미지 저장소 ECR을 생성하고, Dockerfile을 빌드한 후에 레포지토리에 컨테이너 이미지를 업로드하는 작업을 수행한다.
ec2-user:~/environment $ aws ecr create-repository --repository-name "django"
{
"repository": {
"repositoryUri": "132520104923.dkr.ecr.ap-northeast-2.amazonaws.com/django",
"imageScanningConfiguration": {
"scanOnPush": false
},
"encryptionConfiguration": {
"encryptionType": "AES256"
},
"registryId": "132520104923",
"imageTagMutability": "MUTABLE",
"repositoryArn": "arn:aws:ecr:ap-northeast-2:132520104923:repository/django",
"repositoryName": "django",
"createdAt": 1666578804.0
}
}
ec2-user:~/environment $ aws ecr create-repository --repository-name "nginx"
{
"repository": {
"repositoryUri": "132520104923.dkr.ecr.ap-northeast-2.amazonaws.com/nginx",
"imageScanningConfiguration": {
"scanOnPush": false
},
"encryptionConfiguration": {
"encryptionType": "AES256"
},
"registryId": "132520104923",
"imageTagMutability": "MUTABLE",
"repositoryArn": "arn:aws:ecr:ap-northeast-2:132520104923:repository/nginx",
"repositoryName": "nginx",
"createdAt": 1666578860.0
}
}
output의 repositoryUri는 추후에 Dockerfile을 빌드한 후 컨테이너 이미지를 ECR에 업로드할 때 필요하기 때문에 복사해둔다.


: Dockerfile을 빌드하여 컨테이너 이미지를 생성한다.

## 이동
ec2-user:~/environment $ cd django/
## 확인
ec2-user:~/environment/django $ cat Dockerfile
FROM ubuntu:18.04
RUN apt-get update && \
apt install -y software-properties-common &&\
apt-get install --no-install-recommends -y \
python3.8 python3-pip python3.8-dev &&\
apt-get install gcc -y
RUN /usr/bin/python3.8 -m pip install --upgrade pip
RUN ln -s /usr/bin/python3.8 /usr/bin/python
RUN pip install -U setuptools
RUN pip install django==3.2 asgiref==3.3.3 gunicorn==20.0.4 setproctitle==1.1.10
RUN pip install django-common-models phonenumbers
COPY ./app /app
RUN chown -R root:root /app
RUN chmod -R +x /app/bin
RUN chmod -R +x /app/cmd
WORKDIR /app/larva
RUN echo yes | python manage.py collectstatic
WORKDIR /app
VOLUME /app
ENTRYPOINT [ "/app/cmd/start" ]
ec2-user:~/environment/django $ docker build -t django .
ec2-user:~/environment/django $ cd ..
ec2-user:~/environment $ cd nginx/
ec2-user:~/environment/nginx $ cat Dockerfile
FROM nginx
WORKDIR /etc/nginx/
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/
EXPOSE 80
ec2-user:~/environment/nginx $ docker build -t nginx .
ec2-user:~/environment/nginx $ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest a349fa9cbdf4 12 seconds ago 142MB
django latest d3e8a9849905 44 seconds ago 594MB
: 생성된 이미지에 tag를 생성한 후 ECR에 업로드 한다.
ec2-user:~/environment $ aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 132520104923.dkr.ecr.ap-northeast-2.amazonaws.com
ec2-user:~/environment $ docker tag django:latest 132520104923.dkr.ecr.ap-northeast-2.amazonaws.com/django:latest
ec2-user:~/environment $ docker push 132520104923.dkr.ecr.ap-northeast-2.amazonaws.com/django:latest

ec2-user:~/environment $ docker tag nginx:latest 132520104923.dkr.ecr.ap-northeast-2.amazonaws.com/nginx:latest
ec2-user:~/environment $ docker push 132520104923.dkr.ecr.ap-northeast-2.amazonaws.com/nginx:latest

: EC2 인스턴스 기반으로 컨테이너가 서비스 될 수 있도록 클러스터를 구성한다.








: ECR에 저장된 컨테이너 이미지로 작업 정의를 구성한다.














: 클러스터에서 구성된 작업 정의로 서비스를 생성한다.









: 서버를 구성하거나 관리하지 않고 Application과 Service를 구축하고 실행한다.
-> DevOps 환경
: 서버 구성을 생각하지 않고 애플리케이션과 서비스를 구축하고 실행할 수 있다.
: 완전 관리형 컴퓨팅 서비스. 구성이 아닌 애플리케이션에 집중한다.
요청 시에만 컴퓨팅 리소스를 사용하고, 상태 비저장 코드를 실행한다.
비용은 Lambda를 실행한 마이크로서비스에 대해서만 지불한다.
회사에서 중요한 애플리케잉션을 AWS로 마이그레이션하려고 합니다. 애플리케이션의 런타임이 짧습니다. 응용 프로그램은 데이터 변경 또는 시스템 상태 변경에 의해 호출됩니다. 이 회사는 운영 효율성을 극대화하고 애플리케이션 실행 비용을 최소화하는 컴퓨팅 솔루션이 필요합니다. 이러한 요구 사항을 충족하기 위해 회사는 어떤 AWS 솔루션을 사용해야 합니까?
A. Lambda







import json
def lambda_handler(event, context):
response = {
"statusCode": 200,
"statusDescription": "200 OK",
"Access-Control-Allow-Origin" : "*",
"isBase64Encoded": False,
"headers": {
"Content-Type": "text/html; charset=utf-8"
}
}
response['body'] = """<html>
<head>
<meta charset="utf-8" name="viewport" content="width=device-width, height=device-height, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<title>Hello Kakao!</title>
<style>
#title {
font-family: arial; font-size: 2em;color: #eb971a; margin-top:50px;
text-align: center;
}
button {
background-color: #eb971a;
border:none;
color:white;
border-radius: 5px;
width:40%;
height:35px;
font-size: 13pt;
margin-top:30px;
text-align: center;
}
#sentence {
font-size: 17pt;
margin-top:30px;
font-weight: bold;
color: #eb971a;
}
</style>
</head>
<body>
<p id="title">Hello Kakao From <b>Lambda</b></p>
<hr id="lambda-line" width="800px" align="center" color="#eb971a;">
<center><button onclick="checkEvent();">Who are you?</button></center>
<center><div id="sentence"></div></center>
</body>
<script type="text/javascript">
function checkEvent(){
$.ajax({ type: "GET",
url: "URL을입력하세요",
dataType:'json',
success: function(data){
document.getElementById('sentence').innerHTML = data.status + " " + data.name
},
error: function (error){
alert('ERROR::');
console.log(error)
}
});
}
</script>
</html>
"""
return response





import json
import boto3
import random
import json
def lambda_handler(event, context):
member_name = ['kevin','soyeon','gibin','yeji','yuri', 'taelim']
member_status = ['Happy','Sad','Serious','Satisfied','Free', 'Soso']
dynamodb = boto3.resource('dynamodb',endpoint_url='http://dynamodb.ap-northeast-2.amazonaws.com')
member_table = dynamodb.Table('kakao-member')
name = member_name[random.randint(0,5)]
status = member_status[random.randint(0, 5)]
member_table.put_item(
Item={
'name': name,
'status': status,
}
)
documents = {'name':name,'status':status}
print(documents)
return {
'statusCode': 200,
'headers': {'Access-Control-Allow-Origin': '*'},
'body': json.dumps(documents)
}


=> DB쪽에 table이 없기 때문에 error가 발생한다.




























CloudFormation은 템플릿을 작성하는 것 하나로 모든 리소스와 해당 속성에 대한 설정을 한번에 할 수 있다.
리소스를 단 한곳에서만 관리하면 되기 때문에 전체적인 흐름도 파악할 수 있게 되고 변경 작업(update → change dataset)도 용이하다.
=> 코드로 인프라를 관리하기 때문에 이 코드만 버전관리한다면 초기부터 인프라
변경 과정을 추적할 수 있다. (IaC 서비스의 특징)
Template(*.yaml)과 Stack(resource list)으로 작업한다.
템플릿을 코드로 취급하고, 원하는 버전 제어 방법으로 이를 관리한다. JSON/YAML 템플릿 파일 내에 전체 애플리케이션 스택을 정의한다.
스택을 생성할 때마다 CloudFormation이 템플릿에 작성된 리소스를 프로비저닝 수행


: 템플릿 생성, 보기 및 수정을 위한 그래픽 도구
AWSTemplateFormatVersion: 2010-09-09
Resources:
MYCFNBUCKET:
Type: AWS::S3::Bucket
Properties:
AccessControl: PublicRead
Outputs:
BucketName:
Value: MYCFNBUCKET







AWSTemplateFormatVersion: '2010-09-09'
Description: EC2 instance Resources LABs.
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: 'Amazon EC2 Configuration'
Parameters:
- InstanceType
ParameterLabels:
InstanceType:
default: 'Type of EC2 Instance'
Parameters:
InstanceType:
Type: String
Default: t2.micro
AllowedValues:
- t2.micro
- t2.small
Description: 'Enter t2.micro or t2.small. Default is t2.micro.'
Resources:
WebServerInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-09cf633fe86e51bf0 # Seoul Resion의 Amazon Linux AMI-ID
InstanceType: !Ref InstanceType






AWSTemplateFormatVersion: '2010-09-09'
Description: EC2 instance Resources LAB2.
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: 'Amazon EC2 Configuration'
Parameters:
- InstanceType
ParameterLabels:
InstanceType:
default: 'Type of EC2 Instance'
Parameters:
InstanceType:
Type: String
Default: t2.micro
AllowedValues:
- t2.micro
- t2.small
Description: 'Enter t2.micro or t2.small. Default is t2.micro.'
Resources:
WebServerInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-09cf633fe86e51bf0 # Seoul Resion의 Amazon Linux AMI-ID
InstanceType: !Ref InstanceType
KeyName: kakao-oeckikek
BlockDeviceMappings:
-
DeviceName: /dev/sdm
Ebs:
VolumeType: io1
Iops: 300
DeleteOnTermination: false
VolumeSize: 10



AWSTemplateFormatVersion: "2010-09-09"
Description: EC2 for webserver
Parameters:
KeyName:
Description: Name of KeyPair
Type: AWS::EC2::KeyPair::KeyName
AMI:
Description: AMI of EC2
Type: AWS::EC2::Image::Id
Default: ami-09cf633fe86e51bf0
AZpublic:
Description: AvailabilityZone for public
Type: AWS::EC2::AvailabilityZone::Name
AZprivate:
Description: AvailabilityZone for private
Type: AWS::EC2::AvailabilityZone::Name
VPCCidr:
Description: Cidr Block for VPC
Type: String
Default: 10.0.0.0/16
PublicSubnetCidr:
Description: Cidr Block for Public Subnet
Type: String
Default: 10.0.0.0/24
PrivateSubnetCidr:
Description: Cidr Block for Private Subnet
Type: String
Default: 10.0.10.0/24
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCidr
EnableDnsHostnames: true
Tags:
- Key: Name
Value: soyeonVPC
PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !Ref PublicSubnetCidr
AvailabilityZone: !Ref AZpublic
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: public subnet
PrivateSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !Ref PrivateSubnetCidr
AvailabilityZone: !Ref AZprivate
Tags:
- Key: Name
Value: private subnet
IGW:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: myigw
Attachigw:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref IGW
VpcId: !Ref VPC
PublicRT:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: Public RT
PublicRoute:
Type: AWS::EC2::Route
DependsOn: Attachigw
Properties:
RouteTableId: !Ref PublicRT
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref IGW
PublicSubnetRTAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicRT
SubnetId: !Ref PublicSubnet
SGforWeb:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: allow 22, 80
GroupName: webaccess
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
VpcId: !Ref VPC
SGforDB:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: allow webserver
GroupName: dbaccess
SecurityGroupIngress:
- IpProtocol: -1
SourceSecurityGroupId : !GetAtt SGforWeb.GroupId
VpcId: !Ref VPC
EC2forWeb:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref AMI
KeyName: !Ref KeyName
AvailabilityZone: !GetAtt PublicSubnet.AvailabilityZone
InstanceType: t2.micro
SubnetId: !Ref PublicSubnet
SecurityGroupIds:
- !Ref SGforWeb
UserData:
Fn::Base64:
!Join [ "", [
"#!/bin/bash\n",
"#Install APM for Web Server\n",
"yum install -y mariadb* php httpd php-mysql\n",
"systemctl enable httpd mariadb\n",
"systemctl start httpd mariadb\n"] ]
Tags:
- Key: Name
Value: Web Server




