Kubernetes
Kubernetes
Kubernetes
Kubernetes (often abbreviated as "K8s") is an open-source container
orchestration platform used for automating the deployment, scaling, and
management of containerized applications. It was originally developed by Google
and is now maintained by the Cloud Native Computing Foundation (CNCF).
Kubernetes provides a highly flexible and scalable framework for managing
containerized applications across different environments, such as on-premises
data centres or public cloud platforms. It allows you to deploy, manage, and scale
containers across a cluster of nodes, ensuring high availability and fault tolerance.
Kubernetes is based on a declarative approach, where you specify the desired
state of your application, and Kubernetes takes care of maintaining that state.
Kubernetes is an important tool in modern cloud-native computing and is widely
used by organizations of all sizes to manage their containerized applications. It
provides a rich set of features, including automated scaling, self-healing, rolling
updates, service discovery, and load balancing, among others. Its popularity has
led to a vibrant ecosystem of tools and services that integrate with Kubernetes,
making it a cornerstone technology for modern application development and
deployment.
Microservices
It is an architectural development style in which the application is made up of
smaller services that handle a small portion of the functionality and data by
communicating with each other directly using lightweight protocols like HTTP.
According to Sam Newman, “Microservices are the small services that work
together.”
functionality. You can also say that: the number of microservices you should
develop is equal to the number of functionalities you require. The database is also
decentralized and, generally, each microservice has its own database.
Built around business capabilities: In today’s world, where so many technologies
exist, there is always a technology that is best suited for implementing a particular
functionality. But in monolithic applications, it was a major drawback, as we
can’t use different technology for each functionality and hence, need to
compromise in particular areas. A microservice shall never restrict itself from
adopting an appropriate technology stack or backend database storage that is most
suitable for solving the business purpose, i.e., each microservice can use different
technology based on business requirements.
Design for failure: Microservices must be designed with failure cases in mind.
Microservices must exploit the advantage of this architecture and going down one
microservice should not affect the whole system, other functionalities must
remain accessible to the user. But this was not the case in the Monolithic
applications, where the failure of one module leads to the downfall of the whole
application.
Service-oriented architecture (SOA) vs Microservices architecture:
Steve Jones, MDM at Capgemini once said, “Microservices is SOA, for those
who know what SOA is”. So, those who know about SOA, most think that they
are the same, or the difference is not much clearer in their mind. We can’t blame
them also, if we talk about a cake and a pastry, we will find more similarities than
differences. So let’s try to understand the differences between the two.
SOA evolved in order to deal with the problems in monolithic architecture and
became popular in the early 2000s. In SOA, the large application is split up into
multiple smaller services that are deployed independently. These services don’t
communicate with each other directly. There used to be an Enterprise Service Bus
(ESB, a middleware or server with the help of services using different protocols
or message standards that can communicate with each other easily) where these
services expose themselves and communicate with each other through it. Also,
there was no guideline to have an independent database for each service.
Kubernetes Components
A Kubernetes cluster consists of a set of worker machines, called nodes, that run
containerized applications. Every cluster has at least one worker node.
The worker node(s) host the Pods that are the components of the application
workload. The control plane manages the worker nodes and the Pods in the
cluster. In production environments, the control plane usually runs across
multiple computers and a cluster usually runs multiple nodes, providing fault-
tolerance and high availability.
This document outlines the various components you need to have for a complete
and working Kubernetes cluster.
The control plane's components make global decisions about the cluster (for
example, scheduling), as well as detecting and responding to cluster events (for
example, starting up a new pod when a deployment's replicas field is unsatisfied).
Control plane components can be run on any machine in the cluster. However,
for simplicity, set up scripts typically start all control plane components on the
same machine, and do not run user containers on this machine. See Creating
Highly Available clusters with kubeadm for an example control plane setup that
runs across multiple machines.
8
kube-apiserver:
The Kubernetes API server is a critical component of a Kubernetes cluster that
serves as the primary management interface for the cluster. As such, it is designed
to be fault-tolerant, meaning that it can continue to operate even in the face of
failures or disruptions.
One of the key mechanisms that Kubernetes uses to ensure fault tolerance of the
API server is replication. The API server can be deployed as a replicated set of
instances, with multiple instances running on different nodes in the cluster. This
allows the API server to continue operating even if one or more instances fail or
become unavailable, ensuring that the control plane remains operational and
available to users and applications.
Health checks: Kubernetes uses health checks to monitor the status of the API
server and automatically perform actions like restarting or relocating the server if
it becomes unavailable.
Backups and disaster recovery: Kubernetes provides options for backing up and
restoring the API server's data, allowing you to recover from disasters or data loss
events.
In Kubernetes, a manifest is a YAML or JSON file that defines the desired state
of the resources to be created or managed in the cluster. The manifest file
typically contains a list of Kubernetes objects, such as pods, services,
deployments, and config maps, along with their desired properties, such as the
number of replicas, container images, resource limits, and network configuration.
A manifest file can be created and edited using a text editor, or it can be generated
automatically using tools like kubectl, Helm, or Kubernetes Operators. Once the
manifest file is created, it can be applied to the Kubernetes cluster using kubectl
apply command. The Kubernetes API server will read the manifest and create,
update or delete the resources specified in the file to match the desired state.
Using manifests, you can automate the deployment and management of your
application and infrastructure in a consistent, repeatable, and scalable way. You
can version control the manifests to track changes and roll back to previous
9
The Kubernetes API server uses the Raft consensus algorithm to ensure that
multiple instances of the API server can work together to maintain a consistent
view of the cluster's state.
When a client sends a request to the API server, the request is processed by the
leader API server, which then replicates the change to the other replicas using the
Raft algorithm. This ensures that all instances of the API server have a consistent
view of the cluster's state and can respond to requests in a coordinated and
consistent manner.
etcd:
etcd is a distributed key-value store that is used by Kubernetes to store and
manage the state of the cluster. It is a highly available, consistent, and fault-
tolerant data store that is designed to provide a reliable and scalable foundation
for distributed systems.
etcd is used by Kubernetes to store information about the state of the cluster, such
as information about nodes, pods, services, and other Kubernetes objects. This
information is stored as key-value pairs, and can be accessed and updated by the
Kubernetes API server and other Kubernetes components.
Replication: etcd uses a Raft consensus algorithm to replicate data across multiple
nodes, ensuring that the data remains available even in the event of failures or
network partitions.
10
Consistency: etcd ensures that all nodes in the cluster have a consistent view of
the data, even in the face of concurrent updates or failures.
Automatic failover: etcd automatically detects failures and promotes a new leader
to ensure continued availability and consistency.
kube-scheduler:
The kube-scheduler is a component of Kubernetes that is responsible for
scheduling pods to run on nodes in the cluster. When a new pod is created in
Kubernetes, the kube-scheduler is responsible for selecting a suitable node to run
the pod based on various factors such as resource availability, node affinity/anti-
affinity, pod affinity/anti-affinity, and other constraints.
The kube-scheduler takes into account various factors when selecting a node for
a pod, such as the amount of CPU and memory resources available on each node,
the node's geographical location, the pod's affinity/anti-affinity requirements, and
any other constraints specified in the pod's configuration. It also considers factors
such as node taints and tolerations, which allow nodes to be marked as unsuitable
for certain types of workloads.
Once the kube-scheduler has selected a node for a pod, it updates the pod's
configuration to reflect the node assignment, and then sends the updated
configuration to the Kubernetes API server to be stored and processed by other
components such as the kubelet and container runtime.
scheduled. For each pod, it evaluates all the available nodes in the cluster and
selects the best node based on the scheduling requirements and constraints
specified in the pod's configuration.
The kube-scheduler takes into account various factors when selecting a node for
a pod, such as the amount of CPU and memory resources available on each node,
the node's geographical location, the pod's affinity/anti-affinity requirements, and
any other constraints specified in the pod's configuration. It also considers factors
such as node taints and tolerations, which allow nodes to be marked as unsuitable
for certain types of workloads.
Once the kube-scheduler has selected a node for a pod, it updates the pod's
configuration to reflect the node assignment, and then sends the updated
configuration to the Kubernetes API server to be stored and processed by other
components such as the kubelet and container runtime.
Kubelet:
The kubelet is a component of Kubernetes that runs on each node in the cluster
and is responsible for managing the state of the node and ensuring that containers
are running as expected.
When a pod is scheduled to run on a node, the kubelet is responsible for ensuring
that the necessary containers are running and that they remain running throughout
the lifetime of the pod. It does this by communicating with the container runtime
(such as Docker or containerd) to start, stop, and manage container processes.
Monitoring node health: The kubelet regularly reports the node's status to the
Kubernetes API server, indicating whether the node is healthy and ready to
receive new workloads.
Managing container logs: The kubelet collects container logs and sends them to
the appropriate destination (such as a centralized logging system).
Handling pod lifecycle events: The kubelet is responsible for handling various
pod lifecycle events, such as pod initialization, termination, and garbage
collection.
The kubelet communicates with the Kubernetes API server to receive instructions
and updates about the state of the node and the workloads that should be running
on it. It also exposes a local API that can be used by other Kubernetes components
to interact with the node.
kube-controller-manager:
The kube-controller-manager is a component of Kubernetes that runs on the
master node(s) and is responsible for managing various controllers that oversee
different aspects of the cluster's state. These controllers include:
1. Node controller: This controller monitors the health of nodes in the cluster
and takes action if a node becomes unreachable or unresponsive.
2. Replication controller: This controller ensures that the specified number of
replicas of a pod are running at any given time, and takes action to create
or destroy pods as needed.
3. Endpoints controller: This controller updates the endpoints object
whenever a service is created or updated, ensuring that the endpoints for
the service are up to date and can be used to route traffic to the service.
4. Service account and token controllers: These controllers manage the
creation and deletion of service accounts and API access tokens for pods
in the cluster.
5. The kube-controller-manager is responsible for ensuring that these
controllers are running correctly and responding appropriately to changes
in the cluster's state. It also manages the lifecycle of the controllers,
ensuring that they are started and stopped as necessary.
Installing Kubeadm
Deploying Kubernetes Cluster using Kubeadm
EOF
sudo swapoff -a
rm /etc/containerd/config.toml
Install Calico:
kubectl create -f
https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/tigera-
operator.yaml
kubectl apply -f
https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/custo
m-resources.yaml
WorkerNode:
curl -sL https://get.docker.com | bash
EOF
sudo swapoff -a
rm /etc/containerd/config.toml
Cluster Configuration:
alias ku=kubectl
15
The “kubectl get pods” command is used to list all the running pods in a
Kubernetes cluster.
To use this command, you need to have kubectl installed on your system and
configured to connect to a Kubernetes cluster.
Smoke testing:
Smoke testing is a type of software testing that is typically performed early in the
development cycle or after a major change to the software. The goal of smoke
testing is to verify that the most critical functions of the software are working
correctly and that the software is stable enough to proceed with further testing.
In smoke testing, a limited set of tests is performed to check that the software is
able to perform its most important functions and that it does not crash or exhibit
any major issues. This may include testing basic functionality such as user
authentication, data input and output, and simple calculations.
The term "smoke testing" comes from the idea of testing whether the software is
stable enough to "smoke" or not. If the software passes the smoke tests, it is
considered to be stable enough to proceed with further testing. If it fails the smoke
tests, it is usually considered to be too unstable to proceed and needs to be fixed
before further testing can be performed.
Smoke testing is often used as a quick and simple way to verify that software is
working correctly before investing more time and resources in additional testing.
It can also be used as a way to identify major issues early in the development
cycle, before they become more difficult and costly to fix.
16
1. Kubernetes master endpoint: This will show the API server endpoint of the
Kubernetes cluster that is currently configured in your kubectl context.
2. Kubernetes API version: This will display the version of the Kubernetes
API that is being used by the cluster.
3. Kubernetes DNS service IP: This will display the IP address of the
Kubernetes DNS service that is used for service discovery within the
cluster.
Kubernetes service account token: This will display the service account token that
is used by kubectl to authenticate with the Kubernetes API server.
The “kubectl get ns” command is used to list all the namespaces in the
Kubernetes cluster that are currently available to the user. When you run this
command, it will display a table of information about each namespace, including
the following columns:
STATUS: The current status of the namespace, which will typically be Active.
AGE: The amount of time that the namespace has been active since it was created.
By default, the kubectl get ns command will list all the namespaces that are
currently available to the user. However, you can also use various flags and
options to filter and customize the output of the command, such as using --show-
labels to show the labels associated with each namespace, or using -o wide to
display additional details about each namespace, such as its creation timestamp,
resource version, and annotations.
The “kubectl get events” command is used to display a list of events that have
occurred in the Kubernetes cluster. When you run this command, it will display
a table of information about each event, including the following columns:
TYPE: The type of event that has occurred, such as Normal or Warning.
SOURCE: The source of the event, such as the name of the Kubernetes API
server.
The “kubectl get services -A” command is used to list all the services in all
namespaces in the Kubernetes cluster. When you run this command, it will
display a table of information about each service, including the following
columns:
TYPE: The type of the service, which can be ClusterIP, NodePort, LoadBalancer,
or ExternalName.
AGE: The amount of time that the service has been running.
By default, the kubectl get services -A command will list all the services in all
namespaces in the Kubernetes cluster. However, you can also use various flags
and options to filter and customize the output of the command, such as using -n
or --namespace to specify a particular namespace, or using -o wide to display
additional details about each service, such as the node on which it is running, the
selector used to route traffic to the service, and any associated endpoints.
18
“kubectl run” is a command that creates a new deployment or a new job based
on a specific image.
Here, <name> is the name you want to give to the new deployment or job, and
<image-name> is the name of the container image you want to use.
Kubernetes can fetch container images from various sources, depending on how
the cluster is configured. Some common sources include:
Docker Hub: This is the default image repository for Kubernetes. If no specific
registry is specified in the image name, Kubernetes will assume that the image is
hosted on Docker Hub.
Private registry: Kubernetes can also fetch images from a private Docker registry,
such as Harbor, Quay.io, or a self-hosted Docker registry.
Google Container Registry (GCR): If you are using Google Kubernetes Engine
(GKE), you can use Google Container Registry to host your container images.
Amazon Elastic Container Registry (ECR): If you are using Amazon Elastic
Kubernetes Service (EKS), you can use Amazon ECR to host your container
images.
Other container registries: Kubernetes can also fetch images from other container
registries, such as Azure Container Registry, JFrog Artifactory, or GitLab
Container Registry.
When deploying a Kubernetes application, you specify the container image to use
in the YAML manifest for the deployment or pod. Kubernetes will then use the
specified registry to fetch the container image and run it as a pod or deployment
in the cluster.
Here, <pod-name> is the name of the pod you want to retrieve information for. If
you omit <pod-name>, the command will return information about all pods in the
current namespace.
You can use various options and flags with kubectl get pod to customize the
output. Some common options include:
-o <output-format>: specifies the output format. The available formats are json,
yaml, wide, and custom-columns.
--selector <label-selector>: retrieves only pods that match the specified label
selector.
For example, to retrieve information about all pods in the current namespace in
the wide format, you can use:
Here, <pod-name> is the name of the pod you want to expose, <service-name> is
the name you want to give to the new service, <port> is the port number you want
to expose on the service, <target-port> is the port number on the pod to forward
traffic to, and <service-type> is the type of service you want to create (e.g.
ClusterIP, NodePort, LoadBalancer).
“kubectl get svc” is a command used to list all the services in a Kubernetes
cluster. The svc in the command stands for "service".
When you run the kubectl get svc command, it will display a list of all the services
in the default namespace. If you want to see the services in a specific namespace,
you can use the -n or --namespace option followed by the namespace name.
The output of kubectl get svc will include the following columns:
For example, to list all the services in the default namespace, you can use:
Namespace:
In Kubernetes, a namespace is a virtual cluster that provides a way to organize
and isolate resources within a cluster. A namespace allows you to create a logical
separation between different sets of resources, such as pods, services, and
replication controllers, in the same physical cluster.
Namespaces can also be used to limit the scope of resource access and provide
resource quota management. You can assign resource quotas to namespaces to
limit the amount of CPU, memory, and other resources that can be consumed by
resources deployed in a namespace.
Replace "<namespace-name>" with the name you want to give to the namespace.
Once a namespace is created, you can deploy resources in it using the same
kubectl command that you would use to deploy resources in the default
namespace, but with the addition of the "-n" flag to specify the namespace:
kube-apiserver: The API server is the central control plane component that
exposes the Kubernetes API and handles API requests from various Kubernetes
components.
etcd: The etcd key-value store is used by Kubernetes to store configuration data
and maintain cluster state.
kube-scheduler: The scheduler is responsible for placing newly created pods onto
available nodes based on resource requirements, node capacity, and other factors.
kubelet: The kubelet is an agent that runs on each node and is responsible for
managing the state of the node, including running and monitoring containers.
KOPS
Kops stands for Kubernetes Operations and is a popular command-line tool used
for deploying, managing, and scaling Kubernetes clusters. It automates the
deployment of highly available clusters on public cloud platforms such as
Amazon Web Services (AWS), Google Cloud Platform (GCP), and Microsoft
Azure. It is an open-source project that is written in Golang and maintained by
the Kubernetes community.
Kops allows users to create and manage Kubernetes clusters by defining the
desired state of the cluster in a YAML configuration file. It automates the process
of provisioning and configuring the underlying infrastructure required to run a
Kubernetes cluster, such as virtual machines, load balancers, and network
settings. It also provides features such as automatic scaling, rolling updates, and
self-healing.
Kops has several requirements that must be met before you can use it to deploy
and manage Kubernetes clusters. Here are the main requirements:
Cloud Provider Account: You will need a valid account for your desired cloud
provider, such as AWS, GCP, or Azure.
Command Line Tools: You will need to install command-line tools such as
kubectl and the AWS CLI (if using AWS).
DNS: You will need to have a registered domain name that can be used to access
your cluster.
SSH Key Pair: You will need an SSH key pair that can be used to access the nodes
in your cluster.
Storage: You will need to create a storage bucket or container to store the state of
your Kubernetes cluster.
Network: You will need to create a Virtual Private Cloud (VPC) or similar
network configuration to ensure that your nodes can communicate with each
other.
24
Operating System: You will need to have a supported operating system, such as
Linux, macOS, or Windows.
KOPS REQUIREMENTS:
1.AWS ACCOUNT
2.Install ubuntu server & configure IAM role with admin access
3.cofigure awscli
Wrapper:
A pod can contain one or more containers, which are co-located and share the
same network and storage resources. The containers within a pod can
communicate with each other using localhost, which makes it easier to create
complex, multi-container applications that work together.
The pod is also the basic unit of scaling in Kubernetes. You can create multiple
replicas of a pod to increase the availability and resilience of your application.
Kubernetes manages the scheduling and placement of pods across the nodes in a
cluster to ensure that the desired number of replicas are running.
emptyDir:
Open a terminal window and ensure that you have the kubectl command-line
tool installed, configured, and connected to your Kubernetes cluster.
Run the following command to get information about the Pod's volumes:
Replace <pod-name> with the name of the Pod that you want to check.
Look for the volumes section in the output. This section lists all the volumes
defined in the Pod's configuration. If an emptyDir volume is created in the Pod,
you should see an entry for it in the volumes section with a name field that
matches the name of the emptyDir volume.
"volumes": [
"name": "my-emptydir",
"emptyDir": {}
If you see the entry for the emptyDir volume in the volumes section, that means
the emptyDir volume is defined in the Pod's configuration and created in the
Pod.
Each Pod is meant to run a single instance of a given application. If you want to
scale your application horizontally (to provide more overall resources by running
more instances), you should use multiple Pods, one for each instance. In
Kubernetes, this is typically referred to as replication. Replicated Pods are
usually created and managed as a group by a workload resource and its controller.
27
CrashLoopBackOff:
ReplicaSet:
A ReplicaSet's purpose is to maintain a stable set of replica Pods running at any
given time. As such, it is often used to guarantee the availability of a specified
number of identical Pods.
A ReplicaSet is a process that runs multiple instances of a Pod and keeps the
specified number of Pods constant. Its purpose is to maintain the specified
number of Pod instances running in a cluster at any given time to prevent users
from losing access to their application when a Pod fails or is inaccessible.
ReplicaSet helps bring up a new instance of a Pod when the existing one fails,
scale it up when the running instances are not up to the specified number, and
scale down or delete Pods if another instance with the same label is created. A
ReplicaSet ensures that a specified number of Pod replicas are running
continuously and helps with load-balancing in case of an increase in resource
usage.
Deployments:
In Kubernetes, a Deployment is an object used to define and manage the
deployment of application containers. It provides a declarative way to create,
update, and scale application instances in a Kubernetes cluster.
By using a Deployment, you can define the desired state of your application and
let Kubernetes handle the details of managing and maintaining that state. It
simplifies the management of application deployments, provides self-healing
capabilities, and helps ensure high availability and resilience within a
Kubernetes cluster.
max surge:
"max surge" is a parameter used during a rolling update of a deployment. It
determines the maximum number or percentage of pods that can be created above
the desired replica count during the update process. The purpose of max surge is
to control the rate at which new pods are introduced while ensuring that the
desired level of availability is maintained.
Let's consider an example to understand how max surge works. Suppose you have
a deployment with a desired replica count of 5, and you set the max surge to 2.
During a rolling update, Kubernetes will ensure that no more than 7 pods (5
desired replicas + 2 surge) are running simultaneously.
29
• Initially, you have 5 pods running, which matches the desired replica count.
• You initiate a rolling update, specifying the new version of your
application.
• Kubernetes starts creating new pods with the updated version.
• As per the max surge value of 2, Kubernetes allows a maximum of 2
additional pods to be created.
• Kubernetes gradually scales up the new pods while scaling down the old
ones.
• At any given point, the total number of pods will not exceed 7 (5 desired
replicas + 2 surge).
• Once all the new pods are successfully running, Kubernetes proceeds with
scaling down the old pods.
• Finally, you have 5 pods running with the updated version, and the rolling
update is complete.
max unavailable:
"max unavailable" is a parameter used in the context of a rolling update to specify
the maximum number or percentage of pods that can be unavailable during the
update process. It helps control the number of pods that can be taken down or
become unavailable at any given time, ensuring the desired level of availability
is maintained during the update.
Suppose you have a Deployment with a replica count of 10, and you set the "max
unavailable" value to 2. During a rolling update, Kubernetes ensures that no more
than 2 pods are unavailable at any given time.
• Initially, you have 10 pods running, which match the desired replica count.
30
By setting an appropriate value for "max unavailable," you can control the rate of
pod replacement during a rolling update. It prevents too many pods from
becoming unavailable simultaneously, ensuring the desired level of availability
and reducing the impact on the running application.
31
SERVICES
Kubernetes is a platform that helps you run your containerized applications on a
massive scale. And a key aspect of this is making sure that different parts of
your apps can easily communicate with each other. Kubernetes does this by
using Kubernetes Services. These Services not only allow smooth
communication between components within the cluster but also between the
cluster and the outside world.
What Problems Do Kubernetes Services Solve?
In Kubernetes, Pods are non-permanent resources - they can appear and
disappear as needed. This is because Kubernetes constantly checks to make sure
the cluster is running the desired number of replicas (copies) of your app. And
Pods are created or destroyed to match this desired state.
if you need more replicas of your app because of an increase in incoming traffic
(more demand), Kubernetes will spin up some new Pods to handle it. If a Pod
fails for some reason, no worries - Kubernetes will quickly create a new one to
replace it. And if you want to update your app, Kubernetes can destroy old Pods
and create new ones with the updated code. So the set of Pods running at one
moment could be totally different from the set running a moment later.
But here's the thing - if you want to access your app, how do you keep track of
which Pod to connect to with all these changing IP addresses of Pods?
That's where Services come in. They provide an unchanging location for a
group of Pods. So even though the Pods themselves are dynamic, the Services
make sure you always have a central location to access your app.
ClusterIP Service:
ClusterIP Services are used for communication between Pods within the same
Kubernetes cluster.
The Service gets exposed on a static IP that's unique within the cluster. When
you make a request to that IP, the Service takes care of redirecting traffic to one
of the Pods it's associated with. And if there's more than one Pod, the Service
will automatically balance the traffic, so no single Pod gets bogged down by too
many requests.
Note that ClusterIP Services are meant for Pod-to-Pod communication only.
They aren't accessible from outside the cluster.
NodePort Service:
The NodePort Service is useful when you need to expose your application to
external clients. This means all traffic that is coming from outside of the cluster.
When you create a NodePort Service, Kubernetes opens a port (in the range of
30000 and 32767) on all of its worker nodes. Note that the same port number is
used across all of them. All traffic incoming to the worker node's IP address,
and that specific port, is redirected to a Pod linked with that Service.
Keep in mind that a NodePort Service doesn't do any kind of load balancing
across multiple nodes. All the incoming traffic goes straight to the node that the
external client is connected to. This can result in some nodes getting hit hard
with traffic while others are barely used.
33
LoadBalancer Service:
A LoadBalancer Service is another way you can expose your application to
external clients. However, it only works when you're using Kubernetes on a
cloud platform that supports this Service type.
The LoadBalancer Service detects the cloud computing platform on which the
cluster is running and creates an appropriate load balancer in the cloud
provider’s infrastructure. The load balancer will have its own unique, publicly
accessible IP address. mFor example, if the cluster is running on Amazon Web
Services (AWS), the Service will create an Elastic Load Balancer (ELB) to
distribute incoming traffic across multiple nodes in the cluster.
For example, say you have a web application running on a Kubernetes cluster
and exposed using the LoadBalancer Service. External users can access the
application by visiting the external IP address of the load balancer in their web
browser. The load balancer will then forward their request to a node. If another
user connects, their connection will be forwarded to a different node. This way,
traffic gets distributed evenly, across multiple nodes, so that none gets
overloaded with too many requests. Finally, the connection gets forwarded from
node to Pod through a Service that sits in front of them. Each user will then get
the response in their web browser. But users won't hit the same node, because of
our LoadBalancer. So our worker nodes will have an easier time responding to
requests.
34
ExternalName Service
An ExternalName Service in Kubernetes is useful when you have a service that
is running outside your Kubernetes cluster, such as a database, and you want to
access it from within your cluster.
For example, let's say you have an app in a Pod that needs to access an external
database running at the domain name "db-prod.example.com". For this
database, you can create an ExternalName Service named, say, "db-prod". Then,
when the app wants to connect to the database, it will send a request to the local
name "db-prod". Next, Kubernetes will look up the ExternalName Service for
"db-prod" and see that it has an external name of "db-prod.example.com".
Kubernetes will then use DNS to resolve the external name to an IP address and
route the request to the appropriate external service outside the Kubernetes
cluster. This process happens automatically and seamlessly. The app doesn’t
need to be aware of the details of the external service.
Note: DNS lookup is like looking up a phone number in a directory. When you
type in a website address or domain name, your computer sends a request to a
special directory called a DNS server to find the IP address of the server hosting
that website. This helps your computer connect to the website you want to visit.
35
We now understand what an ExternalName Service is, but what are the benefits
of using one?
One of the key benefits of ExternalName Service in Kubernetes is that it helps
you keep the details of your external service separate from your application.
Instead of hard-coding IP addresses or domain names, you can give these
services a nickname using an ExternalName Service. If the service provider
moves to a new IP address or gets a new domain name, you can simply update
the ExternalName Service definition to point to the new location. Kubernetes
will handle the DNS resolution of the new address so that the application can
continue to access the external service using the same local name. No
modifications are required in the application code. This makes managing your
external services much easier as you don't have to update the application code
each time the external service changes.
Kubernetes Services help us connect all of the components we have running on
our Pods. They provide a stable front gate, where Pods can be reached at,
allowing for reliable communication both within the cluster and between the
cluster and external clients. I hope this article has helped you understand how
Services fit into the overall Kubernetes ecosystem.
36
Ingress controller
Step1:
Execute the below command in management server
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-
nginx/controller-v1.3.1/deploy/static/provider/aws/deploy.yaml
Step2:
To get the name spaces
ku get ns
when you give above command you can see a new namespace is created with
name “ingress-nginx”
If you give “kubens” command it will display the current name space
37
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: nginx
spec:
tls:
- hosts:
- "vote.cgitk8s.xyz"
secretName: my-tls-secret
rules:
- host: vote.cgitk8s.xyz
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: vote
port:
number: 80
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: result-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: nginx
spec:
tls:
- hosts:
- "result.cgitk8s.xyz"
secretName: my-tls-secret
rules:
- host: result.cgitk8s.xyz
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: result
port:
41
You will get load balancer updated for both the vote and result
Decommissioning:
ku delete -f voting-app-ClusterIP.yml
ku get svc,deploy
ku delete -f https://raw.githubusercontent.com/kubernetes/ingress-
nginx/controller-v1.3.1/deploy/static/provider/aws/deploy.yaml
42
Kubernetes — Probes
Kubernetes provides probes (health checks) to monitor and act on the state of
Pods (Containers) and to make sure only healthy Pods serve traffic. With help of
Probes, we can control when a pod should be deemed started, ready for service,
or live to serve traffic.
Probes are used to detect:
Containers that haven’t started yet and can’t serve traffic.
Containers that are overwhelmed and can’t serve additional traffic.
Containers that are completely dead and not serving any traffic.
Types of Probes
Kubernetes gives you three types of health checks probes:
Liveness
Readiness
Startup
Liveness Probe
Liveness probes let Kubernetes know whether your app (running in a container
inside Pod) is healthy.
Indicates whether the container is running.
If app is healthy, Kubernetes will not interfere with pod functioning. If app is
unhealthy, Pod will be marked as unhealthy. If a Pod fails health-checks
continuously, the Kubernetes terminates the pod and starts a new one.
Liveness probes could catch a deadlock, where an application is running, but
unable to make progress. Restarting a container in such a state can help to make
the application more available despite bugs.
Kubelet uses liveness probes to know when to restart a container. If the liveness
probe fails, the kubelet kills the container, and the container is subjected to its
restart policy.
Configure a health check that periodically checks if your application is still alive.
Containers can be restarted if the check fails.
43
Kubelet will periodically send a GET request to the Pod and expect a response;
if the Pod responds between 200–399 then the kubelet considers that Pod is
healthy; otherwise, the Pod will be marked as unhealthy.
Use Cases
Use Liveness Probe to remove unhealthy pods.
If you’d like your container to be killed and restarted if a probe fails, then specify
a liveness probe, and specify a restartPolicy of Always or OnFailure.
Use a liveness probe for a container that can fail with no possible recovery.
If your container cannot crash by itself when there is an unexpected error occur,
then use liveness probes. Using liveness probes can overcome some of the bugs
the process might have.
Readiness Probe
Readiness probes let Kubernetes know when your app (running in a container
inside Pod) is ready to serve traffic.
Indicates whether the container is ready to respond to requests.
Kubernetes makes sure the readiness probe passes before allowing a service to
send traffic to the pod.
Unlike a liveness probe, a readiness probe doesn’t kill the container. If the
readiness probe fails, Kubernetes simply hides the container’s Pod from
corresponding Services, so that no traffic is redirected to it.
Liveness probes do not wait for readiness probes to succeed. If you want to wait
before executing a liveness probe you should use initialDelaySeconds or
startupProbe.
A side-effect of using Readiness Probes is that they can increase the time it takes
to update Deployments.
Use Cases
Use Readiness Probe to detect partial unavailability.
If you’d like to start sending traffic to a Pod only when a probe succeeds, specify
a readiness probe.
44
If you want your container to be able to take itself down for maintenance, you
can specify a readiness probe that checks an endpoint specific to readiness that is
different from the liveness probe.
Startup Probe
Startup probes let Kubernetes know whether your app (running in a container
inside Pod) has properly started.
Indicates whether the application within the container is started.
Startup probe has higher priority over the two other probe types. Until the Startup
Probe succeeds, all the other Probes are disabled.
Startup probes are useful in situations where your app can take a long time to
start, or could occasionally fail on startup.
Rather than set a long liveness interval, you can configure a separate
configuration for probing the container as it starts up, allowing a time longer than
the liveness interval would allow.
Use Cases
Use Startup Probe for applications that take longer to start.
When your app needs additional time to startup, you can use the Startup Probe to
delay the Liveness and Readiness Probe.
If your container needs to work on loading large data, configuration files, or
migrations during startup, you can use a startup probe.
Probes Key Points
While Liveness probe detects failures in an app that are resolved by terminating
the Pod (i.e. restarting the app), Readiness Probe detects conditions where the app
may be temporarily unavailable.
Liveness probe passes when the app itself is healthy, but the readiness probe
additionally checks that each required back-end service is available. This helps
you avoid directing traffic to Pods that can only respond with error messages.
By combining liveness and readiness probes, you can instruct Kubernetes to
automatically restart pods or remove them from backend groups. If your app has
a strict dependency on back-end services, you can implement both liveness and
readiness probes.
45
By default, the probe will stop if the application is not ready after three attempts.
In case of a liveness probe, it will restart the container. In the case of a readiness
probe, it will mark pods as unhealthy.
In many applications, the /health and /ready endpoints are merged into a single
/health endpoint because there is no real difference between their healthy and
ready states.
Ways to check Pods/Containers’ health using Probes
Kubelet can check a Pods’ health in three ways. Each probe must define exactly
one of these mechanisms:
HTTP
We define a Port number along with the URL. Kubernetes pings this path, and if
it gets an HTTP response in the 200 or 300 range, it marks the app as healthy.
Otherwise, it is marked as unhealthy.
HTTP probes are the most common type of custom probe.
Even if your app isn’t an HTTP server, you can create a lightweight HTTP server
inside your app to respond to the liveness probe.
TCP
Kubernetes tries to establish a TCP connection on the specified port. If it can
establish a connection, the container is considered healthy; if it can’t it is
considered unhealthy.
TCP probes come in handy if you have a scenario where HTTP probes or
Command probes don’t work well.
For example, a gRPC or FTP service is a prime candidate for this type of probe.
Command
Kubernetes runs a command inside the container. If the command returns with
exit code 0, then the container is marked as healthy. Otherwise, it is marked
unhealthy.
This type of probe is useful when you can’t or don’t want to run an HTTP server,
but can run a command that can check whether or not your app is healthy.
46
Probe Parameters
Probes have a number of fields that can be used to more precisely control the
behavior of liveness and readiness checks.
initialDelaySeconds: Number of seconds after the container has started before
probes are initiated. (default: 0, minimum: 0)
periodSeconds: How often to perform the probe (i.e. frequency). (default: 10,
minimum: 1)
timeoutSeconds: Number of seconds after which the probe times out. (default: 1,
minimum: 1)
successThreshold: Minimum consecutive successes for the probe to be
considered successful after failure. (default: 1, minimum: 1)
failureThreshold: How many failed results were received to transition from a
healthy to a failure state. (default: 3, minimum: 1)
47
Sidecar Container
A pod is the basic building block of kubernetes application. Kubernetes manages
pods instead of containers and pods encapsulate containers. A pod may contain
one or more containers, storage, IP addresses, and, options that govern how
containers should run inside the pod.
A pod that contains one container refers to a single container pod and it is the
most common kubernetes use case. A pod that contains Multiple co-related
containers refers to a multi-container pod. There are few patterns for multi-
container pods one of them is the sidecar container pattern.
What are Sidecar Containers?
Sidecar containers are the containers that should run along with the main
container in the pod. This sidecar pattern extends and enhances the functionality
of current containers without changing it.
Imagine that you have the pod with a single container working very well and you
want to add some functionality to the current container without touching or
changing, how can you add the additional functionality or extending the current
functionality? This sidecar container pattern really helps exactly in that situation.
If you look at the above diagram, you can define any number of containers for
Sidecar containers and your main container works along with it successfully. All
the Containers will be executed parallelly and the whole functionality works only
if both types of containers are running successfully. Most of the time these sidecar
48
containers are simple and small that consume fewer resources than the main
container.
Init Container :
Init Containers are the containers that should run and complete before the startup
of the main container in the pod. It provides a separate lifecycle for the
initialization so that it enables separation of concerns in the applications.
AdapterContainer:
Namespaces
In Kubernetes, namespaces provides a mechanism for isolating groups of
resources within a single cluster. Names of resources need to be unique within a
namespace, but not across namespaces.
Initial namespaces:
default
Kubernetes includes this namespace so that you can start using your new cluster
without first creating a namespace.
kube-node-lease
This namespace holds Lease objects associated with each node. Node leases
allow the kubelet to send heartbeats so that the control plane can detect node
failure.
kube-public
This namespace is readable by all clients (including those not authenticated).
This namespace is mostly reserved for cluster usage, in case that some resources
should be visible and readable publicly throughout the whole cluster. The public
aspect of this namespace is only a convention, not a requirement.
49
kube-system
The namespace for objects created by the Kubernetes system.
To create a namespace:
Here a pod is created but you need to understand the po is running on a default
namespace. Any pod you create without specifying the namespace it will default
created in default namespace.
So we need to mention the namespace when creating the pod.
From the above example we can clearly see that a pod is created in customized
namespace. But the problem is every time when we are creating the pod we
need to mention the namespace, to over come this problem we a special tool
called as kubens, with the help of the tool we can move into over desired name
spaces.
50
From the above example when we execute kubens command it is displaying the
all namespaces and the active namespace is show in green colour.
To change the namespace the command is
kubens <namespace>
now we don’t need to provide -n option when creating a pod in our desired
namespace , why because we are now in that namespace only.
Now the problem is there is no restrictions on the namespace.
When I provide the access for the users on the namespace,the user can access
the total resources for only this namespace.
To avoid this we can apply resource quotas.
Kubernetes Resource Quotas:
When several teams of people share Kubernetes development and production
nodes, it is typically a requirement to divide the computing resources equally.
Kubernetes namespaces help with this via creating logically isolated work
environments. But namespaces does not enforce limitations / quotas.
We need to use Kubernetes quotas to precisely specify strict quota limits for
around 15 Kubernetes API resources.
51
Basic Quota:
To check the quota of a namespace.
The above code will create a resource quota with maximum number of pod for
the namespace as 2.
52
From the above picture we can understand that a resource quota is created and it
will allow only 2 pods per namespace
Usage: LimitRange helps ensure that pods created within a namespace adhere
to certain resource constraints, preventing resource overconsumption and
ensuring fair allocation of resources across pods.
Enforcement: When a pod is created without explicit resource requests and
limits, the LimitRange sets default resource requests and limits for the pod. It can
also enforce maximum resource limits, preventing pods from requesting more
resources than allowed.
RBAC
Role-based access control (RBAC) is a method of regulating access to computer
or network resources based on the roles of individual users within your
organization.
1. Create Kubernetes cluster
2. Login to master server
3. ll /etc/Kubernetes/kop-controller
You can use any of the following methods to choose where Kubernetes schedules
specific Pods:
• NodeSelector
• NodeAffinity
• Taints & Tolerations
• Pod Affinity & Anti-Affinity
NodeAffinity:
Node Affinity is a feature that allows you to schedule pods on nodes based on
various node attributes such as labels, taints, and others. Node Affinity makes use
of several operators to specify how node selectors are matched or how multiple
selectors are combined.
In: This operator matches when the node label value is equal to the specified
value. For example, nodeSelectorTerm.matchExpressions.key: "disktype",
nodeSelectorTerm.matchExpressions.operator: "In",
nodeSelectorTerm.matchExpressions.values: ["ssd", "hdd"] matches nodes with
the label disktype=ssd or disktype=hdd.
NotIn: This operator matches when the node label value is not equal to any of the
specified values. For example, nodeSelectorTerm.matchExpressions.key:
"disktype", nodeSelectorTerm.matchExpressions.operator: "NotIn",
nodeSelectorTerm.matchExpressions.values: ["ssd", "hdd"] matches nodes
without the label disktype=ssd or disktype=hdd.
58
Exists: This operator matches when the node has a label with the specified key,
regardless of its value. For example, nodeSelectorTerm.matchExpressions.key:
"disktype", nodeSelectorTerm.matchExpressions.operator: "Exists" matches
nodes with the label disktype.
DoesNotExist: This operator matches when the node does not have a label with
the specified key. For example, nodeSelectorTerm.matchExpressions.key:
"disktype", nodeSelectorTerm.matchExpressions.operator: "DoesNotExist"
matches nodes without the label disktype.
Gt/Lt: These operators match when the node label value is greater than or less
than the specified value, respectively. For example,
nodeSelectorTerm.matchExpressions.key: "memory",
nodeSelectorTerm.matchExpressions.operator: "Gt",
nodeSelectorTerm.matchExpressions.values: ["4Gi"] matches nodes with more
than 4 GB of memory.
Exists Match: This operator matches when the node has at least one label
matching the specified regular expression. For example,
nodeSelectorTerm.matchExpressions.key: "kubernetes.io/hostname",
nodeSelectorTerm.matchExpressions.operator: "ExistsMatch",
nodeSelectorTerm.matchExpressions.values: ["node-.+"] matches nodes whose
hostname matches the regular expression node-.+.
Not Exists Match: This operator matches when the node does not have any label
matching the specified regular expression. For example,
nodeSelectorTerm.matchExpressions.key: "kubernetes.io/hostname",
nodeSelectorTerm.matchExpressions.operator: "NotExistsMatch",
nodeSelectorTerm.matchExpressions.values: ["node-.+"] matches nodes whose
hostname does not match the regular expression node-.+.
Using this Kubernetes feature we can create nodes that are reserved (dedicated)
for specific pods. E.g. pods which require that most of the resources of the node
be available to them in order to operate flawlessly should be scheduled to nodes
that are reserved for them.
system pods are created with toleration settings that tolerate all taints thus can be
scheduled onto any node. This is by design, as system pods are required by the
59
users can’t be stopped from deploying pods that tolerate “wrong” taint thus,
beside system pods, pods other than desired ones may still run on the reserved
nodes.
HELM
Helm is widely known as "the package manager for Kubernetes. Helm is an open-
source project which was originally created by DeisLabs and donated to CNCF,
which now maintains it. The original goal of Helm was to provide users with a
better way to manage all the Kubernetes YAML files we create on Kubernetes
projects.
The path Helm took to solve this issue was to create Helm Charts. Each chart is
a bundle with one or more Kubernetes manifests – a chart can have child charts
and dependent charts as well.
This means that Helm installs the whole dependency tree of a project if you run
the install command for the top-level chart. You just a single command to install
your entire application, instead of listing the files to install via kubectl.
chart.yaml: This is where you'll put the information related to your chart. That
includes the chart version, name, and description so you can find it if you publish
it on an open repository. Also in this file you'll be able to set external
dependencies using the dependencies key.
values.yaml: Like we saw before, this is the file that contains defaults for
variables.
templates (dir): This is the place where you'll put all your manifest files.
Everything in here will be passed on and created in Kubernetes.
charts: If your chart depends on another chart you own, or if you don't want to
rely on Helm's default library (the default registry where Helm pull charts from),
you can bring this same structure inside this directory. Chart dependencies are
installed from the bottom to the top, which means if chart A depends on chart B,
and B depends on C, the installation order will be C ->B ->A.
61