• Время чтения ~3 мин
  • 14.11.2023

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

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

Здесь мы хотим рассказать вам о некоторых подводных камнях в управлении сессиями Laravel, с которыми вы столкнетесь при переходе к развертыванию Kubernetes. Хорошая новость заключается в том, что все они могут быть исправлены при понимании внутренней работы контейнеризации.

Эта статья спонсируется Scout APM.

Преимущества использования Kubernetes с Laravel

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

  1. Stateless horizontal scaling. Laravel is inherently designed to be stateless for most of its components (excluding sessions and cache if stored locally). This design complements Kubernetes' scaling capabilities. When traffic to your Laravel application increases, Kubernetes can quickly spawn more replicas of your Laravel application to handle the load, and vice-versa when traffic decreases.
  2. Background processing. Laravel's job and queue system, built around tools like Laravel Horizon, can benefit from Kubernetes' deployment strategies. For instance, worker containers can be scaled independently of the main application, allowing for effective processing of queued jobs.
  3. Configuration management. Laravel's configuration system relies heavily on environment variables. Kubernetes' ConfigMaps and Secrets make it easy to manage and inject these environment variables consistently and securely across different environments (development, staging, production).
  4. Storage flexibility. If your Laravel application requires file storage (for example, for user uploads), Kubernetes offers Persistent Volume Claims (PVCs) that abstract the underlying storage backend. This means your Laravel application can seamlessly store files whether you're on cloud object storage, a block storage device, or a network file system.
  5. Service mesh integration. If you adopt a service mesh like Istio with your Laravel application on Kubernetes, you gain enhanced observability, traffic management, and security features without modifying the Laravel application itself.

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

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

Проблемы управления сессиями с помощью Laravel и Kubernetes Таким образом, сложность управления сессиями возникает из-за трех факторов, неотъемлемых от того, как работает Kubernetes

.

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

Во-вторых, эфемерная природа стручков. Модули pod в Kubernetes можно завершить работу и заменить в любое время, особенно если они становятся неработоспособными или во время обновлений. Если сеанс хранится локально в модуле pod и этот модуль pod завершается, данные сеанса теряются, что влияет на взаимодействие с пользователем.

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

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

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

  1. Leverage Kubernetes' session affinity feature to ensure requests from a user consistently land on the same replica.
  2. Store sessions in distributed systems like Redis or databases, ensuring that session data is centralized and accessible to all replicas.

Давайте рассмотрим каждый вариант и то, как они работают с Laravel.

Привязка

сеансов Сходство сеансов, также известное как «закрепленные сеансы», может иметь решающее значение в сценариях, где развернуты приложения или рабочие нагрузки с отслеживанием состояния, и вы хотите, чтобы все запросы от определенного клиента всегда направлялись в один и тот же модуль. В Kubernetes этого можно добиться с помощью сходства сеансов службы.

В традиционных монолитных архитектурах приложения обычно выполняются на одном сервере, где данные сеанса хранятся локально. Эта модель гарантирует, что все последующие запросы от конкретного пользователя всегда будут иметь доступ к данным сеанса этого пользователя. Но в среде оркестрации контейнеров, такой как Kubernetes, ваше приложение может работать в нескольких модулях pod, распределенных по разным узлам. Здесь нет никакой встроенной гарантии, что последующие запросы пользователя будут попадать в один и тот же модуль каждый раз.

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

Kubernetes предоставляет концепцию сходства сеансов, позволяя указать, что все запросы от конкретного клиента должны направляться в один и тот же модуль pod. Это достигается с помощью файлов cookie или IP-адреса.

При настройке сходства сеансов на основе IP-адреса клиента Kubernetes проверяет исходный IP-адрес входящего запроса и направляет его в тот же модуль pod, что и предыдущие запросы с этого IP-адреса. Если сходство сеансов основано на файлах cookie, Kubernetes гарантирует, что все запросы с определенным файлом cookie направляются в один и тот же модуль.

В определении YAML службы необходимо указать тип сходства сеансов. Например:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
  sessionAffinity: ClientIP

sessionAffinityВ приведенной выше конфигурации в поле установлено значение ClientIP, что означает, что служба Kubernetes будет использовать IP-адрес клиента, чтобы гарантировать, что все запросы с этого IP-адреса будут направлены в один и тот же pod.

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

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 3600

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

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

Распределенные хранилища сеансов с Redis Распределенное хранилище сеансов, такое как Redis

