Деплой что это такое


деплоить — Викисловарь

Содержание

  • 1 Русский
    • 1.1 Морфологические и синтаксические свойства
    • 1.2 Произношение
    • 1.3 Семантические свойства
      • 1.3.1 Значение
      • 1.3.2 Синонимы
      • 1.3.3 Антонимы
      • 1.3.4 Гиперонимы
      • 1.3.5 Гипонимы
    • 1.4 Родственные слова
    • 1.5 Этимология
    • 1.6 Фразеологизмы и устойчивые сочетания
    • 1.7 Перевод
    • 1.8 Библиография

Морфологические и синтаксические свойства[править]

  наст. прош. повелит.
Я депло́ю депло́ил
депло́ила
 —
Ты депло́ишь депло́ил
депло́ила
депло́й
Он
Она
Оно
депло́ит депло́ил
депло́ила
депло́ило
 —
Мы депло́им депло́или
Вы депло́ите депло́или депло́йте
Они депло́ят депло́или  —
Пр. действ. наст. депло́ящий
Пр. действ. прош. депло́ивший
Деепр. наст. депло́я
Деепр. прош. депло́ив, депло́ивши
Будущее буду/будешь… депло́ить

де-пло́-ить

Глагол, несовершенный вид, непереходный, тип спряжения по классификации А. Зализняка — 4a.

Корень: -деплоj-; суффикс: ; глагольное окончание: -ть.

Произношение[править]

  • МФА: [dʲɪˈpɫoɪtʲ]

Семантические свойства[править]

Значение[править]
  1. прогр., жарг. осуществлять деплой, производить действия, направленные на перевод исходного кода в рабочее состояние на конкретном сервере ◆ Отсутствует пример употребления (см. рекомендации).
Синонимы[править]
Антонимы[править]
Гиперонимы[править]
Гипонимы[править]

Родственные слова[править]

Ближайшее родство
  • глаголы: деплоиться

Этимология[править]

От ??

Фразеологизмы и устойчивые сочетания[править]

Перевод[править]

Список переводов

Библиография[править]

Для улучшения этой статьи желательно:
  • Добавить пример словоупотребления для значения с помощью {{пример}}
  • Добавить синонимы в секцию «Семантические свойства»
  • Добавить гиперонимы в секцию «Семантические свойства»
  • Добавить сведения об этимологии в секцию «Этимология»
  • Добавить хотя бы один перевод в секцию «Перевод»

деплой — Викисловарь

Содержание

  • 1 Русский
    • 1.1 Морфологические и синтаксические свойства
    • 1.2 Произношение
    • 1.3 Семантические свойства
      • 1.3.1 Значение
      • 1.3.2 Синонимы
      • 1.3.3 Антонимы
      • 1.3.4 Гиперонимы
      • 1.3.5 Гипонимы
    • 1.4 Родственные слова
    • 1.5 Этимология
    • 1.6 Фразеологизмы и устойчивые сочетания
    • 1.7 Перевод
    • 1.8 Библиография
В Викиданных есть лексема деплой (L105192).

Морфологические и синтаксические свойства[править]

падеж ед. ч. мн. ч.
Им. депло́й депло́и
Р. депло́я депло́ев
Д. депло́ю депло́ям
В. депло́й депло́и
Тв. депло́ем депло́ями
Пр. депло́е депло́ях

де-пло́й

Существительное, неодушевлённое, мужской род, 2-е склонение (тип склонения 6a по классификации А. А. Зализняка).

Корень: -деплой-.

Произношение[править]

  • МФА: [dʲɪˈpɫoɪ̯]

Семантические свойства[править]

Значение[править]
  1. прогр., жарг. совокупность действий, направленных на перевод исходного кода в рабочее состояние на конкретном сервере ◆ Отсутствует пример употребления (см. рекомендации).
Синонимы[править]
Антонимы[править]
Гиперонимы[править]
Гипонимы[править]

Родственные слова[править]

Ближайшее родство
  • глаголы: деплоить

Этимология[править]

От англ. deploy.

Фразеологизмы и устойчивые сочетания[править]

Перевод[править]

Список переводов

Библиография[править]

Для улучшения этой статьи желательно:
  • Добавить пример словоупотребления для значения с помощью {{пример}}
  • Добавить синонимы в секцию «Семантические свойства»
  • Добавить гиперонимы в секцию «Семантические свойства»
  • Добавить хотя бы один перевод в секцию «Перевод»

Как правильно деплоить проект? — Хабр Q&A

1) Инициатор деплоя: это может быть как гит-хук, так и допустим вызванная вручную команда. Для начала рекомендую не зацикливаться на хуках, а вызывать в ручную. Если деплоите не так часто, то этого будет вполне достаточно и более безопасно.
2) миграции - это всего лишь sql команды которые меняют бд. Запуск миграций - это то же самое если вручную запустить любой sql клиент у себя на компьютере, присоединиться к бд и начать добавлять/удалять таблицы и столбцы. Я веду к тому, что миграцию на prod сервере можно выполнить и с локальной машины, если миграции будут выполнены с продакшн конфигурацией.
3) Конфигурация. В случае с .env файлом это можно сделать таким образом:
- создаем файл .env.dist в котором указываем все переменные которые требуются для приложения, но оставляем значения пустыми
- комитим .env.dist в репозиторий. Теперь у нас в репозитории есть шаблон по которому мы можем создать .env файл на локальной машине и заполнить значения переменных
- добавляем .env в .gitignore (если .env уже был закомичен, то надо его сперва удалить и закомитить удаление, иначе .gitignore будет неправильно игнорировать .env)
- теперь когда .env игнорируется гитом, можно скопировать наш шаблон .env.dist как .env и заполнить значения переменных. Каждый, кто устанавливает этот проект с нуля у себя на машине должен будет сделать то же самое.

Вообще деплой можно разбить на несколько этапов:
- инициатор деплоя (любое событие по которому начинается деплой)
- сборка проекта (подготовка всех файлов в то состояние в котором они должны отправиться на prod сервер и заменить собой текущие файлы на сервере)
- тестирование проекта (запуск юнит и функциональных тестов, чтобы убедиться что мы заливаем рабочий код)
- собственно перенос проекта на сервер
- выполнение post-deployment команд, которые должны быть выполнены когда новые файлы уже на сервере (например миграции и т.п.)
- интеграционные smoke-тесты (можно оправить GET запросы на ключевые страницы нашего prod сервера и проверить, что в ответах содержится ожидаемый текст или HTML, это делается чисто для того чтобы убедиться, что после деплоя сервер все еще живой и отображает нужные страницы)

