μ˜€λžœλ§Œμ— μ‹ κ·œ ν”„λ‘œμ νŠΈλ‘œ μΈν•˜μ—¬ μ•„λ§ˆμ‘΄ μ›Ή μ„œλΉ„μŠ€μ˜ λΉˆμŠ€ν†‘ ν™˜κ²½ ꡬ성에 λŒ€ν•΄μ„œ μ‚΄νŽ΄λ³Ό κΈ°νšŒκ°€ μžˆμ–΄ λ¦¬λˆ…μŠ€ ν”Œλž«νΌμ˜ ν™•μž₯에 λŒ€ν•΄ 더 μžμ„Έν•˜κ²Œ ν•™μŠ΅ν•˜κ³  μ–΄λ–»κ²Œ μ΄μš©ν•  수 μžˆλŠ”μ§€ μ •λ¦¬ν•΄λ³΄κ³ μž ν•œλ‹€. μ˜ˆμ „κ³Ό λ‹€λ₯΄κ²Œ λ³€κ²½λ˜λŠ” 뢀뢄이 생각보닀 λ§Žμ•„μ„œ μ˜€λž˜μ „μ— μ •λ¦¬ν–ˆλ˜ AWS Elastic Beanstalk Java SE ν”Œλž«νΌ ν™˜κ²½μœΌλ‘œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ°°ν¬ν•˜κΈ°λΌλŠ” 글은 μ˜¬λ°”λ₯΄μ§€ μ•Šμ€ λ‚΄μš©μ„ ν¬ν•¨ν•˜κ³  μžˆμŒμ„ μ•Œλ¦°λ‹€.

AWS Elastic Beanstalk 은 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μš΄μ˜ν•˜κΈ° μœ„ν•œ 인프라λ₯Ό μ‰½κ²Œ κ΅¬μ„±ν•˜κ³  배포할 수 μžˆλ„λ‘ 관리해쀀닀. κ°œλ°œμžκ°€ 인프라에 λŒ€ν•΄μ„œ 신경쓰지 μ•Šμ•„λ„ νŠΈλž˜ν”½μ΄λ‚˜ 일정 μž„κ³„κ°’ 기반으둜 μŠ€μΌ€μΌ 아웃이 κ°€λŠ₯ν•˜λ„λ‘ μ„€μ •ν•  수 있으며 λ‹€μ–‘ν•œ μ–Έμ–΄λ‘œ μž‘μ„±λ˜λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— λŒ€ν•΄μ„œ μ§€μ›ν•˜κ³  μ‹¬μ§€μ–΄λŠ” 도컀 μ»¨ν…Œμ΄λ„ˆ λ‚΄μ—μ„œ μ‹€ν–‰ν•˜λŠ” ν™˜κ²½κΉŒμ§€λ„ μ œκ³΅ν•œλ‹€. Amazon EKS와 같은 μΏ λ²„λ„€ν‹°μŠ€ 인프라 ν™˜κ²½μ„ ꡬ성할 ν•„μš”κ°€ μ—†λŠ” μž‘μ€ 규λͺ¨μ˜ ν”„λ‘œμ νŠΈλΌλ©΄ AWS Elastic Beanstalk은 쒋은 선택에 ν•΄λ‹Ήν•  수 μžˆλ‹€.

개발 μ‘°μ§μ—μ„œ μΏ λ²„λ„€ν‹°μŠ€λ₯Ό κ³ λ―Όν•˜κ³  μžˆλ‹€λ©΄ μ •λ§λ‘œ μΏ λ²„λ„€ν‹°μŠ€κ°€ ν•„μš”ν•œ 규λͺ¨μΈκ°€μ— λŒ€ν•΄μ„œ κ³ λ―Όν•΄λ³Ό ν•„μš”κ°€ μžˆλ‹€. 개인적으둜 μΏ λ²„λ„€ν‹°μŠ€κ°€ ν•„μš”ν•΄λ³΄μ΄λŠ” 규λͺ¨μ˜ ν”„λ‘œμ νŠΈλŠ” 생각보닀 λ§Žμ§€ μ•Šμ„κ±°λΌκ³  μƒκ°ν•˜λŠ” νŽΈμ΄λ‹€. μ΅œμ†Œν•œ μΏ λ²„λ„€ν‹°μŠ€λ₯Ό μ œλŒ€λ‘œ 관리할 수 μžˆλŠ” 운영 쑰직을 ꡬ성할 수 μžˆμ–΄μ•Όν•œλ‹€.

