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

Введение

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

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

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

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

php illustration for: Предварительные требования
  • Базовое понимание объектов Kubernetes. Ознакомьтесь с нашей статьей Введение в Kubernetes для получения дополнительной информации.
  • Учетная запись the cloud provider и маркер доступа 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.

				
					
mkdir definitions

				
			

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

				
					
cd definitions

				
			

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

				
					
nano php_service.yaml

				
			

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

				
					
[label php_service.yaml]

...

apiVersion: v1

kind: Service

				
			

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

				
					
[label php_service.yaml]

...

metadata:

 name: php

				
			

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

				
					
[label php_service.yaml]

...

 labels:

 tier: backend

				
			

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

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

				
					
[label php_service.yaml]

...

spec:

 selector:

 app: php

 tier: backend

				
			

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

				
					
[label php_service.yaml]

...

 ports:

 - protocol: TCP

 port: 9000

				
			

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

				
					
[label 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

				
			

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

				
					
[secondary_label Output]

service/php created

				
			

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

				
					
kubectl get svc

				
			

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

				
					
[secondary_label 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 с помощью редактора:

				
					
nano nginx_service.yaml

				
			

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

				
					
[label nginx_service.yaml]

apiVersion: v1

kind: Service

metadata:

 name: nginx

 labels:

 tier: backend

				
			

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

				
					
[label nginx_service.yaml]

...

spec:

 selector:

 app: nginx

 tier: backend

 ports:

 - protocol: TCP

 port: 80

				
			

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

				
					
[label nginx_service.yaml]

...

spec:

 externalIPs:

 - &lt;^&gt;your_public_ip&lt;^&gt;

				
			

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

				
					
[label 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:

 - &lt;^&gt;your_public_ip&lt;^&gt; 

				
			

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

				
					
kubectl apply -f nginx_service.yaml

				
			

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

				
					
[secondary_label Output]

service/nginx created

				
			

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

				
					
kubectl get svc

				
			

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

				
					
[secondary_label Output]

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

kubernetes ClusterIP 10.96.0.1 &lt;none&gt; 443/TCP 13m

nginx ClusterIP 10.102.160.47 &lt;^&gt;your_public_ip&lt;^&gt; 80/TCP 50s

php ClusterIP 10.100.59.238 &lt;none&gt; 9000/TCP 8m

				
			

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

				
					
kubectl delete svc/&lt;^&gt;service_name&lt;^&gt;

				
			

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

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

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

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

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

				
					
nano secret.yaml

				
			

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

				
					
[label secret.yaml]

apiVersion: v1

kind: Secret

metadata:

 name: the cloud provider

 namespace: kube-system

				
			

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

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

				
					
[label secret.yaml]

...

stringData:

 access-token: &lt;^&gt;your-api-token&lt;^&gt;

				
			

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

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

				
					
[label secret.yaml]

apiVersion: v1

kind: Secret

metadata:

 name: the cloud provider

 namespace: kube-system

stringData:

 access-token: &lt;^&gt;your-api-token&lt;^&gt;

				
			

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

				
					
kubectl apply -f secret.yaml

				
			

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

				
					
[secondary_label Output]

secret/the cloud provider created

				
			

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

				
					
kubectl -n kube-system get secret the cloud provider

				
			

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

				
					
[secondary_label Output]

NAME TYPE DATA AGE

the cloud provider Opaque 1 41s

				
			

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

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

				
					
kubectl apply -f https://kubernetes.io/docs/home/

				
			

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

				
					
[secondary_label 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

				
			

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

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

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

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

				
					
nano code_volume.yaml

				
			

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

				
					
[label code_volume.yaml]

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

 name: code

				
			

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

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

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

				
					
[label code_volume.yaml]

...

spec:

 accessModes:

 - ReadWriteOnce

 resources:

 requests:

 storage: &lt;^&gt;1Gi&lt;^&gt;

				
			

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

				
					
[label code_volume.yaml]

...

 storageClassName: do-block-storage

				
			

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

				
					
[label code_volume.yaml]

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

 name: code

spec:

 accessModes:

 - ReadWriteOnce

 resources:

 requests:

 storage: &lt;^&gt;1Gi&lt;^&gt;

 storageClassName: do-block-storage

				
			

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

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

				
					
kubectl apply -f code_volume.yaml

				
			

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

				
					
[secondary_label Output]

persistentvolumeclaim/code created

				
			

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

				
					
kubectl get pv

				
			

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

				
					
[secondary_label 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, а также из инфраструктуры the cloud provider. Вы можете получить дополнительные данные о параметрах Reclaim Policy (Политика восстановления) и Status (Статус) в документации Kubernetes PV.

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

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

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

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

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

				
					
[label index.php]

&lt;?php

echo phpinfo();

				
			

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

				
					
nano php_deployment.yaml

				
			

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

				
					
[label php_deployment.yaml]

apiVersion: apps/v1

kind: Deployment

metadata:

 name: php

 labels:

 tier: backend

				
			

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

				
					
[label php_deployment.yaml]

...

spec:

 replicas: 1

				
			

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

				
					
[label php_deployment.yaml]

...

 selector:

 matchLabels:

 app: php

 tier: backend

				
			

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

				
					
[label php_deployment.yaml]

...

 template:

 metadata:

 labels:

 app: php

 tier: backend

				
			

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

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

				
					
[label php_deployment.yaml]

...

 spec:

 volumes:

 - name: code

 persistentVolumeClaim:

 claimName: code

				
			

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

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

				
					
[label php_deployment.yaml]

...

 containers:

 - name: php

 image: php:7-fpm

				
			

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

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

				
					
[label php_deployment.yaml]

...

 volumeMounts:

 - name: code

 mountPath: /code

				
			

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

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

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

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

				
					
[label php_deployment.yaml]

...

 initContainers:

 - name: install

 image: busybox

				
			

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

				
					
[label php_deployment.yaml]

...

 volumeMounts:

 - name: code

 mountPath: /code

				
			

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

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

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

				
					
[label php_deployment.yaml]

...

 command:

 - wget

 - "-O"

 - "/code/index.php"

 - &lt;^&gt;https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php&lt;^&gt;

				
			

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

				
					
[label 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"

 - &lt;^&gt;https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php&lt;^&gt;

				
			

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

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

				
					
kubectl apply -f php_deployment.yaml

				
			

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

				
					
[secondary_label Output]

deployment.apps/php created

				
			

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

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

				
					
kubectl get deployments

				
			

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

				
					
[secondary_label Output]

NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE

php 1 1 1 0 19s

				
			

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

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

				
					
kubectl get pods

				
			

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

				
					
[secondary_label 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:

				
					
[secondary_label Output]

NAME READY STATUS RESTARTS AGE

php-86d59fd666-lkwgn 0/1 podInitializing 0 39s

				
			

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

				
					
[secondary_label Output]

NAME READY STATUS RESTARTS AGE

php-86d59fd666-lkwgn 1/1 Running 0 1m

				
			

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

  • Просмотр подробной информации о поде:
				
					
kubectl describe pods &lt;^&gt;pod-name&lt;^&gt;

				
			
  • Просмотр журналов, сгенерированных подом:
				
					
kubectl logs &lt;^&gt;pod-name&lt;^&gt;

				
			
  • Просмотр журналов для конкретного контейнера в поде:
				
					
kubectl logs &lt;^&gt;pod-name&lt;^&gt; &lt;^&gt;container-name&lt;^&gt;

				
			

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

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

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

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

				
					
nano nginx_configMap.yaml

				
			

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

				
					
[label 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:

				
					
[label 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 &lt;^&gt;php:9000&lt;^&gt;;

 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 будет выглядеть следующим образом:

				
					
[label 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 &lt;^&gt;/code&lt;^&gt;;



 location / {

 try_files $uri $uri/ /index.php?$query_string;

 }



 location ~ \.php$ {

 try_files $uri =404;

 fastcgi_split_path_info ^(.+\.php)(/.+)$;

 fastcgi_pass &lt;^&gt;php:9000&lt;^&gt;;

 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

				
			

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

				
					
[secondary_label Output]

configmap/nginx-config created

				
			

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

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

				
					
nano nginx_deployment.yaml

				
			

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

				
					
[label nginx_deployment.yaml]

apiVersion: apps/v1

kind: Deployment

metadata:

 name: nginx

 labels:

 tier: backend

				
			

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

				
					
[label nginx_deployment.yaml]

...

spec:

 replicas: 1

 selector:

 matchLabels:

 app: nginx

 tier: backend

				
			

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

				
					
[label nginx_deployment.yaml]

...

 template:

 metadata:

 labels:

 app: nginx

 tier: backend

				
			

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

				
					
[label nginx_deployment.yaml]

...

 spec:

 volumes:

 - name: code

 persistentVolumeClaim:

 claimName: code

				
			

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

				
					
[label nginx_deployment.yaml]

...

 - name: config

 configMap:

 name: nginx-config

 items:

 - key: config

 path: site.conf

				
			

[warning]

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

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

				
					
[label nginx_deployment.yaml]

...

 containers:

 - name: nginx

 image: &lt;^&gt;nginx:1.7.9&lt;^&gt;

 ports:

 - containerPort: 80

				
			

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

				
					
[label nginx_deployment.yaml]

...

 volumeMounts:

 - name: code

 mountPath: /code

				
			

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

				
					
[label nginx_deployment.yaml]

...

 - name: config

 mountPath: /etc/nginx/conf.d

				
			

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

				
					
[label 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: &lt;^&gt;nginx:1.7.9&lt;^&gt;

 ports:

 - containerPort: 80

 volumeMounts:

 - name: code

 mountPath: /code

 - name: config

 mountPath: /etc/nginx/conf.d

				
			

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

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

				
					
kubectl apply -f nginx_deployment.yaml

				
			

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

				
					
[secondary_label Output]

deployment.apps/nginx created

				
			

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

				
					
kubectl get deployments

				
			

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

				
					
[secondary_label Output]

NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE

nginx 1 1 1 0 16s

php 1 1 1 1 7m

				
			

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

				
					
kubectl get pods

				
			

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

				
					
[secondary_label 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:

				
					
[secondary_label Output]

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR

kubernetes ClusterIP 10.96.0.1 &lt;none&gt; 443/TCP 39m &lt;none&gt;

nginx ClusterIP 10.102.160.47 &lt;^&gt;your_public_ip&lt;^&gt; 80/TCP 27m app=nginx,tier=backend

php ClusterIP 10.100.59.238 &lt;none&gt; 9000/TCP 34m app=php,tier=backend

				
			

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

Заключение

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