Все эти шаги можно выполнять вручную, а можно автоматизировать (вплоть до полной автоматизации), но я не рекомендую автоматизировать всё и сразу - лучше добавлять автоматизацию аккуратно шаг за шагом, чтобы не наломать дров.

Для автоматизации сборки и деплоя существует множество инструментов. Большинство из них просто предлагает дополнительный уровень абстракции над низкоуровневыми командами, что позволяет удобнее организовывать сборки больших проектов с множеством шагов и меньше задумываться о деталях. Обычно разработчики используют для любых проектов какой либо один инструмент, с которым они на "ты" - это всегда удобно, не надо учить ничего нового, все шишки уже набиты, все грабли наступлены. Если у разработчика нет опыта с подобными инструментами и проект достаточно простой, то я бы порекомендовал начать с написания простого скрипта на любом удобном языке программирования. В этом случае не придется тратить время на освоение нового фреймворка и в ваших руках будет максимум контроля над процессом.

У меня нет опыта с ларавел, но для симфони проекта я бы написал приблизительно такой bash скрипт:

# если Вы деплоите с локальной машины, # то как минимум не стоит собирать проект из файлов с которыми Вы работаете в редакторе, # потому что там у нас могут быть незакомиченые изменения, локальные настройки # и еще много чего, что не должно попасть на prod сервер # поэтому проект будем собирать с нуля в отдельной директории, например "build" # (которую тоже нужно предварительно добавить в .gitignore) # очищаем директорию build и заходим в нее rm -rf build mkdir build cd build # клонируем наш проект git clone [email protected]/user/project . # "." клонирует в текущую директорию git checkout master # создаем конфиг для prod cp .env.dist .env # дальше надо заполнить значения переменных в .env файле # для начала можно просто поставить скрипт на паузу в этом моменте и заполнить вручную, # а в будущем как нибудь автоматизировать этот процесс, # например хранить файл с prod конфигами где нибудь на машине # и во время сборки копировать их в проект # устанавливаем вендоры composer install # прогоняем юнит и функциональные тесты, чтобы убедиться что мы не зальем какой нибудь баг vendor/bin/phpunit -c unit.xml vendor/bin/phpunit -c functional.xml # прогреваем кеш bin/console cache:clear --no-warmup --env=prod bin/console cache:warmup --env=prod # выполняем любые другие шаги по подготовке проекта # ... # теперь наш проект готов к заливке на сервер # например через scp scp -r . <username>@<hostname>:<destination path> # наконец, можно накатить миграции баз данных php app/console doctrine:migrations:migrate --env=prod # запускаем смок-тесты которые покажут, что деплоймент прошел успешно vendor/bin/phpunit -c smoke.xml

Беглый деплой или как развернуть front-end за 15 минут / Habr

Уже очень давно у нас стоял вопрос: как же просто и быстро деплоить front-end проекта?

Мы думали насчет такого инструмента, как Jenkins. Многие, кто настраивал его, знают: настройка занимает немало времени и, что еще важно — затрачивается много ресурсов системы. Поднять его на сервере значит выделить полтора гигабайта памяти. Такое себе удовольствие, когда у тебя 500 мегабайт на всё, например.

Альтернативный вариант — Mina. Это отличное решение, и мы используем его в Ruby проектах. Но как быть, если у тебя только front-end? Ставить Ruby и делать Bundle? Нет, это слишком сложно. Mina, конечно, имеет большой функционал, но мы хотим это делать на NodeJS без лишних телодвижений.

В итоге мы писали Bash скрипты, но это нас утомило. И нам в голову пришла идея написать свой небольшой сервис для деплоя front-end приложений, который будет:

  • npm пакетом
  • иметь небольшой и простенький конфиг
  • занимать 10 минут для его настройки и 5 минут для деплоя
  • иметь систему релизов (если всё-таки что-то пойдет не так и кто-то скажет — «оно само
сломалось», то смело и быстро можно вернуться на предыдущий релиз)

И мы сделали Runy — удобный и практичный инструмент для деплоя front-end.

Все что нужно для его настройки и первого деплоя после установки пакета — это три команды:
init — создать конфиг и внести свои данные в него
setup — создать структуру проекта
deploy — задеплоить ваш проект

И это все!

Данный модуль упростил нам жизнь! Теперь деплой проходит одной командой. Быстро и просто. Когда к нам приходят новые разработчики, можно дать им доступы к dev/stage серверу, чтобы ребята могли сами деплоить. Junior разработчикам тоже будет полезно, для использования не нужен порог вхождения, а в дальнейшем они могут разобраться в модуле и приобрести новые знания.

Немного о технической части (более подробный мануал есть на github). На данный момент, Runy имеет следующие команды: init, setup, deploy, unlock, rollback.

Init

Создает конфиг файл в месте вызова команды. Вам следуют внести в него свои данные. Как видно, мы используем подключение по ssh-agent, так что никакие пароли в конфиге находиться не будут.
// runy.js module.exports = { host: '0.0.0.0', // адрес сервера username: 'username', // имя пользователя для входа на сервер port: 22, // порт сервера remotePath: '/your/project/path', // путь структуры релизов и проекта git: 'link-to-your-git-repository', // ссылка (лучше ssh) на ваш репозиторий agent: process.env.SSH_AUTH_SOCK, // ключ авторизации commands: [ // список команд для развертывания проекта 'npm install', 'npm run build', ], }; 

Setup

По указанному пути в конфиге, создает папку releases (в ней хранятся релизы по номерам 1, 2, 3 и тд.) и файл .current.release (в нем хранится номер текущего релиза).
Deploy

Данная команда имеет некую защиту, в одно и тоже время только один человек может производить деплой.

Команда делает следующие действия. Создает временную папку, устанавливает проект, выполняет список ваших команд из конфиг файла (commands) для подтягивания зависимостей и сборки приложения, создает новую релиз папку, переносит туда только что собранный проект, проверяет количество релизов и удаляет старые (сейчас хранится 3 релиза), создает символическую ссылку на текущий релиз (текущий релиз всегда будет доступен по данному пути your-remote-path/current), обновляет файл с цифрой релиза, чистит папки.

