Image
Comments
mcr.microsoft.com/dotnet/aspnet:
7.0
ASP.NET Core, with runtime only and ASP.NET Core
optimizations, on Linux and Windows (multi-arch)
mcr.microsoft.com/dotnet/sdk:
7.0
.NET 7, with SDKs included, on Linux and Windows (multi-
arch)
You can find all the available docker images in
dotnet-docker
and also refer to the latest preview
releases by using nightly build
mcr.microsoft.com/dotnet/nightly/*
18
CHAPTER 3 | Architecting container and microservice-based applications
CHAPTER
3
Architecting container and
microservice-based
applications
Microservices offer great benefits but also raise huge new challenges. Microservice architecture patterns
are fundamental pillars when creating a microservice-based application.
Earlier in this guide, you learned basic concepts about containers and Docker. That information was
the minimum you needed to get started with containers. Even though containers are enablers of, and
a great fit for microservices, they aren’t mandatory for a microservice architecture. Many architectural
concepts in this architecture section could be applied without containers. However, this guide focuses
on the intersection of both due to the already introduced importance of containers.
Enterprise applications can be complex and are often composed of multiple services instead of a
single service-based application. For those cases, you need to understand other architectural
approaches, such as the microservices and certain Domain-Driven Design (DDD) patterns plus
container orchestration concepts. Note that this chapter describes not just microservices on
containers, but any containerized application, as well.
Container design principles
In the container model, a container image instance represents a single process. By defining a
container image as a process boundary, you can create primitives that can be used to scale or batch
the process.
When you design a container image, you’ll see an
ENTRYPOINT
definition in the Dockerfile. This
definition defines the process whose lifetime controls the lifetime of the container. When the process
completes, the container lifecycle ends. Containers might represent long-running processes like web
servers, but can also represent short-lived processes like batch jobs, which formerly might have been
implemented as Azure
WebJobs
.
If the process fails, the container ends, and the orchestrator takes over. If the orchestrator was
configured to keep five instances running and one fails, the orchestrator will create another container
instance to replace the failed process. In a batch job, the process is started with parameters. When the
process completes, the work is complete. This guidance drills-down on orchestrators, later on.
19
CHAPTER 3 | Architecting container and microservice-based applications
You might find a scenario where you want multiple processes running in a single container. For that
scenario, since there can be only one entry point per container, you could run a script within the
container that launches as many programs as needed. For example, you can use
Supervisor
or a
similar tool to take care of launching multiple processes inside a single container. However, even
though you can find architectures that hold multiple processes per container, that approach isn’t very
common.
Containerizing monolithic applications
You might want to build a single, monolithically deployed web application or service and deploy it as
a container. The application itself might not be internally monolithic, but structured as several
libraries, components, or even layers (application layer, domain layer, data-access layer, etc.).
Externally,
however, it’s a single container—
a single process, a single web application, or a single
service.
To manage this model, you deploy a single container to represent the application. To increase
capacity, you scale out, that is, just add more copies with a load balancer in front. The simplicity
comes from managing a single deployment in a single container or VM.
Figure 4-1. Example of the architecture of a containerized monolithic application
You can include multiple components, libraries, or internal layers in each container, as illustrated in
Figure 4-1. A monolithic containerized application has most of its functionality within a single
container, with internal layers or libraries, and scales out by cloning the container on multiple
servers/
VMs. However, this monolithic pattern might conflict with the container principle “a container
does one thing, and does it in one process”, but might be ok for some cases.
The downside of this approach becomes evident if the application grows, requiring it to scale. If the
entire application can scale, it isn’t really a problem. However, in most cases, just a few parts of the
application are the choke points that require scaling, while other components are used less.
For example, in a typical e-commerce application, you likely need to scale the product information
subsystem, because many more customers browse products than purchase them. More customers use
20
CHAPTER 3 | Architecting container and microservice-based applications
their basket than use the payment pipeline. Fewer customers add comments or view their purchase
history. And you might have only a handful of employees that need to manage the content and
marketing campaigns. If you scale the monolithic design, all the code for these different tasks is
deployed multiple times and scaled at the same grade.
There are multiple ways to scale an application-horizontal duplication, splitting different areas of the
application, and partitioning similar business concepts or data. But, in addition to the problem of
scaling all components, changes to a single component require complete retesting of the entire
application, and a complete redeployment of all the instances.
However, the monolithic approach is common, because the development of the application is initially
easier than for microservices approaches. Thus, many organizations develop using this architectural
approach. While some organizations have had good enough results, others are hitting limits. Many
organizations designed their applications using this model because tools and infrastructure made it
too difficult to build service-oriented architectures (SOA) years ago, and they did not see the need-
until the application grew.
From an infrastructure perspective, each server can run many applications within the same host and
have an acceptable ratio of efficiency in resources usage, as shown in Figure 4-2.
Figure 4-2. Monolithic approach: Host running multiple apps, each app running as a container
Monolithic applications in Microsoft Azure can be deployed using dedicated VMs for each instance.
Additionally, using
Azure virtual machine scale sets
, you can easily scale the VMs.
Azure App Service
can also run monolithic applications and easily scale instances without requiring you to manage the
VMs. Since 2016, Azure App Services can run single instances of Docker containers as well, simplifying
deployment.
As a QA environment or a limited production environment, you can deploy multiple Docker host VMs
and balance them using the Azure balancer, as shown in Figure 4-3. This lets you manage scaling with
a coarse-grain approach, because the whole application lives within a single container.
21
CHAPTER 3 | Architecting container and microservice-based applications
Figure 4-3. Example of multiple hosts scaling up a single container application
Deployment to the various hosts can be managed with traditional deployment techniques. Docker
hosts can be managed with commands like
docker run
or
docker-compose
performed manually, or
through automation such as continuous delivery (CD) pipelines.
Dostları ilə paylaş: |