0% found this document useful (0 votes)
48 views

Kubernetes

Uploaded by

aabc008
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
48 views

Kubernetes

Uploaded by

aabc008
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 61

1

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.

Kubernetes is designed to be a highly decoupled system. This means that


different components of Kubernetes are designed to work independently and can
be swapped out or upgraded without affecting the rest of the system.
For example, Kubernetes has a decoupled architecture where the Kubernetes API
server, etcd, and kubelet all communicate with each other using well-defined
APIs. This allows each component to function independently, with its own set of
responsibilities and requirements, while still working together seamlessly.
This decoupling allows Kubernetes to be more flexible and adaptable to a wide
range of use cases and environments. It also makes it easier to develop and
maintain Kubernetes, as each component can be tested and updated
independently.
Overall, Kubernetes' decoupled architecture is one of its key strengths, as it
enables a high degree of modularity and extensibility, making it a popular choice
for managing containerized applications and microservices at scale.
2

Monolithic and Microservices


Monolithic and microservices are two different software architecture patterns
used in software development.
Monolithic architecture is a traditional software architecture pattern in which all
the components of an application are tightly coupled and packaged together into
a single, large executable or codebase. In a monolithic architecture, all the
functions of the application, such as the user interface, business logic, and data
storage, are combined into a single codebase. This approach can make it easier to
develop and test the application as a whole, but it can also make it difficult to
scale and maintain over time, particularly as the application grows larger and
more complex.
Microservices architecture, on the other hand, is a modern approach to software
architecture that emphasizes breaking down an application into smaller,
independent components or services that communicate with each other via APIs.
Each service is designed to perform a specific function or task, such as handling
user authentication, managing data storage, or processing payments.
Microservices are typically deployed as containers or virtual machines and can
be scaled and updated independently of each other. This approach can make it
easier to scale and maintain an application over time, as changes to one service
do not necessarily require changes to other services.
Overall, both monolithic and microservices architectures have their advantages
and disadvantages, and the choice between the two depends on the specific needs
of the application and the development team's expertise and preferences.
Monolithic applications
If all the functionalities of a project exist in a single codebase, then that
application is known as a monolithic application. We all must have designed a
monolithic application in our lives in which we were given a problem statement
and were asked to design a system with various functionalities. We design our
application in various layers like presentation, service, and persistence and then
deploy that codebase as a single jar/war file. This is nothing but a monolithic
application, where “mono” represents the single codebase containing all the
required functionalities.
3

Disadvantages of Monolithic applications:


1. It becomes too large with time and hence, difficult to manage.
2. We need to redeploy the whole application, even for a small change.
3. As the size of the application increases, its start-up and deployment time
also increases.
4. For any new developer joining the project, it is very difficult to understand
the logic of a large Monolithic application even if his responsibility is
related to a single functionality.
5. Even if a single part of the application is facing a large load/traffic, we need
to deploy the instances of the entire application in multiple servers. It is
very inefficient and takes up more resources unnecessarily. Hence,
horizontal scaling is not feasible in monolithic applications.
6. It is very difficult to adopt any new technology which is well suited for a
particular functionality as it affects the entire application, both in terms of
time and cost.
7. It is not very reliable, as a single bug in any module can bring down the
entire monolithic application.
Advantages of monolithic applications:
Simple to develop relative to microservices, where skilled developers are required
in order to identify and develop the services.
Easier to deploy as only a single jar/war file is deployed.Relatively easier and
simple to develop in comparison to microservices architecture.
The problems of network latency and security are relatively less in comparison
to microservices architecture.
4

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.”

The Microservice architecture has a significant impact on the relationship


between the application and the database. Instead of sharing a single database
with other microservices, each microservice has its own database. It often results
in duplication of some data, but having a database per microservice is essential if
you want to benefit from this architecture, as it ensures loose coupling. Another
advantage of having a separate database per microservice is that each
microservice can use the type of database best suited for its needs. Each service
offers a secure module boundary so that different services can be written in
different programming languages. There are many patterns involved in
microservice architecture like service discovery & registry, caching, API gateway
& communication, observability, security, etc.

Principles of microservices: Single responsibility: It is one of the principles


defined as a part of the SOLID design pattern. It states that a single unit, either a
class, a method, or a microservice should have one and only one responsibility.
Each microservice must have a single responsibility and provide a single
5

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.