Unlock

Удаляет защитный файл, который создается при исполнении команды deploy. Вообще файл удаляется автоматически и даже при обработке ошибок, но на все случае жизни существует данная команда.
Rollback

Возвращает обратно символическую ссылку на предыдущий релиз и удаляет текущий.

P.S. У нас еще есть идеи по развитию этого инструмента, вы также можете поучаствовать в развитии проекта, создавая/делая задачи здесь.

Пусть deployment каждого разработчика станет удобнее и быстрее.

Как правильно выстроить разработку и деплой сайта? — Хабр Q&A

Хьюстон, у нас проблемы. Проблема номер один - я не пользовался системами контроля версий до 2019 года. Собственно, из нее вытекает и набор других проблем, породивших этот вопрос. Суть в чем - я пытаюсь в голове разложить процесс "правильной" разработки вебсайта, чтоб все как у людей - с нормальным версионированием, непрерывной интеграцией и максимальной автоматизацией. Но не очень понимаю стек инструментов, которыми это все можно и нужно рулить.
Если позволите, покажу весь масштаб проблемы на примере небольшого пет-проекта.
Проект - вебсайт на php/Laravel + vuejs + mysql + небольшой набор всяких bash-скриптов.

Как сейчас происходит разработка: случайно и чудом.
1. Собсно, пишу код. Коммичу в dev-ветку все, что плохо лежит (все то, что laravel по умолчанию не выпилил из-под гита)
2. dev-ветку ручками делаю clone на тестовый сервак (локальная машина с окружением, сходным с prod-сервером) в отдельный каталог (не в тот, который рут для сайта)
3. Собираю composer'ом и npm'ом back и front
4. Перемещаю собранный готовый проект в рут-папку сайта
5. Плачу от отсутствия тестов (знаю, что надо, но не понимаю, что нужно тестировать и как)
6. Руками гоняю (гусары, молчать) возможные состояния основных добавленных функций.
7. Если все проходит хорошо, то сливаю ветку с мастером и повторяю процедуру уже с прод-сервером

После нескольких мануалов по unit-тестированию, selenium ide, git, svn и всяких жутких вещах вроде CD\CI (конкретно читал про TeamCity) в голове каша. Мозгом понимаю, что каждый из этапов можно делать лучше. Но какой стороны подойти - хз. Так что, комрады, очень надеюсь на помощь по нескольким вопросам.

1. Разработка.
Стараюсь делать хорошо. После многих лет попыток делать хоть как-то, но быстро - не всегда получается, но потихоньку идет. Паттерны, рефакторинг - уже не просто пустой звук.
Для laravel рекомендуют наращивать функционал пакетами. Собственно, так и делаю. Не уверен, что это можно назвать пакетами, но делаю. Имеет ли смысл такой подход, когда в проекте, предположим, используется разный функционал, который не связан друг с другом? (например, магазин - один пакет, оповещения - другой пакет). Или, может, наоборот, стоит разбивать на более мелкие элементы (типа не отдельный пакет магазина, а поделить на Корзину/Склад/Доставку и т.п.)?

2. Тестирование.
Читал про TDD, пробовал делать - понравилось. Не слишком понравилось, ибо голова так думать не привыкла, но зашло. Возник вопрос - что именно надо тестировать и как выбрать набор тестов? Я всегда ориентировался на 3 варианта использования любого функционала - ожидаемый правильный, ожидаемый неправильный и неожиданный неправильный. Не уверен, что это верно, т.к. это просто выбор пальцем в небо. Если знаете, где почитать/послушать про это дело, буду весьма признателен за информацию.

Опять же, тестировать отдельно фронт и бэк - кажется очень странным. Например, на написание функционала формы для отправки файлов можно уложить в 5-10 минут, но как покрыть ее тестами? Стоит ли вообще? Если правильно понимаю, то на бэке надо тестировать ожидаемый результат (открытие страницы с формой + обработка запроса с файлом + обработка файла) + на фронте тоже есть, чем заняться (отображение страницы в браузерах на разных разрешениях, прикрепление файла, вывод результатов отправки файла). Скорее всего я не совсем понимаю этого, но пока что мне кажется такое поведение слегка безумным (десяток тестов на одну функцию).

3. Контроль версий
Продолжение безумия. Освоил простой путь - тупо храню в vcs ветку с результатами разработки. Но, опять же, здравый смысл подсказывает, что при хреновой памяти и перерывах между коммитами в несколько месяцев надо что-то менять. Как минимум, я не уверен, что правильно хранить все пакеты в одним месте. Однако как сделать правильно - не знаю. С одной стороны, можно вообще пакеты хранить в разных репозиториях и при необходимости перебирать только их. С другой - если большинство из них используются только в одном проекте (хотя могут, потенциально, и еще где-нибудь пригодиться), имеет ли смысл делить все настолько? Или это выносить как часть gitflow и каждый пакет будет чисто feature-веткой?

Про БД читал, что имеет смысл хранить лог запросов и спихивать в vcs именно этот лог. Хорошая ли затея в целом? Или есть какие-то более правильные методы (При условии, что субд MySQL)?

4. Деплой.
Читал где-то занимательную фразу типа "прекратите деплоить, делая clone на production". Я бы и рад, да только как и куда копать? Сдается мне, тут должен помочь TeamCity, но пока что я в него как баран на новые ворота.
Предположим, что код написан, тесты на dev пройдены и пришло врем сделать так, чтобы текущая ветка мастера внезапно оказалась на боевом серваке. Как правильно организовать эту самую доставку кода? В какой момент собирать приложение? Тестировать ли сборку на prod-сервере (при условии, что идентичен dev)?

5. Документирование
С docblock в php все более-менее хорошо, тут иногда даже помогает. Читал, что тесты фронтенда можно использовать в качестве документации/пользовательских мануалов. В каком виде лучше хранить документацию и нужна ли она для конечного продукта (предположим, что бэкендом может заниматься некоторый абстрактный разработчик, а на фронте временами и клиент может бывать, который не знает о системе ничего и не отказался бы от мануала по использованию)? Опять же, если это подход из прошлого века - просветите, пожалуйста, по поводу новинок всего этого.

Сине-зеленый деплой / Habr

