5 common sense principles for building cloud-native apps

"Cloud-oriented" (cloud native) or simply "cloud" applications are created specifically to work in cloud infrastructures. They are usually built as a set of loosely coupled microservices packaged in containers, which are in turn managed by a cloud platform. These applications are fail-safe by default, which means they perform reliably and scale even in the face of severe infrastructure-level failures. The reverse side of the coin is the sets of restrictions (contracts) that the cloud platform imposes on container applications in order to be able to manage them automatically.

5 common sense principles for building cloud-native apps

Fully aware of the need and importance of moving to the cloud, many organizations still don't know where to start. In this post, we will look at a number of principles that, when developing containerized applications, will allow you to realize the potential of cloud platforms and achieve reliable operation and scaling of applications even with severe failures at the IT infrastructure level. The ultimate goal of the principles outlined here is to learn how to build applications that can be automatically managed by cloud platforms such as Kubernetes.

Software Design Principles

In the world of programming, principles are fairly general rules that must be observed when developing software. They can be used with any programming language. Each principle has its own goals, which are usually achieved through patterns and practices. There are also a number of fundamental principles for creating high-quality software, from which all the rest follow. Here are some examples of fundamental principles:

  • KISS (Keep it simple, stupid) - do not complicate;
  • DRY (Don't repeat yourself) - do not repeat yourself;
  • YAGNI (You aren't gonna need it) - do not create something that there is no immediate need for;
  • SoC (Separation of concerns) - to share responsibilities.

As you can see, these principles do not set any specific rules, but belong to the category of so-called common sense considerations based on practical experience, which are shared by many developers and to which they regularly refer.
In addition, there is SOLID - a set of the first five principles of object-oriented programming and design, formulated by Robert Martin. SOLID includes generalized and open to interpretation complementary principles that - when applied in combination - help to create better software systems and better maintain them in the long term.

The principles of SOLID belong to the realm of OOP and are formulated in the language of concepts and concepts such as classes, interfaces, and inheritance. By analogy, for cloud applications, development principles can also be formulated, only the basic element here will not be a class, but a container. By following these principles, you can create containerized applications that better serve the goals and objectives of cloud platforms like Kubernetes.

Cloud-Based Containers: The Red Hat Approach

Today, almost any application can be packaged relatively easily in containers. But in order for applications to be effectively automated and orchestrated within a cloud platform like Kubernetes, additional efforts are required.
The following methodology was used as the basis for the ideas The Twelve Factor App and many other works on various aspects of building web applications, from source code management to scaling models. The described principles apply only to the development of containerized applications that are built on top of microservices and are designed for cloud platforms such as Kubernetes. The base element in our discussion is the container image, and the target runtime of containers is the container orchestration platform. The purpose of the proposed principles is to create containers for which, on most orchestration platforms, it is possible to automate the tasks of scheduling (scheduling - choosing a host to run a container instance), scaling and monitoring. The principles are presented in no particular order.

The Single Concern Principle (SCP)

This principle is similar in many ways to the Single Responsibility Principle. SRP), which is part of the SOLID set and states that each object must have one responsibility, and this responsibility must be fully encapsulated in a class. The essence of SRP is that every responsibility is a reason to change, and a class should have one and only one reason to change.

In SCP, instead of the word "responsibility" (responsibility), we use the word "task" (concern) to indicate a higher level of abstraction and wider purpose of the container compared to the OOP class. And if the goal of SRP is to have only one reason for change, then the desire behind SCP is to expand the possibilities of reusing and replacing containers. By following the SRP and creating a container that does a single thing and does it in a functionally complete way, you increase the chances of reusing that container's image in different application contexts.

The SCP principle says that each container should solve one single task and do it well. Moreover, SCP in the container world is easier to achieve than SRP in the OOP world, since containers usually run one single process, and most of the time this process solves one single task.

If a containerized microservice needs to solve several tasks at once, then it can be divided into single-tasking containers and combined within one pod (container platform deployment unit) using sidecar templates and init containers. In addition, SCP makes it easy to replace an old container (such as a web server or message broker) with a new one that does the same job but has more functionality or scales better.

5 common sense principles for building cloud-native apps

High Observability Principle (HOP)

When using containers as a unified way to package and run applications, the applications themselves are treated as a "black box". However, if they are cloud containers, then they must provide specific APIs to the runtime to monitor the health of the containers and take appropriate action if necessary. Without this, it will not be possible to unify the automation of updating containers and managing their life cycle, which, in turn, will worsen the stability and usability of the software system.

5 common sense principles for building cloud-native apps
In practice, a containerized application should at least have an API for various types of health checks: liveness tests and readiness tests. If an application claims more than that, it must provide other means of monitoring its state. For example, logging important events via STDERR and STDOUT for logging aggregation using Fluentd, Logstash and other similar tools. As well as integration with tracing and metrics libraries such as OpenTracing, Prometheus, etc.

In general, an application can still be considered a "black box", but it must be provided with all the APIs that the platform needs in order to monitor and manage it in the best possible way.

Life-cycle Conformance Principle (LCP)

LCP is the antithesis of HOP. While the HOP says that the container must provide read APIs to the platform, the LCP requires the application to be able to read information from the platform. Moreover, the container should not only receive events, but also adapt, in other words, respond to them. Hence the name of the principle, which can be thought of as a requirement to provide write APIs to the platform.

5 common sense principles for building cloud-native apps
Platforms have different types of events to help manage the lifecycle of a container. But it is up to the application to decide which of them to perceive and how to react.

It is clear that some events are more important than others. For example, if an application does not tolerate crashing well, then it must accept signal: terminate (SIGTERM) messages and initiate its termination procedure as soon as possible in order to be in time for the signal: kill (SIGKILL) that comes after SIGTERM.

In addition, events such as PostStart and PreStop can be important to the lifecycle of an application. For example, after launching an application, it may take a certain amount of time to β€œwarm up” before it can respond to requests. Or the application must release resources in some special way when it shuts down.

The principle of immutability of the container image (Image Immutability Principle, IIP)

It is generally accepted that containerized applications should remain the same after being built, even if they are run in different environments. This necessitates the need to externalize data storage at runtime (in other words, use external tools for this), and also rely on external runtime-specific configurations, rather than modifying or creating unique containers for each environment. After any changes to the application, the container image must be rebuilt and deployed to all environments used. By the way, when managing IT systems, a similar principle is used, known as the principle of immutability of servers and infrastructure.

The goal of IIP is to prevent the creation of separate container images for different runtime environments and to use the same image everywhere along with the appropriate environment-specific configuration. Following this principle allows you to implement such important practices from the point of view of automating cloud systems as rollback (roll-back) and roll-forward (roll-forward) of application updates.

5 common sense principles for building cloud-native apps

Process Disposability Principle (PDP)

One of the most important characteristics of a container is its ephemeral nature: an instance of a container is easily created and easily destroyed, so it can be easily replaced with another instance at any time. There can be many reasons for such a replacement: failure of the health test, application scaling, transfer to another host, exhaustion of platform resources, or other situations.

5 common sense principles for building cloud-native apps
As a consequence, containerized applications must store their state using some external means, or use internal redundant distributed schemes for this. In addition, the application must start and finish quickly, and be prepared for a sudden fatal hardware failure.

One practice to help implement this principle is to keep containers small. Cloud environments can automatically choose a host to run a container instance on, so the smaller the container size, the faster it will start - it will just copy to the target host over the network faster.

Self-containment Principle (S-CP)

According to this principle, at the assembly stage, all the necessary components are included in the container. The container should be built with the assumption that the system has only a pure Linux kernel, so all the necessary additional libraries should be placed in the container itself. It should also contain things such as the runtime for the appropriate programming language, the application platform (if necessary), and other dependencies that will be required during the operation of the containerized application.

5 common sense principles for building cloud-native apps

Exceptions are made only for configurations, which vary from environment to environment, and must be provided at run time, for example, through the Kubernetes ConfigMap.

An application can include multiple containerized components, such as a separate DBMS container as part of a containerized web application. According to the S-CP principle, these containers should not be combined into one, but should be made so that the DBMS container contains everything necessary for the operation of the database, and the web application container contains everything necessary for the operation of the web application, the same web server . As a result, at runtime, the web application container will depend on the DBMS container and access it as needed.

Runtime Confinement Principle (RCP)

The S-CP principle defines how the container should be built and what the binary image file should contain. But a container is not just a "black box" that has only one characteristic - file size. At runtime, the container also acquires other dimensions: the amount of memory used, processor time, and other system resources.

5 common sense principles for building cloud-native apps
And here the RCP principle comes in handy, according to which the container must decapitate its requirements for system resources and transfer them to the platform. By having resource profiles for each container (how much CPU, memory, network, and disk resources it needs), the platform can optimally dispatch and autoscale, manage IT capacity, and maintain SLA levels for containers.

In addition to satisfying the resource requirements of the container, it is also important for the application not to go beyond the limits indicated by itself. Otherwise, when a resource shortage occurs, the platform is more likely to include it in the list of applications that need to be interrupted or migrated.

When we talk about being cloud-centric, we primarily mean the way we work.
Above, we formulated a number of general principles that set the methodological foundation for building high-quality containerized applications for cloud environments.

Note that in addition to these general principles, you will also need additional advanced methods and techniques for working with containers. In addition, we have a few short guidelines that are more specific and should be applied (or not applied) depending on the situation:

Webinar on the new version of OpenShift Container Platform – 4
11 on 11.00

What will you learn:

  • Immutable Red Hat Enterprise Linux CoreOS
  • OpenShift service mesh
  • operator framework
  • Knative framework

Source: habr.com

Add a comment