Microservices architecture is an evolution of SOA. People also consider SOA as


a superset of microservices. In simple terms, microservices is a fine-grained SOA.
Here, the microservices communicate with each other directly and there is no
central dependency for communication such as ESB in SOA. Also, there is a
guideline to have a separate database for each microservice. The fundamental
6

idea of the evolution of microservices from SOA is to reduce the dependency


between the services and make them loosely coupled with the above-mentioned
guidelines.
Advantages of microservices:
It is easy to manage as it is relatively smaller.
If there’s any update in one of the microservices, then we need to redeploy only
that microservice.
Microservices are self-contained and, hence, deployed independently. Their start-
up and deployment times are relatively less.
It is very easy for a new developer to onboard the project as he needs to
understand only a particular microservice providing the functionality he will be
working on and not the whole system.
If a particular microservice is facing a large load because of the users using that
functionality in excess, then we need to scale out that microservice only. Hence,
the microservices architecture supports horizontal scaling.
Each microservice can use different technology based on the business
requirements.
If a particular microservice goes down due to some bug, then it doesn’t affect
other microservices and the whole system remains intact and continues providing
other functionalities to the users.
Disadvantages of microservices:
Being a distributed system, it is much more complex than monolithic
applications. Its complexity increases with the increase in a number of
microservices.
Skilled developers are required to work with microservices architecture, which
can identify the microservices and manage their inter-communications.
Independent deployment of microservices is complicated.
Microservices are costly in terms of network usage as they need to interact with
each other and all these remote calls result in network latency.
Microservices are less secure relative to monolithic applications due to the inter-
services communication over the network.
Debugging is difficult as the control flows over many microservices and to point
out why and where exactly the error occurred is a difficult task.
7

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.

Control Plane Components

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.

In addition to replication, Kubernetes provides several other mechanisms for


ensuring the fault tolerance of the API server, including:

High availability configurations: Kubernetes provides configuration options that


allow you to configure the API server for high availability, including options for
load balancing and failover.

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

versions if needed. Manifests also allow you to easily replicate your


environment..

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.

Raft is a widely-used consensus algorithm that allows a group of nodes to


coordinate and agree on a shared state even in the presence of failures and
network partitions. In a Raft-based system, each node maintains a replicated log
of state changes and participates in a leader election process to ensure that there
is always a single leader responsible for processing requests.

In a Kubernetes cluster, the Raft algorithm is used to maintain consistency across


the replicas of the API server. Each API server instance maintains a copy of the
cluster's configuration data in a distributed key-value store called etcd. The API
server instances use the Raft algorithm to coordinate changes to this data,
ensuring that updates are made atomically and consistently across the replicas.

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.

etcd is designed to be highly available and fault-tolerant. It achieves this through


a number of features, including:

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.

Scalability: etcd is designed to scale horizontally by adding new nodes to the


cluster as needed.

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 performs its scheduling function by periodically querying the


Kubernetes API server to find new pods that need to be 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.

The kube-scheduler schedules pods by selecting a suitable node in the cluster


based on various factors such as resource availability, node affinity/anti-affinity,
pod affinity/anti-affinity, and other constraints.

When a new pod is created in Kubernetes, it is initially in the "Pending" state,


indicating that it has not yet been scheduled to run on a node. The kube-scheduler
periodically queries the Kubernetes API server to find new pods that need to be
11

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.

The kube-scheduler can also be extended with custom scheduling policies or


plugins, allowing users to implement their own scheduling logic and decision-
making criteria.

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.

In addition to managing containers, the kubelet also performs other important


functions on the node, such as:

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.

Mounting and managing volumes: The kubelet is responsible for mounting


volumes and managing their lifecycle on the node.
12

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.

In addition to these controllers, the kube-controller-manager also performs other


functions such as:

• Garbage collection: The kube-controller-manager is responsible for


garbage collecting unused objects in the cluster, such as pods and services
that are no longer needed.
• Node labeling: The kube-controller-manager can automatically label nodes
in the cluster based on their characteristics, such as their hardware
specifications or geographical location.
13

Installing Kubeadm
Deploying Kubernetes Cluster using Kubeadm

Installing kubeadm Master Node:

curl -sL https://get.docker.com | bash

sudo apt-get update

sudo apt-get install -y apt-transport-https ca-certificates curl

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key


add –

for ubuntu 21.0 later servers

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo tee


/etc/apt/trusted.gpg.d/kubernetes.gpg >/dev/null

cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list

deb https://apt.kubernetes.io/ kubernetes-xenial main

EOF

sudo swapoff -a

sudo apt-get update

sudo apt-get install -y kubelet=1.27.1-00 kubeadm=1.27.1-00 kubectl=1.27.1-00

sudo apt-mark hold kubelet kubeadm kubectl

rm /etc/containerd/config.toml

kubeadm init --pod-network-cidr 192.168.0.0/16 --kubernetes-version 1.26.1

kubectl get pods

kubectl get nodes


14

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

sudo apt-get update

sudo apt-get install -y apt-transport-https ca-certificates curl

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add


-

cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list

deb https://apt.kubernetes.io/ kubernetes-xenial main

EOF

sudo swapoff -a

sudo apt-get update

sudo apt-get install -y kubelet=1.26.1-00 kubeadm=1.26.1-00 kubectl=1.26.1-00

sudo apt-mark hold kubelet kubeadm kubectl

rm /etc/containerd/config.toml

kubeadm join 10.100.1.56:6443 --token uwpz4k.tosuuz2eyu8zq09h --discovery-


token-ca-cert-hash
sha256:aec0aaa203ba3fdd24eab52e918b29465ccf058279a3bd369cd609626f6b
a97f

Cluster Configuration:

alias ku=kubectl
15

kubectl describe nodes ip-10-100-1-56

assign lable to a node

kubectl label nodes ip-10-100-1-56 node-role.kubernetes.io/master=yes

kubectl label nodes <node-slave> node-role.kubernetes.io/worker=yes

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

The “kubectl cluster-info” command is used to display information about the


Kubernetes cluster that is currently configured in your kubectl context. When you
run the command, it will display the following information:

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:

NAME: The name of the namespace.

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:

LAST SEEN: The last time the event was seen.

FIRST SEEN: The first time the event was seen.

COUNT: The number of times the event has occurred.

NAME: The name of the object associated with the event.


17

KIND: The type of object associated with the event.

SUBOBJECT: The sub-object associated with the event.

TYPE: The type of event that has occurred, such as Normal or Warning.

REASON: The reason for the event, such as Created or Deleted.

SOURCE: The source of the event, such as the name of the Kubernetes API
server.

MESSAGE: A brief message describing the event.

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:

NAMESPACE: The namespace in which the service is deployed.

NAME: The name of the service.

TYPE: The type of the service, which can be ClusterIP, NodePort, LoadBalancer,
or ExternalName.

CLUSTER-IP: The IP address of the service within the cluster.

EXTERNAL-IP: The external IP address of the service, if applicable.

PORT(S): The port number(s) used by the service.

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.

The basic syntax for kubectl run is:

kubectl run <name> --image=<image-name>

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.

kubectl get pod is a command used to retrieve information about pods in a


Kubernetes cluster.

The basic syntax for kubectl get pod is:

kubectl get pod <pod-name>


19

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.

-n <namespace>: specifies the namespace to retrieve pods from. If omitted, the


current namespace is used.

--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:

kubectl get pod -o wide

“kubectl expose pod” is a command used to create a new Kubernetes service


for a pod. A service is a way to expose a set of pods as a network service.

The basic syntax for kubectl expose pod is:

kubectl expose pod <pod-name> --name=<service-name> --port=<port> --target-


port=<target-port> --type=<service-type>

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:

NAME: The name of the service


20

TYPE: The type of service (ClusterIP, NodePort, or LoadBalancer)

CLUSTER-IP: The IP address assigned to the service

EXTERNAL-IP: The external IP address (if any) assigned to the service

PORT(S): The port(s) exposed by the service

AGE: The amount of time since the service was created

For example, to list all the services in the default namespace, you can use:

kubectl get svc

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.

By default, Kubernetes creates a namespace called "default" where resources are


created if no namespace is specified during deployment. However, you can create
multiple namespaces and deploy resources in them as per your requirements.

Namespaces can be used to provide isolation and resource allocation between


