Blog Cloud Native Drupal 9 min
DrupalDigital Transformation

Cloud Native Drupal

SparkFabrik Team9 min read
Cloud Native Drupal

Why do we want to transform Drupal into a Cloud Native application? To answer that, we need to start from the beginning by addressing the preceding question: why the Cloud, and what are its promises.

Cloud infrastructures today allow us to overcome a series of issues that were commonplace until recently (sites crashing due to traffic spikes, time needed for machine downtime dedicated to new deployments, misalignments between software versions in development and production environments, to name just a few examples that every developer has experienced in their career).

YOU MIGHT ALSO BE INTERESTED IN: Why choose Drupal for complex enterprise websites

The promises that the Cloud and the cloud native approach make are of various kinds:

  • the ability to rationalize our resources;
  • cost optimization because resources are used when needed (traffic peaks and dips will be more easily manageable thanks to the fact that resources are scalable);
  • better overall performance;
  • the possibility of continuous delivery & deployment (without having to put the site in maintenance mode for hours anymore)
  • simplified onboarding of new colleagues and easier integration of external development teams — when a new developer joins a project, days will no longer be wasted configuring the local environment.

Cloud Native simplifies

Cloud native simplifies. So, going back to the original point, why not a Cloud Native Drupal?

There are two levels of action to take, closely interconnected, along which you will need to operate: the Drupal application architecture and the adoption of DevOps best practices, without which many of the advantages of Cloud Computing would actually be nullified — and this is because going to the Cloud is not simply taking an application and installing it on a cloud vendor’s VM, it is much more than that.

But what does a cloud native app look like? Someone has already formalized its distinctive traits, and on the Twelve Factor App website you can find a list of agnostic factors, baseline requirements for considering a generic web application cloud native. In this talk (and article) we don’t have time to explore them all; we will focus on the most relevant ones for our case. One thing we must highlight: containers are not mentioned in that list, because they are not a requirement, but rather the solution available today to make an application cloud native.

YOU MIGHT ALSO BE INTERESTED IN: Headless Drupal - Modern Approach to (Micro)Services and APIs

Drupal’s Cloud Native Journey

Containers, and specifically Docker, are the first step of the journey toward cloud native, because they allow you to package the application with everything it needs to run and to take it wherever you want, including the local environment (every time we talk about deploy, we also implicitly mean local deploy). So, in practice, you could have only Docker and a few other tools installed on your machine (we’ll get to that shortly) and you would have everything you need to get started.

How to build a Docker image that will bring containers to life? All instructions reside in the codebase, which must be one, single, and versioned — beyond all the advantages that code versioning gives us in itself: our repository is the source of truth for our Docker image. From the repository we can build the entire application, including the necessary dependencies. In our codebase we will therefore have: a Dockerfile, all scripts including those for automation, our custom code, and Drupal’s configuration. This is an important point, because the repository will not contain everything that is a dependency, which instead will be managed with a package manager (in the PHP world, that’s Composer) — and this includes not only contrib modules and themes, but also the Drupal core, because we don’t want to version what is not our direct responsibility. So all dependencies will be listed in the project’s composer.json and the build process will take care of fetching them.

Additionally, in the composer.json it is advisable to list as dev-dependency everything that is only needed for development, because we want to have images that are as small as possible and contain only what is necessary.

At this point, a single codebase could be a problem, because configurations across different environments will vary. The most classic example is the database: we have different configurations for connecting to the local database, the production database, or any other environment we have. However, we can manage this with environment variables, which we can inject into our Docker container. We pass at runtime everything needed to have a configuration dependent on the environment we are in, leveraging various methods: if locally we will probably use Docker Compose, on CI we will take advantage of the ability to register environment variables directly on our platform, and so on. Going back to the database example, in settings.php we use a simple getenv() to get any necessary variable from the environment. A convenient procedure not only for setting different configurations, but also for enabling or disabling certain services as needed. A classic example is Google Tag Manager: you probably wouldn’t want to activate it locally, just as you probably wouldn’t want to pollute production data with, for example, staging data. So we can decide whether or not to pass this variable to Drupal or pass different variables. In this way we isolate the behavior of our services precisely based on the needs of a specific environment.

Storage

Let’s continue our journey. We need to keep in mind that a container is ephemeral by nature — it is not persistent. It has a lifecycle that leads it to die and be replaced by another container, built from the same image. However, on Drupal, we have information that must be persisted: user data. Database and file storage are backing services that we can manage by connecting them to our container. Data will not be saved in the container, but will reside in a persistent volume, mounted on the container itself.

When we are in the cloud, the most convenient thing to do is to rely on one of the services provided by the vendors. A modification that is strongly recommended regarding storage is to switch to an object storage, something different from Drupal’s standard file storage. And locally? MinIO is extremely useful: thanks to the already mentioned environment variables, we will have an identical Drupal configuration, regardless of the environment it is in. But do we throw away the standard file storage entirely? Not necessarily. It might be needed because perhaps we have a legacy application that requires this support, so while object storage is a recommended solution when possible, it is not necessarily the only one.

