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 ํ์ธ