Создание production-сервера c Ansible

Автоматизация серверной инфраструктуры. Автоматическая установка Docker и Compose на виртуальную машину через Ansible. Подключение сертификатов Let's Encrypt.

  • 00:00:54 Ручная установка виртуальной машины
  • 00:03:10 Автоматизация через скрипты
  • 00:04:35 Проблема мутабельной инфраструктуры
  • 00:05:44 Установка нужного состояния
  • 00:07:19 Декларативное описание состояния
  • 00:11:01 Обзор Ansible
  • 00:13:35 Написание плейбука
  • 00:15:35 Установка Docker через Ansible
  • 00:20:20 Разделение на файлы задач
  • 00:20:52 Установка Certbot
  • 00:22:57 Получение Let's Encrypt сертификатов
  • 00:26:41 Условия и циклы в Ansible
  • 00:30:39 Ручная перегенерация сертификатов
  • 00:31:22 Файлы для переменных
  • 00:32:04 Создание пользователя для деплоя
  • 00:33:57 Пробрасывание SSH-ключа
  • 00:35:06 Логин в Docker-реестр
  • 00:37:01 Плагин для работы с Docker
  • 00:37:33 Использование ролей для разных машин
  • 00:43:05 Makefile для запуска
  • 00:43:42 Запуск на реальной машине
  • 00:48:50 Деплой сайта на виртуалку
  • 00:50:45 Перезапуск Nginx при обновлении сертификатов
  • 00:52:12 Обзор результата и выводы

Позже в 61-ом эпизоде мы рассмотрим, как для выпуска сертификатов вместо нашего gateway использовать прокси-сервер Traefik.

Скрытый контент (код, слайды, ...) для подписчиков. Открыть →
Дмитрий Елисеев
elisdn.ru
Комментарии (229)
Arunas

спасибо, очень поможет, очень хорошый урок.

Ответить
Руслан

Отличный эпизод, как всегда. Огромная просьба рассмотреть возможность добавить в материалы настройку Github Actions для CI/CD.

PS: интересует также, имеются ли в Ваших курсах материалы по опыту правильной организации multi-tenant архитектуры на любом из фреймовоков? Либо в планах на будущее)

Спасибо еще раз за супер курс!

Ответить
Ruslan

Тёзка, там заявлен Дженкинс. Видел на Ютубе CI/CD для Битбакета и для ГитЛаба тоже наверняка найдется.

Ответить
Руслан

Руслан, спасибо, конечно, видел то что Jenkins заявлен. Просто Github Actions видется более перспективней в плане популярности в ближайшие время, хотелось на него перескочить в плане self-hosted CI/CD, не ставить на сервак java (Jenkins) или ruby (Gitlab CI).

Ответить
Ruslan

А что с приватными репами, только за деньги, как и на самом Github ?

А вообщем, я о том, что нужно придерживаться плана. Я тоже могу написать, что сейчас большой downtime и давайте поднимем кластер для CI/CD без downtime.

Какие-то такие дополнения можно сделать в самом конце когда станет известно как делать: "Разработка аукциона на Slim и ReactJS" :)

Ответить
Paul

Мощно!

Ответить
Алекс Про

Снимайте, пожалуйста, видео на чёрной теме IDE!!!

Ответить
Дмитрий Елисеев

Приведите пример видео с YouTube с красивой тёмной темой.

Ответить
Дмитрий Елисеев

Эта нечёткая (пыльная)

Ответить
Иван

Тема: ayu, темная подтема: mirage

Ответить
Дмитрий Елисеев

Это для Visual Studio. Есть форк для PhpStorm?

Ответить
Иван

Visual Studio Code, если быть точным, но и это частность - тема не принадлежит одной какой-то сущности.

Для Sublime Text 3 - есть точно, для PhpStorm - не знаю, должна быть.

Тема мощная и крутая, очень досадно будет, если не портирована.

Ответить
Алексей

Все отлично. Но, хотелось бы краем глаза глянуть как вы настраивали реестр для докера. Сама установка вроде бы элементарна.

docker run --entrypoint ./auth/htpasswd registry:2 -Bbn registry passwd > ./auth/htpasswd

docker-compose.yml

version: "3.7" services:

registry:
    restart: always
    image: registry:2
    ports:
        - 5000:5000
    environment:
        REGISTRY_HTTP_TLS_CERTIFICATE: /certs/example.com.crt
        REGISTRY_HTTP_TLS_KEY: /certs/example.com.key
        REGISTRY_AUTH: htpasswd
        REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
        REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
    volumes:
        - ./registry:/var/lib/registry
        - ./auth:/auth
        - /etc/letsencrypt/live/example.com:/certs

Но с сертификатами у меня получился жуткий костыль. Из коробки докер с letsencrypt не заработал, хотя в документации пишут, что должен. Или, может, дело в версии убунты? У меня 16.04

Ответить
Дмитрий Елисеев

Просто можно как с gateway закрыть сертификатами и htpasswd снаружи в Nginx:

version: '3'
services:
    nginx:
        image: nginx:alpine
        restart: always
        ports:
            - "80:80"
            - "443:443"
        volumes:
            - /etc/letsencrypt:/etc/letsencrypt
            - /var/www/html:/var/www/html
            - ./docker/nginx/conf.d:/etc/nginx/conf.d
            - ./htpasswd:/etc/nginx/auth/htpasswd
        depends_on:
            - registry
    registry:
        image: registry:2
        restart: always
        volumes:
            - registry:/var/lib/registry
volumes:
    registry:
Ответить
Роман
  • ./docker/nginx/conf.d:/etc/nginx/conf.d

А в этом случае прокидываемый конфиг в контейнер как будет выглядеть? Самый базовый с ssl сниппетами и auth_basic_user_file /path/to/.htpasswd; в главном локейшене для nginx на домен registry.domain.com, к примеру, верно?

Ответить
Дмитрий Елисеев

Да, примитивный с секцией server как приведённый в документации к registry, только переделанный для Let's Encrypt.

Ответить
Роман

Спасибо!

Ответить
drakulitka

Было бы не плохо, если бы в одном уроке настройку registry сервера показали на этой же виртуалке, чтобы охватить все технологии, которые используется, мне было бы очень полезно ))

Ответить
Роман

Дмитрий, я правильно понимаю что ваш кейс с оркестрацией сервера подразумевает абсолютно голый сервер? Если на удаленной машине, на которой я хочу поднять образы из реестра, уже стоит nginx и слушает 80 и 443 порты, то в этом случае не получится проброска этих портов для gateway в docker-compose-production и, как следствие образы не поднимутся. Завелось вместе с ssl только тогда, когда я сделал проброс незанятого порта, к примеру 5001 на 443 ("5001":"443", в докер композ прод), но для этого приходится добавлять порт на продакшене в строке браузера, для того чтобы происходило перенаправление в обработку докера на 443 порт. Хотел узнать, может есть какой-то лайфхак, чтобы разрулить эту ситуацию на уровне конфигов nginx, хотя пробовал разные варианты. Просто не хочется добавлять все время порт в строке браузера

Ответить
Дмитрий Елисеев

Да, на сервере можно поднять только один Nginx на одном порту. Поэтому если уже стоит внешний Nginx, то можно в него добавить хост с proxy_pass localhost:5001

Ответить
Александр Кулик

Курс супер. Но зачем так заморачиваться с сертификатами, если можно использовать Treafik. Он все это умеет из коробки.

Ответить
Руслан

Александр, интересуют подробности других преимуществ Traefik vs nginx / haproxy etc. (кроме сертификатов) и опыт оптимальной установки/настройки?

Ответить
Александр Кулик

Я только осваиваю. Но он много чего умеет. Про haroxy не слышал.

Ответить
Руслан

Насколько понимаю, чтобы разобраться как обойтись средствами уже задействованного nginx, чем вводить дополнительный слой либо отдавать предпочтение одному из многих специализированных прокси-серверов/балансировщиков, уже заточенных под микросервисы и k8s (traefik, haproxy, envoy, kong и пр.). Последние конечно удобны разными плюшками из коробки, но на них можно будет легко мигрировать при необходимости и от нужд в этих плюшках конкретного проекта.

Ответить
Дмитрий Елисеев

UPD 1: В Cron-задаче очистки Docker нужно добавить флаг "a":

docker system prune -af --filter "until=$((30*24))h"
Ответить
Ruslan

А в эту чистку используемые контейнеры попадают, ведь проект может быть и год без изменений? Или это очищает только элементы из которых собирается наш контейнер?

Ответить
Дмитрий Елисеев
$ docker system prune -a

This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all images without at least one container associated to them
  - all build cache
Ответить
Sergei

ничего_не_понял_но_очень_интересно.jpg

Ответить
drakulitka

Буду переходить на vscale.io

Ответить
Сарибжанов Ильдар

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

Мы же сейчас говорим про разработчиков, которые разворачивание окружения производят раз в несколько месяцев, а то и реже. Что скрипт отдельный писать, что мануалы использовать итог один - всё равно придётся актуализировать скрипт под нужды. К тому же сам алгоритм инсталяции может поменяться, например, добавятся зависимости или платформа поменяется. Например, докер переедет go на rust и потребуется отдельно доставлять раст. А по итогу, чтобы починить свой шел придётся лезть в мануалы.

Я не говорю, что представленный материал не нужен, но я бы «продавал» его с позиции управления сложностью: производим декомпозицию алгоритма разворачивания сервера и уход от низкоуровневых абстракций (общение с терминалом) к высокому уровню - ансибл.

Спасибо за материал =)

Ответить
Дмитрий Елисеев

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

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

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

Так что как только виртуалок и программистов становится много, то автоматизация во всём очень помогает. И пусть все сисадмины тоже коммитят в tasks.yml.

Ответить
Руслан

Подскажите, доступа к root нет, использую в качестве remote_user пользователя,

remote_user: deploy become: yes become_user: deploy

Пишет ошибку: Failed to lock apt for exclusive operation

Подскажите, как настроить без root доступа?

Ответить
Дмитрий Елисеев

Задачи с apt запускайте только от root (через become без become_user).

Ответить
Arunas

после успешного make site, в кроне хостинга (в /etc/cron.d/certbot) введётся команда "...certbot -q renew". Но как реально автоматом происходит certbot renew, если gateway (nginx) работает в докере, а сертификат продлен снаружи? как в этой ситуации, происходит автоматическое продление сертификата?

Ответить
Дмитрий Елисеев

Как упомянули после деплоя, в cli.ini вместо хука service nginx restart нужно вписать перезапуск gateway вроде такого:

post-hook = /bin/sh -c 'cd /home/deploy/site && docker-compose restart gateway'
Ответить
Дмитрий Елисеев

Например, в site/tasks добавить задачу добавления строки:

-   name: Add Certbot hook
    lineinfile:
        path: /etc/letsencrypt/cli.ini
        line: "post-hook = /bin/sh -c 'cd /home/deploy/site && docker-compose restart gateway'"
Ответить
Arunas

в чем разница между этими вариантами? Ведь, в первом варианте, когда в provisioning/roles/certbot/files/cli.ini записываем renew-hook = /bin/sh -c 'cd /home/deploy/site && docker-compose restart gateway' , то при make site этот cli.ini пападает в /etc/letsencrypt/cli.ini (VM Debian у хостинга).

Ответить
Arunas

у demo-auction.skucai.com деплоил (18-01-2020) проект, по первому варианту, и подожду 32 дней, посмотрю, продлится сертификат или нет.

Ответить
Arunas