μƒ˜ν”Œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜

AWS Elastic Beanstalk 을 μ‚¬μš©ν•˜λ©΄ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ‰½κ²Œ 배포할 수 μžˆλŠ” ν™˜κ²½μ„ λ§Œλ“€ 수 μžˆμ§€λ§Œ 개인적인 κ²½ν—˜μ„ 기반으둜 μ΄μ•ΌκΈ°ν•΄λ³΄μžλ©΄ μ²˜μŒμ— ν™˜κ²½μ„ κ΅¬μ„±ν•΄λ³΄κ³ μžν•˜λŠ” 경우 생각보닀 λ§Žμ€ 였λ₯˜λ₯Ό κ²½ν—˜ν•˜κ³  μ‹€νŒ¨ν•΄μ„œ ν™˜κ²½μ„ 지웠닀가 μƒˆλ‘œ μƒμ„±ν•˜λŠ” κ²½μš°κ°€ λ§Žμ„ 것이닀. λΉˆμŠ€ν†‘ ν™˜κ²½μ— λŒ€ν•œ κ²½ν—˜μ΄ μžˆλ”λΌλ„ μ΅œμ†Œν•œ μ²˜μŒμ—λŠ” μƒ˜ν”Œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ‚¬μš©ν•΄μ„œ ν™˜κ²½μ„ μ‹œμž‘ν•˜λŠ” 것을 ꢌμž₯ν•œλ‹€. AWS CloudFormation 을 μ΄μš©ν•˜μ—¬ Elastic Beanstalk ν™˜κ²½ μŠ€νƒμ„ κ΅¬μ„±ν•˜κΈ° λ•Œλ¬Έμ— λΉˆμŠ€ν†‘ μ„œλΉ„μŠ€μ—μ„œ μ‘°μ°¨ ν•΄κ²°ν•  수 μ—†λŠ” μƒνƒœκ°€ λœλ‹€λ©΄ CloudFormation μ—μ„œ 직접 μŠ€νƒμ„ μˆ˜μ •ν•˜κ±°λ‚˜ μ‚­μ œν•΄μ•Όν•œλ‹€.

μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ†ŒμŠ€ λ²ˆλ“€

ν”Œλž«νΌ ν™•μž₯에 λŒ€ν•΄μ„œ μ΄μ•ΌκΈ°ν•˜κΈ° μ•žμ„œ λΉˆμŠ€ν†‘ ν™˜κ²½μ— μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 배포 μ‹œ μ‚¬μš©λ˜λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ†ŒμŠ€ λ²ˆλ“€μ— λŒ€ν•΄μ„œ μ •λ¦¬ν•΄λ³΄μž. μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ†ŒμŠ€ λ²ˆλ“€μ— λŒ€ν•œ μ£Όμ˜μ‚¬ν•­μœΌλ‘œ 인해 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 배포가 μ‹€νŒ¨ν•˜μ—¬ λ‘€λ°±λ˜λŠ” κ²½μš°λ„ 있기 λ•Œλ¬Έμ΄λ‹€.

  • 단일 ZIP 파일 λ˜λŠ” WAR νŒŒμΌμ΄μ–΄μ•Ό ν•œλ‹€.
  • μ†ŒμŠ€ λ²ˆλ“€μ˜ ν¬κΈ°λŠ” 500 MBλ₯Ό μ΄ˆκ³Όν•˜μ§€ μ•Šμ•„μ•Ό ν•œλ‹€.

단일 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ°°ν¬ν•˜λ”λΌλ„ ZIP 파일둜 κ΅¬μ„±λœ μ†ŒμŠ€ λ²ˆλ“€μ„ μ‚¬μš©ν•˜μ—¬ Procfile을 λ°˜λ“œμ‹œ μ΄μš©ν•˜κΈ°λ₯Ό ꢌμž₯ν•œλ‹€.