different teams, applications, or environments in the same cluster. For example,
you can create separate namespaces for development, testing, and production
environments.

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.

To create a namespace, you can use the kubectl command:

kubectl create namespace <namespace-name>

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:

kubectl create deployment my-app --image=my-image -n <namespace-name>


21

The kube-system namespace is a default namespace in Kubernetes that contains


system-level resources that are required for the Kubernetes cluster to function
properly. This namespace is typically used to manage infrastructure-level
components that are essential for the operation of the Kubernetes system, such as
the Kubernetes API server, the etcd data store, the kubelet service, and the kube-
proxy service.

Some common resources that are deployed in the kube-system namespace


include:

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.

kube-controller-manager: The controller manager runs various controllers that


monitor and manage the state of the Kubernetes cluster.

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.

kube-proxy: The proxy is responsible for routing network traffic to the


appropriate service endpoints.

The kube-system namespace is managed by the Kubernetes system and should


not be modified by users unless they have a good understanding of the system-
level components and their dependencies. Modifying or deleting resources in this
namespace could potentially affect the operation of the entire cluster.

kuberentes cluster vs namespace:


Kubernetes cluster and namespace are two different concepts in Kubernetes.

A Kubernetes cluster is a set of nodes (physical or virtual machines) that run


containerized applications and are managed by Kubernetes. It consists of one or
more master nodes and one or more worker nodes. The master nodes run the
Kubernetes control plane, which is responsible for managing and orchestrating
the cluster's resources, while the worker nodes run the actual workloads in the
form of containers.
22

A namespace, on the other hand, is a way to logically divide a Kubernetes cluster


into smaller virtual clusters, which can be used to organize and isolate resources
within a cluester. It allows you to create a virtual environment that provides a way
to organize and isolate resources within a cluster. It helps in managing resource
usage and access control between different teams or applications.

In summary, a Kubernetes cluster is the entire infrastructure of nodes, control


plane components, and networking components that are used to deploy and
manage containerized applications, while a namespace is a way to organize and
partition resources within a cluster. Clusters are the foundation on which
namespaces are built. Namespaces help you to manage your resources better
within a Kubernetes cluster by providing logical separation and resource
allocation between different teams or applications.
23

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 is widely used in production environments because it simplifies the process


of creating and managing Kubernetes clusters, reducing the risk of errors and
downtime. It is also highly configurable, allowing users to customize their
clusters to meet their specific requirements.

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

4.Buy a domian in godaddy

5.create route53 zone in aws and update the dns in godaddy

6.reate AWS s3 bucket with same domain name in godaddy

7.Generate sshkey pair

8.Download KOPS to /usr/local/bin with 700 access

9.create cluster with kops


25

Primary components of Kubernetes


Pods:
A pod is a wrapper which will contain one or more containers. Pod is a
collection of containers that can run on a host. This resource is created by
clients and scheduled onto hosts.

Wrapper:

In computer programming, a wrapper is a code component that serves as an


interface or mediator between two different modules or systems. The purpose of
a wrapper is to simplify the communication or integration between these
modules by providing a more convenient or standardized interface.

In Kubernetes, a pod is the smallest deployable unit that can be created,


scheduled, and managed. A pod is a logical host for one or more containers that
are deployed together on the same node and share the same network namespace.

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:

An emptyDir volume is a type of volume that is created when a Pod is launched,


and it is used to store temporary data that is deleted when the Pod is terminated.

In Kubernetes, you can check if an emptyDir volume is created in a Pod by


examining the Pod's configuration using the kubectl get pod command. Here's
how you can do it:

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:

kubectl get pod <pod-name> -o json


26

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.

Pods in a Kubernetes cluster are used in two main ways:

• Pods that run a single container. The "one-container-per-Pod" model is


the most common Kubernetes use case; in this case, you can think of a Pod
as a wrapper around a single container; Kubernetes manages Pods rather
than managing the containers directly.
• Pods that run multiple containers that need to work together. A Pod
can encapsulate an application composed of multiple co-located containers
that are tightly coupled and need to share resources. These co-located
containers form a single cohesive unit of service—for example, one
container serving data stored in a shared volume to the public, while a
separate sidecar container refreshes or updates those files. The Pod wraps
these containers, storage resources, and an ephemeral network identity
together as a single unit.

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:

"CrashLoopBackOff" is a state in Kubernetes where a Pod is continuously


restarting due to a failure or error. When a Pod encounters an issue, such as a
container repeatedly crashing or failing to start, Kubernetes automatically
attempts to restart the Pod. However, if the issue persists, the Pod goes into a
"CrashLoopBackOff" state, indicating that it is stuck in a loop of restarting and
failing. This could be caused by various reasons, such as misconfiguration,
resource constraints, or application errors. Further investigation and
troubleshooting are typically required to identify and resolve the underlying issue.

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.

A Deployment is responsible for maintaining a desired state of replica pods,


ensuring the specified number of replicas are running and handling updates to
the application. It abstracts away the underlying infrastructure and provides
features for rolling updates, scaling, and rollback.
28

Here are some key features and functionalities of a Deployment:

Pod Template: A Deployment defines a pod template, which specifies the


configuration for the application pods. It includes information such as container
images, environment variables, ports, and resource requirements.

Replica Management: The Deployment ensures that a specified number of


replicas (instances) of the application are running at all times. If a pod fails or
terminates, the Deployment automatically creates a new pod to maintain the
desired replica count.

Rolling Updates: Deployments support rolling updates, which allow you to


update the application without downtime. During a rolling update, new pods
with the updated configuration are created gradually, while the old pods are
gradually terminated. This approach ensures seamless transitions and
availability during the update process.

Rollback: In case an update introduces issues or errors, Deployments provide


the ability to rollback to the previous stable version. You can easily roll back to
the previous configuration and ensure that the previous version of the
application is running.

Scaling: Deployments allow you to scale the number of replicas up or down


to meet the demand or adjust resource utilization. Scaling can be performed
manually or automatically based on defined policies or metrics.

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

Here's a step-by-step scenario:

• 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 surge helps to ensure a controlled transition during rolling updates. It


prevents sudden spikes in the number of pods and avoids overwhelming the
underlying infrastructure or causing disruptions due to resource constraints. By
setting an appropriate value for max surge, you can balance the need for fast
updates with the need for maintaining stability and availability in your
Kubernetes cluster.

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.

Let's consider an example to understand how "max unavailable" works in


Kubernetes:

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.

Here's a step-by-step scenario:

• Initially, you have 10 pods running, which match the desired replica count.
30

• 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 unavailable" value of 2, Kubernetes allows a maximum of
2 pods to be unavailable at any time.
• Kubernetes gradually replaces the old pods with the new ones, ensuring
that at most 2 pods are unavailable.
• Once a new pod is successfully running, Kubernetes terminates an old pod,
ensuring that the total number of unavailable pods doesn't exceed 2.
• This process continues until all the old pods are replaced, and the rolling
update is completed.
• Finally, you have 10 pods running with the updated version, and the rolling
update is finished.

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.

Different types of available Services:


ClusterIP Service
NodePort Service
LoadBalancer Service
ExternalName Service
32

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

To change the name space excute the command


“kubens <namespace>”

When you run the command “ku get po”


You can see the pods running in the current name space
In the current situation it is displaying the pods in ingress-ngix namespace

To increases the number of replicas of ingress controller


Execute the below command
ku scale deployment -n ingress-nginx ingress-nginx-controller --replicas 3

By executing the above command, the pods are increased

When you execute the command “ku get svc”

A load balancer will be created.


38

Previously we created two ssl certificates :


1.tls.crt
2.tls.key
Create the files in the management server

In Kubernetes there is a concept called as kubentes secrets


If you execute the command
Ku create secrets tls -h Kubernetes will provide the command to execute

Change the name space to default

And give the command


kubectl create secret tls my-tls-secret --cert=/tmp/tls.crt --key=/tmp/tls.key
ku get secrets
we can see the created secrets
39

you can verify the certs

Create a voting app with cluster ip


nano voting-app-ClusterIP.yml

Create records in route 53 for vote and result


Create ingress with the below code for vote and result
#Ingress for vote.k8sbatch17.xyz
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: vote-ingress
annotations:
40

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:

Lets create a pod

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.

From above picture there are no quotas running.


apiVersion: v1
kind: ResourceQuota
metadata:
name: count-quotas
spec:
hard:
pods: "2"

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