Я и мои коллеги всегда склоняем своих клиентов полностью автоматизировать процесс деплоя. Автоматизация помогает сократить количество конфликтов и задержек, которые возникают в процессе между "завершением" работы над программой и введением в эксплуатацию. Дэйв Фарли (Dave Farley) и Джез Хамбл (Jez Humble) заканчивают книгу "Непрерывная доставка" (Continuous Delivery) на эту тему. Она основывается на множестве идей, которые в целом связаны с непрерывной интеграцией и подталкивают к возможности быстро пустить софт в работу. Глава о сине-зеленом деплое привлекла мое внимание, потому что это один из малоиспользуемых методов, и я решил кратко его осветить.

Одна из задач автоматизации деплоя — переход из одного состояния в другое внутри себя же, с переводом софта из финальной стадии тестирования в действующий продакшен. Обычно это нужно сделать быстро, чтобы минимизировать время простоя. При сине-зеленом подходе у вас есть два продакшена, насколько возможно идентичных. В любое время один из них, допустим синий, активен. При подготовке новой версии софта, вы делаете финальное тестирование в зелёном продакшене. Вы убеждаетесь, что программа в этом продакшене работает и настраиваете роутер так, чтобы все входящие запросы шли в зелёную операционную среду — синяя в режиме ожидания.

Сине-зелёный деплой также даёт вам возможность быстро откатиться до старого состояния: если что-то пойдет не так, переключите роутер обратно на синий продакшен. Но вам всё ещё придётся справляться с пропущенными транзакциями, пока зелёный продакшен активен, и, в зависимости от структуры кода, вы сможете направлять транзакции в оба продакшена, чтобы сохранять синий как резервную копию, при активном зелёном. Или можете перевести приложение в read-only режим, перед синхронизацией, запустить его на время в этом режиме, а потом переключить в режим read-write. Этого может оказаться достаточно, чтобы избавиться от многих нерешенных проблем.

Две среды должны быть полностью самостоятельными, но настолько идентичными, насколько возможно. Иногда это могут быть разные компьютеры, иногда просто две виртуальные машины, запущенные одном (или нескольких) компьютерах. Они также могут быть единой операционной средой, разбитой на обособленные зоны с отдельными IP-адресами.

После того, как зелёный продакшен оказывается в работе, и вы довольны его стабильностью, можете использовать синий как staging, чтобы прогнать его через финальные тесты следующего деплоя. Когда вы будете готовы к следующему релизу, сможете переключаться с зеленого на синий так же как переключались с синего на зелёный. В такой конфигурации и зеленый и синий продакшен регулярно проходят через три состояния — действующее приложение, предыдущую версию (для отката) и staging следующей версии.

Преимущество такого подхода в том, что это тот же самый базовый механизм, который нужен для горячего резервирования (hot-standby). Он позволит вам тестировать процедуру аварийного восстановления при каждом релизе. (Надеюсь, что вы релизите чаще, чем у вас происходит аварийное восстановление).

Основная идея в том, чтобы иметь две легко переключаемых среды, а способов изменять детали — множество. Один вариант — делать переключение перезапуском веб-сервера, а не через роутер. Другой — использовать единую базу данных, а сине-зеленые переключения делать для веба и прикладного уровня.

С базами данных при таком подходе часто бывают проблемы, особенно если вам нужно менять их логические структуры для поддержки новой версии софта. Хитрость тут в том, чтобы разделить деплой изменения логических структур и обновление приложения. Для этого сначала нужно применить рефакторинг базы данных, чтобы изменить структуры для поддержки новой и старой версий приложения, задеплоить эти изменения, проверить, что всё хорошо работает, и у вас есть версия предыдущего состояния, и только потом задеплоить новую версию приложения. (А когда обновления уже устаканились, удалить поддержку базы данных для старой версии).

Этот подход существует уже давно, но я не вижу, чтобы его часто использовали. А должны. Название придумали Дан Норс (Dan North) и Джез Хамбл (Jez Humble).

(Перевод Наталии Басс)

Простой и безопасный способ автоматизации канареечных деплоев с помощью Helm

Канареечный деплой — это очень эффективный способ тестирования нового кода на каком-то подмножестве пользователей. Он значительно снижает трафик-нагрузку, с которой могут возникнуть проблемы в процессе развертывания, так как происходит только в пределах определенной подгруппы. Эта заметка посвящена тому, как организовать подобный деплой средствами Kubernetes и автоматизации деплоя. Предполагается, что вы кое-что знаете о Helm и ресурсах Kubernetes.

Простой канареечный деплой в Kubernetes включает в себя два ключевых ресурса: сам сервис и инструмент развертывания. Канареечный деплой работает через одну службу, которая взаимодействует с двумя разными ресурсами, обслуживающими трафик обновления. Один из этих ресурсов будет работать с «канареечной» версией, а второй — со стабильной. В этой ситуации мы можем регулировать количество канареечных версий для того, чтобы снизить объем необходимого к обслуживанию трафика. Если, к примеру, вы предпочитаете использовать Yaml, то выглядеть в Kubernetes это будет следующим образом:

kind: Deployment metadata: name: app-canary labels: app: app spec: replicas: 1 ... image: myapp:canary --- kind: Deployment metadata: name: app labels: app: app spec: replicas: 5 ... image: myapp:stable --- kind: Service selector: app: app # Selector will route traffic to both deployments.

Еще проще представить такой вариант можно на kubectl, а в документации по Kubernetes даже есть полноценный туториал по этому сценарий. Но главный вопрос этого поста заключается в том, как мы собираемся автоматизировать этот процесс, используя Helm.

Автоматизация канареечного деплоя


Прежде всего нам понадобится карта чартов Helm, в которую уже внесены обсуждаемые нами выше ресурсы. Выглядеть она должна быть примерно так:
~/charts/app ├── Chart.yaml ├── README.md ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ └── service.yaml └── values.yaml

Основа концепции Helm — управление мультиверсиями релизов. Stable-версия — это наша основная стабильная ветка кода проекта. Но с помощью Helm мы можем развернуть канареечный релиз с нашим экспериментальным кодом. Главное — сохранить обмен трафиком между стабильной версией и канареечным релизом. Управлять всем этим мы будем с помощью специального селектора:
selector: app.kubernetes.io/name: myapp