А как проверит cron: правильно введена команда? Теперь, после успешного деплое, в VM Debian /etc/cron.d/certbot есть такая: 0 /12 * root test -x /usr/bin/certbot -a ! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew . А с crontab -e видно: 0 1 * docker system prune -af --filter "until=$((3024))h"

Ответить
Дмитрий Елисеев

Разница в том, что роль certbot будет общая для всех production и staging серверов. Им может быть нужен разный хук и одинаковый cli.ini может всем не подойти. Поэтому можно всем скопировать общий cli.ini без хука, а потом уже в ролях site и staging добавить им по своей строке. Зависит от ситуации.

Ответить
Arunas

спасибо.

Ответить
Ruslan

Я что-то совсем запутался. Registry требует установки перед ним вэбсервера или нет?

version: '3'

services:
  registry:
    image: registry:2
    restart: always
    ports:
      - "5000:5000"
    environment:
      REGISTRY_HTTP_TLS_CERTIFICATE: /certs/live/{{ registry_host }}/cert.pem
      REGISTRY_HTTP_TLS_KEY: /certs/live/{{ registry_host }}/privkey.pem
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/password
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
    volumes:
      - ./auth:/auth
      - ./data:/data
      - /etc/letsencrypt/:/certs:ro

Из этого конфига я подумал, что Registry может сам работать без вэба, но

docker push registry.mydomain.com/auction-gateway:master-1

И видно, что он лезет по https в папку V2 :

Get https://registry.mydomain.com/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
Ответить
Ruslan

На это можно не отвечать. Я уже разобрался. В итоге у меня собралась рабочая среда из: WSL 2, CentOS и docker repository в одном контейнере без вэба впереди. А можно ли в конфигах nginx применять пересенные, чтоб не перебивать названия сайтов "deworker.pro" на свои? В 19и местах пришлось менять руками, так и запутаться можно.

Ответить
Дмитрий Елисеев

Два варианта. Либо запускать его со своими сертификатами TLS_CERTIFICATE и htpasswd без внешнего Nginx, либо реестр запускать без сертификатов, настроив их в дополнительном Nginx.

Ответить
Ruslan

Спасибо.

Мне понравился вариант, когда реро само за себя, если нужно на той же машине использовать вэб, то не нужно учитывать , что 80 и 443 уже используется.

Ответить
Иван

Это тоже для новичков или курилка спецов по devops'у?
Вы не понимаете, что такое объяснение.
Объяснение, это не рассказ.

Ответить
Дмитрий Елисеев

Здесь практика по разработке проекта.
Рассказывать что такое консоль, apt и cron здесь нет смысла.

Ответить
Иван

Понял, спасибо.

Ответить
Роман

https://i.imgur.com/GrKChZd.png

По команде ansible-playbook -i hosts.yml site.yml у меня на удаленной машине (Ubuntu 18.04) произошла ошибка на шаге Add Certbot repository. Видимо он не смог потом сделать apt-get update. Возможно попробовать другой repo: ?

Ответить
Роман
-   name: Add Certbot repository
    apt_repository:
        repo: 'ppa:certbot/certbot'
        state: present
        update_cache: yes

-   name: Install Certbot
    apt:
        name: certbot
        state: present
        update_cache: yes

вот такой вариант прошел, кстати

Ответить
Дмитрий Елисеев

Да, мы уже обсуждали под эпизодом про Xdebug.

Ответить
Дмитрий

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

Ответить
Дмитрий Елисеев

Ещё нужно прописать A-записи с IP-адресом сервера в настройках DNS этих доменов и поддоменов.

Но это уже производится в панели управления регистратора, а не в проекте.

Ответить
Дмитрий

На примере vscale, ip повторяет адрес основного домена? а порт нужно указать?

Ответить
Дмитрий Елисеев

В панели управления регистратора или хостинга проставляем домену и поддомену одинаковую A-запись с одним IP-адресом нашей виртуалки. Или A-запись проставляем тоько домену, а с поддомена ссылаемся на домен через CNAME-запись.

Ответить
Дмитрий

ошибка в таске Add Cert Repository, что тут можно предпринять?

upd: увидел ответ выше

Ответить
Тимур

Дмитрий, привет После выпуска сертификата apache не останавливается (Debian 10) - в связи не получается сделать deploy так как nginx не запускается Иногда при запуске playbook для выпуска сертификата certbot дает ошибку, и после пользователь deploy не создается (в связи с чем не authorize не docker-login не работают). Если create-user раньше вытащить, ничего страшного? И еще: как сделать интерпритатор питона по умолчанию на 3 версию - в логах ловлю сообщения на прекращение поддержки старых версий

Ответить
Дмитрий Елисеев

После выпуска сертификата apache не останавливается

Это со свежим кодом из репозитория с конструкцией wait_for?

Если create-user раньше вытащить, ничего страшного?

Ничего страшного. Можно ставить в любой последовательности. Для игнорирования ошибок можно добавить ignore_errors: true к задаче получения сертификатов.

как сделать интерпритатор питона по умолчанию на 3 версию

Они постепенно переходят и описывают это так.

Ответить
Дмитрий

Столкнулся с проблемой. Если создать пароль nginx.htpasswd с параметром -B то nginx возвращает ошибку 500. Если этот параметр не применять, то всё хорошо. Образ был просто nginx.

Ответить
Дмитрий Елисеев

Да, Nginx не поддерживает этот алгоритм.

Ответить
Дмитрий Елисеев

UPD: Улучшили фрагмент с 26-й минуты про запуск Apache-сервера на использование конструкции wait_for.

Ответить
Александр

Ошибка в make docker-login на шаге [Log into private registry]

fatal: [server]: FAILED! => {"changed": true, "cmd": "docker login -u ** -p *** registry.tiru.ru", "delta": "0:00:00.306697", "end": "2020-03-09 14:13:12.031002", "msg": "non-zero return code", "rc": 1, "start": "2020-03-09 14:13:11.724305", "stderr": "WARNING! Using --password via the CLI is insecure. Use --password-stdin.\nError response from daemon: Get registry.tiru.ru/v2/: dial tcp: lookup registry.tiru.ru on 188.93.16.19:53: no such host", "stderr_lines": ["WARNING! Using --password via the CLI is insecure. Use --password-stdin.", "Error response from daemon: Get registry.tiru.ru/v2/: dial tcp: lookup registry.tiru.ru on 188.93.16.19:53: no such host"], "stdout": "", "stdout_lines": []}

Ответить
Дмитрий Елисеев

Поддомен не находит. Настройте его DNS-записи на хостинге или в панели регистратора.

Ответить
Александр

Добрый день, а что именно написать в DNS , какой именно айпишник? Чтото гдето не найду момент по видео, какие записи вставлять. Да и в личном кабинете докерхаб про это не сказано.

Ответить
Дмитрий Елисеев

В панели хостинга в настройках доменов создать A-запись с названием поддомена и вписать туда IP-адрес вашей виртуальной машины.

Ответить
Александр

что не хватает ему не пойму, может надо в своем докер репозитории какие нить теги создать ? А то он пустой.

Ответить
Юрий

Добрый вечер!!! после Check if server is running все обрубается и вылетает ошибка

fatal: [server]: FAILED! => {"changed": true, "cmd": "docker run -d --name apache -v /var/www/html:/usr/local/apache2/htdocs/ -p 80:80 httpd:2.4", "delta": "0:00:00.128552", "end": "2020-03-09 19:28:01.553707", "msg": "non-zero return code", "rc": 125, "start": "2020-03-09 19:28:01.425155", "stderr": "docker: Error response from daemon: Conflict. The container name \"/apache\" is already in use by container \"4ac2b371a956a4025e9415757d3b1578b2906ae308a63a45b5fa6a014edd3b9e\". You have to remove (or rename) that container to be able to reuse that name.\nSee 'docker run --help'.", "stderr_lines": ["docker: Error response from daemon: Conflict. The container name \"/apache\" is already in use by container \"4ac2b371a956a4025e9415757d3b1578b2906ae308a63a45b5fa6a014edd3b9e\". You have to remove (or rename) that container to be able to reuse that name.", "See 'docker run --help'."], "stdout": "", "stdout_lines": []}
Ответить
Юрий

После повторного выполнения make site task path: /home/pamparam/PhpstormProjects/auction/provisioning/roles/site/tasks/generate_certificates.yml:15 skipping: [server] => {"changed": false, "skip_reason": "Conditional result was False"}

и здоровенная портянка

