AWS — CodeDeploy на EC2 Instance

Пример создания AWS Pipeline, где CloudWatch отслеживает состояние репозитория в CodeCommit, при изменении запускает CodeBuild который выкачивает содержимое репозитория и загружает его в S3 Bucket. CodeDeploy обращается к EC2 Instance и codedeploy-agent скачивает с S3 архив с содержимым репозитория и выполняет действия, описанные в скрипте.

 

S3 Bucket необходим только для передачи артефакта от CodeBuild до codedeploy-agent'а на EC2 инстансе, так как агент не может скачивать напрямую репозиторий с CodeCommit.

 

CloudWatch — Logs — Action — Create log group

CodeBuild

CodeDeploy

CodeDeploy -> Applications -> Create application
Deployment Groups -> Create deployment group

Environment configuration — выбираем EC2 Instance

Теперь по уникальному имени и значению тега нужно определить инстанс. Для его, если не создавали тег, то добавьте его к EC2 Instance. В данном примере тег с именем "ENV" и значением "Staging"

Проверьте количество уникальных совпадений.

Load balancer — снимаем галочку, в данном примере один EC2 Instance

Deployment group deployment -> Create deployment

https://docs.aws.amazon.com/en_us/codedeploy/latest/userguide/codedeploy-agent-operations-install-ubuntu.html

https://docs.aws.amazon.com/en_us/codedeploy/latest/userguide/codedeploy-agent-operations-install-linux.html

sudo service codedeploy-agent start

service codedeploy-agent status

wget https://aws-codedeploy-us-east-1.s3.us-east-1.amazonaws.com/latest/install

Создать роль для EC2 !!!!!!!!!!!!!!!!

CodeDeploy-EC2

Добавляем следующую полиси:

CodeDeploy-EC2-Permissions

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:Get*",
                "s3:List*"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}

AWS — CodeBuild: Добавляем инкрементный номер сборки

Как оказалось CodeBuild не имеет встроенной инкрементной переменной для номера сборки, как в том же Jenkins'е к примеру.

Решение было найдено на medium.com

Для добавления номера сборки понадобятся следующие сервисы:

  • AWS SSM (Systems Manager Parameter Store)
  • AWS Lambda
  • AWS CloudWatch
  • AWS IAM

 

Создаем Parameter Store

Переходим в сервис AWS Systems Manager > Parameter Store

Создаем параметр с именем "/build-number/artem-test"

 

Задаем параметры:

  • Type: String
  • Value: 1

Сохраняем наш "Parameter store"

Переходим в AIM -> Policy

Создаем новую Policy с именем "codebuild-buildnumber-ssm" для "CodeBild" проекта со следующим содержимым:

    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssm:GetParameter",
                "ssm:GetParameters"
            ],
            "Resource": "arn:aws:ssm:us-east-1:XXXXXXXXXXXX:parameter/build-number/*"
        }
    ]

 

XXXXXXXXXXXX — замените на свой AWS ID. Так же проверьте свой регион.

 

Переходим в AIM -> Roles и находим роль CodeBuild для нашего проекта и делаем ему "Attach" созданного Policy.

Читать далее "AWS — CodeBuild: Добавляем инкрементный номер сборки"

AWS — CodeCommit и CodeBuild собираем Docker образ и пушаем его в ECR

В данном примере рассмотрим создание репозитория в CodeCommit и сборку простого Docker образа при помощи CodeBuild и запушаем его в ECR.

Создадим в CodeCommit репозиторий. Имя моего репозитория — "artem-test"

Для того, чтобы работать с репозиторием убедитесь, что у вашего пользователя загружен SSH ключ. Если уже загружен, посмотрите его ID, он будет нужен.

 

Клонируем себе репозиторий:

git clone ssh://[email protected]/v1/repos/artem-test

 

Не забудьте поменять регион, в котором создан репозиторий.

 

Добавим в него для теста пример простого Dockerfile

Dockerfile:

FROM php:7.1-apache-jessie

RUN apt update && \
    apt install curl net-tools && \
    apt-get clean