в Laravel, позволяет обмениваться данными сеанса между несколькими экземплярами приложения. Это особенно полезно в масштабируемых средах, таких как Kubernetes, где приложение может выполняться в нескольких модулях pod, и любой из этих модулей pod может обслуживать запросы пользователей.

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

  1. Performance. Redis is an in-memory data structure store offering rapid data access. This makes it exceptionally well-suited for session management, where fast read and write operations are crucial for maintaining a seamless user experience.
  2. Scalability. Redis supports horizontal partitioning or sharding, making it scalable across multiple machines. In high-traffic scenarios where a single Redis instance might become a bottleneck, you can distribute your data across multiple Redis instances.
  3. Persistence. While primarily an in-memory store, Redis provides mechanisms to persist data on disk without compromising much on performance. This ensures that session data isn't lost if the Redis service restarts.
  4. Data structures. Redis isn't just a simple key-value store. It supports a variety of data structures like strings, hashes, lists, and sets. This flexibility can be beneficial for more complex session-related operations.

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

Давайте рассмотрим шаги по настройке Redis в качестве драйвера сессии в Laravel. Во-первых, вам нужно установить необходимый пакет:Затем вы можете обновить файл Laravel .env, чтобы он указывал на Redis для управления сеансами:В Laravel вам нужно обновить свой config/session.php, чтобы использовать драйвер сеанса из файла .env:Затем убедитесь, что конфигурация Redis в config/database.php выглядит следующим образом:

composer require predis/predis

SESSION_DRIVER=redis
REDIS_HOST=your_redis_server
REDIS_PASSWORD=your_redis_password
REDIS_PORT=6379

'driver' => env('SESSION_DRIVER', 'file'),

'redis' => [
    'client' => 'predis',
    'default' => [
        'host'     => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD', null),
        'port'     => env('REDIS_PORT', 6379),
        'database' => env('REDIS_DB', 0),
    ],
],

Далее вам понадобится таблица для хранения сеансов. Laravel предоставляет команду для создания этой таблицы:

php artisan session:table

Это создаст файл миграции. Запустите миграцию, чтобы сделать таблицу сессий:

php artisan migrate

После вышеуказанных конфигураций Laravel будет автоматически обрабатывать сеансы с использованием Redis, не требуя какого-либо специального кода в вашем приложении. Например, когда вы устанавливаете переменную сессии:

session(['key' => 'value']);

Это значение будет сохранено в Redis. Чтобы получить его:

$value = session('key');

Когда вы вызываете такие функции, Laravel автоматически использует Redis в качестве бэкенда для управления данными сеанса.

Чтобы развернуть Redis в Kubernetes, необходимо использовать Helm для развертывания экземпляра Redis в кластере Kubernetes:

# Add the Bitnami repository which has the Redis chart
helm repo add bitnami <https://charts.bitnami.com/bitnami>
# Install Redis using Helm
helm install my-redis bitnami/redis

Обязательно запишите пароль для экземпляра Redis, предоставленный Helm во время установки. Затем создайте манифест службы Kubernetes. Назовем его redis-service.yaml:Вы можете применить манифест службы Kubernetes для создания службы:Затем убедитесь, что служба запущена:Наконец, укажите Laravel на службу Redis Kubernetes, обновив файл или конфигурацию Laravel .env, чтобы использовать службу Redis, созданную в Kubernetes:

apiVersion: v1
kind: Service
metadata:
  name: redis-service
spec:
  selector:
    app: redis
  ports:
    - protocol: TCP
      port: 6379
      targetPort: 6379

redis-service является хостом,

kubectl apply -f redis-service.yaml

потому что это имя службы Kubernetes,

kubectl get svc redis-service

REDIS_HOST=redis-service
REDIS_PORT=6379

и внутренний DNS Kubernetes разрешит это имя в соответствующий IP-адрес для службы.

Поздравляем, вы интегрировали Redis с Laravel и обеспечили, чтобы приложение Laravel взаимодействовало с экземпляром Redis, развернутым в Kubernetes. Это обеспечивает эффективное хранение и управление данными сеанса в распределенной среде.

Масштабируемые сеансы с помощью Laravel и Kubernetes

Используя сходства сеансов и распределенное хранилище сеансов, ваше приложение Laravel может хранить и сохранять данные сеанса, к которым могут получить доступ все экземпляры вашего приложения. Затем вы можете масштабировать приложение, гарантируя, что все пользователи сохранят данные сеанса независимо от того, какой экземпляр вашего приложения обрабатывает их запрос. В среде Kubernetes, где модули pod могут быть эфемерными, а пользовательские запросы могут направляться в любой pod, эти параметры необходимы для поддержания согласованности пользовательских сеансов.

По мере развития технологий обеспечение бесперебойного взаимодействия с пользователями приобретает первостепенное значение, особенно в распределенных и масштабируемых средах, таких как Kubernetes. Используя присущую Laravel адаптивность с надежностью Kubernetes, разработчики могут решать проблемы управления сессиями. Эта комбинация не только повышает устойчивость приложений, но и прокладывает путь к будущей масштабируемости без ущерба для удобства пользователей.

Попробуйте Scout APM уже сегодня!

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Об авторе CrazyBoy49z
WORK EXPERIENCE
Контакты
Ukraine, Lutsk
+380979856297