task path: /home/pamparam/PhpstormProjects/auction/provisioning/roles/site/tasks/generate_certificates.yml:19
skipping: [server] => (item={'failed': False, u'stat': {u'charset': u'binary', u'uid': 0, u'exists': True, u'attr_flags': u'', u'lnk_target': u'../../archive/auction.pamdev.ru/cert1.pem', u'woth': True, u'device_type': 0, u'mtime': 1583773134.6051612, u'block_size': 4096, u'inode': 154082, u'isgid': False, u'size': 41, u'executable': False, u'roth': True, u'isuid': False, u'readable': True, u'isreg': False, u'version': None, u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True, u'writeable': True, u'isdir': False, u'blocks': 0, u'xoth': True, u'rusr': True, u'nlink': 1, u'issock': False, u'rgrp': True, u'gr_name': u'root', u'path': u'/etc/letsencrypt/live/auction.pamdev.ru/cert.pem', u'xusr': True, u'atime': 1583773134.6211607, u'lnk_source': u'/etc/letsencrypt/archive/auction.pamdev.ru/cert1.pem', u'mimetype': u'inode/symlink', u'ctime': 1583773134.6051612, u'isblk': False, u'xgrp': True, u'dev': 65025, u'wgrp': True, u'isfifo': False, u'mode': u'0777', u'islnk': True, u'attributes': []}, 'ansible_loop_var': u'item', 'item': u'auction.pamdev.ru', u'invocation': {u'module_args': {u'follow': False, u'get_checksum': True, u'path': u'/etc/letsencrypt/live/auction.pamdev.ru/cert.pem', u'checksum_algorithm': u'sha1', u'get_md5': False, u'get_mime': True, u'get_attributes': True}}, u'changed': False})  => {"ansible_loop_var": "item", "changed": false, "item": {"ansible_loop_var": "item", "changed": false, "failed": false, "invocation": {"module_args": {"checksum_algorithm": "sha1", "follow": false, "get_attributes": true, "get_checksum": true, "get_md5": false, "get_mime": true, "path": "/etc/letsencrypt/live/auction.pamdev.ru/cert.pem"}}, "item": "auction.pamdev.ru", "stat": {"atime": 1583773134.6211607, "attr_flags": "", "attributes": [], "block_size": 4096, "blocks": 0, "charset": "binary", "ctime": 1583773134.6051612, "dev": 65025, "device_type": 0, "executable": false, "exists": true, "gid": 0, "gr_name": "root", "inode": 154082, "isblk": false, "ischr": false, "isdir": false, "isfifo": false, "isgid": false, "islnk": true, "isreg": false, "issock": false, "isuid": false, "lnk_source": "/etc/letsencrypt/archive/auction.pamdev.ru/cert1.pem", "lnk_target": "../../archive/auction.pamdev.ru/cert1.pem", "mimetype": "inode/symlink", "mode": "0777", "mtime": 1583773134.6051612, "nlink": 1, "path": "/etc/letsencrypt/live/auction.pamdev.ru/cert.pem", "pw_name": "root", "readable": true, "rgrp": true, "roth": true, "rusr": true, "siz .....

проверил по этим адресам есть /etc/letsencrypt/live/auction.pamdev.ru/cert.pem но к доменам и поддоменам они не привязаны и make push не проходит так как стучится по https

Ответить
Дмитрий Елисеев

Так как файлы уже есть, то при последующих запусках всегда будет skipping

К доменам и поддоменам они теперь должны привязываться в Nginx.

Ответить
Юрий

да но в директории /etc/nginx/snippets/ файлов ssl.conf certbot.conf нет и nginx дальше не дает выполнить команды

Ответить
Дмитрий Елисеев

А почему их там нет?

Ответить
Юрий

пока сам не понимаю.. выполняю команду make site

ожидаю что должны появится но их нет

Ответить
Юрий

вообще нет nginx

Ответить
Дмитрий Елисеев

Ansible толлько устанавливает Docker с Certbot и генерирует сертификаты.

А сам проект с Nginx и PHP деплоится через make deploy после make build и make push.

Ответить
Дмитрий Елисеев

Если в первый раз вылетела ошибка, то добавьте к командам запуска и остановки apache значения ignore_errors: yes и перезапустите снова.

Ответить
Александр

Вобщем запнулся на этом уроке. Вторые выходные сижу на нем. выше писал про Error response from daemon: Get registry.tiru.ru/v2/: dial tcp: lookup registry.tiru.ru on 188.93.16.19:53: no such host"]

Создал поддомен registry.tiru.ru какие NS записи создавать, надоли сервак под этот домен, и если надо как его настроить. Откуда на вашем регистре поддомене nginx. Ни какой инфы в видосах не нашел, как смотреть дальнейшие видео нипонятно, тк на практике не выходит ничего. Спулил с гита ветку последней версии и откатывал на версию этого урока. Менял домен deworker.pro автозаменой на свой , не выходит. Дмитрий объясните по подробнее про домен registry.tiru.ru , тк хочется проверить вашу теорию на практике , своими ручками. А не просто поверить этой "теории"

Ответить
Дмитрий Елисеев

Сам поддомен нужно создать в панели управления вашего хостинга, где вы регистрировали домен.

Там должно быть примерно так, но с вашими адресами:

Хост              |   Тип   |  Значение
---------------------------------------------
tiru.ru           |   A     |  31.184.254.199
registry.tiru.ru  |   A     |  31.184.254.199

Так поддомены создаются и привязываются к виртуальным машинам по их IP-адресам. И только после этого начинают открываться в браузере.

Ответить
Александр

так и есть у меня сейчас

только ошибка не с айпишником 188.93.16.19 как раньше, а с моим 31.184.254.199

.......", "msg": "non-zero return code", "rc": 1, "start": "2020-03-14 12:35:45.822078", "stderr": "WARNING! Using --password via the CLI is insecure. Use --password-stdin.\nError response from daemon: Get registry.tiru.ru/v2/: dial tcp 31.184.254.199:443: connect: connection refused", "stderr_lines": ["WARNING! Using --password via the CLI is insecure. Use --password-stdin.", "Error response from daemon: Get registry.tiru.ru/v2/: dial tcp 31.184.254.199:443: connect: connection refused"], "stdout": "", "stdout_lines": []}

сертификат тоже чтоли нужен на этот домен сделать, походу.

Ответить
Дмитрий Елисеев

Да, сделать сертификат и для него.

Ответить
Александр

сделал не помогло , ...login attempt to registry.tiru.ru/v2/ failed with status: 404 Not Found".... ни какой формы авторизации нету по этому адресу как у Вас. Чтото я вобще не догоняю.

registry.tiru.ru", "delta": "0:00:00.529081", "end": "2020-03-16 18:12:43.121638", "msg": "non-zero return code", "rc": 1, "start": "2020-03-16 18:12:42.592557", "stderr": "WARNING! Using --password via the CLI is insecure. Use --password-stdin.\nError response from daemon: login attempt to registry.tiru.ru/v2/ failed with status: 404 Not Found", "stderr_lines": ["WARNING! Using --password via the CLI is insecure. Use --password-stdin.", "Error response from daemon: login attempt to registry.tiru.ru/v2/ failed with status: 404 Not Found"], "stdout": "", "stdout_lines": []}

Ответить
Дмитрий Елисеев

Виртуалку и поддомен для реестра вы сделали.

Теперь осталось установить туда сам реестр по примерам из комментариев выше.

Ответить
Arunas

после make deploy demo-auction.arsku.com/работает, а api.demo-auction.arsku.com кидает ошибку: 502 Bad Gateway.

команда docker logs --since 30s -f auction_api_1 даёт ответ:

2020/03/18 15:17:46 [error] 6#6: *66 connect() failed (113: Host is unreachable) while connecting to upstream, client: 172.18.0.7, server: , request: "GET / HTTP/1.0", upstream: "fastcgi://172.18.0.3:9000", host: "api.demo-auction.arsku.com"

как решить эту проблему?
правда, после ansible make site остался контейнер httpd:2.4 apache, я его остановил...

вид http://www.arvidija.lt/turinys.php?autoidpsl=16&puslapio_PVD=programming

Ответить
Дмитрий Елисеев

Не запустился api-php-fpm.

Ответить
Arunas

Да, передеплоил с другого компьютера и всё ок.

Ответить
Олег

Дмитрий, приветствую. А не могли бы вы объяснить, за что отвечает переменная REGISTRY при команде make docker-login Видел в комментариях, что люди тоже столкнулись с проблемой на этой команде, но точного ответа и понимания так и не последовало после ваших советов/ответов.

Я правильно понимаю, что вы не используете докер хаб, а создали свой регистр для хранения образов? Или я ошибаюсь?

Если это так, то не ясно, как создавать свой регистр из данных видео. На хабре есть конечно статьи, но хотелось бы тут узнать все нюансы которые вы затрагиваете.

По крайней мере у меня есть аккаунт на DockerHub и я успешно сделал туда пуш в виде docker push myaccount/php:1 (например), но если я пытаюсь использовать команду "docker login -u {{ username }} -p {{ password }} {{ registry }}", как в видео, меня шлют лесом и говорят что нет такого регистра. Вот хотелось бы понять, почему у вас работает и что это за registry.deworker.pro

Заранее спасибо за ответ

UPD - нашел в комментах инфу что требуется поднять свой регистр. Как то не приятно, что требуется копаться в комментах, в поисках информации которая не дается в курсе. Это прям минус.

Ответить
Олег

Если кто столкнулся с таким моментов, что у него нет собственного докер регистра, можно поступить так:

Регистрируетесь на докер хаб
Меняете docker_login.yml на такое

---
-   name: Log into private registry
    hosts: site
    remote_user: root
    become: yes
    become_user: deploy
    vars_prompt:
        -   name: username
            prompt: "Username"
            private: no
        -   name: password
            prompt: "Password"
    tasks:
        -   name: Log into private registry
            shell: "docker login -u {{ username }} -p {{ password }}"

При использование команды make build и make push используется для переменной REGISRTY ваш айдишник на докер хабе.

Пулится пушится логинится успешно.

Минус всего этого - ваши образы на докер хабе публичные

Ответить
Дмитрий Елисеев

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

Да, именно так. И в параметре REGISTRY мы его адрес указываем.

Если это так, то не ясно, как создавать свой регистр из данных видео.

Про это запишу скоро отдельное видео.

Ответить
elmut

Спустя 10 дней получился настроить wsl 2->Ubuntu-18.04 = Ansible +Docker Registry и wsl 2->Debian это у нас production-сервера и wsl 2->Ubuntu-20 = dev

Ответить
Александр

В шторме, Не могу понять по комитам на гите, какой соответствует окончанию этого урока? Даты коммитов перемешаны му собой не разберешь. Хорошо бы подписывали , на какой комит переключаться под конец урока, чтоб ручками все проверить самому ))

Ответить
Дмитрий Елисеев

К этому уроку вся группа коммитов про provisioning до "Added site certbot renew hook".

Ответить
Владимир Перепеченко

К этому уроку вся группа коммитов про provisioning до "Added site certbot renew hook".

Воот! такое бы примечание для каждого урока!

Ответить
Ярослав

При попытке запушить билды на AWS мне выпадает сообщение "no basic auth credentials". До этого успешно создал реестр и команда make docker-login успешно сработала. Что теперь делать?

Ответить
Ярослав

P.S. Разобрался уже. Я просто вводил одну команду, а в makefile она уже другая.

Ответить
Ярослав

И все равно. Я застрял на этом уроке. Не понимаю, почему у меня не работает. Делаю пошагово за автором. Дохожу до создания своего отдельного приватного репозитория. Перехожу на урок 33, создаю репозиторий. Логинюсь в него. Пушу туда образы. Все проходит нормально. Ввожу команду деплоя и вижу следующее:

regal@regal-Inspiron-5521:~/projects/auction$ HOST=deploy@ec2-34-253-166-211.eu-west-1.compute.amazonaws.com PORT=22 REGISTRY=registry.newmagic.space IMAGE_TAG=master-1 BUILD_NUMBER=1 make deploy
ssh deploy@ec2-34-253-166-211.eu-west-1.compute.amazonaws.com -p 22 'rm -rf site_1'
ssh deploy@ec2-34-253-166-211.eu-west-1.compute.amazonaws.com -p 22 'mkdir site_1'
scp -P 22 docker-compose-production.yml deploy@ec2-34-253-166-211.eu-west-1.compute.amazonaws.com:site_1/docker-compose-production.yml
docker-compose-production.yml                                                                                                                                        100%  683     6.2KB/s   00:00    
ssh deploy@ec2-34-253-166-211.eu-west-1.compute.amazonaws.com -p 22 'cd site_1 && echo "COMPOSE_PROJECT_NAME=auction" >> .env'
ssh deploy@ec2-34-253-166-211.eu-west-1.compute.amazonaws.com -p 22 'cd site_1 && echo "REGISTRY=registry.newmagic.space" >> .env'
ssh deploy@ec2-34-253-166-211.eu-west-1.compute.amazonaws.com -p 22 'cd site_1 && echo "IMAGE_TAG=master-1" >> .env'
ssh deploy@ec2-34-253-166-211.eu-west-1.compute.amazonaws.com -p 22 'cd site_1 && docker-compose -f docker-compose-production.yml pull'
Pulling frontend    ... error
Pulling api-php-fpm ... error
Pulling api         ... error
Pulling gateway     ... error

ERROR: for gateway  Get registry.newmagic.space/v2/auction-gateway/manifests/master-1: no basic auth credentials

ERROR: for api-php-fpm  Get  registry.newmagic.space/v2/auction-api-php-fpm/manifests/master-1: no basic auth credentials

ERROR: for api  Get  registry.newmagic.space/v2/auction-api/manifests/master-1: no basic auth credentials

ERROR: for frontend  Get  registry.newmagic.space/v2/auction-frontend/manifests/master-1: no basic auth credentials
Get registry.newmagic.space/v2/auction-gateway/manifests/master-1: no basic auth credentials
Get registry.newmagic.space/v2/auction-api-php-fpm/manifests/master-1: no basic auth credentials
Get registry.newmagic.space/v2/auction-api/manifests/master-1: no basic auth credentials
Get registry.newmagic.space/v2/auction-frontend/manifests/master-1: no basic auth credentials
make: *** [Makefile:55: deploy] Ошибка 1

Я худо-бедно умею программировать, но таким разворачиванием еще не занимался, я в этом новичок. Помогите разобраться пожалуйста.

Ответить
Дмитрий Елисеев

Логинюсь в него. Пушу туда образы.

Теперь залогиньтесь с сервера для пулла:

cd provisioning
make docker-login
Ответить
Ярослав

Да, получилось. Но тут же пошла другая ошибка:

Creating network "auction_default" with the default driver
Creating auction_api-php-fpm_1 ... done
Creating auction_frontend_1    ... done
Creating auction_api_1         ... done
Creating auction_gateway_1     ... 
Creating auction_gateway_1     ... error

ERROR: for auction_gateway_1  Cannot start service gateway: driver failed programming external connectivity on endpoint auction_gateway_1 (3ca58f973879dc9b13c525aba77c02b9e90edae106d3350e426c1b8027b8a4c9): Bind for 0.0.0.0:443 failed: port is already allocated

ERROR: for gateway  Cannot start service gateway: driver failed programming external connectivity on endpoint auction_gateway_1 (3ca58f973879dc9b13c525aba77c02b9e90edae106d3350e426c1b8027b8a4c9): Bind for 0.0.0.0:443 failed: port is already allocated
Encountered errors while bringing up the project.
make: *** [Makefile:56: deploy] Ошибка 1

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

Ответить
Игорь

Подскажите, у вас получилось разобраться в чем тут проблема? Завис на этом же месте.

Ответить
Максим

Не знаю, актуально ли. Но если кто столкнётся с подобным, то помогла вот эта команда:

docker rm -f apache
Ответить
Pavel N

Подскажите выполняю команды:

cd provisioning
make docker-login
ssh deploy@89.108.64.12 -p 22 'rm -rf site_'
ssh deploy@89.108.64.12 -p 22 'mkdir site_'
scp -P 22 docker-compose-production.yml deploy@89.108.64.12:site_/docker-compose.yml
docker-compose-production.yml    100%  761     0.7KB/s   00:00    
ssh deploy@89.108.64.12 -p 22 'cd site_ && echo "COMPOSE_PROJECT_NAME=auction" >> .env'
ssh deploy@89.108.64.12 -p 22 'cd site_ && echo "REGISTRY=pavel" >> .env'
ssh deploy@89.108.64.12 -p 22 'cd site_ && echo "IMAGE_TAG=master-1" >> .env'
ssh deploy@89.108.64.12 -p 22 'cd site_ && docker-compose pull'
[20633] Cannot open self /usr/local/bin/docker-compose or archive /usr/local/bin/docker-compose.pkg
Makefile:51: ошибка выполнения рецепта для цели «deploy»
make: *** [deploy] Ошибка 255

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

и после выполнения

make site

не удаляет apahe приходится удалять ручками, что нужно настроить для автоматического удаления

    name: Down certbot Apache
    shell: "docker rm -f apache"
    when: port_check.failed == true
Ответить
Дмитрий Елисеев

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

Значит либо пользователь deploy, либо файлу docker-compose не проставлена группа docker.

не удаляет apahe

Надо проверить.

Ответить
Дмитрий

да, что то сегодня всё рухнуло, пользователь deploy не может запустить docker-compose

хотя root норм запускает

система ubuntu

Ответить
Дмитрий

если не удасться это полечить, то придется под рутом всё делать ((

Ответить
Дмитрий

я вручную сделал: добавил deploy в группу sudo, задал ему пароль, зашел по ssh с паролем и вызвал sudo chmod a+rx /usr/local/bin/docker-compose

в результате docker-compose у пользователя deploy заработал

Дима, как через ansible сделать тоже самое для пользователя deploy?

Ответить
Дмитрий

P.S. вроде в ansible достаточно добавить a+rx в mode: 'u+x,g+x,a+rx' при установке docker-compose

Ответить
Дмитрий

а чтобы это сработало, надо переустановить docker-compose предварительно, например, удалив его зайти под root rm /usr/local/bin/docker-compose

Ответить
Дмитрий

либо создавать отдельный ансибл таск на изменение прав доступа к /usr/local/bin/docker-compose

Ответить
Дмитрий Елисеев

Отдельный не нужен. Группа должна быть указана в существующем:

-   name: Install Docker Compose
    get_url:
        url: ...
        dest: /usr/local/bin/docker-compose
        group: docker
        mode: 'u+x,g+x'
Ответить
Дмитрий

[20633] Cannot open self /usr/local/bin/docker-compose or archive /usr/local/bin/docker-compose.pkg

тоже возникла такая ошибка

если захожу под рутом, то всё хорошо

Ответить
Роман

Всем привет, я только подключился

TASK [certbot : Add Certbot repository]
fatal: [server]: FAILED! => {"changed": false, "msg": "apt cache update failed"}

может кто знает как это бороть?

Ответить
Санжар

А как в итоге решил? =)

Ответить
Дмитрий Елисеев

Можно вручную зайти на сервер по ssh от рута и там запустить apt update. После этого проблемы с установками не будет.

Ответить
Санжар

Спасибо большое за ваш труд! Очень нравится новый формат, раньше мастер-классы больше как стримы выглядели, но все равно было интересно.

Ответить
Рачков Роман

А если не помогло?

ЗЫ. Спасибо великолепный контент. За такое не жалко подписку оформить

Ответить
Рачков Роман

Помогла команда

gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys KEY

KEY в данном случае ключи которые выводятся ошибкой NO_PUBKEY на команде apt update

Ответить
Дмитрий Гончаров

К сожалению, ни apt update, ни apt-upgrade не помогает решить проблему. Есть еще идеи как побороть? Сервер настраиваю для jenkins.

Полностью чистый и ни чем не загажен

Ответить
kashamamina

поделитесь своей темой, очень красивая, не видел раньше таких. сами делали?

Ответить
Дмитрий Елисеев

Да, cделал сам специально для скринкастов. Выложил на GitHub.

Ответить
kashamamina

а почему при установке докера и сертификатов в конфигурации ансибла у тебя в начале обновляются пакеты, а в коммитах на гитхабе этого нету

- name: Update apt packages
  apt:
    update_cache: yes
Ответить
Дмитрий Елисеев

Лишний раз такие конструкции можно не прописывать если такие update_cache: yes есть у других шагов.

Ответить
slo_nik

Добрый вечер. Дмитрий, подскажите пожалуйста. Получится использовать Ваш пример для частного репозитория на docker hub? Будет ли частный репозиторий доступен кому-то кроме меня? Как я понял, необходимо установить на локальный компьютер ansible и certbot?

Ответить
Дмитрий Елисеев

Для приватного доступа к DockerHub достаточно выполнить тот же docker login, но не в свой реестр, а в registry-1.docker.io

Ответить
slo_nik

Я как раз имел ввиду свой реестр. Если я его обозначил как "private", то кроме меня его никто не увидит?

Ответить
Дмитрий Елисеев

Никто без пароля к нему не подключится.

Ответить
slo_nik

Благодарю.)

Ответить
Дядя Женя

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

TASK [site : Up certbot standalone Apache] *****************************************************************************
skipping: [server]

TASK [site : Generate new certificate] *************************************************************************************
failed: [server] (item={'invocation': {'module_args': {'checksum_algorithm': 'sha1', 'get_checksum': True, 'follow': False, 'path': '/etc/letsencrypt/li
ve/demo.my.company/cert.pem', 'get_md5': False, 'get_mime': True, 'get_attributes': True}}, 'stat': {'exists': False}, 'changed': False, 'failed': Fals
e, 'item': 'demo.my.company', 'ansible_loop_var': 'item'}) => {"ansible_loop_var": "item", "changed": true, "cmd": "certbot certonly --noninteractive -
-agree-tos --email user@my.company -d demo.my.company", "delta": "0:00:00.003260", "end": "2021-04-05 14:26:05.217382", "item": {"ansible_loop_var":
"item", "changed": false, "failed": false, "invocation": {"module_args": {"checksum_algorithm": "sha1", "follow": false, "get_attributes": true, "get_ch
ecksum": true, "get_md5": false, "get_mime": true, "path": "/etc/letsencrypt/live/demo.my.company/cert.pem"}}, "item": "demo.my.company", "stat": {"ex
ists": false}}, "msg": "non-zero return code", "rc": 127, "start": "2021-04-05 14:26:05.214122", "stderr": "/bin/sh: 1: certbot: not found", "stderr_lin
es": ["/bin/sh: 1: certbot: not found"], "stdout": "", "stdout_lines": []}
...
PLAY RECAP *********************************************************************************************************************************************
server                     : ok=12   changed=0    unreachable=0    failed=1    skipped=1    rescued=0    ignored=0

Не подскажите что это может быть и как с ним бороться?

Ответить
Дмитрий Елисеев

Судя по сообщению:

"stderr_lines": ["/bin/sh: 1: certbot: not found"]

у вас по какой-то причине не установился certbot.

Ответить
Дядя Женя

Поясните, пжл, ведь письмо с сертификатом должно быть на почте? Почту получаю, а сертификат не вижу. (раньше никогда с сертификатами дела не имел). И в чем ещё может быть причина?

Ответить
Роман

я ранее имел дело с certbot и letsencrypt - сертификат на почту не приходит, но https норм работал как надо. видимо, так и должно быть

Ответить
Роман

На сервере Ubuntu 20.04 сертификат не ставится. Почему - не знаю, переустановил сервер на Вebian 10, как у Дмитрия. Однако возникли проблемы с Add GPG key для докера.

Если у вас сервер Debian 10, замените блок ниже

    name: Add GPG key
    apt_key:
        url: https://download.docker.com/linux/debian/gpg
        state: present

на:

    name: Add Docker's official apt key.
    apt_key:
        url: https://download.docker.com/linux/ubuntu/gpg
        id: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88
        state: present
    register: add_key
    ignore_errors: true

Это не ошибка, сервер у меня Debian 10, а в url "ubuntu"
Если у вас Ubuntu 20.04 - Add GPG key работает.
Почему так - непонятно.
Решение нашел здесь. https://github.com/dwdraju/ansible-install-docker/blob/master/tasks/ubuntu.yml

Ответить
Дядя Женя

А в каком именно месте у вас выдавало ошибку сертификата и что писало? Я попробовал ваш метод с подменой ссылки и к сожалению ничего не получилось, та же ошибка, что и была

Ответить
Роман

Насколько я помню, была ошибка при выполнении самого первого таска из роли об установке сертификата.

Какой у вас vps-server? Debian 10?

Много где еще ошибки могут быть. Например, если вы скачаете коммит, о котором говорил Дмитрий в комментариях под уроком - там в файле hosts.yml не прописан пароль юзера. Я понимаю конечно, что возможно до этого Дмитрий сделал соединение ssh по ключу. Но это просто в качестве примера, а есть еще другие моменты, из-за которых у вас ошибки.

Я специально для этих уроков взял Debian 10 чистый, 512 мб оперативки, как у Дмитрия. В ruvds стоит 130р. в месяц, норм.

Ответить
Дядя Женя

Да, взял как в уроке. Кстати, сразу не обратил внимание, но таск с присоединением ключа вроде проходит и без замены TASK [docker : Add GPG key] ok: [server] Если в нем поменять на левый адрес, то сразу вылетает ошибка. Значит у меня на этом этапе все нормлаьно. Запинается на таске генерации нового сертификата. При этом таск с проверкой существования сертификата вроде тоже нормально проходит: TASK [site : Check if certificate already exists] ok: [server] => (item=demo.my.company) ok: [server] => (item=api.demo.my.company)

И по ssh-key тоже вроде заходит: TASK [docker : Verify fingerprint] ok: [server]

Ответить
Роман

Дядя Женя, Вы пишете "Запинается на таске генерации нового сертификата", то есть на таске "name: Generate new certificate". То есть на этом таске:

name: Generate new certificate
shell: "certbot certonly --noninteractive --agree-tos --email {{ certbot_email }} -d {{ item.item }}"
with_items: "{{ letsencrypt_certs.results }}"
when: not item.stat.exists

А вы сменили емаил на свой?

Ответить
Дядя Женя

В смысле на свой? На тот емаил, который настроен на моем сервере? Да и я его привел в отчете, который привел как пример. Сервер demo.my.company, а почта user@my.company. Она же указана в certbot.yml и site/defaults/main.yml. Конечно почта и сервер выдуманные, но смысл, думаю понятен. Или нужно было где-то ещё поменять? Или даже на другую почту?

Ответить
Роман

Не знаю, я указал реальный емаил. Возможно, как-то проверяется существование реального емаила перед генерацией сертификата?

Ответить
Дядя Женя

Ну так у меня реальный. Я почту на сервере поднял, принимаю с неё письма, отправляю с неё на свою обычную гмайловскую почту и ещё на пару почтовиков. Только в примере, что выложил тут выше в отчете, заменил на выдуманную. Зачем реальную светить? ))) Чтоб спамеры спамили? ))))) Только вот в папке с почтой у обоих юзеров (пока настроил почту для двух юзеров) пусто, в смысле сертификата нет. А по идее должен прийти