Наши как «канареечные», так и stable-ресурсы деплоя будут указывать эту метку на модулях. Если все настроить правильно, то во время деплоя канареечной версии нашей карты чартов Helm мы увидим, что трафик будет направляться на свежеразвернутые модули. Стабильная версия этой команды будет выглядеть так:
helm upgrade --install myapp \ --namespace default \ --set app.name=myapp \ # Goes into app.kubernetes.io/name --set app.version=v1 \ # Goes into app.kubernetes.io/version --set image.tag=stable \ --set replicaCount=5

Теперь давайте проверим наш канареечный релиз. Чтобы задеплоить канареечную версию, нам надо помнить о двух вещах. Название релиза должно отличаться, чтобы мы не накатили апдейт на текущую stable-версию. Версия и тег также должны отличаться, чтобы мы могли развернуть другой код и определить различия по меткам ресурсов.
helm upgrade --install myapp-canary \ --namespace default \ --set app.name=myapp \ # Goes into app.kubernetes.io/name --set app.version=v2 \ # Goes into app.kubernetes.io/version --set image.tag=canary \ --set replicaCount=1

Вот, собственно, и все! Если пингануть службу, то можно увидеть, что канареечное обновление маршрутизирует трафик только часть времени.

Если вы ищите инструменты автоматизации деплоя, которые включают в себя описанную логику, то обратите внимание на Deliverybot и на инструменты автоматизации Helm на GitHub. Чарты Helm, используемые для реализации описанного выше способа лежат на Github, вот тут. Вообще, это был теоретический обзор того, как реализовать автоматизацию деплоя канареечных версий на практике, с конкретными концепциями и примерами.

Capifony. Или деплоим symfony проект через Capistrano / Habr

Я уже год программирую на PHP с использованием symfony framework и нахожу в этом истинное удовольствие. Однако, есть некоторые процессы разработки сайта, которые данный фрэймворк не полностью покрывает, да и не обязан =)
Одним из таких процессов является деплоймент или разворачивание и обновление проекта на рабочем сервере. Для выполнения подобной рутинной операции было написано множество скриптов и одним из самых популярных является Capistrano. Он чрезвычайно прост в освоении, совершенен функционально и крайне гибок в настройке, однако, из коробки заточен под деплой RoR приложений, для чего собственно и создавался.
Сегодня я постараюсь вам рассказать как использовать Capistrano для деплоймента symfony проектов.

Что такое capify?


Capistrano — ruby библиотека, выполняющая рутину по выкатыванию сайта и предоставляющая гибкие средства для своевременного отката проекта до предыдущей версии (предыдущий деплоймент).
Capistrano путем подключения через SSH оперирует удаленными директориями, создавая новую директорию с актуальным кодом и созданием нужных симлинков. Актуальный код Capistrano может копировать с любой другой машины по SSH серверу, использовать GIT или SVN репозитории. На этом возможности capify не заканчиваются. В принципе, скрипт при должной настройке способен выполнять любой набор unix комманд на любом количестве удаленных систем (к которым у вас есть доступ, естественно). Однако, наибольшее количество скриптов и настроек Capistrano имеет в основном для удаленного развертывания приложений, о котором мы сегодня и говорим.
capify — команда для создания конфига Capistrano

Стандартный процесс деплоймента


Выполнение процесса деплоймента разделено на атомарные операции-задачи (tasks), каждый из которых отвечает за отдельный аспект «выкатки». При этом глобальное выполнение деплоя ведет себя как полноценная транзакция и если хотя бы одна операция не выполняется — весь процесс отменяется, а удаленная файловая система возвращается к состоянию до деплоя.
Основные комманды для capistrano:
  1. capify . — создает в текущей директории файлы для конфигурации доступа к удаленной системе и настройки процесса. Файлы эти:
    1. Capfile — основной скрипт, подтягиваемый коммандой «capify»
    2. config/deploy.rb — настройки процесса, заинклуженные в Capfile. Именно в этот файл необходимо прописывать все наши пути до серверов и настройки перед выполнением следующих комманд

  2. cap deloy:setup — разворачивает на удаленном сервере/серверах (их может быть несколько) файловую структуру для последующих процессов деплоймента
  3. cap deploy — выполняет деплоймент. При этом создается новая директория для проекта, в ней делаются симлинки на общие (shared) ресуры и затем, делается симлинк current на эту директорию, подсовывая web серверу актуальный код
  4. cap rollback — откатываемся до предыдущего деплоймента. При этом удаляется директория с текущей версией (при хардовом роллбэке), а симлинк current перебивается на предыдущую директорию деплоя

Зачем нужен capifony?


Как я уже говорил, capistrano изначально создавался для деплоя RoR приложений и есть некоторые места, которые его (из коробки) привязывают именно к этому фрэймворку. Например, структура и список shared папок у Rails и symfony проектов разные. При деплойменте symfony проекта также необходимо выполнять некоторые таски, такие как symfony plugin:publish-assets для создания симлинков на ассеты из плагинов, symfony cc для сброса кэша и symfony fix-perms для восстановления пермишенов на папки cache и web/uploads.
Для решения всех этих проблем я слегка расширил базовые скрипты деплоймента capistrano, что дало рождение capifony
Скачать скрипт и поучаствовать в его разработке можно тут: http://github.com/everzet/capifony/tree/master.

Использование


Итак, у нас есть проект, который необходимо развернуть на рабочем сервере. Этот проект у нас хранится в удаленном git-репозитории на рабочем сервере (это может быть и не git и хранится код может где угодно, куда есть доступ по SSH и в любом виде, о котором знает Capistrano, а он знает много =) ).
Для начала мы переходим в локальную директорию с проектом, который необходимо залить и удаленный git-репозиторий которого находится на сервере:
  1. В корне мы выполняем комманду capify ., создающую нам Capfile в корне и deploy.rb в config/
  2. Скачиваем файл capifony.rb с гитхаба и кладем его в config/
  3. В конец Capfile дописываем load 'config/capifony'
  4. И последний штрих — прописываем настройки коннекта к удаленному серверу в deploy.rb:
    set :application, "YOUR_APPLICATION_NAME"<br>set :repository, "YOUR_SSH_SERVER_NAME:/PATH/TO/repos/#{application}.git"<br>set :deploy_to,  "/PATH/TO/www/#{application}.com"<br>set :scm,     "git"<br><br>default_run_options[:pty] = true<br>ssh_options[:forward_agent] = true<br><br>server "YOUR_SSH_SERVER_NAME", :web, :app, :db<br><br>* This source code was highlighted with Source Code Highlighter.
  5. Теперь из консоли вызываем cap deploy:setup, чтобы настроить удаленную файловую структуру и cap deploy, чтобы выполнить деплоймент. И не забываем, если что-то вдруг при последующих деплоях идет не так (деплой прошел, но сайт упал, к примеру) — cap rollback поможет

