⬆️ ⬇️

5 principles of common sense for creating cloud-native apps

"Cloud-oriented" (cloud native) or simply "cloud" applications are created specifically for work in cloud infrastructures. Usually they are built as a set of loosely coupled microservices packed into containers, which, in turn, are managed by a cloud platform. Such applications are by default ready for failures, which means they work reliably and scale even with serious infrastructure failures. The other side of the coin is sets of restrictions (contracts) that the cloud platform imposes on container applications in order to be able to manage them automatically.







Well aware of the need and importance of switching to cloud applications, many organizations still do not know where to start. In this post, we will look at a number of principles, the observance of which in the development of container applications will allow to realize the potential of cloud platforms and to achieve reliable operation and scaling of applications, even with serious 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.



Principles of software design



In the programming world, principles are understood as quite general rules that must be followed when developing software. They can be used when working with any programming language. Each principle has its own goals, the tools for achieving which usually serve patterns and practices. There are also a number of fundamental principles for creating high-quality software, from which all the rest flow. Here are some examples of fundamental principles:

')



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 incorporates mutually reinforcing and open-ended, mutually reinforcing principles that, when used in combination, help create better software systems and better support them in the long term.



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



Cloud-oriented containers: Red Hat approach



Today, almost any application can be packaged into containers relatively easily. But in order for applications to be effectively automated and orchestrated within a cloud platform like Kubernetes, additional efforts are required.

The basis for the ideas outlined below was the methodology of The Twelve-Factor App and many other works on various aspects of creating web applications, from source code management to scaling models. The principles described relate only to the development of container applications that are based on microservices and are intended for cloud platforms such as Kubernetes. The basic element in our reasoning is the image of the container, and the target environment for the execution 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 scheduling tasks (scheduling — select a host for running the container instance), scaling and monitoring. Principles are presented in arbitrary order.



Single Concern Principle (SCP)



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



In SCP, instead of the word “responsibility” (responsibility) we use the word “task” (concern) to indicate a higher level of abstraction and a wider purpose of the container compared to the OOP class. And if the goal of the SRP is to have only one reason for the change, then the SCP has a desire to expand the reuse and replacement of containers. By following SRP and creating a container that solves one single task and makes it functionally complete, you increase the chances of reusing the image of this container in different application contexts.



The SCP principle states that each container must solve one single task and do it well. Moreover, SCP in the container world is achieved easier than SRP in the OOP world, since containers usually perform one single process, and most of the time this process solves one single task.



If a container microservice has to solve several tasks at once, then it can be divided into single-task containers and merged them within one pod (units of container platform deployment) using sidecar templates and init containers. In addition, SCP makes it easy to replace the old container (for example, a web server or a message broker) with a new one, which solves the same problem, but has enhanced functionality or scales better.







The principle of convenience monitoring (High Observability Principle, HOP)



When using containers as a unified way to package and launch applications, the applications themselves are considered as a “black box”. However, if they are cloud containers, they must provide the runtime with special APIs to monitor the health of the containers and, if necessary, take appropriate measures. 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.





In practice, a container application should, at a minimum, have an API for various types of health checks: liveness tests and readiness tests. If the application claims to be more, it should provide other means of controlling its state. For example, recording important events via STDERR and STDOUT to aggregate logs using Fluentd, Logstash and other similar tools. As well as integration with the libraries of trace and collection of metrics, such as OpenTracing, Prometheus, etc.



In general, an application can still be viewed as a “black box”, but it should 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. If the HOP says that the container must provide the platform with APIs for reading, then the LCP requires the application to be able to perceive information from the platform. Moreover, the container must not only receive events, but also adapt itself, in other words, respond to them. Hence the name of the principle, which can be viewed as a requirement to provide APIs for writing to the platform.





Platforms have different types of events that help manage the life cycle of a container. But deciding which ones to perceive and how to react should the application itself.



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



In addition, events such as PostStart and PreStop may be important for the application lifecycle. For example, after starting an application it may take some time to “warm up” before it can respond to requests. Or, the application must in some special way release resources at the completion of work.



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



It is generally accepted that container applications should remain unchanged after assembly, even if they run in different environments. Hence the need to externalize data storage at the execution stage (in other words, to use external means for this), and also to rely on external configurations configured for a specific execution environment, instead of modifying or creating unique containers for each environment. After any changes to the application, the container image must be reassembled and deployed in all the environments used. By the way, the management of IT systems uses a similar principle, known as the principle of the 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 configuration for a specific environment. Following this principle allows you to implement such important in terms of automation of cloud systems practices such as rollback (roll-back) and roll-forward (roll-forward) application updates.





Process Disposability Principle (PDP)



One of the most important characteristics of the container is its ephemerality: a container instance is easily created and easily destroyed, so it can be easily replaced with another one at any time. The reasons for this replacement can be mass: failure of the test for serviceability, scaling of the application, transfer to another host, exhaustion of platform resources, or other situations.





As a result, container applications must retain their state using some external means, or use internal distributed circuits with redundancy for this. In addition, the application should start quickly and shut down quickly, as well as be ready for a sudden fatal failure of the equipment.



One of the practices that helps to implement this principle is to create small containers. Cloud environments can automatically select a host to launch a container instance, so the smaller the container size, the faster it will start — it will simply be copied to the target host over the network.



Self-containment Principle, S-CP



According to this principle, at the assembly stage all necessary components are included in the container. The container must be built with the expectation that there is only a pure Linux kernel in the system, so all the necessary additional libraries should be located in the container itself. Such things as the runtime for the corresponding programming language, the application platform (if necessary) and other dependencies that are required during the operation of the container application should be located there.







Exceptions are made only for configurations that vary from environment to environment, and should be provided at runtime, for example, through Kubernetes ConfigMap.



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



The principle of restrictions at runtime (Runtime Confinement Principle, RCP)



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





And here the RCP principle is useful, according to which the container must decapitate its requirements for system resources and transfer them to the platform. With the resource profiles of each container (how much CPU, memory, network, and disk system resources it needs), the platform can optimally perform dispatching and autoscaling, manage IT capacities, and maintain SLA levels for containers.



In addition to meeting the requirements for container resources, it is also important for an application not to go beyond the framework designated by it. Otherwise, in case of a shortage of resources, the platform is more likely to include it in the list of applications that need to be interrupted or migrated.



Speaking of cloud orientation, we primarily mean the way of working.

Above, we formulated a number of general principles that set the methodological foundation for building high-quality container 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 several short recommendations that are more specific and should be applied (or not) depending on the situation:





Webinar on the new version of OpenShift Container Platform - 4

June 11 at 11:00



What you will learn:



Source: https://habr.com/ru/post/455024/



All Articles