With logs, we can leverage a characteristic of containers to our advantage. If it was already good practice not to save logs to the database before, now we don’t even need to worry about it because Drupal will be configured to write them directly to the container’s standard output. We will then decide, based on the environment we are in, how to access these logs and how to manage them (e.g., aggregating and filtering them based on our needs).

Bringing Cloud Native Drupal to the cloud

We are at a great point in our journey because our application is effectively ready — it’s cloud native! — but it’s not yet in the cloud. And we do this using pipelines, that is, automation scripts for continuous integration and continuous delivery, which execute automatic tasks in response to specific events in our repository. Regardless of the provider we choose, the operation is essentially the same: we ask our pipeline to execute certain tasks in a certain order. We will certainly ask the pipeline for two basic operations: building the images according to the instructions found in the repository and executing the deploy, i.e., updating the application on the designated environment, which in the case of Drupal obviously means updating the codebase, running database updates, importing the configuration, and so on. But it will all be automatic — we won’t have to do it manually anymore, and we’ll be free to add a whole series of other activities such as code quality checks, various types of automated tests (end-to-end, visual regression, etc.). The better we are at these operations, i.e., at covering our application with tests and running tests at the most appropriate times, the more we can rest easy, since the pipeline, when it encounters an error, will stop, preventing us from going to production with something that isn’t as we’d like (and thus saving us from a rollback). Once we have configured our pipelines, we finally need to define our cloud provider and which services to use. As a general concept, we can say that we will have one or more containers that we will need to orchestrate, and we can go for either custom solutions or managed solutions that already offer a lot out of the box.

YOU MIGHT ALSO BE INTERESTED IN: What is the best Headless CMS? The advantages of Drupal

Kubernetes is today the de-facto standard, and rightly so given that it offers enormous firepower and allows you to control all services with extreme precision and a great deal of flexibility. Moreover, it is open source, and we can install it wherever we want (yes, even locally). Due to these characteristics, however, it is a very complex tool that requires specific expertise.

We can consider intermediate managed solutions offered by vendors, such as AWS ECS, which obviously imply a greater degree of lock-in, but are simpler and closer to tools we already know.

Finally, we find extremely simple solutions that can be adapted to use cases for sites that don’t require special interventions (Cloud Run on GCP is one of these).

What if you need to go with multiple vendors? For example, you might want instances on AWS for Europe and the United States, and an instance in China. We can deploy simultaneously to multiple vendors without any issue because the base architecture, Drupal, is always the same.

Last but not least: monitoring

The last step, and an essential one, is monitoring. We know well that for a developer, the work doesn’t end when a site or digital product goes live: monitoring is important, and the data to collect is vast. Beyond the logs mentioned earlier, we need to keep resource usage under control because autoscaling is active, but it is also necessary to understand how much they are actually scaling, and we need to collect Drupal’s status report without logging into the Drupal instance. Given such a wealth of data, you will need tools to manage, organize, and filter it. Every vendor provides some, not to mention external services that can be configured once the right metrics have been identified: without clear ideas in this regard, you risk being overwhelmed by logs and data unnecessarily.

In this whole scenario, how “collaborative” is Drupal? Let’s say that from Drupal 8 onwards, moving to the Cloud with a Cloud Native approach is fairly easy. The configuration is exportable to files, so it can be versioned and be part of the build. D8 uses Composer to manage dependencies (it’s not advisable to use Drupal without Composer — that’s our heartfelt recommendation). Today, Drupal complies with most PHP standards and can be considered in every respect a modern framework, largely based on Symfony components.

That said, don’t despair if you’re facing a Drupal 7 site. It will certainly require more effort, because you will need to compensate for all those features that are only available from version 8 onwards, but it remains a viable path. You don’t have to give up on a cloud native D7 — just factor in the greater effort required.

Watch the Cloud Native Drupal tech talk

Don’t feel like reading all the text? The video below is a great alternative to the article.

Watch the Cloud Native Drupal tech talk on YouTube

Domande Frequenti

Making Drupal Cloud Native means adapting the application architecture and adopting DevOps practices so that Drupal can fully leverage the advantages of the cloud: scalability, continuous delivery, cost optimization, and reproducible development environments through Docker containers.
The main benefits include resource rationalization, cost optimization thanks to scalability, better overall performance, the ability to achieve continuous delivery and deployment without downtime, and simplified onboarding for new developers.
Yes, although it requires more effort compared to Drupal 8 or later. You will need to compensate for features only available in more recent versions, such as file-based configuration management and the use of Composer, but it remains a viable path.
Environment-specific configurations (local, staging, production) are managed through environment variables injected into the Docker container. In settings.php, getenv() is used to read the necessary variables, such as database credentials or the activation of services like Google Tag Manager.

Get in touch

Follow us on social media
Listen to Continuous Delivery