Стоит отметить, что директории log/, web/uploads в деплойменте не участвуют, т.к. являются shared ресурсами, которые сохряняются между деплоями. Поэтому, если вы уже накопили набор файлов под web/uploads, их нужно вручную залить на сервер по адресу /PATH/TO/www/#{application}.com/shared/web/uploads/
Вот и все. Если вам понравилась данная статья — дайте мне знать, возможно в следующий раз я расскажу о другом интересном аспекте разработки вместе с замечательным symfony...

upd: Забыл 1 вещь. По стандарту, когда symfony генерирует проект, она прописывает в config/ProjectConfiguration.class.php абсолютный путь до symfony, который на рабочей машине и продакшене может различаться. Для решения проблемы и на продакшене и на рабочей машине добавляем путь до директории с библиотеками (включая symfony) в include_path (прим.: include_path = ".:/php/includes:/opt/local/lib/php"), а путь в ProjectConfiguration.class.php меняем на относительный require_once 'symfony/autoload/sfCoreAutoload.class.php';

Протухшие деплои - Mad Devs

Как известно, разработчики регулярно деплоят софт.

Помню, как раньше деплой был событием. Все к нему по особому готовились. Предупреждали пользователей. Писали большую доку про новую версию.

Так же помню, как все такие деплои оборачивались регулярными провалами. База фризилась. Юзеры не могли залогиниться. Kernel panic. Непонятно откуда растущий LA. Седеющий админ. Курящий одну за другой сигареты тимлид.

Спустя какое-то время инженеры поняли, что деплоить нужно регулярно, лучше даже после каждого пуша. Помимо этого, деплоить нужно так, чтобы большую часть деплоев юзеры не замечали. У них просто чинится какой то баг и они счастливы. Либо появляется новая фича, которую они, как водится, не замечают, а потом узнают про нее в блоге проекта.

Такая штука называется “Непрерывная поставка ПО”. И мне кажется, что сейчас большая часть веб-ориентированного / микросервисного / облачного софта поставляется именно так. Это стало настолько обычным, что мы буквально за 5–6 лет активного использования непрерывной поставки (ну, ок, почти непрерывной) свыклись с тем, что это единственно правильный способ деплоев.

Недавно мне нужно было обновить одного бота, который стабильно, каждый день, вот уже два года шлет в Слак статистику по сервису. В какой-то момент он начал спотыкаться об один дата сорс и рядом с валидной информацией были HTTP 404. Я подумал, что могу просто закомментировать один вызов и ничего не сломается.

Отыскал репозиторий, открыл код. Начал вспоминать что там есть. Даже прогнал тесты и они прошли. Все очень позитивно. Закомментировал ненужный мне вызов и собрался деплоить.

И тут случилось интересное. Я где-то на подкорке, где-то глубоко внутри, начал чувствовать странный запах. Вот бывает, смотришь на код и он плохо пахнет (это значит, что его трудно читать, а следовательно, и поддерживать). А тут готовишься деплоить и понимаешь, что деплой протухший. Понимаете? Колбаса есть, а жрать ее страшно. Чувствуете? Вроде масло сливочное стояло в морозильнике, а через пол года вытащил и на хлеб намазывать не хочется.

Устоявшееся понятие Code Smell можно было и применить к этому случаю, назвав его Deploy Smell. Но я бы назвал Deploy Smell тот деплой, который свежий, но воняет. То есть просто криво сделан, но софт деплоят регулярно. В нашем же случае сам акт поставки достаточно адекватен, просто он прогнил от долгого не использования.

Предлагаю вводить понятие “протухший деплой” или Addled Deploy. Это ситуация, когда нужно перестраховаться перед тем деплоем, который долго не производился. Ситуация, когда все-таки делаешь тухлый деплой и не страхуешься будет называться “тухлить”.

Например, можно не тухлить днем пятницы, а сделать это в понедельник утром, когда все девопсы напились кофе и никуда не собираются уходить. А это значит, что они смогут помочь откатить деплой, если все развалится.

Addled deploy situation. Так можно озаглавить ворклог, в котором разработчики опишут все то, что им пришлось пережить после тухлого деплоя в продакшен.

UPDATE от Vadim Glebov:

Знакомая ситуация. У меня в проекте пока не CD, поставки в бой раз в 2 недели, поставка полуавтоматическая (админ запускает скрипты из пакета поставки вручную и смотрит на выхлоп). Но чтобы деплой не протухал интеграционка крутит поставку на демо 3 раза в день в автоматическом режиме. При таком подходе реальный деплой в продакшен проходит без проблем. Потому что я успеваю обнаруживать проблемы с поставкой рано и сразу их устранять. Короче чтоб деплой не протухал крути его, хотя бы в тестовом режиме.

Деплой Ruby on Rails приложения в Docker при помощи Mina / Habr

Введение


Данное руководство в первую очередь предназначено для новичков, которые хотят научиться азам деплоя и ознакомиться в общих чертах с алгоритмом работы над удаленной unix системой локально, в качестве удаленного сервера мы будем использовать образ Ubuntu запущенный в Docker.

Итак, что же такое Mina? Это инструмент для деплоя и автоматизации выполнения операций на удаленном сервере.Преимущество этого решения, в первую очередь, заключается в быстроте выполнения. Mina работает очень быстро, поскольку деплоит bash скрипт, который генерируется на удаленном сервере из вашего deploy.rb файла и в последствии выполняется.

Capistrano, к примеру, выполняет каждую команду отдельно, в своей ssh сессии, и поэтому уступает по скорости в разы, mina выполняет все в одном bash скрипте, который требует только одну сессию.

Требования


В этом руководстве, предполагается, что вы используете Ubuntu и у вас уже установлено следующее программное обеспечение:

Подготовка Rails приложения


Я не буду рассматривать подробно шаги создания Rails приложения, поскольку самым лучшим вариантом будет наличие у вас своего приложения, которое вы хотели бы задеплоить. Либо вы можете воспользоваться тестовым примером github.com/rails-guides/mina-deploy-example