Ответить
Роман

Рецепт успешного прохождения этого урока. Через публичный репозиторий на docker hub.

  • купить домен. в управлении зоной днс сделать 2 А-записи: 1-запись: @ для ip_сервера_vps; 2-я запись: api для ip_сервера_vps
  • Скачать файлы этого коммита
  • Или перейти на коммит, зайдя в папку проекта через git checkout 65036b2

Имя коммита "Added provisioning roles" 65036b2

  • Пойти в ruvds.com и взять там VPS с голой Debian10, минимум 1 ГБ оперативки! Я брал 512мб, как Дмитрий в видео, но не завелось ("running out of memory" - что-то такое было. (чтобы было дешевле, перейдите в "Готовые тарифы" и возьмите за 240р.)
  • hosts.yml.dist переименовать в hosts.yml
  • hosts.yml
    • hosts.yml ip прописать от вашего vps
    • ansible_ssh_pass добавить в hosts.yml и прописать пароль к root от вашего vps
    • у Дмитрия вообще нет этого параметра в файле hosts.yml! Я так понимаю, он заранее закинул ssh-публичный ключ на сервер, а приватный ключ прописал в конфигах ansible глобально? Дмитрий, если читаете этот пункт, просьба прояснить этот момент).
  • найти и заменить домен и api.домен на свой (ctrl+shift+f в phpStorm) В этих файлах:
    • provisioning/roles/site/defaults/main.yml
    • gateway/docker/production/nginx/conf.d/api.conf
    • gateway/docker/production/nginx/conf.d/frontend.conf
    • gateway/docker/production/nginx/conf.d/default.conf
  • Установка нужных прав на проект:
    • sudo chown -R имя_юзера_на_хостовой_машине:www-data ~/projects/auction
    • sudo chmod -R 755 ~/projects/auction
  • provisioning/roles/site/defaults/main.yml
    • параметр certbot_email: вписать свой email
  • перепроверить provisioning/roles/authorize.yml - путь до ssh на хостовой машине
  • создать ansible.cfg в папке provisioning с такими настройками:([defaults] host_key_checking = false).
  • roles/docker/tasks/main.yml "Install dependencies" добавить еще 2 пункта - gnupg и - lsb-release. Вот так должно быть:
-   name: Install dependencies
    apt:
        name:
            - apt-transport-https
            - ca-certificates
            - curl
            - gnupg
            - lsb-release
            - software-properties-common
        state: present
        update_cache: yes

roles/docker/tasks/main.yml - name: Add GPG key - полностью заменить таск на:

-	name: Add Docker's official apt key.
	apt_key:
    	    url: https://download.docker.com/linux/ubuntu/gpg
    	    id: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88
    	    state: present
	register: add_key
	ignore_errors: true

Это не ошибка, сервер Debian 10, а в url "ubuntu". Если у вас Ubuntu 20.04 - Add GPG key работает. Почему так - непонятно. Решение нашел здесь. https://github.com/dwdraju/ansible-install-docker/blob/master/tasks/ubuntu.yml. НО я использовал не все как в ссылке, а частично, как написал выше.

  • создать аккаунт в докер хаб
  • создать 4 публичных репозитория в докер хабе: auction-api-php-fpm, auction-api, auction-frontend, auction-gateway. (скорее всего этот шаг можно пропустить, запушиться итак должно, но я сделал заранее, если не делать - не проверял)
  • cd provisioning
  • make site
  • make authorize
  • cd ..
  • REGISTRY=ваш_логин_в_докер_хаб IMAGE_TAG=master-1 make build
  • docker login (логин и пароль в докер хаб спросит, вбить). Не через make как у Дмитрия! Это команда докера нативная.
  • REGISTRY=ваш_логин_в_докер_хаб IMAGE_TAG=master-1 make push
  • HOST=deploy@ip_от_вашего_vps PORT=22 REGISTRY=ваш_логин_в_докер_хаб IMAGE_TAG=master-1 BUILD_NUMBER=1 make deploy
Ответить
Роман

Не могу уже отредактировать, напишу сюда, чуть подформатирую свой пункт "Установка нужных прав".

Установка нужных прав на проект.

  • sudo chown -R имя_юзера_на_хостовой_машине:www-data ~/projects/auction
  • sudo chmod -R 755 ~/projects/auction
Ответить
Роман

не могу отредактировать свое большое сообщение, пишу здесь. немного отформатирую эти пункты:

hosts.yml ip прописать от вашего vps

ansible_ssh_pass добавить в hosts.yml и прописать пароль к root от вашего vps

у Дмитрия вообще нет этого параметра в файле hosts.yml! Я так понимаю, он заранее закинул ssh-публичный ключ на сервер, а приватный ключ прописал в конфигах ansible глобально? Дмитрий, если читаете этот пункт, просьба прояснить этот момент).

Ответить
Дядя Женя

Жаль, что ваш ответ не был оформлен как ответ мне. Я на почте его не увидел, а само видео пока не просматривал заново и коменты не листал. Случайно сюда зашел. Чуток попозже попробую все что вы сказали (нужно внимательно вчитываться). В любом случае - спасибо. Но до этого я уже успел сделать первых 5 пунктов. Вроде все так и есть, только сервер на vscale.io как Дмитрия. И 512 оперативки. Но при этом на память не ругается. Остальное буду смотреть

Ответить
Дядя Женя

После вставок в roles/docker/tasks/main.yml, roles/docker/tasks/main.yml, hosts.yml (тут ansible_ssh_pass) у меня запнулся уже на первом шаге с ошибкой:

fatal: [server]: FAILED! => {"msg": "to use the 'ssh' connection type with passwords, you must install the sshpass program"}

с указанием на файл provisioning/site.yml

Все остальное у меня было настроено так же.

Хотя ещё оставался вопрос о правах на запись. Не совсем понял где их прописывать. Я то из под винды работаю. Но по логике разрешение нужно прописывать для юзера на сервере, куда заливаю сайт. Тогда стоит вопрос, куда из файлов каталога provisioning вписать эти разрешения.

Ответить
Роман

Какая у вас хостовая машина? Если ubuntu то видимо надо: apt-get install sshpass.

Ответить
Дядя Женя

Хостовая, тоесть домашняя? Винда + wsl2+ubuntu. Установил sshpass и заливка запнулась на том же шаге, что и раньше, на TASK [site : Generate new certificate]

Если предположить, что ошибка в этой строке отчета: provisioning/roles/site/tasks/generate_certificates.yml:19, то опять приходим к тому, что что-то не так с почтой, потому что в этой секции написано:

-   name: Generate new certificate
    shell: "certbot certonly --noninteractive --agree-tos --email {{ certbot_email }} -d {{ item.item }}"
    with_items: "{{ letsencrypt_certs.results }}"
    when: not item.stat.exists
Ответить
Роман

site/defaults/main.yml

тут все верно?

certbot_email: ваш_емаил действующий

certbot_hosts:
    - example.ru
    - api.example.ru
Ответить
Дядя Женя

Да, почта работающая. Даже свою личную почту прописывал. Ни в спаме нигде нет.

Ответить
Роман

А - записи верные для certbot_hosts?

Ответить
Дядя Женя

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

Ответить
Роман

certbot_hosts - это переменная ansible в файле provisioning/roles/site/defaults/main.yml

А - записи прописываются ж у хостера, где сервер? - нет. А-записи прописываются у регистратора домена (хостер иногда сам может быть регистратором, а может и не быть). Комментарий Дмитрия на этой странице об А-записях: 2020-03-14 15:05. Ну да, если домены пинговались, значит все верно сделано было. Хотя, надо внимательнее посмотреть при пинге, там ай пи совпадает с ай пи вашего сервера или нет? Про почту не скажу ничего, никогда не настраивал

Ответить
Дядя Женя

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

Ответить
Дмитрий Елисеев

у Дмитрия вообще нет этого параметра в файле hosts.yml! Я так понимаю, он заранее закинул ssh-публичный ключ на сервер, а приватный ключ прописал в конфигах ansible глобально? Дмитрий, если читаете этот пункт, просьба прояснить этот момент.

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

Ответить
slo_nik

docker login (логин и пароль в докер хаб спросит, вбить). Не через make как у Дмитрия! Это команда докера нативная.

Добрый вечер.

В make прекрасно работает команда, только надо её немного изменить

---
- name: Log info private registry
     hosts: site
     remote_user: root
     become: yes
     become_user: username
     vars_prompt:
       - name: username
         prompt: "Username"
         private: no
       - name: password
         prompt: "Password"
     tasks:
       - name: Log info private registry
         shell: "docker login -u {{ username }} -p {{ password }}"

username - пользователь на удалённом сервере

password - использовать token, создаётся в учётной записи на hub.docker.com

Ответить
Санжар

Спасибо.

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

Ответить
Дядя Женя

Есть ли возможность запуска команды make site со страницы сайта?

Ответить
Роман

что значит со страницы сайта? на сервере имеется в виду?

Ответить
Дядя Женя

Да хоть на сервере, хоть у себя в продакшене или девелопменте, с последующим переносом на сервер. Но в первую очередь у себя на компе, где продакшен и девелопмент.

Ответить
Роман

На сервере не имеет смысла! make site оно же запускает ansible (а ansible предназначен для управления с хостовой машины вашими серверами).

Хостовая машина == ваш домашний комп в этом контексте

Ответить
Дядя Женя

Кстати, нашел сегодня для понимания смысла по аналогии. В друпале есть такая штука - мультисайт. Фактически тоже, что и Дмитрий демонстрирует. Но в дурпале раньше не было автоматизации этого процесса. Все руками приходилось прописывать. Но вот несколько лет назад оказывается они сами сделали под себя приложение для управления сайтами на основе ansible+php

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

Ответить
Дядя Женя

Слегка уточню свой интерес про запуск команд make site со страницы сайта. Есть два варианта:

  1. Допустим хочу создать вэбинтерфейс для управления докер и всем этим удовольствием. Лень мне залазить в PHPStorm, руками править нужные файлы. Ведь по сути все сводится к добавлению адресов в нужное место пары файлов и потом запуск их с помощью Makefile. Если не нужно править код на странице сайта, добавлять какой-то функционал, исправлять баги, а только задеплоить на какой-то сервер(ы).
  2. Допустим хочу на сервере, где крутиться сайт иметь возможность копировать его (или какую-то часть) на другие сервера. Ведь ансибл для этого и создан, чтоб разворачивать приложения на разных серверах.

На данный момент я понимаю, что в простейшем случае нужен код что-то типа такого (api/public/index.php):

<form method="post">
    <input type="submit" name="ping" value="Start ping"/>
</form>

<?php

if (isset($_POST['ping'])){ system("ping google.com", $result);}

echo $result;
var_dump($result);

Так я могу запустить какую-то команду и отобразить её вывод на странице сайта. Но если прописать:

if (isset($_POST['ping'])){ system("ansible -m ping google.com", $result);}

То выведет 127int(127)

Я так понимаю, что это из-за того, что находимся в "другом образе", не на самом хосте, где разрабатываем сайт, а в контейнере. Пробовал в каталоге provisioning в файле Makefile Добавлять команду типа:

ping:
	ansible -m ping all

Она работает. Но замена на

if (isset($_POST['ping'])){ system("make ping", $result);}

Тоже ничего не дала 127int(127).

Ответить
Дядя Женя

Благодаря ошибке стал понимать, что в моем случае скорее всего нужно доустановить ансибл в один из контейнеров, чтоб получился приблизительный путь /app/public/index.

То есть по идее в docker-compose нужно добавить секцию что-то типа такого:

    ansible:
        build:
            context: api/docker
            dockerfile: development/ansible/Dockerfile
        volumes:
            - ./api:/app

а в Dockerfile что-то типа этого:

FROM php:7.4-cli-alpine
RUN apt install ansible
WORKDIR /app

и потом вызывать командой:

if (isset($_POST['ping'])){ system("make ping google.com", $result);}

Но пока не получилось

Ответить
Дядя Женя

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

docker-compose run --rm api-php-cli apk add ansible

Хоть и установила ансибл, но ничего не дала в плане выполнения команд от его имени Так же и с добавлением

RUN apk add ansible в api/docker/development/php-cli/Dockerfile
Ответить
Дядя Женя

Пробую собрать образ с ансибл. Стал понимать, что к нему нужно докинуть ещё пайтон и другие вещи. Собрал такой Dockerfile:

FROM alpine:3.12

