Инструменты пользователя

Инструменты сайта


aws:beanstalk-environment-options-precedence

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

aws:beanstalk-environment-options-precedence [2017/10/09 23:16] (текущий)
root создано
Строка 1: Строка 1:
 +====== Beanstalk: порядок и приоритет применения опций ======
  
 +
 +===== Введение =====
 +На днях столкнулся с интересным поведением применения опций окружения в [[https://​aws.amazon.com/​ru/​elasticbeanstalk/​|Beanstalk]]. Beanstalk - это PaaS(Platform as a Service), один из способов предоставления клиенту готовой программной среды. Одновременно предоставляются инструменты для тонкой настройки такой среды. Элементами PaaS является аппаратное обеспечение,​ операционная система,​ СУБД, промежуточное ПО, инструменты тестирования и разработки. AWS Elastic Beanstalk – это простой в использовании сервис для развертывания и масштабирования веб-приложений и сервисов,​ разработанных с помощью Java, .NET, PHP, Node.js, Python, Ruby, Go и Docker, на серверах Apache, Nginx, Passenger и IIS.
 +
 +Т.е. по сути AWS предоставляет вам уже настроенную платформу для определенного вида окружений,​ например,​ Java/​PHP/​Python и т.п. И соответственно следит за ее обновлениями и совместимостью. Конечно не все так гладко,​ как хотелось бы, но в целом очень удобный сервис. Другими словами Beanstalk представляет набор сервисов AWS таких как EC2, ELB, Autoscaling,​ RDS, S3 и т.д. и выступает в неком роде оркестратором.
 +
 +Для автоматизации деплоя мы используем Jenkins и одним из параметров сборки является тип EC2 инстанса,​ на котором необходимо запускать приложение. Одним из условий данной сборки является возможность динамически менять тип EC2 при каждой сборке и деплое.
 +
 +
 +===== Создание окружения =====
 +Мы используем Multicontainer docker environment,​ внутри которого запускаем java приложение,​ но в контексте данной статьи это не столь принципиально. Для описания того, как запускать docker образ и с какими параметрами используется специальный файл - **Dockerrun.aws.json**. Ниже привожу самый простой пример ​
 +
 +<​html>​
 +<pre class="​hl_js json">​
 +{
 +    "​AWSEBDockerrunVersion":​ 2,
 +
 +    "​containerDefinitions":​ [{
 +        "​memory":​ 256,
 +        "​cpu":​ 1,
 +        "​name":​ "​nginx",​
 +        "​image":​ "​nginx",​
 +
 +        "​portMappings":​ [{
 +            "​hostPort":​ 80,
 +            "​containerPort":​ 80
 +        }]
 +    }]
 +}
 +</​pre>​
 +</​html>​
 +
 +Это обычный json файл с довольно таки простым синтаксисом. Вышеприведенный файл запустит контейнер с nginx, выделит ему 256 Mb памяти и пробросит 80й порт с docker хоста внутрь контейнера. Для того, чтобы создать окружения на базе нашего Dockerrun.aws.json необходимо воспользоваться утилитой командной строки Beanstalk - aws eb cli. Поскольку написана она на python, то устанавливается она довольно таки просто - через pip.
 +
 +Непосредственно перед созданием самого окружения,​ нам необходимо произвести инициализацию приложения.
 +
 +<cli>
 +# eb init TEST --profile personal --region us-west-1 ​   ​
 +Application TEST has been created.
 +
 +It appears you are using Multi-container Docker. Is this correct?
 +(Y/n): y
 +
 +Select a platform version.
 +1) Multi-container Docker 17.03.2-ce (Generic)
 +2) Multi-container Docker 1.11.2 (Generic)
 +(default is 1): 1
 +Cannot setup CodeCommit because there is no Source Control setup, continuing with initialization
 +Do you want to set up SSH for your instances?
 +(Y/n): y
 +
 +Select a keypair.
 +1) test
 +2) [ Create new KeyPair ]
 +(default is 1): 1
 +</​cli>​
 +
 +По сути, все что делает эта команда - создает служебную папку .elasticbeanstalk и конфигурационный файл config.yml внутри нее.
 +<cli>
 +# tree -a
 +.
 +├── Dockerrun.aws.json
 +├── .elasticbeanstalk
 +│   └── config.yml
 +└── .gitignore
 +
 +1 directory, 3 files
 +
 +# cat .elasticbeanstalk/​config.yml
 +branch-defaults:​
 +  default:
 +    environment:​ null
 +    group_suffix:​ null
 +global:
 +  application_name:​ TEST
 +  branch: null
 +  default_ec2_keyname:​ test
 +  default_platform:​ Multi-container Docker 17.03.2-ce (Generic)
 +  default_region:​ us-west-1
 +  include_git_submodules:​ true
 +  instance_profile:​ null
 +  platform_name:​ null
 +  platform_version:​ null
 +  profile: personal
 +  repository: null
 +  sc: null
 +  workspace_type:​ Application
 +</​cli>​
 +
 +Если посмотреть в веб консоли самого Beanstalk, то там появится созданное нами приложение TEST
 +
 +{{ :​aws:​ebns-web-console.png?​direct |}}
 +
 +Отлично,​ теперь у нас все готово для создания самого окружения.
 +
 +<cli>
 +# eb create ebns-options-precedence --cname ebns-options-precedence \
 +--region us-west-1 --profile personal \
 +--vpc --vpc.id vpc-44bbbb21 --vpc.securitygroups sg-4b8fe72d \
 +--vpc.ec2subnets subnet-140fc770,​subnet-1344584a \
 +--vpc.elbsubnets subnet-140fc770,​subnet-1344584a \
 +--vpc.elbpublic --vpc.public \
 +--keyname test \
 +--instance_profile aws-elasticbeanstalk-ec2-role \
 +--instance_type t2.nano
 +
 +Creating application version archive "​app-171009_183531"​.
 +Uploading TEST/​app-171009_183531.zip to S3. This may take a while.
 +Upload Complete.
 +WARNING: Uploaded SSH public key for "​tkap"​ into EC2 for region us-west-1.
 +Environment details for: ebns-options-precedence
 +  Application name: TEST
 +  Region: us-west-1
 +  Deployed Version: app-171009_183531
 +  Environment ID: e-mxej3cvxn4
 +  Platform: arn:​aws:​elasticbeanstalk:​us-west-1::​platform/​Multi-container Docker running on 64bit Amazon Linux/2.7.5
 +  Tier: WebServer-Standard
 +  CNAME: ebns-options-precedence.us-west-1.elasticbeanstalk.com
 +  Updated: 2017-10-09 15:​35:​38.704000+00:​00
 +Printing Status:
 +INFO: createEnvironment is starting.
 +INFO: Using elasticbeanstalk-us-west-1-012345678910 as Amazon S3 storage bucket for environment data.
 +INFO: Created security group named: sg-568fe730
 +INFO: Created load balancer named: awseb-e-m-AWSEBLoa-QZ2VZZD361DW
 +INFO: Created security group named: sg-2380e845
 +INFO: Created Auto Scaling launch configuration named: awseb-e-mxej3cvxn4-stack-AWSEBAutoScalingLaunchConfiguration-73VVARDND7Z9
 +INFO: Environment health has transitioned to Pending. Initialization in progress (running for 8 seconds). There are no instances.
 +INFO: Added instance [i-0353e83bb20fbbf2d] to your environment.
 +INFO: Created Auto Scaling group named: awseb-e-mxej3cvxn4-stack-AWSEBAutoScalingGroup-CK1YXIHAR1LC
 +INFO: Waiting for EC2 instances to launch. This may take a few minutes.
 +INFO: Created Auto Scaling group policy named: arn:​aws:​autoscaling:​us-west-1:​012345678910:​scalingPolicy:​d6b10534-9844-4256-b66a-68f344979553:​autoScalingGroupName/​awseb-e-mxej3cvxn4-stack-AWSEBAutoScalingGroup-CK1YXIHAR1LC:​policyName/​awseb-e-mxej3cvxn4-stack-AWSEBAutoScalingScaleDownPolicy-RZ43ZCFUSMO4
 +INFO: Created Auto Scaling group policy named: arn:​aws:​autoscaling:​us-west-1:​012345678910:​scalingPolicy:​bc8d32d4-5a90-4110-92cc-85a1874aacaf:​autoScalingGroupName/​awseb-e-mxej3cvxn4-stack-AWSEBAutoScalingGroup-CK1YXIHAR1LC:​policyName/​awseb-e-mxej3cvxn4-stack-AWSEBAutoScalingScaleUpPolicy-18QZ4TJ2YUWGU
 +INFO: Created CloudWatch alarm named: awseb-e-mxej3cvxn4-stack-AWSEBCloudwatchAlarmHigh-116GPNS213CY4
 +INFO: Created CloudWatch alarm named: awseb-e-mxej3cvxn4-stack-AWSEBCloudwatchAlarmLow-111DBMFL47DTV
 +INFO: Starting new ECS task with awseb-ebns-options-precedence-mxej3cvxn4:​1.
 +INFO: ECS task: arn:​aws:​ecs:​us-west-1:​012345678910:​task/​c562d6ef-e9de-42e8-9335-b1da8fd2aa79 is RUNNING.
 +INFO: Successfully launched environment:​ ebns-options-precedence
 +</​cli>​
 +
 +Как мы видем из вывода - окружение было успешно создано и запущено,​ так же в этом можно убедиться с помощью следующей команды
 +<cli>
 +# eb status -v
 +Environment details for: ebns-options-precedence
 +  Application name: TEST
 +  Region: us-west-1
 +  Deployed Version: app-171009_183531
 +  Environment ID: e-mxej3cvxn4
 +  Platform: arn:​aws:​elasticbeanstalk:​us-west-1::​platform/​Multi-container Docker running on 64bit Amazon Linux/2.7.5
 +  Tier: WebServer-Standard
 +  CNAME: ebns-options-precedence.us-west-1.elasticbeanstalk.com
 +  Updated: 2017-10-09 15:​39:​11.239000+00:​00
 +  Status: Ready
 +  Health: Green
 +  Running instances: 1
 +      i-0353e83bb20fbbf2d:​ InService
 +      ​
 +# curl -i http://​ebns-options-precedence.us-west-1.elasticbeanstalk.com/​
 +HTTP/1.1 200 OK
 +Accept-Ranges:​ bytes
 +Content-Type:​ text/html
 +Date: Mon, 09 Oct 2017 15:56:00 GMT
 +ETag: "​5989d7cc-264"​
 +Last-Modified:​ Tue, 08 Aug 2017 15:25:00 GMT
 +Server: nginx/​1.13.5
 +Content-Length:​ 612
 +Connection: keep-alive
 +...
 +...
 +...
 +</​cli>​
 +
 +===== Модификация окружения =====
 +Если вы обратили внимание,​ то при создании окружения мы использовали ключ **--instance_type t2.nano**, где явно задали какой тип инстанса необходимо создать в нашем окружении. И все бы хорошо,​ но теперь нам необходимо сделать возможность менять это значение. Beanstalk поддерживает несколько путей модификации окружений
 +  * через специальную папку [[http://​docs.aws.amazon.com/​elasticbeanstalk/​latest/​dg/​ebextensions.html|.ebextensions]],​ в том числе позволяет использовать Cloudformation шаблоны,​ правда со своими ограничениями
 +  * через api - [[https://​docs.aws.amazon.com/​cli/​latest/​reference/​elasticbeanstalk/​update-environment.html|update-environment]]
 +  * eb cli (eb config/eb upgrade)
 +  * Beanstalk Environment Management Console
 +
 +Последние два способа нам не подходят,​ так как практически не поддаются автоматизации. Использование чистого api тоже довольно таки сложно автоматизировать,​ хотя и можно. А самый простой способ - использование .ebextensions. Все что нам нужно, создать папку .ebextensions и внутри нее добавить файлы с расширением config. И вот тут начинается самое интересное. ​
 +
 +Мы, законопослушные граждане,​ читаем документацию и находим,​ что для изменения типа инстанса достаточно использовать т.н. namespace - //​**[[http://​docs.aws.amazon.com/​elasticbeanstalk/​latest/​dg/​command-options-general.html#​command-options-general-autoscalinglaunchconfiguration|aws:​autoscaling:​launchconfiguration]]**//​. Создаем соответствующую структуру папок и сам файл
 +<cli>
 +# tree -a
 +.
 +├── Dockerrun.aws.json
 +├── .ebextensions
 +│   └── ec2-settings.config
 +├── .elasticbeanstalk
 +│   └── config.yml
 +└── .gitignore
 +
 +2 directories,​ 4 files
 +
 +# cat .ebextensions/​ec2-settings.config
 +option_settings:​
 +    aws:​autoscaling:​launchconfiguration:​
 +        InstanceType:​ t2.micro
 +</​cli>​
 +
 +Напоминаю,​ что изначально мы создали окружение с t2.nano, а сейчас хотим перейти на более мощный инстанс t2.micro. После этого обновляем наше окружение.
 +
 +<cli>
 +# eb deploy
 +Creating application version archive "​app-171009_200401"​.
 +Uploading TEST/​app-171009_200401.zip to S3. This may take a while.
 +Upload Complete.
 +INFO: Environment update is starting.
 +INFO: Deploying new version to instance(s).
 +INFO: Stopping ECS task arn:​aws:​ecs:​us-west-1:​012345678910:​task/​c562d6ef-e9de-42e8-9335-b1da8fd2aa79.
 +INFO: ECS task: arn:​aws:​ecs:​us-west-1:​012345678910:​task/​c562d6ef-e9de-42e8-9335-b1da8fd2aa79 is STOPPED.
 +INFO: Starting new ECS task with awseb-ebns-options-precedence-mxej3cvxn4:​3.
 +INFO: ECS task: arn:​aws:​ecs:​us-west-1:​012345678910:​task/​4d0ea10e-68d1-4990-872b-7fb0e85685b5 is RUNNING.
 +INFO: New application version was deployed to running EC2 instances.
 +INFO: Environment update completed successfully.
 +</​cli>​
 +
 +Проверяем тип инстанса
 +<cli>
 +# aws ec2 describe-instances --profile cardpool-dev --region us-west-1 \
 +--instance-ids i-0353e83bb20fbbf2d ​ --query "​Reservations[].Instances[].InstanceType"​
 +[
 +    "​t2.nano"​
 +]
 +</​cli>​
 +Странно,​ но как мы видим, тип не изменился. Пробуем изменить напрямую через aws api
 +<cli>
 +# aws elasticbeanstalk update-environment --environment-name ebns-options-precedence \
 +--profile personal --region us-west-1 \
 +--option-settings Namespace=aws:​autoscaling:​launchconfiguration,​OptionName=InstanceType,​Value=t2.small
 +
 +# eb status -v | tail -2
 +  Running instances: 1
 +      i-049d31ef7196304a1:​ InService
 +</​cli>​
 +
 +Как мы видим по статусу id у нашего инстанса изменился,​ а значит и тип скорее всего. Проверяем
 +<cli>
 +# aws ec2 describe-instances --instance-ids i-049d31ef7196304a1 \
 +--profile personal --region us-west-1 --query "​Reservations[].Instances[].InstanceType"​
 +[
 +    "​t2.small"​
 +]
 +</​cli>​
 +
 +Да, так и есть. Тип инстанса поменялся. Но каждый раз вызывать из Jenkins //aws elasticbeanstalk update-environment// ​ не очень удобно,​ к тому же нам надо будет отслеживать поменялся ли тип инстанса по сравнению с предыдущим деплоем,​ что лишь усложнит сам процесс деплоя. Через Beanstalk Webconsole тип инстанса так же меняется без проблем.
 +
 +{{ :​aws:​ebns-web-console-config.png?​direct |}}
 +
 +
 +===== Автоматизируем обновление настроек =====
 +Снова обращаемся к документации и находим там раздел [[http://​docs.aws.amazon.com/​elasticbeanstalk/​latest/​dg/​command-options.html#​configuration-options-precedence|Precedence]]
 +
 +Итак, во время создания и/или обновления окружения опции применяется в следующем приоритете. Список приведен от наиболее приоритетных к менее приоритетным.
 +
 +  * Настройки непосредственно применяемые к окружению через Elastic Beanstalk API любым из клиентов,​ включая AWS Management Console, EB CLI, AWS CLI и SDKs. AWS Management Console и EB CLI так же применяют рекомендуемые значения для некоторых настроек.
 +
 +  * Saved Configurations – настройки для любых опций, которые не были заданы явно и загружаются из т.н. сохраненных конфигураций.
 +
 +  * Конфигурационные файлы (.ebextensions) – настройки,​ которые не были заданы явно, а так же не были заданы в сохраненных конфигурациях с предыдущего пункта.
 +
 +  * Значения по умолчанию (Default Values) – если какой-либо параметр имеет значение по умолчанию,​ то оно будет применятся только,​ если сама опция не была задана ни на одном из предыдущих уровней.
 +
 +Теперь становится понятно,​ почему значение InstanceType из нашего файла .ebextensions/​ec2-settings.config не имеет эффекта. Но что же тогда делать,​ оказывается выход есть. После создания окружения нам надо лишь удалить соответствующий параметр на уровне API и тогда начнет действовать значение параметров из .ebextensions
 +
 +<cli>
 +# aws elasticbeanstalk update-environment --profile personal --region us-west-1 \
 +--environment-name ebns-options-precedence \
 +--options-to-remove Namespace=aws:​autoscaling:​launchconfiguration,​OptionName=InstanceType ​
 +</​cli>​
 +
 +Данный вызов необходимо выполнить только один раз, после первоначального создания окружения. Как по мне - то такое поведение является очень не удобным и не очевидным. Получается,​ что с помощью eb cli вы можете задать тип инстанса,​ но сменить его в дальнейшем вы уже не можете.
 +
 +Так же стоит учитывать,​ что если после удаления данной опции, кто либо поменяет ее через Web Console и/или через aws api cli, то настройки из .ebextensions опять перестанут применяться из-за приоритета и нужно будет заново выполнить options-to-remove
aws/beanstalk-environment-options-precedence.txt · Последние изменения: 2017/10/09 23:16 — root