Установка SSH / Rbenv / Ruby & Rails


Итак, у вас установлен Docker и имеется образ Ubuntu. Если все сделано верно, то при вызове команды docker images вы должны увидеть следующую информацию:
root@root:~$ docker images | grep ubuntu ubuntu latest 0ef2e08ed3fa 6 weeks ago 130MB 

Запускаем данную последовательность операций в консоли:
docker run -d -it -p 2222:22 ubuntu:16.04 docker ps //Скопируйте container_id docker attach container_id 

Первая команда запустит образ Ubuntu в фоновом режиме и открытым портом для ssh подключения. Далее мы подключаемся к системе через attach с использованием уникального идентификатора контейнера.

После того, как вы вошли в систему под пользователем root, вам необходимо получить последние обновления, установить ssh-сервер и запустить его.

apt-get update apt-get install openssh-server service ssh start 

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

Система попросит заполнить вас некоторые данные (first_name и т.д), эти шаги можно пропустить. В качестве пароля используйте 123. Далее подключаемся по ssh чтобы удостовериться, что все сделано правильно.
ssh -p 2222 [email protected] 

! Если у вас появится предупреждение `WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED`
Выполните удаление ключей из файла known_host с указанным сокетом (0.0.0.0:2222).
ssh-keygen -f "/home/USER/.ssh/known_hosts" -R [0.0.0.0]:2222 

После этого переподключитесь еще раз и вы увидите следующее:
deployer@e2cad98fb69d:~$ 

SSH работает, отлично! Вернемся к нашему пользователю root, нам все еще необходимо установить rbenv / ruby / rails. В первую очередь нам потребуется git для установки rbenv.
apt-get install git 

Проследуйте шагам описанным в официальной документации для установки.
github.com/rbenv/rbenv#installation

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

apt-get install bzip2 apt-get install -y libssl-dev libreadline-dev zlib1g-dev apt-get install build-essential 

Мне понадобится ruby версии 2.3.1 и RoR 4.2.7.1. Не забудьте определить вашу Ruby версию глобально.
rbenv install -v 2.3.1 rbenv global 2.3.1 gem install rails -v 4.2.7.1 

Установка Postgres / Nginx

apt-get install postgresql postgresql-contrib service postgresql start 

Определим пароль для пользователя postgres (все тот же 123)
su - postgres psql \password create database mina_deploy_example; //заранее создадим базу данных 

Nginx — веб-сервер и почтовый прокси-сервер, работающий на Unix-подобных операционных системах.
apt-get install nginx 

После установки измените конфигурационный файл на нижеследующий.
nano /etc/nginx/sites-available/default 
upstream mysite { server unix:///home/deployer/mina-deploy-example/shared/tmp/sockets/puma.sock fail_timeout=0; } server { listen 80; listen [::]:80; root /home/deployer/mina-deploy-example/current/public; location ~ ^/assets/ { expires max; gzip_static on; gzip_vary on; add_header Cache-Control public; break; } location ~ ^/system/ { expires max; gzip_static on; gzip_vary on; add_header Cache-Control public; break; } location / { proxy_pass http://mysite; # match the name of upstream directive which is defined above proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location ~ ^/(500|404|422).html { root /home/deployer/mina-deploy-example/current/public; } error_page 500 502 503 504 /500.html; error_page 404 /404.html; error_page 422 /422.html; client_max_body_size 4G; keepalive_timeout 10; } 

Настройка git репозитория


Для деплоя через mina вам необходимо создать репозиторий на github, настроить git пользователя, сгенерировать ssh ключ и добавить его в ваш репозиторий. Для примера я буду использовать github
ssh -p 2222 [email protected] git config --global user.name "Some User" git config --global user.email "[email protected]" ssh-keygen -t rsa -b 4096 -C "[email protected]" ssh -T [email protected] 

Скопируйте публичный ключ
cat ~/.ssh/id_rsa.pub 

Переходим на github → ваш репозиторий → settings → слева выбираем Deploy keys → жмем Add deploy key и вставляем скопированное значение.

Deploy при помощи mina


Переходим в директорию проекта, добавляем в Gemfile
gem 'mina' gem 'mina-puma', require: false gem 'mina-nginx', require: false 

В папке config создайте файл deploy.rb, он будет использоваться mina при деплое приложения. Файл конфигурации состоит из нескольких основных частей.
require 'mina/bundler' require 'mina/rails' require 'mina/git' require 'mina/rbenv' require 'mina/nginx' require 'mina/puma' set :application_name, 'mina-deploy-example' set :domain, '127.0.0.1' set :port, '2222' set :user, 'deployer' set :shared_dirs, fetch(:shared_dirs, []).push('tmp', 'log', 'public/uploads', 'public/system') set :shared_files, fetch(:shared_files, []).push('config/puma.rb', 'config/database.yml', 'config/secrets.yml') set :deploy_to, '/home/deployer/mina-deploy-example' set :repository, '[email protected]:rails-guides/mina-deploy-example.git' set :branch, 'master' set :rails_env, 'production' 

В верхней части мы подключаем зависимости, устанавливаем домен приложения, порт и пользователя через которого будет создаваться bash скрипт и идти выполнение команд. На файлы и директории объвленные в shared_dirs и shared_files будет создана символическая ссылка.

Данная часть определяет команды, которые будут выполненны при вызове mina setup.

task :environment do invoke :'rbenv:load' end task setup: :environment do command %{mkdir -p "#{fetch(:shared_path)}/log"} command %{chmod g+rx,u+rwx "#{fetch(:shared_path)}/log"} command %{mkdir -p "#{fetch(:shared_path)}/config"} command %{chmod g+rx,u+rwx "#{fetch(:shared_path)}/config"} command %{touch "#{fetch(:shared_path)}/config/puma.rb"} command %{touch "#{fetch(:shared_path)}/config/database.yml"} command %{touch "#{fetch(:shared_path)}/config/secrets.yml"} command %{mkdir -p "#{fetch(:shared_path)}/tmp/sockets"} command %{chmod g+rx,u+rwx "#{fetch(:shared_path)}/tmp/sockets"} command %{mkdir -p "#{fetch(:shared_path)}/tmp/pids"} command %{chmod g+rx,u+rwx "#{fetch(:shared_path)}/tmp/pids"} end 

И основная часть, то, что будет выполняться каждый раз при деплое приложения.
task deploy: :environment do deploy do invoke :'git:clone' invoke :'deploy:link_shared_paths' on :build do invoke :'bundle:install' invoke :'rails:db_migrate' invoke :'rails:assets_precompile' invoke :'deploy:cleanup' end on :launch do invoke :'puma:restart' end end end 

В директории проекта, в папке config, вам необходимо создать файл puma.rb.
directory '/home/deployer/mina-deploy-example/current' rackup '/home/deployer/mina-deploy-example/current/config.ru' environment 'production' daemonize true pidfile '/home/deployer/mina-deploy-example/shared/tmp/pids/puma.pid' state_path '/home/deployer/mina-deploy-example/shared/tmp/sockets/puma.state' bind 'unix:///home/deployer/mina-deploy-example/shared/tmp/sockets/puma.sock' activate_control_app 'unix:///home/deployer/mina-deployexample/shared/tmp/sockets/pumactl.sock' 

Данный конфиг позволяет запустить сервер в фоновом режим и production окружении привязывая сервер к unix сокету. Хорошее объяснение команд для настройки puma вы можете найти в этом репозитории и официальной документации github.com/puma/puma/blob/master/examples/config.rb.

Создайте database.yml и secrets.yml в папке /home/deployer/mina-deploy-example/shared/config

production: host: localhost database: mina_deploy_example adapter: postgresql encoding: unicode username: postgres password: 123 
production: secret_key_base: SECRET_KEY_BASE 

Для того, чтобы не смотреть на то, как ваш bundler постоянно ругается на то, что у вас отсутствуют определенные зависимости, установите следующие гемы и библиотеки:
gem install bundler apt-get install ruby-dev gem install json -v '1.8.6' gem install pg -v '0.20.0' apt-get install postgresql postgresql-contrib libpq-dev gem install uglifier apt-get install nodejs apt-get install imagemagick 

Далее деплоим приложение и запускаем puma
mina deploy mina puma:start 

Прокидываем ssh тонель на порт nginx’a
sudo ssh -f -N -L 80:localhost:80 [email protected] -p 2222 

При переходе по адресу http://localhost:80 вы увидите надпись New article. Если все шаги выполнены верно, то при создании новых статей и добавлении изображений все будет корректно отображаться.

боль и страдания или простая рутина? / Habr

Коротко для тех, кто спешит


Утилита FTP Deployment: написана на php, принимает в качестве параметра путь к конфигу и выкладывает файлы на удаленный сервер, довольно быстро и хорошо.

Долго и подробно для тех, кому интересно


Все мы любим классные и удобные методы деплоя с помощью capistrano, rsync или, на худой конец, git pull. А если надо выкладывать проекты на shared-хостинг?

Да, некоторые провайдеры предоставляют ssh и git. Но, прямо скажу, их немного.

Однажды я вдруг понял, что привык к хорошему, и ненавижу выкладывать проекты через (S)FTP: не залился какой-то файл; надо вспомнить, где лежат конфиги; вот эту папку не надо выкладывать вообще; вот тут надо проверить права. Думаю, многие этот список легко продолжат.

Тут еще надо сказать, что я с большим удовольствием пользуюсь символическими ссылками для минимизации места (и автоматической актуализации кода). Небольшой shell-скрипт создает контекст нового проекта, в котором уже есть библиотеки, ядро, статика и docroot с htaccess. Мне остается положить правильные конфиги и настроить всё “под клиента”.

В старые времена всё это я делал на своей локальной системе, а потом с помощью FileZilla или GnomeCommander заливал на хостинг. Сейчас перешел на небольшой выделенный сервер, и пришлось искать решение. Хотелось готовое и простое — и я его нашел!

С помощью FTP Deployment выкладка из долгого муторного занятия превращается в одну команду. Ну, на самом деле, в две — тестовый запуск никто не отменял:).

