Elastic Beanstalk은 AWS에 어플리케이션을 배포하는 가장 간편하고 빠른 방법으로 Java, .NET, PHP, Node.js, Python, Ruby, Go, Docker를 사용하여 Apache, Nginx, IIS와 같은 서버에서 구동되는 웹서비스들을 지원합니다. 사용자를 대신해서 인프라를 프로비저닝해주고 업데이트 및 패치도 간단하게 적용할수 있습니다. 인프라 운영 오버헤드등을 줄여서 개발에 더 집중할수 있도록 도와주는 PaaS 입니다.
-
Open Source Python Django Application을 Elastic Beanstalk에 배포
-
구성파일(ebextensions)로 환경구성 Customization
-
AWS CodePipeline 으로 배포 자동화 구성
-
AWS KMS & Systems Manager로 Parameter 암호화
- 본 Hands-on lab에서 사용할 Application 예제는 MDN (the Mozilla Developer Network) 에서 만든 튜토리얼의 예제입니다.
- 본 Hands-on lab은 AWS Seoul region 기준으로 작성되었습니다. Region을 Seoul (ap-northeast-2)로 변경 후 진행 부탁드립니다.
- AWS Credit 추가하기
- Lab 환경 구축
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 Elastic Beanstalk을 검색하거나 [Compute] 밑에 있는 [Elastic Beanstalk] 를 선택
-
[Create New Application] → Application Name = local-library → [Create]
-
Elastic Beanstalk Application Dashboard 에서 [Actions] → [Create environment] → Web server environment 🔘 → [Select]
-
Environment name = local-library-<YOUR_INITIAL>,
Domain = local-library-<YOUR_INITIAL>,
Platform = 🔘 Python - Amazon Linux 1,
Application code = 🔘 Sample application,
→ [Configure more options] -
Configuration presets = 🔘 High availability
-
[Capacity] → [Modify] → Instance type = m5.large, Metric = CPUUtilization, Unit = Percent, Upper threshold = 80, Lower threshold = 30 → [Save]
-
[Security] → [Modify] → EC2 key pair = EC2 인스턴스에 접속할 Key pair 지정, IAM instance profile = eb-lab-InstanceProfile-XXXXX → [Save]
-
[Network] → [Modify] → VPC = eb-vpc, Load balancer visibility = Public, Load balancer subnets = 모든 public subnet 선택, Instance subnets = 모든 private subnet 선택 → [Save]
-
[Create environment]
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 Cloud9를 검색하거나 [Developer Tools] 밑에 있는 [Cloud9] 를 선택 → [Open IDE]
-
해당 링크를 참고해서 EB CLI 설치
-
해당 Git Repository를 Fork (GitHub 계정 필수)
-
Forking한 Repository를 Cloud9으로 환경으로 Clone
git clone http://<REPOSITORY_URL>
-
위에서 Clone한 로컬 Git Repository의 Root 디렉토리로 이동 후 EB CLI 설정
eb init
Select a default region: 10) ap-northeast-2 : Asia Pacific (Seoul) Select an application to use: 1) local-library Do you wish to continue with CodeCommit? (y/N): N
-
EB CLI로 Application 배포
eb deploy
-
Elastic Beanstalk 도메인 주소로 접속해서 어플리케이션이 정상적으로 작동하는지 확인. 에러발생시 아래의 커맨드로 Log를 확인
eb logs -a
- EB Dashboard에서 [Configuration] → Category가 Software 인 탭에서 [Modify] 클릭 → WSGIPath = locallibrary/wsgi.py → [Apply]
-
locallibrary/settings.py
파일을 열고 아래와 같이 수정ALLOWED_HOSTS = ['.elasticbeanstalk.com']
-
EB CLI로 Application 배포 후 변경사항이 적용됬는지 확인
-
수정한 코드를 Commit & Push
git add . git commit -m "fixed DisallowedHost error" git push
-
EB CLI로 Application 배포 후 변경사항이 적용됬는지 확인
-
ebextensions 폴더 생성
mkdir .ebextensions
-
configuration 파일 셍성
touch .ebextensions/05_django.config
-
.ebextensions/05_django.config
파일을 열고 아래의 코드블록 붙여넣기container_commands: 01_collect_static: command: python manage.py collectstatic 02_migrate: command: python manage.py migrate --noinput leader_only: true
-
PostgreSQL client 설치
sudo yum install postgresql -y
-
RDS 인스턴스에 접속 (RDS Endpoint는 RDS Console에서 확인 가능)
psql -h eb-postgres.xxxxxx.ap-northeast-2.rds.amazonaws.com -U master postgres
-
접속이 안될 경우 RDS 인스턴스에 붙어있는 Security Group에 Cloud9 인스턴스에서 PostgreSQL 포트로 접속 가능한 Inbound rule을 설정
-
아래와 같이 비밀번호 입력창이 나올경우,
asdf1234
를 입력Password for user master:
-
Database 생성
CREATE DATABASE local_library;
-
Database User 생성
CREATE USER local_library WITH PASSWORD 'asdf1234';
-
Database User에 권한 부여
GRANT ALL PRIVILEGES ON DATABASE local_library TO local_library;
-
locallibrary/settings.py
파일을 열고 아래와 같이 수정DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'local_library', 'USER': 'local_library', 'PASSWORD': 'asdf1234', 'HOST': '<RDS_ENDPOINT>', 'PORT': '5432', } }
-
locallibrary/settings.py
파일을 열고 아래와 같은 코드블록을 삭제# Heroku: Update database configuration from $DATABASE_URL. import dj_database_url db_from_env = dj_database_url.config(conn_max_age=500) DATABASES['default'].update(db_from_env)
-
수정한 코드를 Commit & Push하고 EB CLI를 통해서 Application 배포
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 CodePipeline를 검색하거나 [Developer Tools] 밑에 있는 [CodePipeline] 를 선택
-
[Create pipeline] → Pipeline name = eb, Service role = New service role → [Next] → Source provider = GitHub → [Connect to GitHub] → Repository = 랩 시작할때 Forking한 Repository, Branch = master → [Skip build stage]
-
Deploy provider = AWS Elastic Beanstalk, Application name과 Environment name에 위에서 생성한 리소스들을 넣고 [Next] → [Create pipeline]
-
locallibrary/settings.py
파일을 열고 아래와 같은 코드블록을 붙여넣기# Get the private IP address of the instance to stop Sentry errors from # Load Balancer health checks. import requests PRIVATE_IP_URL = 'http://169.254.169.254/latest/meta-data/local-ipv4' PRIVATE_IP_REQUEST_DATA = requests.get(PRIVATE_IP_URL) if PRIVATE_IP_REQUEST_DATA: IP_ADDRESS = PRIVATE_IP_REQUEST_DATA.text ALLOWED_HOSTS.append(IP_ADDRESS)
-
requirements.txt
파일을 열고 아래의 라인을 추가requests==2.22.0
-
수정한 코드를 Commit & Push
-
Load balancer 설정에서
Health check path
를/catalog/
로 변경하고 적용 -
Health Status가 ✅
OK
로 변했는지 확인
-
AWS Management Console 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 ssm를 검색하고 [Systems Manager] 를 선택
-
Systems Manager Dashboard 왼쪽 패널 Instances & Nodes 섹션 아래에 있는 [Session Manager] 선택
-
[Start Session] → Instance Name: local-library-xxx 선택 → [Start Session] 클릭
-
Root 환경으로 전환
sudo -i
-
Stress utility 설치
yum install stress -y
-
CPU load 생성
stress --cpu 4 --timeout 600
-
신규 인스턴스가 생성되는지 확인
-
Session Manager를 통해서 EC2 인스턴스에 접속
-
Apache HTTP Server 정지
sudo service httpd stop
-
인스턴스가 자동으로 복구되는지 확인 후 Cloud9 IDE 실행
-
configuration 파일 셍성
touch .ebextensions/03_autoscaling.config
-
.ebextensions/03_autoscaling.config
파일을 열고 아래의 코드블록 붙여넣기Resources: AWSEBAutoScalingGroup: Type: "AWS::AutoScaling::AutoScalingGroup" Properties: HealthCheckType: ELB HealthCheckGracePeriod: 300
-
수정한 코드를 Commit & Push
-
다시 EC2 인스턴스에 접속해서 Apache HTTP Server 정지하고 기존 인스턴스가 새로운 인스턴스로 교체되는지 확인
-
AWS Management Console 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 kms를 검색하고 [Key Management Service] 를 선택
-
[Customer managed keys] → [Create key] → Key type = Symmetric → [Next] → Alias = eb → [Next] → Key administrators = 해당 암호화키에 관리자 권한을 줄 IAM 유저 선택 → [Next] → This account 탭에서 eb-lab-IAMRole-xxxx를 선택 → [Next] → [Finish]
-
AWS Management Console 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 ssm를 검색하고 [Systems Manager] 를 선택
-
Systems Manager Dashboard 왼쪽 패널 Application Management 섹션 아래에 있는 [Parameter Store] 선택
-
[Create parameter] → Name = /LOCAL_LIBRARY/DB_PASSWORD, Tier = Standard, Type = SecureString, KMS Key ID = alias/eb, Value = asdf1234 → [Create parameter]
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 IAM를 검색하거나 [Security, Identity, & Compliance] 바로 밑에 있는 [IAM] 를 선택
-
[Roles] → eb-lab-IAMRole-xxxx를 선택
-
[Add inline policy] 선택 후, Service = Systems Manager, Actions = GetParameter, Resources = ✅ Specific → [Add ARN], Region = ap-northeast-2, Fully qualified parameter name = LOCAL_LIBRARY/DB_PASSWORD → [Add], [Review policy] 클릭, Name = ssm_get_param, [Create policy] 클릭
-
locallibrary/settings.py
파일을 열고DATABASES
블록 위에 아래의 코드블록을 붙여넣기# SSM import boto3 ## Create the SSM Client ssm = boto3.client( 'ssm', region_name='ap-northeast-2' ) ## Get the requested parameter response = ssm.get_parameter( Name='/LOCAL_LIBRARY/DB_PASSWORD', WithDecryption=True ) DB_PASSWORD = response['Parameter']['Value']
-
locallibrary/settings.py
파일을 열고DATABASES
블록을 아래와 같이 수정DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'local_library', 'USER': 'local_library', 'PASSWORD': DB_PASSWORD, 'HOST': '<RDS_ENDPOINT>', 'PORT': '5432', } }
-
requirements.txt
파일을 열고 아래의 라인을 추가boto3==1.11.9
-
수정한 코드를 Commit & Push
-
EB Dashboard에서 [Configuration] → Category가 Software 인 탭에서 [Modify] 클릭 → X-Ray Daemon ✅ Enabled → [Apply]
Elastic Beanstalk 환경에 기본으로 X-Ray Daemon이 설치됩니다만 위의 옵션설정으로 실행시켜주어야 합니다
-
requirements.txt
파일을 열고 아래의 라인을 추가 (AWS X-Ray SDK for Python 설치)aws-xray-sdk==2.4.3
-
locallibrary/settings.py
파일을 열고INSTALLED_APPS
블록에aws_xray_sdk.ext.django
추가INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # Add our new application 'catalog.apps.CatalogConfig', #This object was created for us in /catalog/apps.py, 'aws_xray_sdk.ext.django', ]
-
locallibrary/settings.py
에서MIDDLEWARE
블록에aws_xray_sdk.ext.django.middleware.XRayMiddleware
추가MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'aws_xray_sdk.ext.django.middleware.XRayMiddleware', ]
-
locallibrary/settings.py
에서 아래의 코드블록을 붙여넣기XRAY_RECORDER = { 'AWS_XRAY_DAEMON_ADDRESS': '127.0.0.1:2000', 'AUTO_INSTRUMENT': True, # If turned on built-in database queries and template rendering will be recorded as subsegments 'AWS_XRAY_CONTEXT_MISSING': 'LOG_ERROR', 'PLUGINS': (), 'SAMPLING': True, 'SAMPLING_RULES': None, 'AWS_XRAY_TRACING_NAME': 'locallibrary', # the segment name for segments generated from incoming requests 'DYNAMIC_NAMING': None, # defines a pattern that host names should match 'STREAMING_THRESHOLD': None, # defines when a segment starts to stream out its children subsegments }
-
IAM Dashboard로 이동해서 eb-lab-IAMRole-xxxx에 AWSXRayWriteOnlyAccess 정책 연결
-
수정한 코드를 Commit & Push
-
웹 어플리케이션에 접속 후 Browising
-
AWS Management Console에서 좌측 상단에 있는 [Services] 를 선택하고 검색창에서 X-Ray를 검색하거나 [Developer Tools] 밑에 있는 [X-Ray] 를 선택
-
X-Ray Dashboard에서 [Traces] 선택
- 각 URL별 응답속도 확인
- Trace list 에서 Response Time 이 가장 긴 Trace를 선택 후 Raw data 에서 subsegments 확인