Elastic Beanstalk Linux ν”Œλž«νΌ ν™•μž₯

Elastic Beanstalk Linux ν”Œλž«νΌμ€ μ•„λ§ˆμ‘΄ μ›Ή μ„œλΉ„μŠ€μ—μ„œ μ œκ³΅ν•˜λŠ” Amazon Linuxλ₯Ό 기반으둜 λ¦¬λˆ…μŠ€λ₯Ό κ΅¬μ„±ν•˜λŠ” ν™˜κ²½μ„ λ§ν•œλ‹€. 기본적으둜 일반적인 λ¦¬λˆ…μŠ€ ν™˜κ²½ 섀정을 μ œκ³΅ν•˜κΈ°λŠ” ν•˜μ§€λ§Œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μš”κ΅¬μ‚¬ν•­μ— 따라 λ³΄μ•ˆ 쑰치λ₯Ό ν•΄μ•Όν•˜κ±°λ‚˜ μ‹œκ°„ μ„€μ • λ˜λŠ” λͺ¨λ‹ˆν„°λ§ μ†”λ£¨μ…˜κ³Όμ˜ 연계λ₯Ό μœ„ν•΄ λ³„λ„μ˜ μ—μ΄μ „νŠΈλ‚˜ νŒ¨ν‚€μ§€λ₯Ό μ„€μΉ˜ν•˜μ—¬ ν™˜κ²½ ꡬ성을 ν™•μž₯ν•΄μ•Όν•  수 μžˆλ‹€. Elastic Beanstalk Linux ν”Œλž«νΌ μ—μ„œλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ†ŒμŠ€ λ²ˆλ“€μ— ν¬ν•¨λ˜λŠ” .platform λ˜λŠ” .ebextensions 폴더λ₯Ό 톡해 ν”Œλž«νΌμ— λŒ€ν•΄μ„œ ν™•μž₯을 μ§€μ›ν•œλ‹€.

2023λ…„ 10μ›” 19일뢀터 Amazon Liunx 2와 Amazon Linux 2023을 μ§€μ›ν•˜κ³  있으며 AL2에 λŒ€ν•΄μ„œλŠ” 2025λ…„ 6μ›” 30μΌκΉŒμ§€ 지원 μ˜ˆμ •μ΄λ‹€. AL2023 으둜의 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜μ„ μΆ©λΆ„νžˆ μ œκ³΅ν•˜κΈ° μœ„ν•΄ Amazon Linux 2 지원 μ’…λ£Œ λ‚ μ§œ(EOL)κ°€ 2023λ…„ 6μ›” 30μΌμ—μ„œ 2025λ…„ 6μ›” 30일둜 2λ…„ μ—°μž₯λ˜μ—ˆλ‹€.

λ³Έ κΈ€μ—μ„œλŠ” μžλ°” μŠ€ν”„λ§ 기반의 λ°±μ—”λ“œ 개발자 κΈ°μ€€μ˜ Java SE ν”Œλž«νΌμ— λŒ€ν•΄μ„œλ§Œ μ„€λͺ…ν•œλ‹€. λ‚˜λ¨Έμ§€ ν”Œλž«νΌμ— λŒ€ν•΄μ„œλŠ” κ²½ν—˜ν•  κΈ°νšŒκ°€ 없기에 ν”Œλž«νΌ ꡬ성 ν™•μž₯ μ‹œ λ°œμƒν•  수 μžˆλŠ” μ—¬λŸ¬κ°€μ§€ νŠΈλŸ¬λΈ”μŠˆνŒ…μ— λŒ€ν•΄μ„œ κ³΅μœ ν•˜κΈ°κ°€ μ–΄λ ΅λ‹€. μ•„λ¬΄νŠΌ Elastic Beanstalk μ—μ„œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ°°ν¬ν•˜κΈ° μœ„ν•œ ν™˜κ²½μ„ κ΅¬μ„±ν•˜λŠ” κ³Όμ •, μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ°°ν¬ν•˜λŠ” 과정에 λŒ€ν•΄μ„œ μ΄ν•΄ν•œλ‹€λ©΄ μ–΄λ–€ λ¬Έμ œκ°€ λ°œμƒν–ˆμ„ λ•Œ μ–΄λ–€ λΆ€λΆ„μ˜ 둜그λ₯Ό ν™•μΈν•΄μ•Όν•˜λŠ”μ§€λ₯Ό μ•Œ 수 μžˆλ‹€.