Первый этап: в папку проекта (или в любое удобное место) нужно поместить конфиг утилиты. Ini или php — на ваш выбор. Позволю себе перевести на русский комментарии в примере.

[my site] ; Может быть несколько секций
; удаленный FTP-сервер
remote = ftp://user:[email protected]/directory

; пассивный режим FTP
passiveMode = yes

; локальный путь (опционально, но я обычно указывают абсолютный путь вроде /var/www/production/project_path/)
local = .

; тестовый режим? (можно включить опцией -t или --test)
test = no

; Список игнорируемых файлов и каталогов
ignore = "
.git*
project.pp[jx]
/deployment.*
/log
temp/*
!temp/.htaccess
"
; Удалять файлы на сервере? (по умолчанию -- да)
allowDelete = yes

; скрипты, которые надо запустить до загрузки
before[] = http://example.com/deployment.php?before

; скрипты, которые надо запустить после загрузки
afterUpload[] = http://example.com/deployment.php?afterUpload

; скрипты, которые будут запущены в конце
after[] = http://example.com/deployment.php?after

; каталоги, которые надо очистить после загрузки
purge[] = temp/cache

; файлы для предобработки (по умолчанию -- *.js *.css)
preprocess = no

; Файл, в котором будут контрольные суммы загруженных файлов
deploymentFile = .deployment

В общем-то, всё достаточно очевидно и понятно. Readme проясняет некоторые неясности.

Например, в игнорируемых файлах pp[jx] — означает и ppj и ppx. Восклицательный знак — исключение из предыдущей строчки. В примере — всё, что находится в temp мы не загружаем. Но папку создаем и temp/.htaccess в нее загружаем.

И, наконец, про препроцессор. Утилита может сжимать css с помощью YUI Compressor, а js — с помощью Google Closure Compiler. Оба инструмента в дистрибутиве, но требуют Java.

Когда конфиг готов, можно провести тестовый запуск.

php deployment.php deployment.ini -t 

Утилита расскажет, что она собирается делать и с какими файлами. Если вы сомневаетесь в списке игнорируемого — самое то.

Если всё хорошо — можно деплоиться:

php deployment.php deployment.ini 

Поначалу внимательно читайте, что вам напишет тестовый запуск. По очевидным причинам нельзя закачивать на сервер ftp-deployment.ini. Ну, и вообще, у кого-то и config.php.bak в проектах болтается…

Мне утилита очень понравилась, с удовольствием пользуюсь и друзьям советую. Если знаете удобные альтернативы на других языках — буду благодарен.


Смотрите также