Назад в блог

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

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

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

Nginx работает как прокси для PHP-FPM при запуске PHP-приложения. Управление этими двумя службами в одном контейнере — сложный процесс. Kubernetes помогает нам управлять ними в двух разных контейнерах и избавляет от лишних хлопот. Он также позволяет пользователям повторно использовать контейнеры и не беспокоиться о сборке образа контейнера для каждой новой версии PHP/Nginx.

Вы запустите свое приложение и службу прокси в двух отдельных контейнерах. В руководстве также будет рассказано, как использовать локальное хранилище для создания Persistent Volume (PV) и Persistent Volume Claim (PVC). Затем вы будете использовать этот PVC для хранения файлов конфигурации и кода вне образов контейнеров. После завершения этого руководства вы сможете повторно использовать свой образ Nginx для других приложений, которым требуется прокси-сервер. Вы можете добиться этого, передав конфигурацию вместо повторной сборки образа для нее.

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

  1. Базовое понимание Kubernetes (k8s) и его объектов. Обратитесь к этому руководству для подробного обзора экосистемы Kubernetes.
  2. Кластер Kubernetes, запущенный и работающий на Ubuntu 18.04. Следуйте этому руководству, чтобы создать свой кластер Kubernetes с помощью kubeadm.
  3. Кроме того, вам необходимо разместить код вашего приложения по общедоступному URL-адресу, например, на GitHub.

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

Этот шаг поможет вам создать службы PHP-FPM и Nginx. Любая служба предоставляет доступ к набору подов внутри кластера. Все службы, присутствующие в кластере, могут взаимодействовать друг с другом по своим именам, без IP-адресов. Служба PHP-FPM и служба Nginx предоставят доступ к подам PHP-FPM и Nginx соответственно.

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

Чтобы создать любую службу, вам нужно будет создать файл YAML, содержащий определение объекта. Этот YAML-файл содержит как минимум следующие теги:

  1. apiVersion: версия API Kubernetes, к которой относится определение.
  2. kind: тип объекта Kubernetes, который создает этот YAML-файл. Например: service, job или pod.
  3. metadata: имя объекта и различные labels, которые пользователь может захотеть применить к этому объекту, определяются под этим тегом.
  4. spec: этот тег содержит спецификацию вашего объекта, такую как переменные окружения (ENV), используемый образ контейнера, порты, по которым будет доступна служба контейнера.
Создание службы PHP-FPM

Для начала вам следует создать каталог для хранения определения вашего объекта Kubernetes. Войдите на свой мастер-узел и создайте каталог с именем “definitions:”

Перейдите в каталог definitions:

Затем создайте файл службы PHP-FPM как файл php_service.yaml:

После этого установите apiVersion и kind в файле php_fpm_service.yaml:

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

Пометьте свою службу php как tier: backend, так как PHP-приложение будет работать за этой службой:

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

Включите tier: backend метку, которая назначает ваш pod на уровень backend, вместе с app: php-fpm меткой, указывающей, что в pod запущено приложение PHP-FPM. Вы должны добавить эти метки после раздела metadata раздела:

Затем вам нужно объявить порт для доступа к этой службе php-fpm в разделе spec. Вы можете добавить любой порт по вашему выбору, но в этом руководстве мы будем использовать порт 9000 в этом руководстве:

После выполнения описанных выше шагов ваш файл php_fpm_service.yaml будет выглядеть следующим образом:

Нажмите Ctrl + O, чтобы сохранить файл, а затем нажмите Ctrl + X, чтобы выйти из nano.

Применение команды kubectl для создания службы PHP

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

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

Запустите команду ниже, чтобы убедиться, что служба php-fpm запущена:

Вы сможете увидеть, что служба php-fpm запущена и работает:

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

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

Назовите эту службу nginx, так как она будет нацелена на pods Nginx. Эта служба также относится к backend, поэтому вам следует добавить к ней метку tier: backend:

Как и в случае со службой php-fpm, добавьте селекторные метки app: nginx и tier: backend для выбора целевых pods. Добавьте HTTP-порт по умолчанию 80 для доступа к этой службе:

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

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

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

Применение команды kubectl для создания службы Nginx
Для вышеуказанной команды вы должны увидеть следующий вывод:
Теперь выполните следующую команду, чтобы просмотреть все запущенные сервисы:
После выполнения этой команды вы должны увидеть, что оба ваших сервиса PHP-FPM и Nginx запущены и работают:
Обратите внимание, что если вы хотите удалить любой из запущенных сервисов, вы можете выполнить следующую команду:

Шаг 2. Создание локального хранилища и постоянного тома (Persistent Volume)

Kubernetes предоставляет различные плагины хранения, которые помогают создавать пространство хранения для вашей среды. Этот шаг покажет вам, как создать локальный StorageClass и как этот класс хранения можно использовать в дальнейшем для создания постоянного тома (Persistent Volume).

Создание локального хранилища

Создайте файл, например storageClass.yaml, в вашем редакторе:

Добавьте kind как "storageClass" и apiVersion как "storage.k8s.io/v1" следующим образом:

Назовите этот StorageClass как "my-local-storage" и добавьте provisioner и volumeBindingMode следующим образом:

Сохраните и закройте файл. Ваш итоговый файл storageClass.yaml должен выглядеть следующим образом:

Теперь создайте StorageClass, выполнив команду kubectl create, как показано ниже:

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

Создание локального постоянного тома (Persistent Volume)

После создания локального хранилища вы можете создать локальный постоянный том (Persistent Volume). Постоянный том, также известный как PV, представляет собой блочное хранилище определенного размера, независимое от жизненного цикла пода. Локальный постоянный том — это не что иное, как локальный диск или каталог, доступный на узле кластера Kubernetes. Этот локальный постоянный том позволяет пользователям получать доступ к локальному хранилищу с помощью локального запроса на постоянный том (Persistent Volume Claim) очень простым и переносимым способом. Вы можете создать этот локальный постоянный том, используя класс хранения, который мы только что создали. Откройте файл, например persistentVolume.yaml, в вашем редакторе:

Дайте этому постоянному тому имя, например "my-local-pv":

При создании локального постоянного тома вы можете добавить емкость хранилища в соответствии с вашими потребностями. В этом руководстве мы будем использовать 5 Gi для хранилища:

Добавьте accessModes, persistentVolumeReclaimPolicy и укажите то же имя storageClassName, которое использовалось в storageClass.yaml:

Note: persistentVolumeReclaimPolicy определяет, что происходит с Persistent Volume после освобождения его запроса (Persistent Volume Claim). Для этого параметра существует три допустимых значения: Retain, Delete и Recycle. В нашем коде мы будем использовать вариант Retain. Более подробную информацию о поле persistentVolumeReclaimPolicy можно найти здесь: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#persistentvolumeclaim-v1-core

Добавьте local.path для вашего Persistent Volume, как показано ниже:

Note: Убедитесь, что этот локальный путь (/mnt/disk/vol) существует на узле вашего кластера Kubernetes.

После добавления всех обязательных полей ваш persistentVolume.yaml файл должен выглядеть следующим образом:

Note: Вы должны использовать правильное имя узла вашей машины. В данном случае это: “worker.”
Подготовка локального тома (Local Volume)

Теперь нам нужно подготовить локальный том на узле “worker”, как мы указали в persistentVolume.yaml файле. Выполните приведенные ниже команды на узле, который вы настроили в persistentVolume. В данном случае это узел “worker”:

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

Выполните приведенную ниже команду на главном узле, где находится ваш persistentVolume.yaml файл:

Вы должны получить следующий вывод:

После успешного создания локального хранилища и Persistent Volume вы можете перейти к созданию Persistent Volume Claim для хранения кода вашего приложения и конфигурационных файлов.

Step 3: Create the Persistent Volume

Код вашего приложения должен быть в безопасности во время управления подами или их обновления. Для этого вы будете использовать Persistent Volume, созданный на предыдущем шаге, доступ к которому осуществляется с помощью PersistentVolumeClaim, или PVC. Этот PVC монтирует PV по требуемому пути.

Откройте файл, например code_volume.yaml, в вашем редакторе:

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

Раздел spec в PVC содержит следующие элементы:

  1. accessModes: Возможны следующие значения для этого поля:
    • ReadWriteOnce – монтирует том для одного узла с правами как на чтение, так и на запись.
    • ReadOnlyMany – монтирует том для множества узлов только с правами на чтение.
    • ReadWriteMany – монтирует том для множества узлов с правами как на чтение, так и на запись.
  2. resources: определяет необходимый объем хранилища.

Поскольку локальное хранилище монтируется только к одному узлу, вам потребуется установить accessMode в значение ReadWriteOnce. В этом руководстве вы добавите лишь небольшой фрагмент кода приложения, поэтому здесь будет достаточно 1 ГБ хранилища. Однако, если вы хотите хранить больший объем данных или кода, вы можете изменить параметр storage в соответствии со своими требованиями. Обратите внимание, что после создания тома вы сможете увеличить размер хранилища. Однако уменьшение размера не поддерживается:

Теперь объявите класс хранилища, который кластер Kubernetes будет использовать для выделения томов. Используйте созданный на предыдущем шаге класс хранилища my-local-storage в качестве значения для storageClassName:

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

Теперь сохраните файл и выйдите из него.

Создание PVC

Создайте PVC code, выполнив команду kubectl apply:

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

Вы можете выполнить следующую команду, чтобы проверить доступные Persistent Volume (PV):

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

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

Теперь вы можете создать свои поды с помощью Deployment, так как вы успешно создали Persistent Volume с использованием локального хранилища.

Шаг 4. Создание Deployment для вашего приложения PHP-FPM

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

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

