Why teams run Drupal on Kubernetes and what it changes
If your organization already runs a container platform, or has a requirement for repeatable releases across environments, the question is how a stateful CMS fits into that model. Drupal on Kubernetes means stateless PHP containers, with files, database, cache and cron moved out of the pod. The web pods hold only code built at image build time, so any replica can serve any request. Uploaded files go to a shared file system or object storage, the database runs as a managed service or a separately operated cluster, Redis or Memcache holds the cache, and cron runs as a scheduled Kubernetes job rather than inside a web container. Each of those external dependencies needs an owner, a backup plan and a monitoring target before the first deployment.
The software cost is lower than many teams expect. Drupal core and contributed projects hosted on Drupal.org are licensed under GPL-2.0-or-later, and there is no paid edition of Drupal itself, so the budget goes to build, integration and operations work. Drupal 11 is the current major version. According to the Drupal core release schedule, Drupal 12 is scheduled for the week of December 7, 2026, and Drupal 10 reaches end of life on December 9, 2026. Confirm which version your site targets and the PHP version your base image provides before you choose a container image, because each Drupal release sets its own minimum PHP version on the Drupal.org PHP requirements page.
Plan for the upgrade cadence as part of the platform, not as an afterthought. Bugfix releases arrive on the first Wednesday of each month and security releases on the third Wednesday, according to the Drupal core release schedule, so your pipeline must be able to rebuild and roll out an image on short notice. Ask any partner to show how a security release becomes a new image, how database updates and configuration import run during a rolling deploy, and who approves the change. Those answers determine whether Kubernetes gives you repeatable releases or simply moves the manual work into YAML.
Which file, database and cache patterns fit which situations
Shared ReadWriteMany file storage mounts one volume into every PHP pod, so Drupal's sites/default/files directory behaves as it does on a traditional server. This fits teams that want the least change to core file handling, have contributed modules that write to local paths without an object storage adapter, or run on-premises where an NFS or distributed file system is already supported by operations. The trade-off is that the storage layer becomes a shared dependency: latency on file reads, locking behavior and capacity growth all affect every replica at once. Private files still need a path outside the web root and a clear backup target.
- Access mode support: Confirm that the storage class offers ReadWriteMany and that the vendor documents its behavior under concurrent writes from many pods.
- Performance under load: Ask how file metadata operations scale when image styles generate many small files.
- Private file separation: Plan a separate volume or path for private files, with access controlled by Drupal rather than by network position.
- Backup consistency: Confirm snapshot and restore procedures for the volume, and whether they can run without pausing cron.
- Growth and quotas: Ask how capacity is expanded and whether expansion requires downtime.
Confirm the access mode, latency profile and restore procedure with the storage vendor before the design is fixed.
Object storage keeps public and private files in a bucket accessed over an S3-compatible API, typically through a contributed module that maps Drupal's file system to the bucket. Pods stay stateless, scaling and replacing them does not touch file data, and backup and lifecycle rules sit with the bucket. This fits platforms with high file counts, multiple clusters serving the same content, or a requirement to keep private files in a separately governed store. The trade-off is that Drupal must be configured to treat file paths, image derivatives and private access correctly, and some contributed modules assume local disk.
- Public and private buckets: Use separate buckets or prefixes with distinct access policies, so private documents are never reachable through public URLs.
- Signed URLs for private files: Confirm how the chosen module issues time-limited links and how Drupal's access checks still gate every request.
- Image derivatives: Decide whether generated styles are stored in the bucket or regenerated, since this changes both cost and cache behavior.
- Endpoint and region: Confirm the endpoint, region and TLS settings your storage provider supports for the module version you pin.
- Module compatibility: Check every contributed module that writes files against the object storage adapter before go-live.
Confirm the S3 compatibility level, lifecycle and versioning features, and the bucket access model with the storage provider.
A managed database service runs the database engine, backups, patching and failover under the provider's operations, while the Drupal platform connects to it over the network. This fits teams that lack a database administration function, need point-in-time recovery without building it, or want the database outside the cluster's failure domain. Drupal supports MariaDB, MySQL, PostgreSQL and SQLite according to the Drupal.org system requirements page, so the engine choice comes first. The trade-off is less control over engine tuning and extensions, plus recurring service fees and a dependency on the provider's maintenance windows.
- Engine and version: Confirm the engine and minimum version against the Drupal release you are deploying, and check contributed module requirements for that engine.
- Network path: Plan private connectivity from the cluster to the database, with no public endpoint for application traffic.
- Backup and restore: Confirm retention, point-in-time recovery window and how a restore is tested into a separate environment.
- Maintenance and upgrades: Ask how minor and major engine upgrades are scheduled and whether they require application changes.
- Connection limits: Confirm maximum connections and whether a pooler is required as the number of PHP pods grows.
Confirm the service tier, failover behavior and restore procedure with the provider in writing.
An in-cluster database runs as a stateful workload inside Kubernetes, managed by an operator or a Helm chart with persistent volumes. This fits organizations with an established database operations practice, a requirement to keep all components in one infrastructure boundary, or air-gapped environments where a managed service is unavailable. The trade-off is that the team owns backups, failover, upgrades and storage performance, and a poorly configured stateful set can disrupt the whole platform. Kubernetes stateful workloads also add scheduling and storage class concerns that a managed service hides.
- Operator maturity: Confirm the operator's upgrade path, failover mechanism and how it handles storage class changes.
- Backups outside the cluster: Store backups in a location that survives cluster loss, and test restores on a separate cluster.
- Storage performance: Confirm the volume type delivers the write latency the database needs, not only the capacity.
- Resource isolation: Set requests and limits so database pods are not starved by PHP workloads on shared nodes.
- Ownership: Name the team responsible for database patching and on-call response before deployment.
Confirm the operator's support statement and storage vendor guidance for stateful databases before choosing this option.
Drupal's default database cache works everywhere, but on Kubernetes, moving cache bins to a shared in-memory store lets every replica read the same entries and reduces load on the database. Redis or Memcache backends are the common choices, provided a contributed module or the core cache configuration is set up to use them. This fits platforms with many PHP replicas, heavy anonymous traffic or large render caches. The trade-off is an additional stateful service to run, eviction and memory sizing decisions, and cache invalidation behavior that must match the release and deployment process.
- Bin mapping: Decide which cache bins move to the external store and keep locking and lock bins on a backend that suits them.
- Eviction policy: Confirm how the store evicts keys under memory pressure and whether that causes cache stampedes.
- Persistence: Decide whether the store needs persistence or whether losing it on restart is acceptable.
- Cluster topology: Confirm the vendor's replication and failover model, and whether the module supports it.
- Deployment ordering: Plan how a cache flush or rebuild interacts with rolling deploys.
Confirm eviction, persistence and failover behavior with the cache service vendor, and test cache behavior under the expected concurrency before go-live.
How to build a Drupal Kubernetes release pipeline
This sequence turns a Composer-built Drupal codebase into a repeatable Kubernetes release, where code, files, settings, database changes and scheduled jobs each have a defined home and a check that proves they work before traffic moves.
Build a Composer-built container image
The delivery team installs Drupal and its contributed modules through Composer from a locked composer.lock file, then builds one immutable image that contains only the code, vendor directory and web root. The image is built once per release, tagged with the commit or build identifier, and pushed to a registry you control. Confirm the build runs without network access to Drupal.org if your environment requires it. The step closes when the same image digest can be pulled and started in a test namespace with no database attached.
Separate code, files and settings
Keep the image free of uploaded files, private files and environment secrets. Public and private file directories are mounted from shared storage, while database credentials, hash salt and trusted host patterns are injected at runtime through Kubernetes Secrets and ConfigMaps and loaded from settings.php. Ask whoever owns the cluster how Secrets are encrypted at rest, since Kubernetes stores them unencrypted in etcd by default. The step closes when a pod started from the image reads its settings from the environment and writes uploads to the mounted path rather than the container filesystem.
Provision storage and database services
Platform engineers provision the database, cache service and file storage that the release depends on. Choose between a shared file volume that supports multiple writers or object storage through a Drupal module, and confirm the database engine and version meet the Drupal release you are running. Restore a copy of production data into a staging database to test the upgrade path. The step closes when Drupal can connect to the database from a pod, write a test file to the storage path, and a backup of the database has been taken and restored in a separate location.
Deploy the web workload with readiness checks
Deploy the Drupal web Deployment with a readiness probe that calls a lightweight route and fails until the database connection and file paths are working, plus a liveness probe with a looser threshold. Scale replicas only after the first pod passes. Run drush status inside a pod to confirm Drupal bootstraps, reports the expected database and file paths, and shows the correct release. The step closes when the service endpoint returns successfully and drush status reports a healthy bootstrap on each replica.
Run database updates as a Job
Before the new web pods receive traffic, run a Kubernetes Job from the same image that executes drush updatedb and then drush cache:rebuild. Use a rolling strategy that keeps the previous release compatible with the new schema for the rollout window, or plan a maintenance window if it is not. Confirm the Job exits with status zero and review its logs for each applied update hook. The step closes when the Job reports complete, the update log shows no pending hooks, and the new replicas pass readiness.
Import configuration from version control
Run drush config:import from the same release image as a Job or a controlled step after the database update. Configuration is exported to version control and imported into each environment, so the target environment matches the reviewed code. Check that the import reports no unexpected changes and that the active configuration matches the exported files. The step closes when drush config:status reports no differences and the import output is recorded with the release identifier.
Schedule cron as a CronJob
Move Drupal cron out of web pods into a Kubernetes CronJob that runs drush cron on a fixed schedule with the same image and settings. Set concurrency so overlapping runs cannot start, and set history limits so failed runs remain visible. Confirm the cron run is recorded in the job logs and that the scheduled tasks Drupal reports as last run have updated. The step closes when a manual trigger and at least one scheduled run complete successfully, and the logs show the cron execution with no errors.
How rolling deploys handle database updates and configuration import
The database updates and configuration import must run once per release, not once per pod. A Deployment that scales to several replicas starts each pod with the same image, so an entrypoint that runs drush updatedb or drush config:import on every start will race against its siblings, lock tables, and repeat work that only needs to happen one time. Move these steps into a Kubernetes Job (or a Helm or Argo CD hook that runs before the new Deployment rolls out), keep the web pods free of schema work, and make the Job fail the release if it does not finish cleanly. Confirm the exact Drush command sequence, including whether maintenance mode, cache rebuild and config import order differ, against the Drupal version in use, since the update path changes between major versions.
A rolling update can leave old and new code serving traffic at the same time, and that overlap is the main risk. While some pods run the previous release and others run the new one, the database may already contain columns, tables or config that the old code does not expect. Plan schema changes so they are backward compatible for one release: add new fields or tables first, deploy code that tolerates both states, and remove old structures in a later release. Pausing cron is part of the same discipline. Scheduled runs from a CronJob or a cron pod should be suspended or held in maintenance mode for the duration of the update, so cron does not execute queue workers or entity operations against a half-updated schema. Ask your team to document how cron is paused, resumed and verified in each environment.
Treat the Job, the rollout strategy and the pause or resume steps as one tested runbook. Rehearse the full sequence on a staging cluster with a copy of production data, and record how long the database update and config import take so the rollout window is known before launch. Check the release notes for each Drupal and contributed module upgrade, because update hooks can be long-running or require manual steps. Keep a database backup or snapshot taken immediately before the Job runs, so a failed update has a defined recovery path. Your implementation partner or internal team should own the decision on whether a rollback restores code only or code and database together, since rolling back code after a schema change can leave the site inconsistent.
Which Kubernetes security controls protect Drupal secrets and access
A Drupal site on Kubernetes holds database credentials, the hash salt, and API keys in Secrets, and its pods run code that accepts traffic from the internet. The controls below cover where those secrets rest, who can read them, how pods are allowed to run, and how security releases reach running containers.
Encrypt Secrets at rest in etcd
Kubernetes stores Secrets unencrypted in etcd by default, so anyone who can read the etcd data directory or its backups can read the database password and the Drupal hash salt. Ask your platform team whether the cluster has encryption at rest configured for Secrets, and confirm that etcd snapshots taken for backup are encrypted and access-controlled as well. Check the etcd backup files, not only the live cluster.
Restrict list and watch on Secrets
Reading a single Secret is not the only risk. Permissions to list and watch Secrets in a namespace can expose every value that the Drupal pods depend on at once. Bind the service accounts used by the Drupal deployment, cron jobs and migration jobs to narrowly scoped roles, and review who holds cluster-wide roles that include these verbs. Confirm that CI pipelines do not hold broader rights than the deploy step needs.
Pull external secrets with the CSI driver
Where the organization already runs a vault or cloud secrets manager, the Secrets Store CSI Driver can mount values from that external store into the pod, which keeps the source of truth outside the cluster. This suits the Drupal database credentials and API keys that rotate on a schedule. Confirm with your security team who owns rotation, how the pod reloads after a rotation, and whether the mounted values also land in etcd.
Enforce Pod Security Standards on PHP containers
Drupal containers need a writable file path for public and private files and a PHP runtime, but they rarely need root, host networking or privileged mode. Apply a Pod Security Standard level to the Drupal namespace, run containers as a non-root user, and drop unneeded Linux capabilities. Test the profile against your image before rollout, because a restrictive setting can block Drupal's writes to its file directories.
Rebuild images for Wednesday security releases
The Drupal Security Team publishes advisories and security releases on the third Wednesday of the month, and contributed module fixes arrive on the same windows. A patched Drupal codebase reaches the cluster only when the image is rebuilt and redeployed, so a Kubernetes rollout does not patch Drupal by itself. Agree in advance who watches the advisories, how quickly a rebuild runs, and how the rolling deploy and database updates are verified afterward.
What buyers ask before running Drupal on Kubernetes
What drives the cost of running Drupal on Kubernetes?
The cost is driven by how much of the platform you already run and how many decisions remain open. The main components are design work (container image layout, file storage, database and cache services, cron jobs, and the deploy pipeline), build work (the image, Helm or manifests, and pipeline code), and verification work (load tests, restore tests and a rehearsed rolling deploy). Costs rise with the number of sites, the amount of custom modules, the choice of shared file storage or object storage, and whether you need high availability for the database. Ask any partner for a quote that lists each component separately, states who pays for cluster operations, and says which items are one-time and which recur, such as security rebuilds and upgrade cycles.
How long does it take to build a Drupal platform on Kubernetes?
Duration depends on the state of your cluster and the number of open decisions, not on Drupal alone. A team with an existing, well-governed cluster, a settled database choice and a working CI pipeline has far less to build than a team starting from bare infrastructure. Time is also consumed by file storage design, identity integration and rehearsals of the deploy with database updates and configuration import. No duration is stated here because none has been supplied for this work. Ask for a written timeline tied to the agreed scope, with milestones for a staging environment, a load test and a rollback rehearsal.
What does the work need from our platform team?
Your platform team needs to own the cluster itself, including node pools, ingress, network policy, the database service, backups and the secrets platform. Kubernetes stores Secrets unencrypted in etcd by default, so your team must confirm encryption at rest and least-privilege RBAC before application secrets are added. Your team also needs to provide a container registry, a CI runner, DNS and TLS, and an identity provider for administrator access. Confirm these items before the scope is agreed, because gaps in them move cost and time into the build.
Can our in-house team build and run Drupal on Kubernetes without a partner?
Yes, a capable in-house team can do this, and the decision depends on skills and capacity rather than on Drupal licensing, since Drupal is GPL-2.0-or-later software with no paid edition. The team needs working knowledge of PHP, Composer builds, Drupal's database update and configuration import steps, Kubernetes workloads, and etcd and cluster upgrades. Be honest about the ongoing load: the upgrade path, supported PHP versions and security releases recur. Ask whether the people who build the platform will also carry the on-call and rebuild work after launch, and whether that is funded.
How do Drupal security releases affect image rebuilds?
Drupal security releases force image rebuilds because the code is baked into the container image. Drupal core publishes security releases on the third Wednesday of the month, and bugfix releases on the first Wednesday, so your pipeline should expect a regular rebuild cadence. Each rebuild should pull the updated Composer dependencies, run the test suite, produce a new tagged image and roll it out with the same database update step. Plan who approves an out-of-band rebuild, how long a rollback takes, and how the image registry retains old tags. Confirm the release calendar on the Drupal core release schedule before setting your process.
Which Drupal and Kubernetes versions should we plan around?
Start with the Drupal version that your modules support and your PHP runtime can run. Drupal 10 requires PHP 8.1 or later, Drupal 11 requires PHP 8.3 or later and Drupal 12 requires PHP 8.5 or later, and no supported Drupal version runs on PHP 7. Drupal 10 reaches end of life on December 9, 2026, according to the core release schedule, so a new build should target Drupal 11 unless there is a documented reason otherwise. On the cluster side, the Kubernetes project maintains only the three most recent minor releases, so the upgrade plan must include minor version steps that follow the version skew policy.
What should a quote for Drupal on Kubernetes contain?
A useful quote lists the written scope, deliverables and assumptions before any price. It should separate one-time work, such as design, build, integration, load testing and the first rehearsed deploy, from recurring work, such as security rebuilds, upgrades and monitoring support. It should name the systems you must provide, the environments covered, the acceptance tests and who signs them off. DeployOpen works from a written scope with agreed deliverables and timelines, and it does not publish a price list, so a quote follows from that scope. Ask for the assumptions behind every line, because they determine the final cost.
Does DeployOpen certify our Drupal platform for compliance?
No. DeployOpen prepares systems, controls and evidence for compliance assessments, but independent auditors and certification bodies issue audit reports, attestations and certifications. For a Kubernetes-hosted Drupal platform, evidence usually covers access control to Secrets, encryption at rest for etcd, image provenance, backup and restore records and change history for deploys. Ask any partner which evidence they will produce, in what format, and which parts remain your responsibility to maintain after handover.
When a simpler hosting model is the better choice
Kubernetes is the wrong default for many Drupal estates. A single virtual machine or a managed platform running Nginx or Apache, PHP-FPM and a managed MySQL, MariaDB or PostgreSQL database is usually easier to operate when the team has no container practice, runs one or two sites, and has no need for horizontal scaling that a load balancer and a second web node cannot meet. In that case the cluster adds a control plane, image pipelines, ingress, secrets handling and an etcd backup routine that someone must own for years. Before choosing Kubernetes, ask who will patch the nodes, rotate certificates and respond to a failed upgrade, and whether those people already do this for other workloads.
The number of sites and how tightly they are coupled matters as much as traffic. A small set of independent sites on separate databases can share a simpler host with fewer moving parts. If the estate is a core multisite installation, a shared codebase means one release train, so a Kubernetes rollout does not reduce the coupling; it only adds a layer on top of it. Confirm whether the sites need separate release schedules, separate hostnames with separate settings, or a shared pool of workers. Those answers decide whether the platform work pays back or whether a well-maintained VM with a tested deploy script is the more reliable option.
Ask the team which operations it already runs well. If it operates Kubernetes for other products, reusing its cluster, GitOps tooling and monitoring keeps the Drupal workload small and predictable. If it does not, the first year of Drupal on Kubernetes becomes a platform project with its own backlog, and the Drupal team waits on it. Choose the hosting model that the existing operations team can support through a Drupal security release, a PHP version change and a database upgrade without special handling. Confirm that answer with your own operations staff before the architecture is fixed.
How DeployOpen scopes and delivers Drupal on Kubernetes
DeployOpen plans, builds, documents and supports self-hosted Drupal on Kubernetes inside your own cloud accounts, data centers or air-gapped networks. Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts, and ongoing support is available as a retainer.
How we scope
- Written scope lists the Drupal version, PHP runtime, database service and the cluster you will operate.
- Scope records how files are stored, whether on shared volumes or object storage, and how they are served.
- Scope names cron jobs, queue workers, cache services and the deploy steps that run database updates and config import.
How we build
- Container images are built from a Composer-managed codebase, with code kept separate from files and environment settings.
- Manifests or Helm charts define stateless PHP pods, cron as Kubernetes jobs, health probes and resource limits.
- Rolling deploys are tested in a staging cluster, including database updates and configuration import before production.
How we hand over
- Handover includes runbooks for deploys, rollbacks, etcd backups and restoration of database and file storage.
- Documentation covers secrets handling, RBAC boundaries, Pod Security settings and the image rebuild process for security releases.
- Your team receives the test results, configuration repository and a list of decisions and open risks from the build.
How we support
- Support retainers can cover Drupal core and contributed module updates, Kubernetes upgrades and cluster patching.
- Upgrade work follows the supported Kubernetes version window and the Drupal release schedule, with scope agreed in advance.
- Ongoing testing and monitoring reviews can be added to the retainer, with frequency and coverage set in the written agreement.

