php / php/frankenphp

Worker mode does not use updated endpoints in Kubernetes cluster

Open
#1,563 11 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
11.3k
Forks
488
Avg merge
4d 10h
Merged PRs (30d)
11

Description

What happened?

Good day,

We’ve been using FrankenPHP (in non-worker mode) for quite some time on our Kubernetes cluster with great success. It’s been running smoothly and reliably.

However, when we enable worker mode, FrankenPHP does not appear to pick up updated Kubernetes endpoints, such as new pod IP from services like PostgreSQL and/or RabbitMQ. We use PostgreSQL and RabbitMQ in a HA setup, with multiple replications. For both, the Kubernetes service endpoint always referes to a single replica. Whenever this endpoint changes within the cluster (e.g. we kill the main PostgreSQL/RabbitMQ replica), service discovery becomes stale or broken, even though everything continues to work as expected in non-worker mode.

We’re unsure if this behavior stems from a bug, a misconfiguration, or a limitation by design, and would appreciate any guidance or help you can offer. Especially since worker mode offers significant performance improvements that we’d like to benefit from.

Reproducible With Docker Images:
dunglas/frankenphp:1.4.2-php8.4-alpine  
dunglas/frankenphp:1.5.0-php8.3-alpine  
dunglas/frankenphp:1.5.0-php8.4-alpine  
dunglas/frankenphp:1.5.0-php8.3-bookworm  
dunglas/frankenphp:1.5.0-php8.4-bookworm
Reproducible with the following Caddy configs:
Worker mode enabled:
{
	{$CADDY_GLOBAL_OPTIONS}
        frankenphp {
             worker {
                  file ./public/index.php
                  num 10
                  env APP_RUNTIME "Runtime\FrankenPhpSymfony\Runtime"
             }
        }
	order php_server before file_server
}

{$CADDY_EXTRA_CONFIG}

{$SERVER_NAME:localhost} {
	root * public/
	encode zstd br gzip
	{$CADDY_SERVER_EXTRA_DIRECTIVES}
	php_server
}
Worker mode disabled (this solves our issue mentioned above):
{
	{$CADDY_GLOBAL_OPTIONS}
	frankenphp
	order php_server before file_server
}

{$CADDY_EXTRA_CONFIG}

{$SERVER_NAME:localhost} {
	root * public/
	encode zstd br gzip
	{$CADDY_SERVER_EXTRA_DIRECTIVES}
	php_server
}
PHP configuration:
expose_php = 0
date.timezone = UTC
apc.enable_cli = 1
session.use_strict_mode = 1
zend.detect_unicode = 0
display_errors = 0

opcache.preload_user = root
opcache.preload = /app/config/preload.php
realpath_cache_size = 4096K
realpath_cache_ttl = 600
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.memory_consumption = 256
opcache.enable_file_override = 1
opcache.validate_timestamps = 0

variables_order = EGPCS
Kubernetes cluster environment:
PostgreSQL deployment:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: db-cluster
spec:
  instances: 3
  storage:
    storageClass: longhorn-static
    size: 10Gi
  walStorage:
    storageClass: longhorn-static
    size: 5Gi
RabbitMQ deployment:
apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
  name: rabbitmq
  labels:
    app.kubernetes.io/instance: rabbitmq
spec:
  replicas: 3
  persistence:
    storageClassName: longhorn-static
    storage: 20Gi
  service:
    type: LoadBalancer
  resources:
    requests:
      memory: 2Gi
    limits:
      memory: 2Gi
Application Environment Config

We use a ConfigMap to inject application-level environment variables:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-configmap
data:
  APP_ENV: dev
  APP_ENVIRONMENT: development
  LOCK_DSN: semaphore
  CORS_ALLOW_ORIGIN: '^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'
  DATABASE_HOST: db-cluster-rw
  DATABASE_RO_HOST: db-cluster-ro
  RABBITMQ_HOST: rabbitmq
  [...]

These values are correctly visible within the pod via printenv, for example:

DATABASE_HOST=db-cluster-rw
DATABASE_RO_HOST=db-cluster-ro
RABBITMQ_HOST=rabbitmq
Network Resolution

DNS resolution seems to work fine even from within the pod:

/app # ping db-cluster-rw
PING db-cluster-rw (10.96.240.237): 56 data bytes

This refers to a standard Kubernetes service endpoint.

Expected Behavior

In worker mode, we expect the application to properly recognize updated service endpoints (e.g., whenever we kill/delete a replica and a service/endpoint IP changes) in line with what works in non-worker mode. Currently, these endpoint changes are not being picked up, and simple result in:

An exception occurred while executing a query: SQLSTATE[HY000]: General error: 7 no connection to the server

The issue remains unresolved until the FrankenPHP pod is killed or restarted.

Request for help

Could you confirm whether this is:

  • A bug in FrankenPHP worker mode
  • A configuration mistake on our side
  • A known limitation (and if so, is there a recommended workaround?)

We’re happy to test any patches, experimental flags, or configuration tweaks that might help isolate or resolve this issue.

Thanks in advance for your support and for the amazing work on FrankenPHP!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the failure with one of the listed FrankenPHP Docker images and compare the supplied worker and non-worker Caddy configurations. Investigate whether Kubernetes service resolution or database and RabbitMQ connections remain stale in worker mode; done means endpoint changes recover without restarting the FrankenPHP pod, or the limitation and workaround are documented.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, kubernetes, php, postgresql, rabbitmq
Domain
backend, databases, devops, networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.