На этом шаге мы также рассмотрим применение Init-контейнеров (Init Containers). Init-контейнеры выполняют несколько команд перед запуском обычных контейнеров, указанных в шаблоне пода. В данном случае Init-контейнер будет использовать GitHub Gist (https://gist.github.com/) для получения примера файла index.php. Содержимое этого файла-примера:

Создание PHP Deployment

Откройте новый файл с именем php_deployment.yaml в вашем редакторе, чтобы создать Deployment:

Теперь назовите объект Deployment как PHP, так как этот Deployment будет управлять вашими подами PHP-FPM. Добавьте метку tier: backend, потому что под будет принадлежать к уровню backend:

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

Добавьте app: php и tier:backend метки под ключом selector, который указывает, что этот Deployment будет управлять подами, соответствующими этим двум меткам:

Теперь определению объекта вашего пода требуется шаблон (template) в спецификации Deployment. Этот шаблон определяет спецификацию, необходимую для создания вашего пода. Для начала добавьте метки, которые были указаны для селектора службы php и matchLabels в Deployment. Затем добавьте app:php и tier:backend под template.metadata.labels:

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

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

Затем укажите имя контейнера вместе с образом, который вы хотите запустить внутри вашего пода. В магазине Docker (https://hub.docker.com/explore/) доступно множество различных образов, но в этом руководстве мы будем использовать образ php:7-fpm:

Теперь смонтируйте тома, к которым контейнеру требуется доступ. Поскольку этот контейнер будет запускать ваш PHP-код, ему понадобится доступ к тому code, созданному на предыдущем шаге. На этом шаге вы также узнаете, как скопировать код вашего приложения с помощью Init-контейнера.

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

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

Сначала добавьте ваш initContainer под spec.template.spec и укажите образ busybox:

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

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

Note: Убедитесь, что вы доверяете коду, который вы загружаете на свой сервер с помощью Init-контейнера. Вы можете изучить исходный код и убедиться, что вас устраивает то, что он делает.

Кроме того, добавьте следующие строки под контейнером install в spec.template.spec.initContainers:

После выполнения всех этих шагов ваш php_deployment.yaml файл должен выглядеть следующим образом:

Теперь вы можете сохранить файл и выйти. Далее создайте свой PHP-FPM Deployment с помощью kubectl apply команды:

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

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

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

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

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

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

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

Объяснение:

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

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

Изменение статуса вашего пода на podInitializing может занять несколько минут в зависимости от сложности ваших скриптов запуска:

Это указывает на то, что Init-контейнеры успешно запустились, и теперь инициализируются основные контейнеры:

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

1. Для просмотра подробной информации о поде:

2.  Для просмотра логов пода:

Note: Для команды “kubectl logs” доступно множество опций, вы можете выполнить команду “kubectl logs –help”, чтобы узнать больше.

3. Для просмотра логов конкретного контейнера в поде:

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

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

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

Для начала откройте файл nginx_configmap.yaml в вашем редакторе:

Теперь назовите этот ConfigMap nginx-config и добавьте его в микросервис tier: backend:

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

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

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

Теперь вы можете сохранить изменения и выйти из редактора. Теперь выполните kubectl apply — команду для создания ConfigMap:

После этого вы должны увидеть на экране следующий вывод:

Вы успешно создали Nginx Configmap. Теперь вы можете создать Nginx Deployment.

Создание Nginx Deployment

Для начала вы можете создать новый файл с именем nginx_deployment.yaml в редакторе:

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

После этого укажите количество реплик, добавив поле replica в спецификацию Deployment, и добавьте к нему метки app: nginx и tier: backend:

Аналогично добавьте шаблон пода. Убедитесь, что вы добавили те же метки, которые были добавлены в selector.matchLabels Deployment. Вы можете добавить следующее:

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

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

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

Теперь укажите имя, образ и порт, которые вы хотите использовать в своем поде. Здесь мы будем использовать образ nginx:1.7.9 и порт 80. Добавьте их в раздел spec.template.spec раздел:

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

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

После выполнения всех вышеперечисленных шагов ваш файл nginx_deployment.yaml должен выглядеть следующим образом:

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

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

Вы можете вывести список всех ваших Deployments, выполнив следующие команды:

Теперь вы должны увидеть Deployments как для Nginx, так и для PHP-FPM:

kubernetes deployment status

Кроме того, вы можете выполнить следующую команду, чтобы вывести список подов, управляемых обоими перечисленными выше Deployments:

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

kubernetes pod status

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

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

Запишите External IP вашего сервиса Nginx:external ip of nginx Deploy a PHP Application on Kubernetes Cluster with Ubuntu 18.04

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

Заключение

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

Кроме того, ознакомьтесь с другими нашими руководствами по Docker и Kubernetes, которые вы можете найти в нашем блоге:

Приятной работы!

author

Hark Labs

Автор · CloudSigma

Preslav Dobrev — креативный дизайнер в CloudSigma, сосредоточенный на формировании последовательного корпоративного образа с помощью традиционных и инновационных маркетинговых каналов. Он умело сочетает художественное видение со стратегическим маркетингом, создавая убедительные истории бренда.

Комментарии

Комментариев пока нет. Будьте первым.