RUN apk --no-cache add \
        sudo \
        python3\
        openssl \
        ca-certificates \
        sshpass \
        openssh-client \
        rsync \
        git && \
    apk --no-cache add --virtual build-dependencies \
        python3-dev \
        libffi-dev \
        openssl-dev \
        build-base \
        ansible && \
    apk del build-dependencies && \
    rm -rf /var/cache/apk/*

RUN mkdir /ansible && \
    mkdir -p /etc/ansible && \
    echo 'localhost' > /etc/ansible/hosts

WORKDIR /ansible

RUN ansible --version

вроде показывает, что все собирается, но потом выдает ошибку:

 => ERROR [5/5] RUN ansible --version                                                                                                              1.7s
------
 > [5/5] RUN ansible --version:
#9 1.180 /bin/sh: ansible: not found
------
executor failed running [/bin/sh -c ansible --version]: exit code: 127

Dockerfile лежит в корне. Кроме его ничего нет и по идее не нужно.

Пробовал добавить вместо первой строки такую

FROM php:7.4-cli-alpine

Но результат тот же

Ответить
Дядя Женя

Вернусь к вопросу ошибки при заливке на сервер. Не знаю, насколько правильно поступил, но прописал у хостера добавочную А запись типа api.demo.site.com и все задеплоилось. По крайней мере ошибок нет. Но и есть предупреждение типа:

skipping: [server] => (item={'invocation': {'module_args': {'checksum_algorithm': 'sha1', 'get_checksum': True, 'follow': False, 'path': '/etc/letsencrypt/live/demo.site.com/cert.pem', 'get_md5': False, 'get_mime': True, 'get_attributes': True}}, 'stat': {'charset': 'binary', 'uid': 0, 'exists': True, 'attr_flags': '', 'lnk_target': '../../archive/demo.site.com/cert1.pem', 'woth': True, 'isreg': False, 'device_type': 0, 'mtime': 1618143791.318494, 'block_size': 4096, 'inode': 521595, 'isgid': False, 'size': 40, 'executable': False, 'isuid': False, 'readable': True, 'version': None, 'pw_name': 'root', 'gid': 0, 'ischr': False, 'wusr': True, 'writeable': True, 'mimetype': 'inode/symlink', 'blocks': 0, 'xoth': True, 'islnk': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'root', 'path': '/etc/letsencrypt/live/demo.site.com/cert.pem', 'xusr': True, 'atime': 1620877832.626035, 'lnk_source': '/etc/letsencrypt/archive/demo.site.com/cert1.pem', 'isdir': False, 'ctime': 1618143791.318494, 'isblk': False, 'wgrp': True, 'xgrp': True, 'dev': 2049, 'roth': True, 'isfifo': False, 'mode': '0777', 'rusr': True, 'attributes': []}, 'changed': False, 'failed': False, 'item': 'demo.site.com', 'ansible_loop_var': 'item'})
skipping: [server] => (item={'invocation': {'module_args': {'checksum_algorithm': 'sha1', 'get_checksum': True, 'follow': False, 'path': '/etc/letsencrypt/live/api.demo.site.com/cert.pem', 'get_md5': False, 'get_mime': True, 'get_attributes': True}}, 'stat': {'charset': 'binary', 'uid': 0, 'exists': True, 'attr_flags': '', 'lnk_target': '../../archive/api.demo.site.com/cert1.pem', 'woth': True, 'isreg': False, 'device_type': 0, 'mtime': 1620946259.5864851, 'block_size': 4096, 'inode': 1028362, 'isgid': False, 'size': 44, 'executable': False, 'isuid': False, 'readable': True, 'version': None, 'pw_name': 'root', 'gid': 0, 'ischr': False, 'wusr': True, 'writeable': True, 'mimetype': 'inode/symlink', 'blocks': 0, 'xoth': True, 'islnk': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'root', 'path': '/etc/letsencrypt/live/api.demo.site.com/cert.pem', 'xusr': True, 'atime': 1620946259.610485, 'lnk_source': '/etc/letsencrypt/archive/api.demo.site.com/cert1.pem', 'isdir': False, 'ctime': 1620946259.5864851, 'isblk': False, 'wgrp': True, 'xgrp': True, 'dev': 2049, 'roth': True, 'isfifo': False, 'mode': '0777', 'rusr': True, 'attributes': []}, 'changed': False, 'failed': False, 'item': 'api.demo.site.com', 'ansible_loop_var': 'item'})"

При этом страница сайта туда не загрузилась. Выдает только "Index of/" Я не совсем понял. Откуда она должна заливаться: из репозитория или с нашего компа?

Ответить
Дмитрий Елисеев

Через Ansible только ставится софт и загружаются сертификаты для доменов.

Сам сайт выкладывается уже потом через Docker командой make deploy

Ответить
Дядя Женя

Спасибо. Теперь понятно. А это предупреждение? Оно о чем? Критично? Исправлять как-то надо?

Ответить
Дмитрий Елисеев

Это уведомление о пропуске (skipping) шага по условию. Исправлять не надо.

Ответить
Дядя Женя

Я, кстати, было решил, что Ансибл уже заменяет make deploy

Ответить
Руслан

Дмитрий, добрый день,

пожалуйста, можете добавить в сборку Prometheus + Grafana для мониторинга нагрузки? Думаю будет очень актуально, учитывая разворачивание масштабируемой под нагрузку архитектуры. Либо посоветовать как их грамотно внедрить/настроить в текущей архитектуре в докере.

Спасибо огромное заранее!

Ответить
Дмитрий Елисеев

Это лучше добавить когда-нибудь после разработки. А так да, Prometheus популярен для мониторинга нагрузки и сбора бизнес-метрик самого проекта.

Ответить
Руслан

Дима, спасибо, конечно будет хорошо и после разработки, пока пробую разобраться самостоятельно.

Ответить
slo_nik

Доброе утро.

Дмитрий, возник такой вопрос.

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

Я попробовал написать tasks для решения этой задачи, но до конца не могу довести дело.

Пока у меня получилось два файла, один записывает удалённый хост в файл known_hosts, а второй копирует ключ на сервер.

add_known_hosts.yml (запись хоста в known_hosts)

---
- name: Added known_hosts
  hosts: site
  remote_user: root
  become: yes
  vars_prompt:
      - name: remote_host
        prompt: "Host name"
        private: no
     - name: remote_ip
       prompt: "Host IP"
       private: no
   tasks:
      - known_hosts:
           name: '{{ remote_host }}'   # or 10.9.8.77
           key: '{{ remote_host }}, {{ remote_ip }} ssh-rsa ASDeararAIUHI324324'  # some key gibberish
           #path: /etc/ssh/ssh_known_hosts
           state: present

Запускаю этот файл командой

add_known_hosts:
ansible-playbook -i hosts.yml add_known_hosts.yml

Указываю какой хост, с каким ip надо записать в known_hosts, потом запрашивается подтверждение действия

Are you sure you want to continue connecting (yes/no)?

Затем требуется ввести пароль root для доступа к серверу.

Вот на этом моменте я потерялся.

После ввода хоста, ip и подтвержения не могу понять как указать root пароль. Работа завершается ошибкой

Permission denied (publickey,password)., но и хост записывается в known_hosts

Пробовал изменить команду в make файле на такую

add_known_hosts:
ansible-playbook -i hosts.yml --ask-pass add_known_hosts.yml

Но в этом случае пароль запрашивается самым первым и естественно он не срабатывает.

copy_auth_key.yml (копирует ключ)

- name: Log in server
  hosts: site
  remote_user: root
  tasks:
     - authorized_key:
       user: root
       state: present
       manage_dir: yes
       key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"

Запускаю командой

copy-key:
ansible-playbook -i hosts.yml --ask-pass copy_auth_key.yml

Запрашивается root пароль и ключ успешно копируется.

Этот код работает даже если первый завершится ошибкой из-за того, что не указан root пароль для первой задачи.

1) Как можно убрать ручной ввод подтверждения и как передать пароль, чтобы ansible реагировал на него после ввода подтверждения (для add_known_hosts.yml)?

2) Как можно объединить эти два yml файла, через handler?

Ответить
Дмитрий Елисеев

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

Я добавляю свой ключ сразу в интерфейсе хостинга и потом все виртуалки создаются сразу с ним. Так что прокидывать ключ для root отдельно через Ansible не приходится.

Ответить
slo_nik

Я это понял. Но как сделать так, как я описал в комментарии? Создаётся виртуалка, Вам предоставляется пользователь root и пароль. Вот чтобы не заходить ни в панель хостинга, ни по ssh и вручную копировать, а через ansible, как я пытался сделать.

Ответить
Дмитрий Елисеев

Я бы просто в hosts.yml указал пароль:

hosts:
    server:
        ansible_connection: ssh
        ansible_user: root
        ansible_password: pass
        ansible_host: 95.213.199.169

и потом бы при желании запустил copy-key.

Ответить
slo_nik

Пароль получается в открытом виде будет в ansible_password?

Ответить
Дмитрий Елисеев

Сначала в локальном hosts.yml будет открытым. Потом запущу copy-key и этот пароль удалю.

Ответить
slo_nik

А, ну да. Есть же файл hosts.yml.dist, его в репозиторий, а hosts.yml в gitignore и dockerignore.

Ответить
slo_nik

К сожалению такой вариант не сработал. Выдал ошибку.

fatal: [server]: FAILED! => {"msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this.  Please add this host's fingerprint to your known_hosts file to manage this host."}
Ответить
Sergalas

Может я самый тупой здесь но у меня есть два вопроса:

  1. как и где указать папку для деплоя на сервере тоесть условно /var/www/deworker.pro
  2. как и где узнавать пользователя для ansible для make docker-login
Ответить
slo_nik

Добрый день.

1) В домашней директории пользователя на сервере, то есть, /home/username. При подключении к серверу по ssh Вы попадаете именно в домашний каталог пользователя.

2) Это Ваши данные, которые Вы указали при регистрации на hub.docker.com. Но для docker login, как я понял, лучше использовать token, который можно создать в личном кабинете на hub.docker.com.

Ответить
Sergalas

Спасибо. А не подскажете ещё ? А поменять адерс куда будет деполоиться есть возможность ?

Ответить
slo_nik

В смысле поменять адрес?

В Makefile при выполнении deploy Вы указываете в параметре HOST адрес, на который Вы хотите выгрузить свои наработки. Укажите другой ip и всё. Это если я Вас правильно понял.

HOST=username@id_remote_server
Ответить
slo_nik

Добрый день, Дмитрий.

Появились пару вопросов.

1) Есть некий домен для которого выпущены сертификаты ssl. Этот домен планируется перенести на другой сервер и настроить автоматическое продление сертифкатов. Могут ли возникнуть проблемы при выпуске сертификатов через letsencrypt, если срок действия текущих сертификатов ещё не истёк?

2) При создании cron задачи на очистку docker от неиспользуемых image Вы указываете период в 30 дней

 'docker system prune -af --filter "until=$((30*24))h"'

Почему именно Вы храните image именно месяц? Думаю, что можно чистить от неиспользуемых чаще. Ведь можно и за день заполнить всё дисковое пространство на сервере(что вчера у меня и вышло).

Ответить
Дмитрий Елисеев

1) Сначала пока не обновятся DNS-кэши сервер Lets Encrypt будет попадать на старую виртуалку. Потом это исправится и всё получится. А так никаких проблем не будет.

2) Да, можно и меньше.

Ответить
slo_nik

1) Значит надо указать новые ns записи для домена и подождать, пока они не обновятся, потом только запускать создание ключей lets encrypt?

Ответить
Дмитрий Елисеев

Либо подождать, либо просто скопировать папку /etc/letcencrypt с одной виртуалки на другую.

Ответить
slo_nik

Понял. Скорей всего придётся ждать, так как на старом сервере простой shared хостинг.

Ответить
Дмитрий Елисеев

Чтобы меньше ждать можно за день до переезда в настройках DNS домена для A-записи указать TTL в 60 секунд. Так все кэширующие серверы потом обновятся за минуту.

Ответить
slo_nik

Спасибо.

Ответить
Sam

Здравствуйте, у меня установлен Ansible на Win10, пинг "ansible all -m ping -i hosts.yml" проходит нормально, но при запуске "make site" выдаёт следующую ошибку:

$ make site ansible-playbook -i hosts.yml site.yml process_begin: CreateProcess(NULL, python3.7 C:\cygwin64\bin\ansible-playbook -i hosts.yml site.yml, ...) failed. make (e=193): Error 193 make: *** [site] Error 193

Подскажите, плиз в чём может быть ошибка.

Ответить
Дмитрий Елисеев

Не работаю с Windows, так что не подскажу.

Ответить
Юрий

После первого запуска "make site" получил ошибку:

TASK [site : Generate new certificate]
failed: [server] (item={'changed': False, 'stat': {'exists': False}, 'invocation': {'module_args': {'path': '/etc/letsencrypt/live/site-blade.ru/cert.pem', 'follow': False, 'get_md5': False, 'get_checksum': True, 'get_mime': True, 'get_attributes': True, 'checksum_algorithm': 'sha1'}}, 'failed': False, 'item': 'site-blade.ru', 'ansible_loop_var': 'item'}) => {"ansible_loop_var": "item", "changed": true, "cmd": "certbot certonly --noninteractive --agree-tos --email mail@site-blade.ru -d site-blade.ru", "delta": "0:00:00.685884", "end": "2021-10-03 05:19:18.389513", "item": {"ansible_loop_var": "item", "changed": false, "failed": false, "invocation": {"module_args": {"checksum_algorithm": "sha1", "follow": false, "get_attributes": true, "get_checksum": true, "get_md5": false, "get_mime": true, "path": "/etc/letsencrypt/live/site-blade.ru/cert.pem"}}, "item": "site-blade.ru", "stat": {"exists": false}}, "msg": "non-zero return code", "rc": 1, "start": "2021-10-03 05:19:17.703629", "stderr": "Saving debug log to /var/log/letsencrypt/letsencrypt.log\nPlugins selected: Authenticator webroot, Installer None\nAn unexpected error occurred:\nTraceback (most recent call last):\n  File \"/usr/lib/python3/dist-packages/josepy/interfaces.py\", line 180, in json_loads\n    loads = json.loads(json_string)\n  File \"/usr/lib/python3.8/json/__init__.py\", line 357, in loads\n    return _default_decoder.decode(s)\n  File \"/usr/lib/python3.8/json/decoder.py\", line 337, in decode\n    obj, end = self.raw_decode(s, idx=_w(s, 0).end())\n  File \"/usr/lib/python3.8/json/decoder.py\", line 355, in raw_decode\n    raise JSONDecodeError(\"Expecting value\", s, err.value) from None\njson.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)\n\nDuring handling of the above exception, another exception occurred:\n\njosepy.errors.DeserializationError: Deserialization error: Expecting value: line 1 column 1 (char 0)\nPlease see the logfiles in /var/log/letsencrypt for more details.", "stderr_lines": ["Saving debug log to /var/log/letsencrypt/letsencrypt.log", "Plugins selected: Authenticator webroot, Installer None", "An unexpected error occurred:", "Traceback (most recent call last):", "  File \"/usr/lib/python3/dist-packages/josepy/interfaces.py\", line 180, in json_loads", "    loads = json.loads(json_string)", "  File \"/usr/lib/python3.8/json/__init__.py\", line 357, in loads", "    return _default_decoder.decode(s)", "  File \"/usr/lib/python3.8/json/decoder.py\", line 337, in decode", "    obj, end = self.raw_decode(s, idx=_w(s, 0).end())", "  File \"/usr/lib/python3.8/json/decoder.py\", line 355, in raw_decode", "    raise JSONDecodeError(\"Expecting value\", s, err.value) from None", "json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)", "", "During handling of the above exception, another exception occurred:", "", "josepy.errors.DeserializationError: Deserialization error: Expecting value: line 1 column 1 (char 0)", "Please see the logfiles in /var/log/letsencrypt for more details."], "stdout": "", "stdout_lines": []}
failed: [server] (item={'changed': False, 'stat': {'exists': False}, 'invocation': {'module_args': {'path': '/etc/letsencrypt/live/api.site-blade.ru/cert.pem', 'follow': False, 'get_md5': False, 'get_checksum': True, 'get_mime': True, 'get_attributes': True, 'checksum_algorithm': 'sha1'}}, 'failed': False, 'item': 'api.site-blade.ru', 'ansible_loop_var': 'item'}) => {"ansible_loop_var": "item", "changed": true, "cmd": "certbot certonly --noninteractive --agree-tos --email mail@site-blade.ru -d api.site-blade.ru", "delta": "0:00:00.442266", "end": "2021-10-03 05:19:19.257449", "item": {"ansible_loop_var": "item", "changed": false, "failed": false, "invocation": {"module_args": {"checksum_algorithm": "sha1", "follow": false, "get_attributes": true, "get_checksum": true, "get_md5": false, "get_mime": true, "path": "/etc/letsencrypt/live/api.site-blade.ru/cert.pem"}}, "item": "api.site-blade.ru", "stat": {"exists": false}}, "msg": "non-zero return code", "rc": 1, "start": "2021-10-03 05:19:18.815183", "stderr": "Saving debug log to /var/log/letsencrypt/letsencrypt.log\nPlugins selected: Authenticator webroot, Installer None\nAn unexpected error occurred:\nTraceback (most recent call last):\n  File \"/usr/lib/python3/dist-packages/josepy/interfaces.py\", line 180, in json_loads\n    loads = json.loads(json_string)\n  File \"/usr/lib/python3.8/json/__init__.py\", line 357, in loads\n    return _default_decoder.decode(s)\n  File \"/usr/lib/python3.8/json/decoder.py\", line 337, in decode\n    obj, end = self.raw_decode(s, idx=_w(s, 0).end())\n  File \"/usr/lib/python3.8/json/decoder.py\", line 355, in raw_decode\n    raise JSONDecodeError(\"Expecting value\", s, err.value) from None\njson.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)\n\nDuring handling of the above exception, another exception occurred:\n\njosepy.errors.DeserializationError: Deserialization error: Expecting value: line 1 column 1 (char 0)\nPlease see the logfiles in /var/log/letsencrypt for more details.", "stderr_lines": ["Saving debug log to /var/log/letsencrypt/letsencrypt.log", "Plugins selected: Authenticator webroot, Installer None", "An unexpected error occurred:", "Traceback (most recent call last):", "  File \"/usr/lib/python3/dist-packages/josepy/interfaces.py\", line 180, in json_loads", "    loads = json.loads(json_string)", "  File \"/usr/lib/python3.8/json/__init__.py\", line 357, in loads", "    return _default_decoder.decode(s)", "  File \"/usr/lib/python3.8/json/decoder.py\", line 337, in decode", "    obj, end = self.raw_decode(s, idx=_w(s, 0).end())", "  File \"/usr/lib/python3.8/json/decoder.py\", line 355, in raw_decode", "    raise JSONDecodeError(\"Expecting value\", s, err.value) from None", "json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)", "", "During handling of the above exception, another exception occurred:", "", "josepy.errors.DeserializationError: Deserialization error: Expecting value: line 1 column 1 (char 0)", "Please see the logfiles in /var/log/letsencrypt for more details."], "stdout": "", "stdout_lines": []}

После второго запуска "make site" получил ошибку:

TASK [site : Up certbot standalone Apache]
fatal: [server]: FAILED! => {"changed": true, "cmd": "docker run -d --name apache -v /var/www/html:/usr/local/apache2/htdocs/ -p 80:80 httpd:2.4", "delta": "0:00:00.486208", "end": "2021-10-03 05:15:29.668210", "msg": "non-zero return code", "rc": 125, "start": "2021-10-03 05:15:29.182002", "stderr": "docker: Error response from daemon: Conflict. The container name \"/apache\" is already in use by container \"0526bf077f3cc258c4f88b2399a39c4d7c88c1cf50c092fea9eae6b7b7501bdd\". You have to remove (or rename) that container to be able to reuse that name.\nSee 'docker run --help'.", "stderr_lines": ["docker: Error response from daemon: Conflict. The container name \"/apache\" is already in use by container \"0526bf077f3cc258c4f88b2399a39c4d7c88c1cf50c092fea9eae6b7b7501bdd\". You have to remove (or rename) that container to be able to reuse that name.", "See 'docker run --help'."], "stdout": "", "stdout_lines": []}

В чем причина данного безобразия?

Ответить
Юрий

Поменял --name apache на docker run -d --name apache1 -v опять первая ошибка

Ответить
Юрий

Ошибку в блоке "Up certbot standalone Apache" решил ручным удаление контейнера с именем: apache на сервере

Ошибку "Generate new certificate" не получается исправить

Ответить
Юрий

Вопрос закрыт, разобрался

Ответить
Юрий

Все сделал в соответствии с уроком. Сайт залил на витуалку. Все без ошибок. Сайт не открывается. Все пингуется, A и CNAME записи в DNS прописаны корректно.

Пишет:

Сайт blade.azzorsoft.ru не позволяет установить соединение
Сайт api.blade.azzorsoft.ru не позволяет установить соединение

Все по двадцать раз проверил, НЕ ЗАПУСКАЕТСЯ САЙТ!!! HELP люди!!!!

Ответить
Юрий

Вопрос закрыт

Ответить
Антон

Дмитрий, большое спасибо за ваши скринкасты! Всё очень круто и полезно!

Подскажите пожалуйста, с чем может быть связана эта ошибка на этапе make deploy, вроде всё как у вас сделал, только docker registry сделал на каком то бесплатном сервисе, не на своей виртуалке.

Recreating 546428fe9906_auction_gateway_1 ...
Recreating 546428fe9906_auction_gateway_1 ... error

ERROR: for 546428fe9906_auction_gateway_1  Cannot start service gateway: driver failed programming external connectivity on endpoint auction_gateway_1 (239af4b854dacaee842f436545bc4f5b2df0a603f5272ed9248569b6de799a71): Bind for 0.0.0.0:80 failed: port is already allocated
Ответить
Дмитрий Елисеев

С чем может быть связана эта ошибка

Bind for 0.0.0.0:80 failed: port is already allocated

С тем, что 80 порт в вашем сервисе уже занят каким-либо сервером.

Ответить
Антон

Странно - вроде ничем не занят(

root@dangerous-culebra:~# sudo lsof -i:80
root@dangerous-culebra:~#

Это получается в каком то контейнере какой то процесс занял порт 80?

Ответить
Антон Жданов

А можно поподробнее о том как была написана конфигурация для Nginx.

Например, существует генератор, который создаст готовую, но там всё иначе nginx.conf vs conf.d, sites-available и т.д.

Можете порекомендовать ресурсы для изучения Nginx? Документацию смотрел, там много чего. А вот для начинающего?

Ответить
Дмитрий Елисеев

о там всё иначе nginx.conf vs conf.d, sites-available и т.д.

Если рассматривать конфигурацию, то Nginx изначально загружает один файл:

etc/
    nginx/
        nginx.conf

и все настройки сервера и хостов можно вписывать прямо в него.

Но это неудобно, так как при обновлении Nginx можно этот файл случайно перезатереть. Поэтому чтобы примешивать туда свои настройки в Linux популярен подход добавления импорта всех файлов из особой папки conf.d. Для этого в оригинальном nginx.conf имеется строка импорта всех файлов из этой папки:

include conf.d/*.conf;

В итоге мы можем насоздавать в ней сколько угодно своих файлов:

etc/
    nginx/
        conf.d/
            my-security-params.conf
            my-other-params.conf
        nginx.conf

и все их содержимое в итоге смержится вместе.

Но если устанавливаем Nginx вручную на виртуальную машину для нескольких сайтов, то имеет смысл придерживаться более продвинутой структуры по примеру сервера Apache с отдельными папками sites-available для хостов и sites-enabled для символических ссылок на них. С ними можно включать и отключать сайты по отдельности пробрасыванием и удалением ярлыков в sites-enabled:

etc/
    nginx/
        conf.d/
            my-security-params.conf
            my-other-params.conf

        sites-available/
            default
            site1
            site2

        sites-enabled/
           00-default  -->  ../sites-available/default
           01-site1    -->  ../sites-available/site1

        nginx.conf // include conf.d/*.conf;
                   // include sites-enabled/*;

так как в nginx.conf ещё и производится импорт всех файлов из sites-enabled.

И помимо этого в комплекте по умолчанию имеются вспомогательные файлы вроде fastcgi_params.conf для упрощения добавления проксирования в тот же php-fpm.

Это полноценная конфигурация по умолчанию.

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

Так что по каким файлам раскладывать и как это всё потом импортировать – это дело вкуса.

Ответить
Антон Жданов

Спасибо за ответ. Очень классно.

Ответить
Антон Жданов

Здесь получается редирект 443 https://www -> https:// не работает, т.к сертификат не поддерживает www.

http: error: SSLError: HTTPSConnectionPool(host='www.demo-auction.domain.com', port=443): Max retries exceeded with url: / (Caused by SSLError(CertificateError("hostname 'www.demo-auction.domain.com' doesn't match 'api.demo-auction.domain.com'"))) while doing a GET request to URL: https://www.demo-auction.domain.com/

При генерации нужно указать certbot certonly --standalone -d domain.com -d www.domain.com для использования одного и того же сертификата для обеих блоков в nginx (не проверял лично).

Ответить
Иван

Извиняюсь за оффтоп, а какие-то настройки с шрифтами делали на ubuntu? на видео они кажутся норм, но когда себе ставил то по сравнению с windows сглаживание очень плохое

Ответить
Дмитрий Елисеев

Отдельно в Ubuntu ставил шрифт Tahoma.

Ответить
Pavel N

Добрый день, подскажите как устранить проблему сайт открывается по адресу example.com, а также example.com/index.php все настройки NGINX как в проекте

Ответить
Дмитрий Елисеев

Добавить канонические адреса через link rel="canonical".
Тогда поисковики не будут индексировать дубли.

Ответить
Павел

Здравствуйте, а почему решили выбрать для выпуска и продления сертификатов режим webroot, а не standalone?

Ответить
Павел

Разобрался, standalone используется в тех случаях, когда на сервере нет вебсервера и он не будет ставится, т.к. иначе при каждой установке/обновлении его надо будет останавливать, чтоб запустить вебсервер плагина standalone.

Ответить
Дмитрий Елисеев

Именно. При standalone он постоянно запущен и занимает порт.

Ответить
Андрей

При запуске

ansible-playbook hosts.yml --check

Получаю ошибку

provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

all:

hosts:
    server:
        ansible_connection: ssh
        ansible_user: root
        ansible_host: 188.68.220.228
        ansible_port: 22

В чём может быть проблема?

Ответить
Андрей

Разобрался, проблема была в другом. Ошибке yml докера

Ответить
skazkin

На таске site : Up certbot standalone Apache падает с ошибкой docker: Error response from daemon: cgroups: cgroup mountpoint does not exist: unknown. Кто-нибудь решил?

Ответить
skazkin
shell: "mkdir /sys/fs/cgroup/systemd; mount -t cgroup -o none,name=systemd cgrou/sys/fs/cgroup/systemd; docker run -d --name apache -v /var/www/html:/usr/local/apache2/htdocs/ -p 80:80 httpd:2.4"
Ответить
Павел

У меня после шага Up certbot standalone Apache была ошибка при генерации сертефикатов. Оказалось, что после поднятия контейнера с сервером он падал с ошибкой

AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message

Помогло поменять тег httpd:2.4 на httpd:alpine

Ответить
Павел

У кого MacBook с чипом M1, при билде нужно добавить флаг

docker --platform=linux/amd64

Без этого флага на продовом сервере контейнеры останавливались с ошибкой

exec user process caused: exec format error

https://appdividend.com/2023/01/29/exec-user-process-caused-exec-format-error/

Ответить
Анна

Это. Просто. Офигительно! Спасибо!!

Ответить
Аркадий

При добавлении репозитория certbot возникает ошибка, машина с Ubuntu 22.04

-   name: Add Certbot repository
    apt_repository:
        repo: 'ppa:certbot/certbot'
        state: present
        update_cache: yes

-   name: Install Certbot
    apt:
        name: certbot
        state: present
        update_cache: yes

Сама ошибка:

fatal: [server]: FAILED! => {"changed": false, "msg": "Failed to update apt cache: E:The repository 'http://ppa.launchpad.net/certbot/certbot/ubuntu jammy Release' does not have a Release file., W:Updating from such a repository
 can't be done securely, and is therefore disabled by default., W:See apt-secure(8) manpage for repository creation and user configuration details., W:https://download.docker.com/linux/debian/dists/stretch/InRelease: Key is stor
ed in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details."}

Подскажите пожалуйста.

Ответить
Аркадий

Уже неактуально. Решил благодаря комментариям. Не нашел, где Дмитрий вызывает handler main в docker. Он сам по себе не запускается.

Ответить
Сергей

Подскажите пожалуйста более подробно, как решили описанную ошибку

Ответить
Сергей

Пару дней промучался с воспроизведением данного урока через VPS на Debian 12. В итоге, всё успешно запустил и задеплоил. Может, кому пригодятся данные фиксы:

  1. ошибка "..does not have a Release file" при выполнении таски Add Certbot repository - заменить поддомен на archive

    apt_repository:
      repo: 'deb http://archive.debian.org/debian buster-backports main'
      state: present
      filename: buster-backports
      update_cache: yes
    
  2. Неявная ошибка при выполнении таска Generate new certificate (connection refuse при проверке acme-challenge). В первую очередь надо проверить A-записи для ваших доменов (об этом уже было сказано). Но в моём случае не запускался демон с апачем (запускался и через 4-5 сек отрубался), соответственно, Up certbot standalone Apache отрабатывал без ошибок, но соединение не проходило, надо использовать более старый образ httpd:2.4-bullseye

    shell: "docker run -d --name apache -v /var/www/html:/usr/local/apache2/htdocs/ -p 80:80 httpd:2.4-bullseye"
    when: port_check.failed == true
    
Ответить
Александр
TASK [certbot : Add Certbot repository] ***************************************************************************************************************************************
fatal: [server]: FAILED! => {"changed": false, "msg": "Failed to update apt cache: E:The repository 'http://ppa.launchpad.net/certbot/certbot/ubuntu jammy Release' does not have a Release file., W:Updating from such a repository can't be done securely, and is therefore disabled by default., W:See apt-secure(8) manpage for repository creation and user configuration details., W:https://download.docker.com/linux/ubuntu/dists/jammy/InRelease: Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details."}

подскажите что не так ?

Ответить
Александр

вобщем понял что длЯ убунты 22 надо поменять файл provisioning/roles/certbot/tasks/main.yml

---

-   name: Install Certbot
    apt:
        name: certbot
        state: present
        update_cache: yes

-   name: Copy Certbot configuration
    copy:
        src: files/cli.ini
        dest: /etc/letsencrypt/cli.ini
        owner: root
        group: root
        mode: 0644

-   name: Remove useless packages
    apt:
        autoclean: yes

-   name: Remove useless dependencies
    apt:
        autoremove: yes
Ответить
Александр

Одно не понятно nginx то должен быть уже установлен там или нет для основного домена ?

Ответить
Дмитрий Елисеев

Сначала ничего не должно быть. Первоначальный выпуск сертификатов идёт через Apache в docker.

В будущих эпизодах мы для автовыпуска сертификатов перейдём на Traefik. Там уже этот Apache будет не нужен.

Ответить
Александр
root@debian:/home/auction# make push REGISTRY=registry.**** IMAGE_TAG=master-1
docker push registry.*****/auction-gateway:master-1
The push refers to repository [registry.*****/auction-gateway]
c98cae2b357c: Preparing
b6f4187ddfc7: Preparing
c4f83620b49e: Preparing
3810cc0c140f: Preparing
3e207b409db3: Preparing
no basic auth credentials
make: *** [Makefile:85: push-gateway] Error 1

при попытке запушить ошибка , docker-login до этого отработал нормально/ Подскажите что tver не хватает ?

PS. пришлось вручную из папки auction выполнить docker login итд итп тогда авторизовало , из папки provisioning не подхватывает авторизацию

Ответить
Зарегистрируйтесь или войдите чтобы оставить комментарий

Или войти через:

Yandex
MailRu
GitHub
Google