Поиск по сайту:

Как развернуть приложение PHP с Kubernetes в Ubuntu 16.04


Автор выбрал программу Write for DOnations.

Введение

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

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

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

Примечание. Это руководство было протестировано на кластере Kubernetes, созданном с использованием документации по продукту DigitalOcean Kubernetes, для получения актуальной информации и руководств.

Предпосылки

  • Основное понимание объектов 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.
  • метаданные: содержит имя объекта вместе с любыми метками, которые вы можете применить к нему.
  • spec: содержит определенную конфигурацию в зависимости от типа создаваемого вами объекта, например образа контейнера или портов, через которые контейнер будет доступен.

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

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

  1. mkdir definitions

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

  1. cd definitions

Создайте свой сервис PHP-FPM, создав файл php_service.yaml:

  1. nano php_service.yaml

Установите kind как Service, чтобы указать, что этот объект является службой:

...
apiVersion: v1
kind: Service

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

...
metadata:
  name: php

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

...
  labels:
    tier: backend

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

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

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

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

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

Готовый файл 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.

Создайте свой сервис:

  1. kubectl apply -f php_service.yaml

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

Output
service/php created

Убедитесь, что ваша служба работает:

  1. kubectl get svc

Вы увидите, что ваша служба 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:

  1. nano nginx_service.yaml

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

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

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

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

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

...
spec:
  externalIPs:
  - your_public_ip

Ваш файл 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:

  1. kubectl apply -f nginx_service.yaml

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

Output
service/nginx created

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

  1. kubectl get svc

В выводе вы увидите службы 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

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

  1. kubectl delete svc/service_name

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

Шаг 2 — Установка подключаемого модуля хранилища DigitalOcean

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

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

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

  1. nano secret.yaml

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

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

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

Добавьте токен доступа как stringData:

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

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

Ваш файл secret.yaml будет выглядеть так:

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

Создайте секрет:

  1. kubectl apply -f secret.yaml

Вы увидите этот вывод при создании секрета:

Output
secret/digitalocean created

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

  1. kubectl -n kube-system get secret digitalocean

Вывод будет выглядеть примерно так:

Output
NAME TYPE DATA AGE digitalocean Opaque 1 41s

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

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

  1. 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 — Создание постоянного тома

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

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

  1. nano code_volume.yaml

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

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: code

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

  • Режимы доступа, которые зависят от варианта использования. Это:
    • ReadWriteOnce — монтирует том для чтения и записи одним узлом
    • ReadOnlyMany — монтирует том как доступный только для чтения многими узлами
    • ReadWriteMany — монтирует том для чтения и записи многими узлами

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

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

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

    ...
      storageClassName: do-block-storage
    

    Ваш файл code_volume.yaml будет выглядеть так:

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

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

    Создайте code PersistentVolumeClaim, используя kubectl:

    1. kubectl apply -f code_volume.yaml

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

    Output
    persistentvolumeclaim/code created

    Чтобы просмотреть доступные постоянные тома (PV):

    1. kubectl get pv

    Вы увидите свой 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. Политика возврата определяет, что делать с PV после удаления PVC, обращающегося к нему. Delete удаляет PV из Kubernetes, а также из инфраструктуры DigitalOcean. Подробнее о Политике возврата и Статусе можно узнать из документации Kubernetes PV.

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

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

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

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

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

    <?php
    echo phpinfo(); 
    

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

    1. nano php_deployment.yaml

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

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

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

    ...
    spec:
      replicas: 1
    

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Готовый файл 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:

    1. kubectl apply -f php_deployment.yaml

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

    Output
    deployment.apps/php created

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

    Вы можете просмотреть свое развертывание, запустив:

    1. kubectl get deployments

    Вы увидите вывод:

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

    Эти выходные данные могут помочь вам понять текущее состояние развертывания. Развертывание — это документация по развертыванию Kubernetes.

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

    1. kubectl get pods

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

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

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

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

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

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

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

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

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

    • Просмотр подробной информации о пакете:

    1. kubectl describe pods pod-name

    • Просмотр журналов, созданных модулем:

    1. kubectl logs pod-name

    • Просмотр журналов для определенного контейнера в модуле:

    1. kubectl logs pod-name container-name

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

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

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

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

    1. nano nginx_configMap.yaml

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

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

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

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

    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;
            }
        }
    

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

    Создайте карту конфигурации:

    1. kubectl apply -f nginx_configMap.yaml

    Вы увидите следующий вывод:

    Output
    configmap/nginx-config created

    Вы закончили создание ConfigMap и теперь можете создать развертывание Nginx.

    Начните с открытия нового файла nginx_deployment.yaml в редакторе:

    1. nano nginx_deployment.yaml

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

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

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

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

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

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

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

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

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

    ...
          - 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 добавьте:

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

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

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

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

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

    Ваш файл 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:

    1. kubectl apply -f nginx_deployment.yaml

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

    Output
    deployment.apps/nginx created

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

    1. kubectl get deployments

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

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

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

    1. kubectl get pods

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

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

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

    Список запущенных служб:

    1. 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, чтобы вы могли управлять ими независимо. Такой подход не только улучшит масштабируемость вашего проекта по мере его роста, но и позволит вам эффективно использовать ресурсы. Вы также сохранили код своего приложения на томе, чтобы легко обновлять свои службы в будущем.