Checkout when we are trying to create a 3 pod in the namespace it is not


allowed by the resource quotas.

ResourceQuota and LimitRange are two different Kubernetes objects used to


enforce resource constraints in namespaces, but they serve different purposes and
focus on different aspects of resource management.
ResourceQuota:
Purpose: A ResourceQuota is used to limit the total amount of resources that
can be consumed within a namespace.
Scope: It applies to the sum of resources used by all objects within the
namespace, including pods, deployments, replica sets, and other resources.
Usage: ResourceQuota is typically used to enforce cluster-wide resource usage
policies for different projects, teams, or applications running within namespaces.
Enforcement: When the resource consumption in a namespace exceeds the
specified limits in the ResourceQuota, Kubernetes prevents the creation of
additional pods or other resources until the usage is reduced below the defined
quotas.
LimitRange:
Purpose: A LimitRange is used to set default and maximum resource limits for
pods within a namespace.
Scope: It focuses specifically on individual pod resources (CPU and memory),
rather than the entire namespace's resource usage.
53

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

4. in master node cat /etc/kubernetes/kops-controller/kubernetes-ca.crt


5. create a file in management. server with name ca.crt and paster the data
of kubernetes-ca.crt
6. cat /etc/kubernetes/kops-controller/kubernetes-ca.crt
7. create a file in management. server with name ca.key and paste the data
of kubernetes-ca.key
8. by using these two files we generate certificate for the user we give
separate name space
9. create two name spaces
• kubectl create ns development
54

• kubectl create ns production


10.ku get ns

11.create two users


openssl genrsa -out anand.key 2048
openssl req -new -key anand.key -out anand.csr -subj "/CN=anand/O=development"
openssl genrsa -out bala.key 2048
openssl req -new -key bala.key -out bala.csr -subj "/CN=bala/O=production"

Execute the below command


openssl x509 -req -in anand.csr -CA /root/ca.crt -CAkey /root/ca.key -CAcreateserial -
out anand.crt -days 365
openssl x509 -req -in bala.csr -CA /root/ca.crt -CAkey /root/ca.key -CAcreateserial -out
bala.crt -days 365
55

Now we need to change kubeconfig


cat ~/.kube/config\
take the duplicate session of management server
create a directory name users in ubuntu user only
copy the crt and key files
56

Create the user configuration files from kubeconfig.


57

Kubernetes Advance Schedule


You can constrain a Pod so that it is restricted to run on particular node(s), or to
prefer to run on particular nodes. There are several ways to do this and the
recommended approaches all use label selectors to facilitate the selection.

You can use any of the following methods to choose where Kubernetes schedules
specific Pods:

• NodeSelector
• NodeAffinity
• Taints & Tolerations
• Pod Affinity & Anti-Affinity

Add a label to a node:


List the nodes in your cluster, along with their labels:

kubectl get nodes --show-labels

Choose one of your nodes, and add a label to it:

kubectl label nodes <your-node-name> disktype=ssd

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-.+.

Taints and tolerations


This Kubernetes feature allows users to mark a node (taint the node) so that no
pods can be scheduled to it, unless a pod explicitly tolerates the taint.

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

Kubernetes infrastructure (e.g. kube-proxy) or by the Cloud Provider in case of


managed Kubernetes (e.g. on EKS the aws-node system pod).

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.

The format of a taint is <key>=<value>:<effect>. The <effect> instructs the


Kubernetes scheduler what should happen to pods that don’t tolerate this taint.
We can distinguish between two different effects:

NoSchedule - instructs Kubernetes scheduler not to schedule any new pods to


the node unless the pod tolerates the taint.

NoExecute - instructs Kubernetes scheduler to evict pods already running on


the node that don’t tolerate the taint.

kubectl label i-0072ba304cf7e88eb size=large

ku taint node i-0072ba304cf7e88eb size=large:NoSchedule

ku taint node i-0072ba304cf7e88eb size-

Tolerations are a Kubernetes pod property that allow a pod to be scheduled on a


node with a matching taint.
60

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.

How to Create a Helm Chart


It's pretty easy to create a chart in Helm. First, you need to have Helm installed.
Then, just type in helm create <chart name> and it will create a directory filled
with files and other directories. Those files are required for Helm to create a chart.

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

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy