AWS ElasticBeanstalk: Tips and Tricks

AWS ElasticBeanstalk — PaaS на базі інфраструктури AWS. На мій погляд значна перевага цього сервісу — можливість прямого доступу до елементів інфраструктури (балансировщики, инстансы, черги тощо) У цій статті вирішив зібрати деякі трюки, що дозволяють вирішити типові проблеми при використанні ElasticBeanstalk. Буду доповнювати по мірі знаходження нових. Питання і пропозиції в коментарях вітаються.



Варіанти додавання конфігурації програми
На мій погляд очевидний недолік платформи — невиразний механізм зберігання конфігурації. Тому я застосовую такі методи додавання конфігурації.

Самий очевидний і нативний для ElasticBeanstalk — установка через змінні оточення. Всередині инстанса ці змінні доступні не як зазвичай, а виключно в environment програми. Для встановлення цих параметрів найбільш зручно використовувати команду eb setenv з пакету awsebcli, який використовується для розгортання програми (підходить для невеликих проектів), або API AWS.

eb setenv RDS_PORT=5432 PYTHONPATH=/opt/python/current/app/myapp:$PYTHONPATH RDS_PASSWORD=12345 DJANGO_SETTINGS_MODULE=myapp.settings RDS_USERNAME=dbuser RDS_DB_NAME=appdb RDS_HOSTNAME=dbcluster.us-east-1.rds.amazonaws.com

Другий варіант — коли конфіг инжектится всередину створеної версії програми. Для цього треба пояснити, як відбуватися процес розгортання. Вручну або скриптом створюється zip архів, що містить код програми, викладається на спеціальний S3 bucket, унікальний для кожного регіону ( виду elasticbeanstalk<region_name><my_account_id> — не намагайтеся використовувати інший, працювати не буде — перевірено). Можна створювати даний пакет вручну, або редагувати програмно. Я віддаю перевагу використовувати альтернативний варіант розгортання, коли замість awsebcli використовується власний код створення пакета версії.



Третій варіант — завантаження конфігурації віддалено на етапі розгортання із зовнішньої бази конфігурації. ІМХО найбільш правильний підхід, проте виходить за рамки даної статті. Я використовую схему із зберіганням конфіги на S3 і проксированием запитів до S3 через API Gateway — це дозволяє найбільш гнучко управляти конфіг. S3 також підтримує версії.

Включаємо завдання в crontab
ElasticBeanstalk підтримує створення завдань для планувальника, використовуючи файл cron.yaml. Однак цей конфіг працює тільки для worker environment — конфігурації, що використовується для обробки черги завдань / періодичних завдань. Для вирішення цієї задачі в оточенні WebServer додаємо в каталозі проекту .ebextensions файл з наступним вмістом:

files:
"./etc/cron.d/cron_job":
mode: "000644"
owner: root
group: root
content: |
#Add comands below
15 10 * * * root curl www.google.com >/dev/null 2 > &1<code>

"/usr/local/bin/cron_job.sh":
mode: "000755"
owner: root
group: root
content: |
#!/bin/bash
/usr/local/bin/test_cron.sh || exit
echo "Cron running at " `date` >> /tmp/cron_job.log
# Now do tasks that should only run on 1 instance ...

"/usr/local/bin/test_cron.sh":
mode: "000755"
owner: root
group: root
content: |
#!/bin/bash

METADATA=/opt/aws/bin/ec2-metadata
INSTANCE_ID=`$METADATA -i | awk '{print $2}"
REGION=`$METADATA -z | awk '{print substr($2, 0, length($2)-1)}"

# Find our Auto Scaling Group name.
ASG=`aws ec2 describe-tags --filters "Name=resource-id Values=$INSTANCE_ID" \
--region $REGION --output text | awk '/aws:autoscaling:groupName/ {print $5}"

# Find the first instance in the Group
FIRST=`aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names $ASG \
--region $REGION --output text | awk '/InService$/ {print $4}' | sort | head -1`

# Test if they're the same.
[ "$FIRST" = "$INSTANCE_ID" ]

commands:
rm_old_cron:
command: "rm *.bak"
cwd: "./etc/cron.d"
ignoreErrors: true

Автоматичне застосування міграцій Django і складання статики при розгортанні
Додаємо файл конфига в .ebextensions:

container_commands:
01_migrate:
command: "python manage.py migrate --noinput"
leader_only: true
02_collectstatic:
command: "./manage.py collectstatic --noinput"

Аналогічним чином застосовуються міграції alembic; для того, щоб уникнути застосування міграцій на кожному инстансе autoscaling групи, вказується параметр leader_only

Використання hooks при розгортанні додатків
Створюючи скрипти в каталозі /opt/elasticbeanstalk/hooks/, можна додавати різні керуючі скрипти, зокрема, модифікувати процес розгортання програми. Скрипти, що виконуються перед розгортанням, лежать в каталозі /opt/elasticbeanstalk/hooks/appdeploy/pre/*, під час — в /opt/elasticbeanstalk/hooks/appdeploy/enact/*, і після — в /opt/elasticbeanstalk/hooks/appdeploy/post/*. Скрипти виконуються в алфавітному порядку, завдяки цьому можна вибудувати правильну послідовність розгортання додатків.

Додавання демона Celery у вже наявний конфіг supervisor
files:
"/opt/elasticbeanstalk/hooks/appdeploy/post/run_supervised_celeryd.sh":
mode: "000755"
owner: root
group: root
content: |
#!/usr/bin/env bash

# Get django environment variables
celeryenv=`cat /opt/python/current/env | tr '\n' ',' | sed 's/export //g' | sed 's/$PATH/%(ENV_PATH)s/g' | sed 's/$PYTHONPATH//g' | sed 's/$LD_LIBRARY_PATH//g"
celeryenv=${celeryenv%?}

# Create celery configuraiton script
celeryconf="[program:celeryd]
; Set full path to celery program if using virtualenv
command=/opt/python/run/venv/bin/celery worker -A yourapp -B --loglevel=INFO -s /tmp/celerybeat-schedule

directory=/opt/python/current/app
user=nobody
numprocs=1
stdout_logfile=/var/log/celery-worker.log
stderr_logfile=/var/log/celery-worker.log
autostart=true
autorestart=true
startsecs=10

; Need to wait for currently executing tasks to finish at shutdown.
; Increase this if you have very long running tasks.
stopwaitsecs = 600

; When resorting to send SIGKILL to the program to terminate it
; send SIGKILL to its whole process group instead,
; taking care of its children as well.
killasgroup=true

; if rabbitmq is supervised, set its priority higher
; so it starts first
priority=998

environment=$celeryenv"

# Create the celery supervisord conf script
echo "$celeryconf" | tee /opt/python/etc/celery.conf

# Add configuration script to supervisord conf (if not already there)
if ! grep -Fxq "[include]" /opt/python/etc/supervisord.conf
then
echo "[include]" | tee -a /opt/python/etc/supervisord.conf
echo "files: celery.conf" | tee -a /opt/python/etc/supervisord.conf
fi

# Reread the supervisord config
supervisorctl -c /opt/python/etc/supervisord.conf reread

# Update supervisord in cache without restarting all services
supervisorctl -c /opt/python/etc/supervisord.conf update

# Start/Restart celeryd through supervisord
supervisorctl -c /opt/python/etc/supervisord.conf restart celeryd

До речі, я використовував експериментальну можливість взяти в якості брокера для Celery SQS і це цілком себе виправдало; правда, flower ще не має підтримки такої схеми.

Автоматична переадресація HTTP HTTPS
Використовується така ось добавка до конфіг Apache всередині ElasticBeanstalk

files:
"./etc/httpd/conf.d/ssl_rewrite.conf":
mode: "000644"
owner: root
group: root
content: |
RewriteEngine On
<I "-n '%{HTTP:X-Forwarded-Proto}' && %{HTTP:X-Forwarded-Proto} != 'https'">
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
</I>

Використання декількох SSL доменів
Amazon надає можливість власникам доменів безкоштовно використовувати SSL сертифікати, в тому числі і wildcard, однак тільки всередині самого AWS. Для використання декількох доменів з SSL на одному environment отримуємо сертифікат AWS Certificate Manager, додаємо ще ELB балансувальник і налаштовуємо на ньому SSL. Можна використовувати і отримані в іншого постачальника сертифікати.



UPDATE Нижче коментарі шановний @darren99 навів ще кілька корисних фішок, дозволю додати їх тут з деякими поясненнями

Вимикаємо environment за розкладом

В даному випадку в залежності від зазначеного часового діапазону кількість инстансов в autoscaling групі зменшується з 1 до 0.


option_settings:
- namespace: aws:autoscaling:scheduledaction
resource_name: Start
назва_параметра: MinSize 
value: 1
- namespace: aws:autoscaling:scheduledaction
resource_name: Start
назва_параметра: MaxSize
value: 1
- namespace: aws:autoscaling:scheduledaction
resource_name: Start
назва_параметра: DesiredCapacity
value: 1
- namespace: aws:autoscaling:scheduledaction
resource_name: Start
назва_параметра: Recurrence
value: "0 9 * * 1-5"
- namespace: aws:autoscaling:scheduledaction
resource_name: Stop
назва_параметра: MinSize
value: 0
- namespace: aws:autoscaling:scheduledaction
resource_name: Stop
назва_параметра: MaxSize
value: 0
- namespace: aws:autoscaling:scheduledaction
resource_name: Stop
назва_параметра: DesiredCapacity
value: 0
- namespace: aws:autoscaling:scheduledaction
resource_name: Stop
назва_параметра: Recurrence
value: "0 18 * * 1-5"


Заміна Apache на Nginx
option_settings:
aws:elasticbeanstalk:environment:proxy:
ProxyServer: nginx

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.