In this lesson,
we're going to dive into the concepts of containerization,
its benefits, its use cases,
and how you can perform basic container operations
inside of Linux.
Now, the newest type of virtualization
that's becoming popular in our networks today
is known as container-based virtualization,
also referred to as containerization.
Now, this is a type of virtualization
that is much more focused on servers
than on end user workstations.
With this type of virtualization,
the operating system kernel
is going to be shared across multiple virtual machines,
but the user space for each of those virtual machines
is uniquely created and managed.
Containerization is really a type of virtualization
that's applied by the host operating system
to provision an isolated execution environment
for a given application.
Containerization is considered fairly secure
because it enforces resource separation
at the operating system level.
Now, containerization is commonly used with Linux servers,
and some common examples
of container-based virtualization software
includes things like Kubernetes, Docker,
Parallels Virtuozzo, and the OpenVZ project.
So what does containerization really look like?
Well, you have a piece of hardware,
and then on top of that hardware
you have some host operating system.
And usually this is going to be Linux.
Then you have a container manager,
something like Kubernetes or Docker or something like that.
This container manager is going to be used
to create different containers
that have different applications within them.
In this case, let's say I have three containers.
I have the first environment,
which is based on the kernel of the host OS.
In this example, a Linux system is being used,
and so you can see container one is running Linux
and it has some applications
that can be run inside of there.
Now, in container two, we're going to do the same thing.
And then in container three, we're going to do the same thing.
Now, all three of these containers
are sharing the same host operating system,
in this case Linux,
and so this takes a lot less resources
than doing pure virtualization using virtual machines.
If we instead wanted to use individual virtual machines,
each one would need its own copy
of the Linux operating system,
and this could add eight to 10 gigabytes
for each and every container.
But with containers, we don't have to do that
because we can all share the same operating system,
and therefore it takes a lot less storage space
and a lot less processing power,
and it's much more resource efficient.
This is really the real benefit
of using something like a container
from an operational perspective.
Now, because these containers are logically isolated,
they can't actually interface with each other.
If we want these two containers
to be able to talk to each other,
I have to actually connect them through a virtual network,
and I do that by using the right routing and switching
to allow them to talk.
By default though,
they have no way of talking to each other,
and this is another great thing from a security standpoint
because they are being fully isolated.
Now, here's a big warning for you
when you're dealing with containers.
If the attacker compromises
the host operating system underneath,
for example that Linux operating system I'm using here,
guess what happens?
This attacker now has access to all of the containers
and all of their data
because that one operating system
is being used by all of the containers
that I'm hosting on this physical machine.
This is one of the biggest vulnerabilities
when you use containers.
I can have a container system
that's running 50 different servers right now,
and because I'm running all these different servers
and services using containerization,
they're all hosted on the same physical server.
Now, if somebody gets into that one physical Linux server
that's underneath them
that's hosting all of these containers,
they now have access to all 50
of those hosted services and applications
as well as their data.
So now that we understand the basics of containers,
let's dive a little bit into Kubernetes for a moment.
Kubernetes is an open source system
for automated deployment, scaling, and management
of containerized applications.
Kubernetes is going to be used to group containers
that make up applications
into logical units for production use.
When you deploy Kubernetes,
you're going to gain access to a cluster
that contains a set of worker machines which we call nodes.
These nodes or worker machines
are the objects that are running
the containerized applications.
Now, inside of these nodes,
we host something known as a pod.
A pod is the name used by Kubernetes
for one or more containers
that have shared storage and network resources.
A pod is really the smallest
deployable unit of computing power that you can create
and manage within Kubernetes.
Multiple pods can also be combined into a node
for use in Kubernetes too.
Now, in addition to pods,
there's also these specialized containers
known as sidecars.
Now, a sidecar container is designed to run alongside
a main container or pod.
These two containers are designed to share resources,
like a pod storage or network interfaces,
as well as allowing a sidecar and a main container
to both share a storage volume
so that data can be accessed
by both the main and sidecar containers.
The real benefit of using a sidecar
is that you can enhance and extend
the functionalities of the main container
without having to modify its original code base.
Additionally, the sidecar can also use
a different programming language
than the main container does if you need to.
And this makes it even more extendable and useful
when you're developing and deploying microservices.
Now, in addition to regular sidecar containers,
there's also a specialized type of sidecar
known as an Ambassador container.
Now, an Ambassador container
is a special type of sidecar container
that's going to simplify the process
of accessing data and services outside of a given pod.
The Ambassador container is also used to hide the complexity
involved in accessing external services
by providing you with a uniform interface
to access those services.
For example, let's pretend
that I have a main container application
that's being used to host my website,
and this website is going to be used to sell exam vouchers
for the CompTIA exams.
Now, in addition to providing
inventory management and assignment,
when somebody buys one of those exam vouchers,
we also need to access
our credit card processor's remote service
to get paid for selling that exam voucher.
We could do this by using an Ambassador container
as a proxy between our main application container
that runs our exam voucher store and inventory
and the remote services of our credit card company
that's going to be used to process the sale
and verify that your credit card
has sufficient funds available to make this purchase.
Another area you need to think about
when it comes to containers is storage,
because often we're going to use containerization
with cloud services
to rapidly scale upwards or downwards
based on the demands of our users.
For example, at my company we use containers a lot
to host our websites,
and as the user demand increases,
we can spin up new containers automatically
and add them to our load balancer
to handle those additional requests.
The challenge, though,
is that all the data that we need to store
has to be set up in a separate area
outside of the containers
because these containers will spin up and later be destroyed
along with all the data they have.
And this is because containers
are designed to be non-persistent by default,
and they're responsive to our user demand
of going up and down
and destroying that data when we close them out.
Now, to solve this issue,
we also need to create a persistent storage volume
that these containers can then use.
To do this, you're going to create a PersistentVolume
that exists on your physical storage device,
and then you're going to create a PersistentVolumeClaim
that'll automatically be bound
to that suitable PersistentVolume.
Now, whenever you create a pod,
you can configure it to use the PersistentVolumeClaim
and access this persistent storage
for any data that needs to be read or written
to a more permanent storage media area
outside of a given container.
Now, when you start using containers,
you'll often find yourself becoming a bit overwhelmed
with all the different options that exist
between things like Docker and Kubernetes.
These tools actually work together really well,
even though some people think they're competitors.
For example, using Docker Compose,
you can build a single configuration file
to orchestrate multi-container applications.
Let's say you have a new web application
that's going to be split
between your front end and your back end.
The front end is going to be written in React JavaScript
and the back end is going to be written with Node JavaScript.
Now, this could be built in Docker Compose
as a single node but with multiple containers,
one for the front end and one for the back end.
And maybe you might have a third container
for a database as well.
Now, this could all be converted into Kubernetes as well
if you wanted to use the Kompose tool,
and you do this by entering kompose convert,
and that will create a Kubernetes manifest in YAML format
that's ready to be deployed into your Kubernetes kernel.
Now, why would you want to do this
instead of just using Kubernetes in the first place?
Well, Docker Compose is a lot easier to work with
and it's much more convenient than Kubernetes
when you want to get an application
up and running very quickly during your local development.
So you can do all the necessary configuration
for running a multi-container application
within a single file using Docker Compose.
And then you can convert it using Kompose
to the relevant Kubernetes manifest file inside YAML format
for large scale production deployments.
Another thing we need to talk about is container registries.
Now, a container registry is a place to store,
manage, and secure your container images.
From within the registry,
you can conduct vulnerability analysis of your containers
and implement fine grain access controls
to those containers.
Container registries are set up
to work with Docker containers,
and these registries can be linked from within Kubernetes
to allow you to pull an image from the registry
and launch the container
using automations and orchestrations.
Finally, we need to cover the concepts
of a service mesh within Kubernetes.
Now, a Kubernetes service mesh
is a tool that inserts security, observability,
and reliability features to your applications
at the platform layer instead of at the application layer.
Now, a service mesh is going to be used
to manage the network traffic
between different services, containers, and pods,
which is critical when you're building microservices.
Generally, the service mesh is going to be implemented
as a set of network proxies
that are deployed alongside a sidecar,
and they can make use of the Ambassador containers
that I mentioned earlier.
This service mesh layer
sits on top of a Kubernetes infrastructure
to provide interservice communication over the network
in a reliable and safe manner.
This service mesh is going to consist
of a data plane and a control plane.
And if you think back to your Network+ studies
where you learned about overlay networks,
that's exactly what we're referring to here.
These overlay networks can be used
to bridge physical or logical networks,
conduct network address translation or NAT,
and connect the host and the containers
to other data sources or services
outside of the network or across the internet,
depending on your configuration.