One place for hosting & domains

      развертывание

      Развертывание и управление DNS с использованием OctoDNS в Debian 10


      Автор выбрал фонд Electronic Frontier Foundation для получения пожертвований в рамках программы Write for DOnations.

      Введение

      OctoDNS — это инструмент, созданный по принципу «инфраструктура как код», который поддерживает развертывание и управление зонами DNS с использованием стандартных принципов разработки программного обеспечения, включая контроль версий, тестирование и автоматизированное развертывание. OctoDNS был разработан GitHub и написан на языке Python.

      Использование OctoDNS помогает избавиться от многих сложностей ручного управления DNS, поскольку файлы зон хранятся в структурированном формате (YAML). Инструмент позволяет одновременно развертывать зоны для нескольких поставщиков DNS, определять ошибки синтаксиса и автоматически извлекать конфигурации DNS, за счет чего снижается риск человеческой ошибки. Также OctoDNS часто используется для синхронизации конфигурации DNS разных провайдеров, в частности между тестовыми и производственными системами или между работающими и резервными средами.

      Инструмент OctoDNS аналогичен инструменту DNSControl, созданному Stack Exchange и написанному на Go. В отличие от OctoDNS, в DNSControl для определения зон DNS используется язык конфигурации на базе JavaScript, что позволяет использовать различные функции программирования (например циклы) для определения нескольких похожих записей в одной зоне. Статья Развертывание и управление DNS с помощью DNSControl в Debian 10 рассказывает об основах настройки и конфигурации DNSControl.

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

      Предварительные требования

      Для прохождения этого обучающего руководства вам потребуется следующее:

      • Один сервер Debian 10, настроенный в соответствии с указаниями материала Начальная настройка сервера Debian 10, включая пользователя sudo без привилегий root и активированный брандмауэр для блокировки ненужных портов. your-server-ipv4-address и your-server-ipv6-address означают IP-адреса сервера, где будет размещаться ваш сайт или домен.
      • Полностью зарегистрированное доменное имя с хостингом DNS у поддерживаемого провайдера. В этом обучающем модуле мы используем доменное имя your-domain и DigitalOcean как провайдера услуги.
      • Ключ DigitalOcean API (персональный токен доступа) с разрешениями чтения и записи. Его создание описано в материале Создание персонального токена доступа.

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

      Шаг 1 — Установка OctoDNS

      OctoDNS распространяется как пакет Python pip и выполняется в виртуальной среде Python (virtualenv), так что мы начнем этот шаг с установки необходимых пакетов. virtualenv — это изолированная среда Python, которая может иметь собственные библиотеки и конфигурацию, отдельные от основной версии Python в системе. Python и virtualenv доступны в репозиториях программного обеспечения Debian по умолчанию, и поэтому их можно установить с помощью стандартных инструментов управления пакетами.

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

      Затем мы установим пакеты python и virtualenv:

      • sudo apt install python virtualenv

      После подтверждения установки apt выполнит загрузку и установку Python, virtualenv и всех необходимых зависимостей.

      Затем мы создадим необходимые для OctoDNS директории, где будут храниться конфигурации DNS и программы. Для начала создадим директории ~/octodns и ~/octodns/config:

      • mkdir ~/octodns ~/octodns/config

      Теперь перейдем в директорию ~/octodns:

      Теперь нам нужно создать виртуальную среду Python. Это изолированная среда Python с собственными библиотеками и конфигурацией, где будет работать OctoDNS:

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

      Будет выведен текст следующего вида:

      Output

      Running virtualenv with interpreter /usr/bin/python2 New python executable in /home/user/octodns/env/bin/python2 Also creating executable in /home/user/octodns/env/bin/python Installing setuptools, pkg_resources, pip, wheel...done.

      Строка оболочки Bash будет иметь префикс с именем виртуальной среды. Это показывает, что мы работаем в среде virtualenv:

      (env) user@digitalocean:~/octodns$
      

      Если мы захотим выйти из virtualenv, мы можем использовать команду deactivate в любой момент. Однако нам необходимо оставаться в среде virtualenv, чтобы продолжить выполнение этого обучающего руководства.

      Теперь вы установили и настроили Python и среду virtualenv и можете выполнить установку OctoDNS. OctoDNS распространяется как пакет Python pip (стандартный инструмент управления пакетами и библиотеками Python).

      Мы можем установить пакет OctoDNS pip с помощью команды в среде virtualenv:

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

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

      Output

      octoDNS 0.9.9

      Если будет выведено сообщение об ошибке octodns-sync: command not found, необходимо повторно убедиться, что мы находимся в среде virtualenv.

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

      Шаг 2 — Настройка OctoDNS

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

      Примечание. В этом обучающем руководстве мы рассматриваем начальную настройку OctoDNS, но для использования в производственной среде рекомендуется хранить конфигурацию OctoDNS в системе контроля версий (VCS), такой как Git. Это дает преимущества полного контроля версий, интеграции с CI/CD для тестирования, удобства откатов при развертывании и т. д.

      Вначале нам нужно настроить файл config.yaml, который определит зоны DNS для управления OctoDNS и позволит проводить аутентификацию у провайдера DNS и вносить изменения.

      Формат файла config.yaml может немного отличаться в зависимости от используемого провайдера DNS. Ознакомьтесь со списком поддерживаемых провайдеров в официальной документации OctoDNS, чтобы найти конфигурацию для вашего провайдера. При просмотре этой гиперссылки детали конфигурации выводятся как комментарий к коду в фактическом коде Python нашего провайдера, привязанного в столбце Provider в таблице. Когда мы найдем код Python нашего провайдера, например cloudflare.py или route53.py, соответствующий комментарий к коду можно будет найти в классе ProviderNameProvider. Например:

      Excerpt of octodns/provider/route53.py

      class Route53Provider(BaseProvider):
        '''
        AWS Route53 Provider
        route53:
            class: octodns.provider.route53.Route53Provider
            # The AWS access key id
            access_key_id:
            # The AWS secret access key
            secret_access_key:
            # The AWS session token (optional)
            # Only needed if using temporary security credentials
            session_token:
      

      Перейдите в директорию ~/octodns/config:

      Создайте файл config.yaml и откройте его для редактирования:

      Добавьте в файл образец конфигурации config.yaml для вашего провайдера DNS. Если вы используете DigitalOcean в качестве своего провайдера DNS, вы можете использовать следующее:

      ~/octodns/config/config.yaml

      ---
      providers:
        config:
          class: octodns.provider.yaml.YamlProvider
          directory: ./config
          default_ttl: 300
          enforce_order: True
        digitalocean:
          class: octodns.provider.digitalocean.DigitalOceanProvider
          token: your-digitalocean-oauth-token
      
      zones:
        your-domain.:
          sources:
            - config
          targets:
            - digitalocean
      

      Этот файл сообщает OctoDNS, к каким провайдерам DNS требуется подключаться и какими зонами DNS нужно управлять для этих провайдеров.

      Необходимо указать форму аутентификации для провайдера DNS. Обычно это ключ API или токен OAuth.

      Если вы не хотите хранить токен доступа в текстовой форме в файле конфигурации, вы можете передать его в переменную среды при запуске программы. Для этого нужно использовать следующую строку token: в файле config.yaml:

      ~/octodns/config/config.yaml

      token: env/DIGITALOCEAN_OAUTH_TOKEN
      

      Перед запуском OctoDNS необходимо задать следующую переменную среды для токена доступа, и OctoDNS будет считывать ее в месте запуска:

      • export DIGITALOCEAN_OAUTH_TOKEN=your-digitalocean-oauth-token

      Предупреждение. Этот токен предоставляет доступ к учетной записи провайдера DNS, так что его следует защитить паролем. Также необходимо убедиться, что если вы используете систему контроля версий, файл с токеном исключен (например, с помощью .gitignore) или зашифрован.

      Если в качестве провайдера DNS используется DigitalOcean, можно использовать требуемый токен OAuth в параметрах учетной записи DigitalOcean, сгенерированных при выполнении предварительных требований.

      Если вы используете нескольких провайдеров DNS, например для разных доменных имен или делегированных зон DNS, вы можете определить их в том же самом файле config.yaml.

      Мы настроили начальный файл конфигурации OctoDNS, чтобы программа могла проходить аутентификацию на провайдере DNS и вносить требуемые изменения. Теперь мы создадим конфигурацию для наших зон DNS.

      Шаг 3 — Создание файла конфигурации DNS

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

      Для каждой зоны DNS, управляемой с помощью OctoDNS, должен существовать собственный файл, например your-domain.yaml. В этом файле записи DNS для зоны определяются с помощью YAML.

      Для начала перейдем в директорию ~/octodns/config:

      Затем создадим файл your-domain.yaml и откроем его для редактирования:

      Добавим в файл следующий образец конфигурации:

      ~/octodns/config/your-domain.yaml

      ---
      '':
        - type: A
          value: your-server-ipv4-address
      
      www:
        - type: A
          value: your-server-ipv4-address
      

      В этом файле образца определяется зона DNS для your-domain с двумя записями A, указывающими на адрес IPv4, на котором размещен домен или сайт. Одна запись A предназначена для корневого домена (например, your-domain), а другая — для субдомена www (например, www.your-domain).

      После завершения следует сохранить и закрыть файл.

      Мы настроили базовый файл конфигурации зоны DNS для OctoDNS с двумя базовыми записями A, указывающими на адрес IPv4 вашего домена или сайта. Далее мы заполним файл полезными записями DNS.

      Шаг 4 — Заполнение файла конфигурации DNS

      Теперь мы можем заполнить файл конфигурации DNS практическим набором записей DNS для нашего сайта или сервиса, используя струткурированный язык конфигурации YAML.

      В отличие от традиционных файлов зоны BIND, где записи DNS записаны в необработанном построчном формате, записи DNS в OctoDNS определены как ключи и подключи YAML с рядом связанных значений, как кратко показано на шаге 3.

      Ключ 'name' обычно является ключом верхнего уровня, то есть идентификатором записи. Ключи www, subdomain1 и mail являются примерами ключа name службы DNS. В OctoDNS имеется два имени специального назначения: " для корневой записи (обычно @), и '*' для записей с подстановочными символами. Для каждого ключа (записи DNS) требуется значение type. Оно определяет, какой тип записей DNS мы определяем ключом YAML верхнего уровня. Значение type существует для каждого из стандартных типов записей DNS, в том числе A, AAAA, MX, TXT, NS, CNAME и т. д. Полный список доступных типов записей можно найти в разделе Записи в документации по OctoDNS.

      Значения записей DNS определяются напрямую как значения ключей верхнего уровня (если используется только одно значение) или в форме списка (если используется несколько значений, например несколько IP-адресов или адресов MX).

      Например, для определения одного значения можно использовать следующую конфигурацию:

      ~/octodns/config/your-domain.yaml

      'www':
        type: A
        value: 203.0.113.1
      

      Также можно определить несколько значений для одной записи:

      ~/octodns/config/your-domain.yaml

      'www':
        type: A
        values:
        - 203.0.113.1
        - 203.0.113.2
      

      Синтаксис настройки записей DNS немного отличается для каждого типа записей. Далее приведены несколько примеров наиболее распространенных типов записей:

      Записи A:

      Назначение: указывают на адрес IPv4.

      Синтаксис:

      'name':
        type: A
        value: ipv4-address
      

      Пример:

      'www':
        type: A
        value: your-server-ipv4-address
      

      Записи AAAA:

      Назначение: указывают на адрес IPv6.

      Синтаксис:

      'name':
        type: AAAA
        value: ipv6-address
      

      Пример:

      'www':
        type: AAAA
        value: your-server-ipv6-address
      

      Записи CNAME:

      Назначение: делают домен или субдомен псевдонимом другого домена или субдомена.

      Синтаксис:

      'name':
        type: CNAME
        value: fully-qualified-domain-name
      

      Пример:

      'www':
        type: CNAME
        value: www.example.org
      

      Записи MX:

      Назначение: направляют электронную почту на определенные серверы или адреса.

      Синтаксис:

      'name':
        type: MX
        value:
          exchange: mail-server
          preference: priority-value
      

      Следует отметить, что если в значении MX содержатся точки, завершающий символ . обязательно должен быть указан в конце строки.

      Пример:

      '':
        type: MX
        value:
          exchange: mail.your-domain.
          preference: 10
      

      Записи TXT:

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

      Синтаксис:

      'name':
        type: TXT
        value: content
      

      Пример:

      '':
        type: TXT
        value: This is a TXT record.
      

      Чтобы начать добавлять записи DNS для нашего домена или делегированной зоны DNS, нам нужно отредактировать файл конфигурации DNS:

      • cd ~/octodns/config
      • nano your-domain.yaml

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

      Приведенный здесь блок кода содержит полный образец начальной конфигурации DNS, предназначенный для справочных целей:

      ~/octodns/config/your-domain.yaml

      ---
      '':
        - type: A
          value: your-server-ipv4-address
      
        - type: AAAA
          value: your-server-ipv6-address
      
        - type: MX
          value:
            exchange: mail.your-domain.
            preference: 10
      
        - type: TXT
          value: v=spf1 -all
      
      _dmarc:
        type: TXT
        value: v=DMARC1; p=reject; rua=mailto:abuse@your-domain; aspf=s; adkim=s;
      
      mail:
        - type: A
          value: your-server-ipv4-address
      
        - type: AAAA
          value: your-server-ipv6-address
      
      www:
        - type: A
          value: your-server-ipv4-address
      
        - type: AAAA
          value: your-server-ipv6-address
      

      После завершения начальной настройки DNS следует сохранить и закрыть файл.

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

      Шаг 5 — Тестирование и развертывание конфигурации DNS

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

      Вначале мы перейдем в директорию octodns:

      Еще раз проверим, что мы работаем в среде Python virtualenv, посмотрев на имя перед Bash в командной строке:

      (env) user@digitalocean:~/octodns$
      

      Затем используем команду octodns-validate для проверки синтаксиса файла или файлов конфигурации. Также необходимо указать путь к файлу конфигурации:

      • octodns-validate --config=./config/config.yaml

      Если синтаксис YAML конфигурации DNS правильный, OctoDNS не выводит никаких результатов. Если вы увидите предупреждение об ошибке в составе результатов, OctoDNS даст дополнительные данные о сущности ошибки и ее местонахождении в файле YAML.

      Далее можно выполнить пробную установку конфигурации DNS. При этом будет показано, какие будут произведены изменения, но выполняться они не будут:

      • octodns-sync --config=./config/config.yaml

      Результат должен выглядеть примерно так:

      Output

      ******************************************************************************** * your-domain. ******************************************************************************** * digitalocean (DigitalOceanProvider) * Create <ARecord A 300, mail.your-domain., ['your-server-ipv4-address']> (config) * Create <AaaaRecord AAAA 300, mail.your-domain., ['your-server-ipv6-address']> (config) * Create <TxtRecord TXT 300, your-domain., ['v=spf1 -all']> (config) * Create <AaaaRecord AAAA 300, your-domain., ['your-server-ipv6-address']> (config) * Create <ARecord A 300, your-domain., ['your-server-ipv4-address']> (config) * Create <ARecord A 300, www.your-domain., ['your-server-ipv4-address']> (config) * Create <MxRecord MX 300, your-domain., [''10 mail.your-domain.'']> (config) * Create <TxtRecord TXT 300, _dmarc.your-domain., ['v=DMARC1; p=reject; rua=mailto:abuse@your-domain; aspf=s; adkim=s;']> (config) * Create <AaaaRecord AAAA 300, www.your-domain., ['your-server-ipv6-address']> (config) * Summary: Creates=9, Updates=0, Deletes=0, Existing Records=2 ********************************************************************************

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

      В заключение мы можем передать изменения на рабочий провайдер DNS:

      • octodns-sync --config=./config/config.yaml --doit

      Примечание. В некоторых случаях OctoDNS может отказаться применять изменения, если количество модификаций значительно. Это функция автоматической защиты, которая позволит предотвратить случайные ошибки конфигурации. В случае такого отклонения можно повторно запустить octodns-sync с опцией --force, но при этом нужно быть уверенным в правильности этого шага.

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

      Output

      2019-07-07T23:17:27 INFO DigitalOceanProvider[digitalocean] apply: making changes 2019-07-07T23:17:30 INFO Manager sync: 9 total changes

      Если теперь мы проверим параметры DNS нашего домена на панели управления DigitalOcean, мы увидим изменения.

      Снимок экрана панели управления DigitalOcean, показывающий некоторые изменения DNS, которые были внесены OctoDNS.

      Также мы можем проверить создание записи, отправив запрос DNS для нашего домена или делегированной зоны с помощью команды dig.

      Если команда dig не установлена, необходимо установить пакет dnsutils:

      • sudo apt install dnsutils

      После установки команды dig мы сможем использовать ее для запроса DNS нашего домена. Мы увидим, что записи обновлены соответствующим образом:

      В результатах выводится IP-адрес и запись DNS из вашей зоны, которая была развернута с помощью OctoDNS. Распространение записей DNS может занять некоторое время, поэтому можно подождать и запустить команду чуть позже.

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

      Заключение

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

      Если вы хотите узнать об этом больше, OctoDNS предусматривает интеграцию с конвейером CI/CD, что позволяет проводить детальные испытания и обеспечивает дополнительный контроль над развертыванием в производственной среде. Также можно интегрировать OctoDNS в процессы сборки и развертывания инфраструктуры, что позволит развертывать серверы и добавлять их в службу DNS в полностью автоматическом режиме.

      Если вы хотите узнать больше о возможностях OctoDNS, в следующих статьях DigitalOcean вы найдете интересную информацию о следующих шагах по интеграции OctoDNS в рабочие процессы управления изменениями и развертывания инфраструктуры:



      Source link

      Развертывание приложения PHP с Kubernetes на Ubuntu 16.04


      Автор выбрал фонд Open Internet/Free Speech Fund для получения пожертвования в рамках программы Write for DOnations.

      Введение

      Kubernetes — это система с открытым исходным кодом, предназначенная для оркестрации контейнеров. Она позволяет вам создавать, обновлять и масштабировать контейнеры, не беспокоясь о вынужденном простое.

      Для запуска PHP-приложения Nginx выступает в роли прокси-сервера для PHP-FPM. Контейнеризация этой системы в одном контейнере может быть обременительной задачей, но Kubernetes поможет организовать управление обоими службами, расположенными в отдельных контейнерах. Использование Kubernetes позволяет вам организовать многократное использование ваших контейнеров и переключение между ними, и вам не придется каждый раз повторно собирать образ контейнера при выходе новой версии Nginx или PHP.

      В этом руководстве вы развернете приложение PHP 7 в кластере Kubernetes с помощью Nginx и PHP-FPM, работающих в отдельных контейнерах. Также вы узнаете, как хранить ваши файлы конфигурации и код приложения за пределами образа контейнера, используя блочную систему хранения DigitalOcean. Такой подход позволит вам повторно использовать образ Nginx для любого приложения, которое нуждается в веб-сервере или прокси-сервере, передавая только том конфигурации без необходимости повторной сборки образа.

      Предварительные требования

      • Базовое понимание объектов Kubernetes. Ознакомьтесь с нашей статьей Введение в Kubernetes для получения дополнительной информации.
      • Кластер Kubernetes, работающий на Ubuntu 16.04 Вы можете выполнить данную настройку с помощью руководства Создание кластера Kubernetes 1.10 с помощью Kubeadm на Ubuntu 16.04.
      • Учетная запись DigitalOcean и маркер доступа API с разрешениями на чтение и запись для создания нашего тома хранения. Если у вас нет маркера доступа API, вы можете создать его здесь.
      • Код вашего приложения, размещенный на общедоступном URL, например, Github.

      Шаг 1 — Создание служб PHP-FPM и Nginx

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

      Поскольку поды Nginx будут проксировать поды PHP-FPM, вам нужно показать службе, как их найти. Вместо IP-адресов вы сможете использовать преимущества автоматической службы обнаружения Kubernetes для использования человекочитаемых имен для перенаправления запросов на соответствующую службу.

      Чтобы создать службу, вы создадите файл определения объекта. Каждое определение объекта Kubernetes — это файл YAML, содержащий по крайней мере следующие элементы:

      • apiVersion: версия API Kubernetes, к которой принадлежит определение.
      • kind: объект Kubernetes, который представляет этот файл. Например, pod или service.
      • metadata: здесь содержится name объекта наряду с labels, который вы можете захотеть применить к объекту.
      • spec: этот элемент содержит конкретную конфигурацию в зависимости от вида создаваемого объекта, например, образ контейнера или порты, через которые контейнер будет доступен.

      Сначала мы создадим директорию для хранения определений объекта Kubernetes.

      Подключитесь по SSH к своему главному узлу и создайте директорию definitions, где будут храниться определения объекта Kubernetes.

      Перейдите в недавно созданную директорию definitions:

      Создайте службу PHP-FPM с помощью создания файла php_service.yaml:

      Задайте значение Service для параметра kind для указания того, что этот объект представляет собой службу:

      php_service.yaml

      ...
      apiVersion: v1
      kind: Service
      

      Назовите службу php, поскольку она будет предоставлять доступ к PHP-FPM:

      php_service.yaml

      ...
      metadata:
        name: php
      

      Вы будете логически группировать различные объекты с помощью меток. В этом руководстве вы будете использовать метки для группирования объектов в уровни, например, фронтэнд или бекэнд. PHP-поды будут работать в фоне службы, поэтому вы можете пометить это следующим образом: tier: backend.

      php_service.yaml

      ...
        labels:
          tier: backend
      

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

      Используйте метку tier: backend для привязки пода к уровню бекэнда. Затем вы должны добавить метку app: php, чтобы указать, что этот под запускает PHP. Добавьте две эти метки после раздела metadata.

      php_service.yaml

      ...
      spec:
        selector:
          app: php
          tier: backend
      

      Затем укажите порт, используемый для доступа к этой службе. В этом руководстве вы будете использовать порт 9000. Добавьте его в файл php_service.yaml под разделом spec:

      php_service.yaml

      ...
        ports:
          - protocol: TCP
            port: 9000
      

      Ваш готовый файл php_service.yaml будет выглядеть следующим образом:

      php_service.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: php
        labels:
          tier: backend
      spec:
        selector:
          app: php
          tier: backend
        ports:
        - protocol: TCP
          port: 9000
      

      Нажмите CTRL + o для сохранения файла, а затем CTRL + x для выхода из редактора nano.

      Теперь, когда вы создали определение объекта для службы, для запуска службы вы будете использовать команду kubectl apply с аргументом -f и указанием файла php_service.yaml.

      Создайте службу:

      • kubectl apply -f php_service.yaml

      Данный вывод подтверждает создание службы:

      Output

      service/php created

      Убедитесь, что служба запущена:

      Вы увидите, что служба PHP-FPM работает:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10m php ClusterIP 10.100.59.238 <none> 9000/TCP 5m

      Существуют различные типы служб, поддерживаемые Kubernetes. Ваша служба php использует тип службы по умолчанию, ClusterIP. Данный тип службы назначает внутренний IP-адрес и делает службу доступной только внутри кластера.

      Теперь, когда служба PHP-FPM готова, мы перейдем к созданию службы Nginx. Создайте и откройте новый файл nginx_service.yaml с помощью редактора:

      Данная служба будет затрагивать поды Nginx, поэтому вы должны будете назвать ее nginx. Затем вы должны будете добавить метку tier: backend, потому что она принадлежит к уровню бекэнда.

      nginx_service.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: nginx
        labels:
          tier: backend
      

      Как и в случае со службой php, настройте работу с подами с помощью меток selector — app: nginx и tier: backend. Cделайте эту службу доступной для порта 80, порта HTTP по умолчанию.

      nginx_service.yaml

      ...
      spec:
        selector:
          app: nginx
          tier: backend
        ports:
        - protocol: TCP
          port: 80
      

      Служба Nginx будет доступна из Интернета при использовании вашего открытого IP-адреса Droplet. <^>your_public_ip^> можно найти в вашей облачной панели DigitalOcean. В разделе spec.externalIPs добавьте:

      nginx_service.yaml

      ...
      spec:
        externalIPs:
        - your_public_ip
      

      Ваш файл nginx_service.yaml будет выглядеть следующим образом:

      nginx_service.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: nginx
        labels:
          tier: backend
      spec:
        selector:
          app: nginx
          tier: backend
        ports:
        - protocol: TCP
          port: 80
        externalIPs:
        - your_public_ip    
      

      Сохраните и закройте файл. Создайте службу Nginx:

      • kubectl apply -f nginx_service.yaml

      После запуска службы вы увидите следующий вывод:

      Output

      service/nginx created

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

      Вы увидите службы PHP-FPM и Nginx, представленные в результате выполнения команды:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13m nginx ClusterIP 10.102.160.47 your_public_ip 80/TCP 50s php ClusterIP 10.100.59.238 <none> 9000/TCP 8m

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

      • kubectl delete svc/service_name

      Теперь, когда вы создали службы PHP-FPM и Nginx, вам нужно указать, где вы будете хранить ваш код приложения и файлы конфигурации.

      Шаг 2 — Установка плагина хранилища DigitalOcean

      Kubernetes предоставляет различные плагины для хранения, которые позволяют создавать пространство для хранения вашей среды. На этом шаге вы будете устанавливать плагин хранилища DigitalOcean для создания блочного хранилища в DigitalOcean. После завершения установки будет добавлен класс хранения под названием do-block-storage, который вы будете использовать для создания блочного хранилища.

      Сначала вам нужно будет настроить для Kubernetes объект типа Secret для хранения маркера API DigitalOcean. Объекты Secret используются для обмена чувствительной информацией, например, ключами и паролями SSH, с другими объектами Kubernetes в одном пространстве имен. Пространства имен предоставляют способ логического разделения ваших объектов Kubernetes.

      Откройте файл secret.yaml в редакторе:

      Назовите ваш объект типа Secret digitalocean и добавьте его в пространство имен kube-system. Пространство имен kube-system — это используемое по умолчанию пространство имен для внутренних служб Kubernetes, которое также используется в плагине хранилища DigitalOcean для запуска различных компонентов.

      secret.yaml

      apiVersion: v1
      kind: Secret
      metadata:
        name: digitalocean
        namespace: kube-system
      

      Вместо ключа spec объект Secret использует ключ data или stringData для хранения необходимой информации. Параметр data хранит закодированные с помощью стандарта base64 данные, которые автоматически расшифровываются при получении. Параметр stringData хранит незашифрованные данные, автоматически закодированные во время создания или обновления, и не выводит данные при получении объектов типа Secret. Для удобства вы будете использовать stringData в рамках этого руководства.

      Добавьте access-token в качестве stringData:

      secret.yaml

      ...
      stringData:
        access-token: your-api-token
      

      Сохраните и закройте файл.

      Ваш файл secret.yaml будет выглядеть следующим образом:

      secret.yaml

      apiVersion: v1
      kind: Secret
      metadata:
        name: digitalocean
        namespace: kube-system
      stringData:
        access-token: your-api-token
      

      Создайте объект типа Secret:

      • kubectl apply -f secret.yaml

      Вы увидите следующий результат при создании объекта Secret:

      Output

      secret/digitalocean created

      Вы можете просмотреть объект Secret с помощью следующей команды:

      • kubectl -n kube-system get secret digitalocean

      Результат будет выглядеть примерно следующим образом:

      Output

      NAME TYPE DATA AGE digitalocean Opaque 1 41s

      Тип Opaque означает, что этот объект типа Secret предназначен только для чтения, что соответствует стандарту для объектов Secret stringData. Вы можете ознакомиться с дополнительной информацией о данных объектах в Спецификации для объектов типа Secret. Поле DATA отображает количество предметов, сохраненных в данном объекте Secret. В этом случае он отображает 1, потому что вы сохранили один ключ.

      Теперь, когда ваш объект Secret был создан, установите плагин хранилища DigitalOcean:

      • kubectl apply -f https://raw.githubusercontent.com/digitalocean/csi-digitalocean/master/deploy/kubernetes/releases/csi-digitalocean-v0.3.0.yaml

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

      Output

      storageclass.storage.k8s.io/do-block-storage created serviceaccount/csi-attacher created clusterrole.rbac.authorization.k8s.io/external-attacher-runner created clusterrolebinding.rbac.authorization.k8s.io/csi-attacher-role created service/csi-attacher-doplug-in created statefulset.apps/csi-attacher-doplug-in created serviceaccount/csi-provisioner created clusterrole.rbac.authorization.k8s.io/external-provisioner-runner created clusterrolebinding.rbac.authorization.k8s.io/csi-provisioner-role created service/csi-provisioner-doplug-in created statefulset.apps/csi-provisioner-doplug-in created serviceaccount/csi-doplug-in created clusterrole.rbac.authorization.k8s.io/csi-doplug-in created clusterrolebinding.rbac.authorization.k8s.io/csi-doplug-in created daemonset.apps/csi-doplug-in created

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

      Шаг 3 — Создание постоянного тома

      После создания объекта типа Secret и установки плагина блочного хранилища вы можете создать собственный постоянный том. Постоянный том (Persistent Volume, PV) — это блочное хранилище заданного размера, которое существует независимо от жизненного цикла пода. Использование постоянного тома позволит вам управлять или обновлять поды, не беспокоясь о потере кода приложения. Доступ к постоянному тому можно получить с помощью PersistentVolumeClaim, или PVC, который монтирует постоянный том по требуемому пути.

      Откройте файл code_volume.yaml в редакторе:

      Присвойте PVC имя code, добавив в файл следующие параметры и значения:

      code_volume.yaml

      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: code
      

      spec для PVC содержит следующие элементы:

      • accessModes, значение которого может меняться в зависимости от варианта использования. Ниже представлены возможные варианты:
        • ReadWriteOnce — монтирует том для чтения и записи с помощью одного узла
        • ReadOnlyMany — монтирует том только для чтения с помощью многих узлов
        • ReadWriteMany — монтирует том для чтения и записи с помощью многих узлов
      • resources — пространство для хранилища, которое вам требуется

      Блочное хранилище DigitalOcean устанавливается только на один узел, поэтому для accessModes нужно установить значение ReadWriteOnce. В этом обучающем руководстве вы будете добавлять небольшое количество кода приложения, поэтому в нашем случае будет достаточно 1 ГБ. Если вы планируете хранить большее количество кода или данных в томе, вы можете изменять параметр storage согласно вашим потребностям. Вы можете увеличить объем хранилища после создания тома, но сокращение диска не поддерживается.

      code_volume.yaml

      ...
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
      

      Далее укажите класс хранилища, который Kubernetes будет использовать для предоставления томов. Вы будете использовать класс do-block-storage, созданный плагином блочного хранилища DigitalOcean.

      code_volume.yaml

      ...
        storageClassName: do-block-storage
      

      Ваш файл code_volume.yaml будет выглядеть следующим образом:

      code_volume.yaml

      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: code
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
        storageClassName: do-block-storage
      

      Сохраните и закройте файл.

      Создайте code PersistentVolumeClaim с помощью команды kubectl:

      • kubectl apply -f code_volume.yaml

      Следующий вывод говорит, что объект был успешно создан, и вы можете монтировать ваш PVC объемом 1 ГБ в качестве тома.

      Output

      persistentvolumeclaim/code created

      Для просмотра доступных постоянных томов (PV):

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

      Output

      NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-ca4df10f-ab8c-11e8-b89d-12331aa95b13 1Gi RWO Delete Bound default/code do-block-storage 2m

      Поля выше представляют собой обзор файла конфигурации, за исключением параметров Reclaim Policy​​​ и Status. Параметр Reclaim Policy (Политика восстановления) определяет, что будет сделано с PV после удаления доступа с помощью PVC. Значение Delete удаляет PV из Kubernetes, а также из инфраструктуры DigitalOcean. Вы можете получить дополнительные данные о параметрах Reclaim Policy (Политика восстановления) и Status (Статус) в документации Kubernetes PV.

      Вы успешно создали постоянный том с помощью плагина блочного хранилища DigitalOcean. Теперь, когда ваш постоянный том готов, вы можете создать ваши поды с помощью развертывания.

      Шаг 4 — Создание Deployment (Развертывания) PHP-FPM

      На этом шаге вы научитесь использовать Deployment (Развертывание) для создания вашего пода PHP-FPM. Развертывания предоставляют единообразный способ создания, обновления подов и управления ими с помощью ReplicaSets. Если обновление не работает ожидаемым образом, Deployment будет автоматически возвращать свои поды к предыдущему образу.

      Ключ для развертывания spec.selector будет содержать список меток подов, которыми будет управлять. Также мы будем использовать ключ template для создания требуемых подов.

      Кроме того, на этом шаге мы познакомимся с использованием Init-контейнеров. Init-контейнеры запускают одну или несколько команд, прежде чем будут запущены обычные контейнеры, указанные в ключе template пода. В этом обучающем руководстве ваш Init-контейнер будет получать пример файла index.php из GitHub Gist с помощью wget. Вот как выглядит содержимое примера файла:

      index.php

      <?php
      echo phpinfo();
      

      Для создания развертывания откройте новый файл с именем php_deployment.yaml в вашем редакторе:

      Это развертывание будет управлять вашими подами PHP-FPM, поэтому вы должны использовать для объекта Deployment имя php. Поды принадлежат к уровню бекэнда, поэтому вы должны объединить развертывание в эту группу с помощью метки tier: backend:

      php_deployment.yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: php
        labels:
          tier: backend
      

      Для элемента spec развертывания вы должны будете указать, сколько экземпляров этого пода нужно создать, используя параметр replicas. Значение параметра replicas будет варьироваться в зависимости от ваших потребностей и доступных ресурсов. В этом обучающем руководстве мы создадим одну реплику:

      php_deployment.yaml

      ...
      spec:
        replicas: 1
      

      Это развертывание будет управлять подами с метками app: php и tier: backend. Рядом с ключом selector добавьте:

      php_deployment.yaml

      ...
        selector:
          matchLabels:
            app: php
            tier: backend
      

      Далее для элемента spec необходимо задать значение template для определения объекта вашего пода. Этот шаблон определяет спецификации, на основании которых создается под. Во-первых, вам нужно добавить метки, которые были указаны для selectors службы php и matchLabels развертывания. Добавьте app: php и tier: backend в template.metadata.labels:

      php_deployment.yaml

      ...
        template:
          metadata:
            labels:
              app: php
              tier: backend
      

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

      Во-первых, укажите тома, к которым будут подключены ваши контейнеры. Вы создали PVC с именем code для хранения кода приложения, поэтому вы должны присвоить этому тому аналогичное имя code. В разделе spec.template.spec.volumes добавьте следующее:

      php_deployment.yaml

      ...
          spec:
            volumes:
            - name: code
              persistentVolumeClaim:
                claimName: code
      

      Затем укажите контейнер, который вы хотите запустить в этом поде. Вы можете найти различные образы в магазине Docker, но в этом руководстве мы будем использовать образ php:7-fpm.

      В разделе spec.template.spec.containers добавьте следующее:

      php_deployment.yaml

      ...
            containers:
            - name: php
              image: php:7-fpm
      

      Теперь нужно смонтировать тома, к которым контейнеру требуется доступ. Этот контейнер будет запускать ваш код PHP, поэтому ему потребуется доступ к тому code. Также вы будете использовать mountPath, чтобы задать /code в качестве точки для монтирования.

      В spec.template.spec.containers.volumeMounts добавьте:

      php_deployment.yaml

      ...
              volumeMounts:
              - name: code
                mountPath: /code
      

      Теперь, когда вы смонтировали ваш том, вам нужно поместить код приложения в том. Возможно, вы ранее использовали FTP/SFTP или клонировали код через соединение SSH, чтобы добиться этого, но на данном этапе мы покажем, как скопировать код с помощью Init-контейнера.

      В зависимости от сложности процесса настройки вы можете использовать либо один initContainer для запуска скрипта, который собирает ваше приложение, либо один initContainer для каждой команды. Убедитесь, что тома монтируются в initContainer.

      В этом руководстве вы будете использовать один Init-контейнер с busybox для загрузки кода. busybox — это небольшой образ, содержащий утилиту wget, которую вы будете использовать для этой цели.

      В spec.template.spec добавьте ваш initContainer и укажите образ busybox:

      php_deployment.yaml

      ...
            initContainers:
            - name: install
              image: busybox
      

      Вашему Init-контейнеру потребуется доступ к тому code, чтобы выполнить загрузку кода в это место. В spec.template.spec.initContainers смонтируйте том code на путь /code:

      php_deployment.yaml

      ...
              volumeMounts:
              - name: code
                mountPath: /code
      

      Для каждого Init-контейнера необходимо запустить command. Ваш Init-контейнер будет использовать wget для загрузки кода с Github в рабочую директорию /code. Параметр -O предоставляет загруженному файлу имя, и вы должны будете назвать этот файл index.php.

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

      Для контейнера install в spec.template.spec.initContainers добавьте следующие строки:

      php_deployment.yaml

      ...
              command:
              - wget
              - "-O"
              - "/code/index.php"
              - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php
      

      Ваш готовый файл php_deployment.yaml будет выглядеть следующим образом:

      php_deployment.yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: php
        labels:
          tier: backend
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: php
            tier: backend
        template:
          metadata:
            labels:
              app: php
              tier: backend
          spec:
            volumes:
            - name: code
              persistentVolumeClaim:
                claimName: code
            containers:
            - name: php
              image: php:7-fpm
              volumeMounts:
              - name: code
                mountPath: /code
            initContainers:
            - name: install
              image: busybox
              volumeMounts:
              - name: code
                mountPath: /code
              command:
              - wget
              - "-O"
              - "/code/index.php"
              - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php
      

      Сохраните файл и выйдите из редактора.

      Создайте развертывание PHP-FPM с помощью kubectl:

      • kubectl apply -f php_deployment.yaml

      Вы увидите следующий результат создания развертывания:

      Output

      deployment.apps/php created

      В конце концов данное развертывание начнет загружать заданные образы. Затем оно запросит PersistentVolume у PersistentVolumeClaim и последовательно запустит ваши initContainers. После завершения контейнеры будут запускаться и монтировать тома в заданную точку монтирования. После завершения всех этих шагов ваш под будет готов к работе и запущен.

      Вы можете просмотреть ваше развертывание с помощью следующей команды:

      Результат будет выглядеть следующим образом:

      Output

      NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE php 1 1 1 0 19s

      Данный вывод поможет вам понять текущее состояние развертывания. Развертывание — один из контроллеров, поддерживающих желаемое состояние. Созданный вами шаблон указывает, что состояние DESIRED будет иметь 1 реплику пода с именем php. Поле CURRENT указывает, сколько реплик запущено, поэтому эти данные должны соответствовать данным состояния DESIRED. Вы можете ознакомиться с дополнительными данными в документации по развертыванию в Kubernetes.

      С помощью следующей команды можно просмотреть поды, запущенные данным развертыванием:

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

      Output

      NAME READY STATUS RESTARTS AGE php-86d59fd666-bf8zd 0/1 Init:0/1 0 9s

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

      • Ready: количество реплик, запускающих под.
      • Status: состояние пода. Init указывает, что Init-контейнеры запущены. В этом выводе 0 из 1 Init-контейнера прекратили работу.
      • Restarts: сколько раз этот процесс был перезапущен для запуска пода. Это число будет увеличиваться, если какой-либо из ваших Init-контейнеров прекратит работу. Развертывание будет перезапущено, пока не будет достигнуто желаемое состояние.

      В зависимости от сложности ваших скриптов запуска может потребоваться несколько минут, чтобы состояние поменялось на podInitializing:

      Output

      NAME READY STATUS RESTARTS AGE php-86d59fd666-lkwgn 0/1 podInitializing 0 39s

      Это означает, что Init-контейнер завершил работу, и контейнеры инициализируются. Если вы запустите команду, когда все контейнеры запущены, вы увидите, что статус пода изменился на Running.

      Output

      NAME READY STATUS RESTARTS AGE php-86d59fd666-lkwgn 1/1 Running 0 1m

      Теперь вы увидите, что ваш под успешно запущен. Если ваш под не был запущен, вы можете выполнить отладку с помощью следующих команд:

      • Просмотр подробной информации о поде:
      • kubectl describe pods pod-name
      • Просмотр журналов, сгенерированных подом:
      • Просмотр журналов для конкретного контейнера в поде:
      • kubectl logs pod-name container-name

      Код вашего приложения был смонтирован, а служба PHP-FPM готова к обработке подключений. Теперь вы можете создать развертывание Nginx.

      Шаг 5 — Создание развертывания Nginx

      На этом шаге вы будете использовать ConfigMap для настройки Nginx. ConfigMap хранит вашу конфигурацию в формате ключ-значение, и вы можете ссылаться на нее в других определениях объектов Kubernetes. Такой подход будет предоставлять возможность повторного использования образа или переключения образа на другую версию Nginx в случае необходимости. Обновление ConfigMap автоматически будет воспроизводить изменения для любого пода, который его монтирует.

      Создайте файл nginx_configMap.yaml для ConfigMap в своем редакторе:

      • nano nginx_configMap.yaml

      Назовите ConfigMap nginx-config и добавьте в группу микросервисов tier: backend​​​:

      nginx_configMap.yaml

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: nginx-config
        labels:
          tier: backend
      

      Затем вы должны будете добавить данные для ConfigMap. Присвойте ключу имя config и добавьте содержимое файла конфигурации Nginx в качестве значения. Вы можете воспользоваться примером конфигурации Nginx из этого руководства.

      Поскольку Kubernetes может перенаправлять запросы на соответствующий хост для службы, вы можете ввести имя службы PHP-FPM для параметра fastcgi_pass вместо его IP-адреса. Добавьте следующее в файл nginx_configMap.yaml:

      nginx_configMap.yaml

      ...
      data:
        config : |
          server {
            index index.php index.html;
            error_log  /var/log/nginx/error.log;
            access_log /var/log/nginx/access.log;
            root ^/code^;
      
            location / {
                try_files $uri $uri/ /index.php?$query_string;
            }
      
            location ~ .php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+.php)(/.+)$;
                fastcgi_pass php:9000;
                fastcgi_index index.php;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_param PATH_INFO $fastcgi_path_info;
              }
          }
      

      Ваш файл nginx_configMap.yaml будет выглядеть следующим образом:

      nginx_configMap.yaml

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: nginx-config
        labels:
          tier: backend
      data:
        config : |
          server {
            index index.php index.html;
            error_log  /var/log/nginx/error.log;
            access_log /var/log/nginx/access.log;
            root /code;
      
            location / {
                try_files $uri $uri/ /index.php?$query_string;
            }
      
            location ~ .php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+.php)(/.+)$;
                fastcgi_pass php:9000;
                fastcgi_index index.php;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_param PATH_INFO $fastcgi_path_info;
              }
          }
      

      Сохраните файл и выйдите из редактора.

      Создайте ConfigMap:

      • kubectl apply -f nginx_configMap.yaml

      Результат будет выглядеть следующим образом:

      Output

      configmap/nginx-config created

      Вы завершили создание ConfigMap и теперь можете выполнить сборку вашего развертывания Nginx.

      Для начала откройте новый файл nginx_deployment.yaml в редакторе:

      • nano nginx_deployment.yaml

      Назовите развертывание nginx и добавьте метку tier: backend:

      nginx_deployment.yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nginx
        labels:
          tier: backend
      

      Укажите, что вам нужна одна реплика в spec развертывания. Это развертывание будет управлять подами с метками app:nginx и tier:backend. Добавьте следующие параметры и значения:

      nginx_deployment.yaml

      ...
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: nginx
            tier: backend
      

      Затем добавьте шаблон пода. Вам нужно использовать те же метки, которые вы добавили для развертывания selector.matchLabels. Добавьте следующее:

      nginx_deployment.yaml

      ...
        template:
          metadata:
            labels:
              app: nginx
              tier: backend
      

      Предоставьте Nginx доступ к code PVC, который вы создали ранее. В spec.template.spec.volumes добавьте:

      nginx_deployment.yaml

      ...
          spec:
            volumes:
            - name: code
              persistentVolumeClaim:
                claimName: code
      

      Поды могут монтировать ConfigMap в качестве тома. При указании имени файла и ключа будет создан файл с содержимым в виде его значения. Для использования ConfigMap настройте в качестве path имя файла, где будет храниться содержимое key. Вам нужно создать файл site.conf из ключа config. В разделе spec.template.spec.volumes добавьте следующее:

      nginx_deployment.yaml

      ...
            - name: config
              configMap:
                name: nginx-config
                items:
                - key: config
                  path: site.conf
      

      Предупреждение: если файл не указан, содержимое key будет заменять mountPath тома. Это означает, что если путь не был явно указан, вы потеряете все содержимое в папке назначения.

      Затем вы должны будете задать образ для создания пода. Это руководство будет использовать образ nginx:1.7.9 для стабильности, но вы можете найти другие образы Nginx в магазине Docker. Кроме того, предоставьте к Nginx доступ из порта 80. В spec.template.spec добавьте:

      nginx_deployment.yaml

      ...
            containers:
            - name: nginx
              image: nginx:1.7.9
              ports:
              - containerPort: 80
      

      Nginx и PHP-FPM требуется доступ к файлу с одним путем, поэтому вы должны смонтировать том code в /code:

      nginx_deployment.yaml

      ...
              volumeMounts:
              - name: code
                mountPath: /code
      

      Образ nginx:1.7.9 будет автоматически загружать любые файлы конфигурации в директорию /etc/nginx/conf.d. При монтировании тома config в этой директории будет создан файл /etc/nginx/conf.d/site.conf. В volumeMounts добавьте следующее:

      nginx_deployment.yaml

      ...
              - name: config
                mountPath: /etc/nginx/conf.d
      

      Ваш файл nginx_deployment.yaml будет выглядеть следующим образом:

      nginx_deployment.yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nginx
        labels:
          tier: backend
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: nginx
            tier: backend
        template:
          metadata:
            labels:
              app: nginx
              tier: backend
          spec:
            volumes:
            - name: code
              persistentVolumeClaim:
                claimName: code
            - name: config
              configMap:
                name: nginx-config
                items:
                - key: config
                  path: site.conf
            containers:
            - name: nginx
              image: nginx:1.7.9
              ports:
              - containerPort: 80
              volumeMounts:
              - name: code
                mountPath: /code
              - name: config
                mountPath: /etc/nginx/conf.d
      

      Сохраните файл и выйдите из редактора.

      Создайте развертывание Nginx:

      • kubectl apply -f nginx_deployment.yaml

      Следующий вывод означает, что ваше развертывание было успешно создано:

      Output

      deployment.apps/nginx created

      Сформируйте список ваших развертываний с помощью этой команды:

      Вы увидите развертывания Nginx и PHP-FPM:

      Output

      NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx 1 1 1 0 16s php 1 1 1 1 7m

      Сформируйте список подов, которые управляются обоими развертываниями:

      Вы увидите запущенные поды:

      Output

      NAME READY STATUS RESTARTS AGE nginx-7bf5476b6f-zppml 1/1 Running 0 32s php-86d59fd666-lkwgn 1/1 Running 0 7m

      Теперь, когда все объекты Kubernetes активны, вы можете посетить службу Nginx в браузере.

      Сформируйте список запущенных служб:

      • kubectl get services -o wide

      Получите внешний IP-адрес для службы Nginx:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 39m <none> nginx ClusterIP 10.102.160.47 your_public_ip 80/TCP 27m app=nginx,tier=backend php ClusterIP 10.100.59.238 <none> 9000/TCP 34m app=php,tier=backend

      В браузере посетите ваш сервер, введя в адресной строке http://your_public_ip. Вы увидите вывод php_info(), что служит подтверждением того, что ваши службы Kubernetes готовы и запущены.

      Заключение

      В данном руководстве вы создали контейнер для служб PHP-FPM и Nginx, чтобы вы могли управлять ими независимо. Такой подход не только повышает масштабируемость вашего проекта в процессе роста, но также позволит эффективно использовать ресурсы. Также вы сохранили код приложения в томе, чтобы вы могли легко обновить ваши службы в будущем.



      Source link

      Создание и развертывание приложения Flask с использованием Docker в Ubuntu 18.04


      Автор выбрал Tech Education Fund для получения пожертвования в рамках программы Write for DOnations.

      Введение

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

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

      Развертывание приложения Flask с помощью Docker позволит вам воспроизводить приложение на разных серверах с минимальными изменениями конфигурации.

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

      Предварительные требования

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

      Шаг 1 — Настройка приложения Flask

      Вначале вы создадите структуру каталогов, где будет размещено ваше приложение Flask. В этом обучающем модуле мы создадим каталог TestApp в каталоге /var/www, но вы можете изменить команду и использовать любое другое название.

      • sudo mkdir /var/www/TestApp

      Перейдите в созданный каталог TestApp:

      Создайте базовую структуру папок для приложения Flask:

      • sudo mkdir -p app/static app/templates

      Флаг -p означает, что команда mkdir создаст каталог и все его родительские каталоги, которых еще не существует. В данном случае команда mkdir создаст родительский каталог app в процессе создания каталогов static и templates.

      В каталоге app будут находиться все файлы, связанные с приложением Flask, в том числе views и blueprints. Views — это создаваемый вами код, обеспечивающий ответы на запросы вашего приложения. Blueprints создает компоненты приложения и поддерживает стандартные шаблоны внутри приложения или для нескольких разных приложений.

      В каталоге static хранятся различные ресурсы, в том числе файлы изображений, CSS и JavaScript. В каталоге templates хранятся шаблоны HTML для вашего проекта.

      Теперь базовая структура папок готова, и вы можете создать все файлы, необходимые для запуска приложения Flask. Вначале создайте файл __init__.py в каталоге app. Этот файл сообщает интерпретатору Python, что каталог app является пакетом, и его следует рассматривать именно как пакет.

      Запустите следующую команду для создания файла:

      • sudo nano app/__init__.py

      Пакеты в Python позволяют группировать модули в логические пространства имен или иерархии. Этот подход позволяет разбивать код на отдельные управляемые блоки, которые выполняют конкретные функции.

      Затем вы добавитье в файл __init__.py код, который создаст экземпляр Flask и импортирует логику из файла views.py, которы вы создадите после сохранения этого файла. Добавьте в новый файл следующий код:

      /var/www/TestApp/__init__.py

      from flask import Flask
      app = Flask(__name__)
      from app import views
      

      После добавления этого кода сохраните и закройте файл.

      После создания файла __init__.py вы будете готовы создать файл views.py в каталоге app. В этом файле будет содержаться большая часть логики вашего приложения.

      Затем добавьте код в файл views.py. Этот код будет возвращать фразу hello world! строка для пользователей, посещающих вашу веб-страницу:

      /var/www/TestApp/app/views.py

      from app import app
      
      @app.route('/')
      def home():
         return "hello world!"
      

      Строка @app.route над функцией называется декоратором. Декораторы изменяют функцию, которая следует за ними. В данном случае декторатор указывает Flask, какой URL активирует функцию home(). Текст hello world, возвращаемый функцией home, будет отображаться пользователю в браузере.

      Создав файл views.py, вы готовы к созданию файла uwsgi.ini. Этот файл будет содержать конфигурации uWSGI для нашего приложения. uWSGI — это опция развертывания Nginx, представляющая собой как протокол, так и сервер приложений, который может обслуживать протоколы uWSGI, FastCGI и HTTP.

      Для создания этого файла запустите следующую команду:

      Затем добавьте в файл следующее содержание для настройки сервера uWSGI:

      /var/www/TestApp/uwsgi.ini

      [uwsgi]
      module = main
      callable = app
      master = true
      

      Этот код определяет модуль, из которого будет обслуживаться приложение Flask. В данном случае это файл main.py, который здесь указывается как main. Опция callable указывает uWSGI использовать экземпляр app, экспортированный основным приложением. Параметр master позволяет вашему приложению продолжать работать, и поэтому даже при перезагрузке всего приложения время простоя будет минимальным.

      Теперь создайте файл main.py, который будет главной точкой входа в приложение. Точка входа сообщает uWSGI, как следует взаимодействовать с приложением.

      Далее скопируйте и вставьте в файл следующий код. Этот код импортирует экземпляр Flask под названием app из пакета приложения, созданного на предыдущих шагах.

      /var/www/TestApp/main.py

      from app import app
      

      Наконец, создайте файл requirements.txt, чтобы указать, какие зависимости диспетчер пакетов pip установит в вашу среду Docker:

      • sudo nano requirements.txt

      Добавьте следующую строку для добавления Flask в качестве зависимости:

      /var/www/TestApp/app/requirements.txt

      Flask==1.0.2
      

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

      Сохраните и закройте файл. Вы успешно настроили свое приложение Flask и готовы к настройке Docker.

      Шаг 2 — Настройка Docker

      На этом шаге вы создадите два файла для развертывания Docker, Dockerfile и start.sh. Dockerfile — это текстовый документ, содержащий команды, используемые для сборки образа. Файл start.sh — это скрипт оболочки, который построит образ и создаст контейнер из файла Dockerfile.

      Вначале создайте файл Dockerfile.

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

      /var/www/TestApp/Dockerfile

      FROM tiangolo/uwsgi-nginx-flask:python3.6-alpine3.7
      RUN apk --update add bash nano
      ENV STATIC_URL /static
      ENV STATIC_PATH /var/www/app/static
      COPY ./requirements.txt /var/www/requirements.txt
      RUN pip install -r /var/www/requirements.txt
      

      В этом примере образ Docker будет построен на основе существующего образа tiangolo/uwsgi-nginx-flask, который можно найти на ресурсе DockerHub. Этот конкретный образ Docker лучше многих других, потому что он поддерживает широкий спектр версий Python и образов ОСs.

      В первых двух строках указывается родительский образ, который вы будете использовать для запуска приложений и установки процессора команд bash и текстового редактора nano. Также он устанавливает клиент git для связи со службами хостинга контроля версий, такими как GitHub, GitLab и Bitbucket. ENV STATIC_URL /static — переменная среды, используемая для конкретного образа Docker. Она определяет статичную папку, где хранятся все ресурсы, включая образы, файлы CSS и файлы JavaScript.

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

      Сохраните и закройте файл после добавления вашей конфигурации.

      Теперь вы установили файл Dockerfile и уже почти готовы написать скрипт start.sh, который построит для вас контейнер Docker. Прежде чем создавать скрипт start.sh, убедитесь, что у вас имеется открытый порт для использования в конфигурации. Чтобы проверить, свободен ли порт, запустите следующую команду:

      • sudo nc localhost 56733 < /dev/null; echo $?

      Если вывод команды больше 1, это означает, что порт свободен и готов к использованию. В противном случае, вам нужно будет выбрать другой порт для использования в файле конфигурации start.sh.

      Когда вы найдете открытый порт для использования, создайте скрипт start.sh:

      Скрипт start.sh — это скрипт оболочки, создающий образ из файла Dockerfile и создающий контейнер на основе полученного образа Docker. Добавьте свою конфигурацию в новый файл:

      /var/www/TestApp/start.sh

      #!/bin/bash
      app="docker.test"
      docker build -t ${app} .
      docker run -d -p 56733:80 
        --name=${app} 
        -v $PWD:/app ${app}
      

      Первая строка называется shebang. Она указывает, что это файл bash, и что его нужно выполнять как команды. В следующей строке указывается, какое имя вы хотите присвоить образу и контейнеру, а также выполняется сохранение этого имени в переменной app. Следующая строка указывает Docker построить образ из файла Dockerfile, находящегося в текущем каталоге. В этом примере будет создан образ с именем docker.test.

      Последние три строки создают новый контейнер с именем docker.test с открытым портом 56733. Наконец, текущий каталог связывается с каталогом /var/www directory в контейнере.

      Флаг -d используется для запуска контейнера в режиме демона или в качестве фонового процесса. Флаг -p используется для привязки порта на сервере к конкретному порту контейнера Docker. В данном случае вы привязываете порт 56733 к порту 80 контейнера Docker. Флаг -v указывает, какой том Docker следует монтировать на контейнер. В данном случае вы монтируете весь каталог проекта в папку /var/www в контейнере Docker.

      Запустите скрипт start.sh для создания образа Docker и построения контейнера на основе этого образа:

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

      В результате будет выведен список контейнеров:

      Output

      CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 58b05508f4dd docker.test "/entrypoint.sh /sta…" 12 seconds ago Up 3 seconds 443/tcp, 0.0.0.0:56733->80/tcp docker.test

      Вы увидите, что контейнер docker.test запущен и работает. Теперь, когда контейнер работает, откройте в браузере IP-адрес на указанном порту: http://ip-address:56733

      Страница будет выглядеть примерно следующим образом:

      Главная страница

      На этом шаге вы успешно развернули свое приложение Flask в контейнере Docker. Теперь вы используете шаблоны, чтобы показать пользователям контент.

      Шаг 3 — Работа с файлами шаблонов

      Шаблоны — это файлы, показывающие статичный и динамический контент пользователям вашего приложения. На этом шаге вы создадите шаблон HTML для создания главной страницы приложения.

      Вначале создайте файл home.html в каталоге app/templates:

      • sudo nano app/templates/home.html

      Добавьте код для вашего шаблона. Этот код создаст страницу HTML5, содержащую заголовок и текст.

      /var/www/TestApp/app/templates/home.html

      
      <!doctype html>
      
      <html lang="en-us">   
        <head>
          <meta charset="utf-8">
          <meta http-equiv="x-ua-compatible" content="ie=edge">
          <title>Welcome home</title>
        </head>
      
        <body>
          <h1>Home Page</h1>
          <p>This is the home page of our application.</p>
        </body>
      </html>
      

      После добавления шаблона сохраните и закройте файл.

      Теперь измените файл app/views.py, чтобы обслуживать созданный файл:

      Вначале добавьте в начале файла следующую строку для импорта метода render_template из Flask. Этот метод проводит синтаксический анализ файла HTML для рендеринга веб-страницы для пользователя.

      /var/www/TestApp/app/views.py

      from flask import render_template
      ...
      

      В конце файла вы добавите новый маршрут для рендеринга файла шаблона. Данный код указывает, что пользователям выводится содержимое файла home.html всегда, когда они посещают маршрут /template в вашем приложении.

      /var/www/TestApp/app/views.py

      ...
      
      @app.route('/template')
      def template():
          return render_template('home.html')
      

      Обновленный файл app/views.py будет выглядеть примерно следующим образом:

      /var/www/TestApp/app/views.py

      from flask import render_template
      from app import app
      
      @app.route('/')
      def home():
          return "Hello world!"
      
      @app.route('/template')
      def template():
          return render_template('home.html')
      

      Сохраните и закройте файл после завершения.

      Чтобы эти изменения вступили в силу, вам нужно будет остановить и перезапустить контейнеры Docker. Запустите следующую команду для повторного построения контейнера:

      • sudo docker stop docker.test && sudo docker start docker.test

      Откройте свое приложение по адресу http://your-ip-address:56733/template, чтобы увидеть, как выводится новый шаблон.

      главная страница

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

      Шаг 4 — Обновление приложения

      Иногда в приложение бывает нужно внести изменения. Это может быть установка новых требований, обновление контейнера Docker или внесение изменений в код HTML и логику. В этом разделе вы настроите команду touch-reload для внесения этих зменений без перезапуска контейнера Docker.

      Функция автоматической перезагрузки Python отслеживает изменения во всей файловой системе и обновляет приложение при обнаружении изменений. Автоматическая перезагрузка не рекомендуется в производственной среди, поскольку она может очень быстро увеличить нагрузку на ресурсы системы. На этом шаге вы используете команду touch-reload для отслеживания изменений определенного файла и перезагрузке контейнера в случае обновления или замены файла.

      Для реализации этой функции откройте файл uwsgi.ini:

      Добавьте в конец файла выделенную строку:

      /var/www/TestApp/uwsgi.ini

      module = main
      callable = app
      master = true
      touch-reload = /app/uwsgi.ini
      

      Эта строка указывает файл, изменение которого запускает перезагрузку приложения. После внесения изменений сохраните и закройте файл.

      Чтобы продемонстрировать это, внесите в ваше приложение небольшое изменение. Для начала откройте файл app/views.py:

      Замените строку, возвращаемую функцией home:

      /var/www/TestApp/app/views.py

      from flask import render_template
      from app import app
      
      @app.route('/')
      def home():
          return "<b>There has been a change</b>"
      
      @app.route('/template')
      def template():
          return render_template('home.html')
      

      Сохраните и закройте файл после внесения изменения.

      Если вы откроете главную страницу приложения по адресу http://ip-address:56733, вы увидите, что изменения не отражаются. Это связано с тем, что условием перезагрузки будет изменение в файле uwsgi.ini. Чтобы перезагрузить приложение, используйте команду touch для активации условия:

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

      Главная страница обновлена

      На этом шаге вы выберете условие команды touch-reload, с которым приложение будет обновляться после внесения изменений.

      Заключение

      В этом обучающем модуле вы создали и развернули приложение Flask в контейнере Docker. Также вы настроили команду touch-reload для обновления приложения без необходимости перезапуска контейнера.

      Новое приложение в Docker можно будет легко масштабировать. Чтобы узнать больше об использовании Docker, ознакомьтесь с официальной документацией.



      Source link