λ¦¬λ²„μŠ€ ν”„λ‘μ‹œλ₯Ό μœ„ν•œ Nginx μ›Ήμ„œλ²„ ꡬ성

Elastic Beanstalk Java SE ν”Œλž«νΌμ—λŠ” λ¦¬λ²„μŠ€ ν”„λ‘μ‹œ 역할을 ν•˜λ©° μΊμ‹œλœ 정적 μ½˜ν…μΈ λ₯Ό μ œκ³΅ν•˜κ³  μš”μ²­μ„ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— μ „λ‹¬ν•˜λŠ” nginx μ„œλ²„κ°€ ν¬ν•¨λ˜μ–΄ μžˆλ‹€. 기본적인 섀정을 μ œκ³΅ν•˜κ³  μžˆμ–΄ .conf νŒŒμΌμ„ ν¬ν•¨μ‹œν‚¬μˆ˜λ„ 있고 nginx.conf νŒŒμΌμ„ μ™„μ „νžˆ λŒ€μ²΄ν•  μˆ˜λ„ μžˆλ‹€. Nginx μ›Ήμ„œλ²„ ꡬ성을 ν™•μž₯ν•˜κΈ° 전에 기본적인 섀정을 μ–΄λ–»κ²Œ μ œκ³΅ν•˜λ©° λΆˆν•„μš”ν•œ ν™•μž₯을 μˆ˜ν–‰ν•˜λŠ” 건 μ•„λ‹Œμ§€ ν™•μΈν•˜λŠ” 것이 μ’‹λ‹€. AWS Beanstalk을 μ΄μš©ν•œ μ„±λŠ₯ νŠœλ‹ μ‹œλ¦¬μ¦ˆμ˜ Nginx νŠœλ‹ μ—μ„œ 확인할 수 μžˆλŠ” 컀λ„₯μ…˜ 처리λ₯Ό μœ„ν•œ 방식을 epoll둜 μ„ νƒν•˜κ³ μž ν•˜λŠ” κ²½μš°λŠ” κ³ λ €ν•΄λ³Όλ§Œ ν•˜λ‹€.

events λ””λ ‰ν‹°λΈŒ μœ„μΉ˜ 상 epoll 방식을 μ μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” .platform/nginx/nginx.conf둜 μ™„μ „νžˆ λŒ€μ²΄ν•  수 밖에 μ—†λ‹€.

λ‹€μŒμ€ Amazon Linux 2023 κΈ°λ°˜μ—μ„œμ˜ 기본값을 ν† λŒ€λ‘œ 일뢀 μ˜΅μ…˜μ„ μ μš©ν•œ 것이닀. include μœ„μΉ˜μ— λ”°λΌμ„œ μ–΄λŠ 폴더에 μ„€μ • νŒŒμΌμ„ λ‘˜ 수 μžˆλŠ”μ§€ 잘 μ‚΄νŽ΄λ³΄κΈ°λ₯Ό λ°”λž€λ‹€. μ–΄μ°¨ν”Ό nginx.conf둜 λŒ€μ²΄ν•  것이라면 nginx.conf νŒŒμΌμ— λͺ¨λ“  섀정을 두어도 상관이 μ—†λ‹€.