CMD ["apache2-foreground"]

 

Для сборки будем использовать: buildspec.yml

buildspec.yml:

version: 0.2

env:
  variables:
    AWS_ACCOUNT_ID: "XXXXXXXXXXXX"
    AWS_DEFAULT_REGION: "us-east-1"
    IMAGE_REPO_NAME: "artem-test"
    IMAGE_TAG: "latest"

phases:
  install:
    runtime-versions:
      docker: 18
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...          
      - docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .
      - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG 
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker image...
      - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG

 

Отправим локальные изменения на сервер:

git add .
git commit -am "git init"
git push

 

Создаем проект в CodeBuild, указав в качестве источника репозиторий в CodeCommit.

Дадим для CodeBuild права в ECR

Открываем IAM -> CodeBuild

Ищем "codebuild-artem-test-service-role"

И добавляем этой роли следующую Policy:

AmazonEC2ContainerRegistryPowerUser

 

Для вывода логов сборки переходим в сервис "CloudWatch" и создаем группу. Так же можно создать S3 Bucket для хранения архивов логов.

Можно пробовать собирать образ в CodeBuild.

Amazon Linux 2 AMI — SFTP доступ

Все действия так же будет актуальны для CentOS систем. В данном примере будет добавлен пользователь для доступа через SFTP по SSH ключу в веб директорию под управлениям Apache. Есть дефолтная для Apache группа "apache", при необходимости замените на нужную.

Все сайты живут по пути:

/var/www/html

 

Добавляем пользователя sftpuser (уже в существующую группу):

useradd -g apache -d /var/www/html -s /sbin/nologin sftpuser

Дадим права группе на запись, так как будем менять владельца:

chmod -R g+w /var/www/html/*

Меняем владельца файлов:

chown -R sftpuser:apache /var/www/html/*

 

Сама директория "html" не должна принадлежать пользователю "sftpuser"

 

Создаем директорию для открытых ключей и задаем ей нужные права:

mkdir /var/www/html/.ssh
chmod 700 /var/www/html/.ssh

В этой директории создаем два файла и помещаем в них открытый SSH ключ:

authorized_keys
id_rsa.pub

Задаем нужные права на файл:

chmod 644 /var/www/html/.ssh/*

Делаем sftpuser пользователя владельцем:

chown -R sftpuser:apache /var/www/html/.ssh

 

Открываем файл настроек SSH сервера:

vim /etc/ssh/sshd_config

Заменяем строку:

Subsystem sftp	/usr/libexec/openssh/sftp-server

На следующую:

Subsystem sftp	internal-sftp

И в конец файла добавляем следующий блок:

Match Group apache
X11Forwarding no
AllowTcpForwarding no
ChrootDirectory %h
ForceCommand internal-sftp

 

Перезагружаем службу SSH:

service restart sshd

 

Подключаемся через SFTP клиент указав имя пользователя "sftpuser" и путь к приватному SSH ключу, на основе которого был сгенерирован открытый, порт для подключения — SSH порт (по умолчанию 22).

FIX ERROR — Terraform: Instance Profile already exists

При попытке выполнить "terraform apply" в ходе выполнения на создании "IAM Profile" он завершается со следующей ошибкой:

	* aws_iam_instance_profile.ecs_profile: 1 error occurred:
	* aws_iam_instance_profile.ecs_profile: Error creating IAM instance profile stg-artem-service-profile: EntityAlreadyExists: Instance Profile stg-artem-service-profile already exists.
	status code: 409, request id: a77fec43-7ad2-11e9-9e4e-7744dbc7b890

 

Решение:

При помощи AWS Cli найти IAM Profile и удалить его.

aws --profile artem iam list-instance-profiles

Смотрим список существующих IAM Profile:

{
    "InstanceProfiles": [
        {
            "Path": "/",
            "InstanceProfileName": "stg-artem-service-profile",
            "InstanceProfileId": "YYYYYYYYYYYYYYYYYYYYY",
            "Arn": "arn:aws:iam::XXXXXXXXXXXX:instance-profile/stg-artem-service-profile",
            "CreateDate": "2019-05-17T14:06:27Z",
            "Roles": []
        }
    ]
}

Удаляем ненужный IAM Profile:

aws iam delete-instance-profile --instance-profile-name stg-artem-service-profile

Nginx RTMP module

 

 

Пример сборки Nginx'а с модулем RTPM на системе Ubuntu

 

Обновляем список пакетов и обновляем их:

apt update
apt upgrade -y

 

Устанавливаем необходимые пакеты для сборки:

apt install unzip build-essential libpcre3 libpcre3-dev openssl libssl-dev zlib1g zlib1g-dev libxslt-dev libgd-dev libgeoip-dev

 

Список аргументов можно подсмотреть где-то на ноде с установленным Nginx с пакетного менеджера.

nginx -V
nginx version: nginx/1.14.0 (Ubuntu)
built with OpenSSL 1.1.0g  2 Nov 2017
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module

 

Читать далее "Nginx RTMP module"

FIX ERROR — Nginx: Зависимости при сборки с исходников

 

В данном примере имена пакетов соответствуют DEB системам.

PCRE

./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre= option.
Решение:
apt install libpcre3 libpcre3-dev

 

OpenSSL

./configure: error: SSL modules require the OpenSSL library.
You can either do not enable the modules, or install the OpenSSL library
into the system, or build the OpenSSL library statically from the source
with nginx by using --with-openssl= option.
Решение:
apt install openssl libssl-dev

 

Gzip

./configure: error: the HTTP gzip module requires the zlib library.
You can either disable the module by using --without-http_gzip_module
option, or install the zlib library into the system, or build the zlib library
statically from the source with nginx by using --with-zlib= option.
Решение:
apt install zlib1g zlib1g-dev

 

XSLT

./configure: error: the HTTP XSLT module requires the libxml2/libxslt
libraries. You can either do not enable the module or install the libraries.
Решение:
apt install libxslt-dev

 

GD

./configure: error: the HTTP image filter module requires the GD library.
You can either do not enable the module or install the libraries.
Решение:
apt install libgd-dev

 

GeoIP

./configure: error: the GeoIP module requires the GeoIP library.
You can either do not enable the module or install the library.
Решение:
apt install libgeoip-dev

Elasticsearch — Копировать содержимое одного домена в другой

 

Для того, чтобы скопировать все индексы с одного домена в другой воспользуемся утилитой elasticdump

Для утилиты elasticdump нужнен npm, если их нет, то устанавливаем nodejs и npm:

yum install -y gcc-c++ make
curl -sL https://rpm.nodesource.com/setup_6.x | sudo -E bash -
yum install nodejs

 

Устанавливаем elasticdump:

npm install elasticdump -g

 

Создадим скрипт, предварительно указав в переменных old_instance и new_instance URL своих ES доменов.

cat <<EOF >elastic_dump.sh
#!/bin/bash

old_instance="https://vpc-artem-old.eu-central-1.es.amazonaws.com"
new_instance="https://vpc-artem-new.eu-central-1.es.amazonaws.com"

es_indexes=$(curl -s "${old_instance}/_cat/indices" | awk '{ print $3 }')

for index in $es_indexes; do
  elasticdump \
    --input="${old_instance}/${index}" \
    --output="${new_instance}/${index}" \
    --type=mapping

  elasticdump \
    --input="${old_instance}/${index}" \
    --output="${new_instance}/${index}" \
    --type=data
done
EOF

 

Делаем скрипт исполняемым и запускаем:

chmod +x elastic_dump.sh
./elastic_dump.sh

Если в качестве Elasticsearch у вас сервис AWS, то не должно быть авторизации в Elasticsearch на момент миграции, для этого можно разрешить доступ основываясь на SecurityGroup и VPC:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:eu-central-1:XXXXXXXXXXXX:domain/artem-old/*"
    }
  ]
}

 

eu-central-1 — регион AWS
XXXXXXXXXXXX — ID укаунта AWS
artem-old — имя Elasticsearch домена