.platform/nginx/nginx.conf
user nginx; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; worker_processes auto; worker_rlimit_nofile 200000; events { use epoll; worker_connections 1024; multi_accept on; } http { server_tokens off; include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; include conf.d/*.conf; map $http_upgrade $connection_upgrade { default "upgrade"; } server { listen 80 default_server; access_log /var/log/nginx/access.log main; client_header_timeout 60; client_body_timeout 60; keepalive_timeout 60; gzip off; gzip_comp_level 4; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; # Include the Elastic Beanstalk generated locations include conf.d/elasticbeanstalk/*.conf; } }
.platform/nginx/conf.d/upstream.conf
upstream web { server 127.0.0.1:5000; keepalive 1024; }
.platform/nginx/conf.d/elasticbeanstalk/00_application.conf
location / { proxy_pass http://web; proxy_http_version 1.1; proxy_set_header Connection $connection_upgrade; proxy_set_header Upgrade $http_upgrade; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }

ν”Œλž«νΌ 슀크립트 도ꡬ

/opt/elasticbeanstalk/bin/get-configλŠ” Amazon Linux ν”Œλž«νΌμ„ μ‚¬μš©ν•˜λŠ” ν™˜κ²½μ— λŒ€ν•΄ AWS Elastic Beanstalkκ°€ μ œκ³΅ν•˜λŠ” 도ꡬ이닀. ν”Œλž«νΌ ν˜Ήμ€ μ»¨ν…Œμ΄λ„ˆ 정보λ₯Ό μ‘°νšŒν•˜κ±°λ‚˜ ν™˜κ²½ λ³€μˆ˜λ₯Ό κ°€μ Έμ˜€λŠ”λ° μ‚¬μš©ν•  수 μžˆλ‹€. λ§Œμ•½, λΉˆμŠ€ν†‘μ— μ˜ν•΄ λ§Œλ“€μ–΄μ§„ EC2 μΈμŠ€ν„΄μŠ€μ— μ ‘μ†ν•˜μ—¬ ν˜„μž¬ 싀행쀑인 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ²ˆλ“€μ΄ μœ„μΉ˜ν•˜λŠ” 폴더 λ˜λŠ” ν™•μΈν•˜κ³ μž ν•˜λŠ” λ‘œκ·Έκ°€ μ–΄λ–€ μœ„μΉ˜μ— μžˆλŠ”μ§€ μ•Œκ³  μ‹Άλ‹€λ©΄ μ•„λž˜μ™€ 같이 λͺ…λ Ήμ–΄λ₯Ό μˆ˜ν–‰ν•˜μ—¬ 확인할 수 μžˆλ‹€.

# /opt/elasticbeanstalk/bin/get-config --output YAML platformconfig
generalconfig:
    appuser: webapp
    appdeploydir: /var/app/current/
    appstagingdir: /var/app/staging/
    proxyserver: nginx
    defaultinstanceport: "80"
platformspecificconfig:
    ApplicationPort: "5000"
    JavaVersion: "11"

# /opt/elasticbeanstalk/bin/get-config --output YAML container
common_log_list:
    - /var/log/eb-engine.log
    - /var/log/eb-hooks.log
default_log_list:
    - /var/log/nginx/access.log
    - /var/log/nginx/error.log
    - /var/log/web.stdout.log
environment_name: test-env
instance_port: "80"
log_group_name_prefix: /aws/elasticbeanstalk
proxy_server: nginx
static_files:
    - ""
xray_enabled: "false"

AWS Elastic Beanstalk ν™˜κ²½μ—μ„œ 뉴렐릭 인프라 및 μžλ°” μ—μ΄μ „νŠΈλ₯Ό μ„€μΉ˜ν•˜λŠ” κ³Όμ •μ—μ„œ ν™œμš©ν•  μ˜ˆμ •μ΄λ‹€.

μΈμŠ€ν„΄μŠ€ 메타데이터 μ„œλΉ„μŠ€ ꡬ성

ν˜„μž¬ μ‚¬μš©ν•˜κ³  μžˆλŠ” ν”Œλž«νΌ 버전과 섀정에 λ”°λΌμ„œ IMDS에 λŒ€ν•œ ν”Œλž«νΌ 지원 μ—¬λΆ€λ₯Ό ν™•μΈν•΄λ³΄λŠ”κ²Œ μ’‹λ‹€. ν”Œλž«νΌ ν™•μž₯ ꡬ성 μ‹œ μΈμŠ€ν„΄μŠ€ 메타데이터 μ„œλΉ„μŠ€λ₯Ό μ΄μš©ν•΄μ•Όν•  ν•„μš”μ„±μ΄ μš”κ΅¬λœλ‹€λ©΄ IMDSv2λ₯Ό μ΄μš©ν•΄μ•Όν•˜λŠ” ν™˜κ²½μ—μ„œλŠ” μΈμŠ€ν„΄μŠ€ 메타데이터 μ„œλΉ„μŠ€ 접근을 μœ„ν•œ 토큰을 λ¨Όμ € λ°œκΈ‰ν•œ 뒀에 μΈμŠ€ν„΄μŠ€ 메타데이터 μ„œλΉ„μŠ€μ— μš”μ²­ν•΄μ•Όν•œλ‹€.

.ebextensions/00_init.config
option_settings: aws:autoscaling:launchconfiguration: DisableIMDSv1: true
.ebextensions/02_newrelic-infra.config
commands: 02_configure-newrelic-infra: command: | NEW_RELIC_LICENSE_KEY=`/opt/elasticbeanstalk/bin/get-config environment -k NEW_RELIC_LICENSE_KEY` METADATA_TOKEN=`curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` INSTANCE_ID=`curl -s -H "X-aws-ec2-metadata-token: $METADATA_TOKEN" http://169.254.169.254/latest/meta-data/instance-id` ENVIRONMENT_NAME=`/opt/elasticbeanstalk/bin/get-config container -k environment_name` NEW_RELIC_HOSTNAME="${ENVIRONMENT_NAME}_${INSTANCE_ID}" sudo sed -i "s/^license_key:.*/license_key: ${NEW_RELIC_LICENSE_KEY}/g" /etc/newrelic-infra.yml sudo sed -i "s/^display_name:.*/display_name: ${NEW_RELIC_HOSTNAME}/g" /etc/newrelic-infra.yml sudo systemctl restart newrelic-infra sudo rm -r /etc/newrelic-infra.*.bak

μ‘°μ§μ—μ„œ κ΅¬μ„±ν•œ Beanstalk ν™˜κ²½λ§ˆλ‹€ IMDSv1 μ˜΅μ…˜ 섀정이 닀름을 ν™•μΈν–ˆμœΌλ‚˜ λ‹€ν–‰νžˆλ„ μΈμŠ€ν„΄μŠ€ 메타데이터 μ„œλΉ„μŠ€λ₯Ό ν™œμš©ν•˜λŠ” 뢀뢄은 μ—†μ—ˆλ‹€. 참고둜, IMDSv1의 경우 κΆŒν•œμ„ μš”κ΅¬ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ λ³΄μ•ˆ 취약점에 ν•΄λ‹Ήν•˜λ―€λ‘œ IMDSv1 μ˜΅μ…˜μ„ λΉ„ν™œμ„±ν™”ν•˜λŠ” 것을 κΆŒκ³ ν•œλ‹€.

μΈμŠ€ν„΄μŠ€ 배포 μ›Œν¬ν”Œλ‘œμš°

μΈμŠ€ν„΄μŠ€ 배포 μ›Œν¬ν”Œλ‘œμš°λ₯Ό μ‚΄νŽ΄λ³΄λ©΄ λΉˆμŠ€ν†‘μ—μ„œ μ–΄λ– ν•œ κ³Όμ •μœΌλ‘œ 배포 단계λ₯Ό κ±°μΉ˜λŠ”μ§€λ₯Ό μ„€λͺ…ν•œλ‹€. ꡬ성 파일(.ebextensions)으둜 뉴렐릭 μ—μ΄μ „νŠΈλ₯Ό μ„€μΉ˜ν• μˆ˜λ„ μžˆμœΌλ‚˜ ν”Œλž«νΌ ν™•μž₯(.platform)의 ν”Œλž«νΌ 후크 μŠ€ν¬λ¦½νŠΈλ‘œλ„ μ„€μΉ˜ λͺ…λ Ήμ–΄λ₯Ό μˆ˜ν–‰ν•  수 μžˆλ‹€.

.platform/hooks/predeploy/01_newrelic.sh
#!/bin/bash NEW_RELIC_LICENSE_KEY=`/opt/elasticbeanstalk/bin/get-config environment -k NEW_RELIC_LICENSE_KEY` NEW_RELIC_APP_NAME=`/opt/elasticbeanstalk/bin/get-config environment -k NEW_RELIC_APP_NAME` METADATA_TOKEN=`curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` INSTANCE_ID=`curl -s -H "X-aws-ec2-metadata-token: $METADATA_TOKEN" http://169.254.169.254/latest/meta-data/instance-id` ENVIRONMENT_NAME=`/opt/elasticbeanstalk/bin/get-config container -k environment_name` NEW_RELIC_HOSTNAME="${ENVIRONMENT_NAME}_${INSTANCE_ID}" sed -i "s/^license_key:.*/license_key: ${NEW_RELIC_LICENSE_KEY}/g" /var/app/newrelic/newrelic.yml sed -i "s/^app_name:.*/app_name: ${NEW_RELIC_APP_NAME}/g" /var/app/newrelic/newrelic.yml sed -i "s/^hostname:.*/hostname: $NEW_RELIC_HOSTNAME/g" /var/app/newrelic/newrelic.yml

뉴렐릭 μΈν”„λΌμŠ€νŠΈλŸ­μ²˜ 및 μžλ°” μ—μ΄μ „νŠΈ μ„€μΉ˜ν•΄λ³΄κΈ°

.ebextensions/01_newrelic.config
files: "/var/app/newrelic/newrelic.jar": mode: "000755" owner: webapp group: webapp source: https://download.newrelic.com/newrelic/java-agent/newrelic-agent/current/newrelic.jar "/var/app/newrelic/newrelic.yml": mode: "000755" owner: webapp group: webapp source: https://download.newrelic.com/newrelic/java-agent/newrelic-agent/current/newrelic.yml commands: 01_configure_newrelic: command: | NEW_RELIC_LICENSE_KEY=`/opt/elasticbeanstalk/bin/get-config environment -k NEW_RELIC_LICENSE_KEY` NEW_RELIC_APP_NAME=`/opt/elasticbeanstalk/bin/get-config environment -k NEW_RELIC_APP_NAME` sed -i "s/<%= license_key %>/${NEW_RELIC_LICENSE_KEY}/g" /var/app/newrelic/newrelic.yml sed -i "s/My Application/${NEW_RELIC_APP_NAME}/g" /var/app/newrelic/newrelic.yml 02_configure_newrelic_instance: command: | METADATA_TOKEN=`curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` INSTANCE_ID=`curl -s -H "X-aws-ec2-metadata-token: $METADATA_TOKEN" http://169.254.169.254/latest/meta-data/instance-id` ENVIRONMENT_NAME=`/opt/elasticbeanstalk/bin/get-config container -k environment_name` NEW_RELIC_HOSTNAME="${ENVIRONMENT_NAME}_${INSTANCE_ID}" sed -i "s/^hostname:.*/hostname: $NEW_RELIC_HOSTNAME/g" /var/app/newrelic/newrelic.yml 03_clear_newrelic_bak_files: command: sudo rm -r /var/app/newrelic/newrelic.*.bak

NEW_RELIC_APP_NAME κ³Ό NEW_RELIC_LICENSE_KEY μ˜ˆμ‹œ

.ebextensions/02_newrelic-infra.config
files: "/etc/newrelic-infra.yml" : mode: "000644" owner: root group: root content: | license_key: display_name: commands: 01_install-newrelic-infra: command: | source "/etc/os-release" ARCH=`uname -m` sudo curl -o /etc/yum.repos.d/newrelic-infra.repo "https://download.newrelic.com/infrastructure_agent/linux/yum/amazonlinux/$VERSION_ID/$ARCH/newrelic-infra.repo" sudo yum -q makecache -y --disablerepo='*' --enablerepo='newrelic-infra' sudo yum install newrelic-infra -y 02_configure-newrelic-infra: command: | NEW_RELIC_LICENSE_KEY=`/opt/elasticbeanstalk/bin/get-config environment -k NEW_RELIC_LICENSE_KEY` METADATA_TOKEN=`curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` INSTANCE_ID=`curl -s -H "X-aws-ec2-metadata-token: $METADATA_TOKEN" http://169.254.169.254/latest/meta-data/instance-id` ENVIRONMENT_NAME=`/opt/elasticbeanstalk/bin/get-config container -k environment_name` NEW_RELIC_HOSTNAME="${ENVIRONMENT_NAME}_${INSTANCE_ID}" sudo sed -i "s/^license_key:.*/license_key: ${NEW_RELIC_LICENSE_KEY}/g" /etc/newrelic-infra.yml sudo sed -i "s/^display_name:.*/display_name: ${NEW_RELIC_HOSTNAME}/g" /etc/newrelic-infra.yml sudo systemctl restart newrelic-infra sudo rm -r /etc/newrelic-infra.*.bak

뉴렐릭 인프라 μ—μ΄μ „νŠΈ μ„€μΉ˜ μ‹œ Amazon Linux 버전과 ARM μ•„ν‚€ν…μ²˜λ„ ν™•μΈν•˜μ—¬ μ„€μΉ˜λ  수 μžˆλ„λ‘ ν•˜μ˜€λ‹€.

.platform/confighooks/prebuild/00_hostname.sh
#!/bin/bash ENVIRONMENT_NAME=`/opt/elasticbeanstalk/bin/get-config container -k environment_name` METADATA_TOKEN=`curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` INSTANCE_ID=`curl -s -H "X-aws-ec2-metadata-token: $METADATA_TOKEN" http://169.254.169.254/latest/meta-data/instance-id` sudo hostnamectl set-hostname "${ENVIRONMENT_NAME}_${INSTANCE_ID}"
.platform/hooks/predeploy/01_newrelic.sh
#!/bin/bash NEW_RELIC_LICENSE_KEY=`/opt/elasticbeanstalk/bin/get-config environment -k NEW_RELIC_LICENSE_KEY` NEW_RELIC_APP_NAME=`/opt/elasticbeanstalk/bin/get-config environment -k NEW_RELIC_APP_NAME` sed -i "s/^license_key:.*/license_key: ${NEW_RELIC_LICENSE_KEY}/g" /var/app/newrelic/newrelic.yml sed -i "s/^app_name:.*/app_name: ${NEW_RELIC_APP_NAME}/g" /var/app/newrelic/newrelic.yml

ν˜ΈμŠ€νŠΈμ΄λ¦„ λ‘œμ§μ— λŒ€ν•΄μ„œλŠ” 쑰금 더 μ‚΄νŽ΄λ³΄μ•„μ•Όν•  λΆ€λΆ„ κ°™λ‹€. λ¬Έμ„œ μƒμœΌλ‘œλŠ” newrelic.yml 에 process_host.display_name 속성을 μΆ”κ°€λ‘œ κΈ°μž¬ν•΄μ•Όν•œλ‹€. 기본적으둜 host:port λ₯Ό μ°Έμ‘°ν•˜λ―€λ‘œ EC2 μΈμŠ€ν„΄μŠ€μ˜ ν˜ΈμŠ€νŠΈμ΄λ¦„ 자체λ₯Ό λ³€κ²½ν•˜μ˜€λ‹€.

Elastic Beanstalk μ£Όμ˜μ‚¬ν•­ 정리

  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ†ŒμŠ€ λ²ˆλ“€μ— 항상 Procfile을 ν¬ν•¨μ‹œν‚€κΈ°
  • μ†ŒμŠ€ λ²ˆλ“€ 크기가 500MBλ₯Ό λ„˜μ§€ μ•Šλ„λ‘ μ²΄ν¬ν•˜κΈ°
  • ν™˜κ²½ ꡬ성 μ‹œ μƒ˜ν”Œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μœΌλ‘œ μ‹œμž‘ν•˜κΈ°
  • ν™˜κ²½ 속성을 μ΅œλŒ€ν•œ ν™œμš©ν•˜λ„λ‘ ν”Œλž«νΌ ν™•μž₯ 슀크립트 μ •μ˜ν•˜κΈ°

Elastic Beanstalk 배포 μ‹œ μ „ν™˜μ΄ μ™„λ£Œλ˜κΈ° κΉŒμ§€ μƒλ‹Ήν•œ μ‹œκ°„μ΄ μ†Œμš”λ˜λŠ” 건 λ„ˆλ¬΄ 큰 단점 κ°™λ‹€.